duckdb 0.3.5-dev464.0 → 0.3.5-dev503.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/duckdb.cpp CHANGED
@@ -23360,6 +23360,13 @@ bool TryCast::Operation(date_t input, date_t &result, bool strict) {
23360
23360
 
23361
23361
  template <>
23362
23362
  bool TryCast::Operation(date_t input, timestamp_t &result, bool strict) {
23363
+ if (input == date_t::infinity()) {
23364
+ result = timestamp_t::infinity();
23365
+ return true;
23366
+ } else if (input == date_t::ninfinity()) {
23367
+ result = timestamp_t::ninfinity();
23368
+ return true;
23369
+ }
23363
23370
  return Timestamp::TryFromDatetime(input, Time::FromTime(0, 0, 0), result);
23364
23371
  }
23365
23372
 
@@ -39321,6 +39328,18 @@ bool Date::ParseDoubleDigit(const char *buf, idx_t len, idx_t &pos, int32_t &res
39321
39328
  return false;
39322
39329
  }
39323
39330
 
39331
+ static bool TryConvertDateSpecial(const char *buf, idx_t len, idx_t &pos, const char *special) {
39332
+ auto p = pos;
39333
+ for (; p < len && *special; ++p) {
39334
+ const auto s = *special++;
39335
+ if (!s || StringUtil::CharacterToLower(buf[p]) != s) {
39336
+ return false;
39337
+ }
39338
+ }
39339
+ pos = p;
39340
+ return true;
39341
+ }
39342
+
39324
39343
  bool Date::TryConvertDate(const char *buf, idx_t len, idx_t &pos, date_t &result, bool strict) {
39325
39344
  pos = 0;
39326
39345
  if (len == 0) {
@@ -39349,7 +39368,19 @@ bool Date::TryConvertDate(const char *buf, idx_t len, idx_t &pos, date_t &result
39349
39368
  }
39350
39369
  }
39351
39370
  if (!StringUtil::CharacterIsDigit(buf[pos])) {
39352
- return false;
39371
+ // Check for special values
39372
+ if (TryConvertDateSpecial(buf, len, pos, "infinity")) {
39373
+ result = yearneg ? date_t::ninfinity() : date_t::infinity();
39374
+ } else if (TryConvertDateSpecial(buf, len, pos, "epoch")) {
39375
+ result = date_t::epoch();
39376
+ } else {
39377
+ return false;
39378
+ }
39379
+ // skip trailing spaces - parsing must be strict here
39380
+ while (pos < len && StringUtil::CharacterIsSpace(buf[pos])) {
39381
+ pos++;
39382
+ }
39383
+ return pos == len;
39353
39384
  }
39354
39385
  // first parse the year
39355
39386
  for (; pos < len && StringUtil::CharacterIsDigit(buf[pos]); pos++) {
@@ -39450,6 +39481,13 @@ date_t Date::FromString(const string &str, bool strict) {
39450
39481
  }
39451
39482
 
39452
39483
  string Date::ToString(date_t date) {
39484
+ // PG displays temporal infinities in lowercase,
39485
+ // but numerics in Titlecase.
39486
+ if (date == date_t::infinity()) {
39487
+ return "infinity";
39488
+ } else if (date == date_t::ninfinity()) {
39489
+ return "-infinity";
39490
+ }
39453
39491
  int32_t date_units[3];
39454
39492
  idx_t year_length;
39455
39493
  bool add_bc;
@@ -41678,6 +41716,9 @@ bool Interval::GreaterThanEquals(interval_t left, interval_t right) {
41678
41716
  }
41679
41717
 
41680
41718
  date_t Interval::Add(date_t left, interval_t right) {
41719
+ if (!Date::IsFinite(left)) {
41720
+ return left;
41721
+ }
41681
41722
  date_t result;
41682
41723
  if (right.months != 0) {
41683
41724
  int32_t year, month, day;
@@ -41707,6 +41748,9 @@ date_t Interval::Add(date_t left, interval_t right) {
41707
41748
  throw OutOfRangeException("Date out of range");
41708
41749
  }
41709
41750
  }
41751
+ if (!Date::IsFinite(result)) {
41752
+ throw OutOfRangeException("Date out of range");
41753
+ }
41710
41754
  return result;
41711
41755
  }
41712
41756
 
@@ -41724,6 +41768,9 @@ dtime_t Interval::Add(dtime_t left, interval_t right, date_t &date) {
41724
41768
  }
41725
41769
 
41726
41770
  timestamp_t Interval::Add(timestamp_t left, interval_t right) {
41771
+ if (!Timestamp::IsFinite(left)) {
41772
+ return left;
41773
+ }
41727
41774
  date_t date;
41728
41775
  dtime_t time;
41729
41776
  Timestamp::Convert(left, date, time);
@@ -42354,7 +42401,14 @@ bool Timestamp::TryConvertTimestamp(const char *str, idx_t len, timestamp_t &res
42354
42401
  return false;
42355
42402
  }
42356
42403
  if (pos == len) {
42357
- // no time: only a date
42404
+ // no time: only a date or special
42405
+ if (date == date_t::infinity()) {
42406
+ result = timestamp_t::infinity();
42407
+ return true;
42408
+ } else if (date == date_t::ninfinity()) {
42409
+ result = timestamp_t::ninfinity();
42410
+ return true;
42411
+ }
42358
42412
  return Timestamp::TryFromDatetime(date, dtime_t(0), result);
42359
42413
  }
42360
42414
  // try to parse a time field
@@ -42461,6 +42515,11 @@ timestamp_t Timestamp::FromString(const string &str) {
42461
42515
  }
42462
42516
 
42463
42517
  string Timestamp::ToString(timestamp_t timestamp) {
42518
+ if (timestamp == timestamp_t::infinity()) {
42519
+ return "infinity";
42520
+ } else if (timestamp == timestamp_t::ninfinity()) {
42521
+ return "-infinity";
42522
+ }
42464
42523
  date_t date;
42465
42524
  dtime_t time;
42466
42525
  Timestamp::Convert(timestamp, date, time);
@@ -42468,6 +42527,11 @@ string Timestamp::ToString(timestamp_t timestamp) {
42468
42527
  }
42469
42528
 
42470
42529
  date_t Timestamp::GetDate(timestamp_t timestamp) {
42530
+ if (timestamp == timestamp_t::infinity()) {
42531
+ return date_t::infinity();
42532
+ } else if (timestamp == timestamp_t::ninfinity()) {
42533
+ return date_t::ninfinity();
42534
+ }
42471
42535
  return date_t((timestamp.value + (timestamp.value < 0)) / Interval::MICROS_PER_DAY - (timestamp.value < 0));
42472
42536
  }
42473
42537
 
@@ -42483,7 +42547,7 @@ bool Timestamp::TryFromDatetime(date_t date, dtime_t time, timestamp_t &result)
42483
42547
  if (!TryAddOperator::Operation<int64_t, int64_t, int64_t>(result.value, time.micros, result.value)) {
42484
42548
  return false;
42485
42549
  }
42486
- return true;
42550
+ return Timestamp::IsFinite(result);
42487
42551
  }
42488
42552
 
42489
42553
  timestamp_t Timestamp::FromDatetime(date_t date, dtime_t time) {
@@ -43049,17 +43113,17 @@ Value Value::MaximumValue(const LogicalType &type) {
43049
43113
  case LogicalTypeId::TIME:
43050
43114
  return Value::TIME(dtime_t(Interval::SECS_PER_DAY * Interval::MICROS_PER_SEC - 1));
43051
43115
  case LogicalTypeId::TIMESTAMP:
43052
- return Value::TIMESTAMP(timestamp_t(NumericLimits<int64_t>::Maximum()));
43116
+ return Value::TIMESTAMP(timestamp_t(NumericLimits<int64_t>::Maximum() - 1));
43053
43117
  case LogicalTypeId::TIMESTAMP_MS:
43054
43118
  return MaximumValue(LogicalType::TIMESTAMP).CastAs(LogicalType::TIMESTAMP_MS);
43055
43119
  case LogicalTypeId::TIMESTAMP_NS:
43056
- return Value::TIMESTAMPNS(timestamp_t(NumericLimits<int64_t>::Maximum()));
43120
+ return Value::TIMESTAMPNS(timestamp_t(NumericLimits<int64_t>::Maximum() - 1));
43057
43121
  case LogicalTypeId::TIMESTAMP_SEC:
43058
43122
  return MaximumValue(LogicalType::TIMESTAMP).CastAs(LogicalType::TIMESTAMP_S);
43059
43123
  case LogicalTypeId::TIME_TZ:
43060
43124
  return Value::TIMETZ(dtime_t(Interval::SECS_PER_DAY * Interval::MICROS_PER_SEC - 1));
43061
43125
  case LogicalTypeId::TIMESTAMP_TZ:
43062
- return Value::TIMESTAMPTZ(timestamp_t(NumericLimits<int64_t>::Maximum()));
43126
+ return MaximumValue(LogicalType::TIMESTAMP);
43063
43127
  case LogicalTypeId::FLOAT:
43064
43128
  return Value::FLOAT(NumericLimits<float>::Maximum());
43065
43129
  case LogicalTypeId::DOUBLE:
@@ -43199,6 +43263,16 @@ bool Value::IsFinite(double input) {
43199
43263
  return Value::DoubleIsFinite(input);
43200
43264
  }
43201
43265
 
43266
+ template <>
43267
+ bool Value::IsFinite(date_t input) {
43268
+ return Date::IsFinite(input);
43269
+ }
43270
+
43271
+ template <>
43272
+ bool Value::IsFinite(timestamp_t input) {
43273
+ return Timestamp::IsFinite(input);
43274
+ }
43275
+
43202
43276
  bool Value::StringIsValid(const char *str, idx_t length) {
43203
43277
  auto utf_type = Utf8Proc::Analyze(str, length);
43204
43278
  return utf_type != UnicodeType::INVALID;
@@ -44149,8 +44223,14 @@ string Value::ToString() const {
44149
44223
  return Timestamp::ToString(value_.timestamp);
44150
44224
  case LogicalTypeId::TIME_TZ:
44151
44225
  return Time::ToString(value_.time) + Time::ToUTCOffset(0, 0);
44152
- case LogicalTypeId::TIMESTAMP_TZ:
44153
- return Timestamp::ToString(value_.timestamp) + Time::ToUTCOffset(0, 0);
44226
+ case LogicalTypeId::TIMESTAMP_TZ: {
44227
+ // Infinite TSTZ values do not display offsets in PG.
44228
+ auto ret = Timestamp::ToString(value_.timestamp);
44229
+ if (Timestamp::IsFinite(value_.timestamp)) {
44230
+ ret += Time::ToUTCOffset(0, 0);
44231
+ }
44232
+ return ret;
44233
+ }
44154
44234
  case LogicalTypeId::TIMESTAMP_SEC:
44155
44235
  return Timestamp::ToString(Timestamp::FromEpochSeconds(value_.timestamp.value));
44156
44236
  case LogicalTypeId::TIMESTAMP_MS:
@@ -87010,17 +87090,30 @@ static void AgeFunctionStandard(DataChunk &input, ExpressionState &state, Vector
87010
87090
  D_ASSERT(input.ColumnCount() == 1);
87011
87091
  auto current_timestamp = Timestamp::GetCurrentTimestamp();
87012
87092
 
87013
- UnaryExecutor::Execute<timestamp_t, interval_t>(input.data[0], result, input.size(), [&](timestamp_t input) {
87014
- return Interval::GetAge(current_timestamp, input);
87015
- });
87093
+ UnaryExecutor::ExecuteWithNulls<timestamp_t, interval_t>(input.data[0], result, input.size(),
87094
+ [&](timestamp_t input, ValidityMask &mask, idx_t idx) {
87095
+ if (Timestamp::IsFinite(input)) {
87096
+ return Interval::GetAge(current_timestamp, input);
87097
+ } else {
87098
+ mask.SetInvalid(idx);
87099
+ return interval_t();
87100
+ }
87101
+ });
87016
87102
  }
87017
87103
 
87018
87104
  static void AgeFunction(DataChunk &input, ExpressionState &state, Vector &result) {
87019
87105
  D_ASSERT(input.ColumnCount() == 2);
87020
87106
 
87021
- BinaryExecutor::Execute<timestamp_t, timestamp_t, interval_t>(
87107
+ BinaryExecutor::ExecuteWithNulls<timestamp_t, timestamp_t, interval_t>(
87022
87108
  input.data[0], input.data[1], result, input.size(),
87023
- [&](timestamp_t input1, timestamp_t input2) { return Interval::GetAge(input1, input2); });
87109
+ [&](timestamp_t input1, timestamp_t input2, ValidityMask &mask, idx_t idx) {
87110
+ if (Timestamp::IsFinite(input1) && Timestamp::IsFinite(input2)) {
87111
+ return Interval::GetAge(input1, input2);
87112
+ } else {
87113
+ mask.SetInvalid(idx);
87114
+ return interval_t();
87115
+ }
87116
+ });
87024
87117
  }
87025
87118
 
87026
87119
  void AgeFun::RegisterFunction(BuiltinFunctions &set) {
@@ -87121,6 +87214,19 @@ namespace duckdb {
87121
87214
  // This function is an implementation of the "period-crossing" date difference function from T-SQL
87122
87215
  // https://docs.microsoft.com/en-us/sql/t-sql/functions/datediff-transact-sql?view=sql-server-ver15
87123
87216
  struct DateDiff {
87217
+ template <class TA, class TB, class TR, class OP>
87218
+ static inline void BinaryExecute(Vector &left, Vector &right, Vector &result, idx_t count) {
87219
+ BinaryExecutor::ExecuteWithNulls<TA, TB, TR>(
87220
+ left, right, result, count, [&](TA startdate, TB enddate, ValidityMask &mask, idx_t idx) {
87221
+ if (Value::IsFinite(startdate) && Value::IsFinite(enddate)) {
87222
+ return OP::template Operation<TA, TB, TR>(startdate, enddate);
87223
+ } else {
87224
+ mask.SetInvalid(idx);
87225
+ return TR();
87226
+ }
87227
+ });
87228
+ }
87229
+
87124
87230
  struct YearOperator {
87125
87231
  template <class TA, class TB, class TR>
87126
87232
  static inline TR Operation(TA startdate, TB enddate) {
@@ -87427,8 +87533,13 @@ static int64_t DifferenceDates(DatePartSpecifier type, TA startdate, TB enddate)
87427
87533
 
87428
87534
  struct DateDiffTernaryOperator {
87429
87535
  template <typename TS, typename TA, typename TB, typename TR>
87430
- static inline TR Operation(TS part, TA startdate, TB enddate) {
87431
- return DifferenceDates<TA, TB, TR>(GetDatePartSpecifier(part.GetString()), startdate, enddate);
87536
+ static inline TR Operation(TS part, TA startdate, TB enddate, ValidityMask &mask, idx_t idx) {
87537
+ if (Value::IsFinite(startdate) && Value::IsFinite(enddate)) {
87538
+ return DifferenceDates<TA, TB, TR>(GetDatePartSpecifier(part.GetString()), startdate, enddate);
87539
+ } else {
87540
+ mask.SetInvalid(idx);
87541
+ return TR();
87542
+ }
87432
87543
  }
87433
87544
  };
87434
87545
 
@@ -87436,51 +87547,51 @@ template <typename TA, typename TB, typename TR>
87436
87547
  static void DateDiffBinaryExecutor(DatePartSpecifier type, Vector &left, Vector &right, Vector &result, idx_t count) {
87437
87548
  switch (type) {
87438
87549
  case DatePartSpecifier::YEAR:
87439
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateDiff::YearOperator>(left, right, result, count);
87550
+ DateDiff::BinaryExecute<TA, TB, TR, DateDiff::YearOperator>(left, right, result, count);
87440
87551
  break;
87441
87552
  case DatePartSpecifier::MONTH:
87442
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateDiff::MonthOperator>(left, right, result, count);
87553
+ DateDiff::BinaryExecute<TA, TB, TR, DateDiff::MonthOperator>(left, right, result, count);
87443
87554
  break;
87444
87555
  case DatePartSpecifier::DAY:
87445
87556
  case DatePartSpecifier::DOW:
87446
87557
  case DatePartSpecifier::ISODOW:
87447
87558
  case DatePartSpecifier::DOY:
87448
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateDiff::DayOperator>(left, right, result, count);
87559
+ DateDiff::BinaryExecute<TA, TB, TR, DateDiff::DayOperator>(left, right, result, count);
87449
87560
  break;
87450
87561
  case DatePartSpecifier::DECADE:
87451
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateDiff::DecadeOperator>(left, right, result, count);
87562
+ DateDiff::BinaryExecute<TA, TB, TR, DateDiff::DecadeOperator>(left, right, result, count);
87452
87563
  break;
87453
87564
  case DatePartSpecifier::CENTURY:
87454
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateDiff::CenturyOperator>(left, right, result, count);
87565
+ DateDiff::BinaryExecute<TA, TB, TR, DateDiff::CenturyOperator>(left, right, result, count);
87455
87566
  break;
87456
87567
  case DatePartSpecifier::MILLENNIUM:
87457
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateDiff::MilleniumOperator>(left, right, result, count);
87568
+ DateDiff::BinaryExecute<TA, TB, TR, DateDiff::MilleniumOperator>(left, right, result, count);
87458
87569
  break;
87459
87570
  case DatePartSpecifier::QUARTER:
87460
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateDiff::QuarterOperator>(left, right, result, count);
87571
+ DateDiff::BinaryExecute<TA, TB, TR, DateDiff::QuarterOperator>(left, right, result, count);
87461
87572
  break;
87462
87573
  case DatePartSpecifier::WEEK:
87463
87574
  case DatePartSpecifier::YEARWEEK:
87464
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateDiff::WeekOperator>(left, right, result, count);
87575
+ DateDiff::BinaryExecute<TA, TB, TR, DateDiff::WeekOperator>(left, right, result, count);
87465
87576
  break;
87466
87577
  case DatePartSpecifier::ISOYEAR:
87467
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateDiff::ISOYearOperator>(left, right, result, count);
87578
+ DateDiff::BinaryExecute<TA, TB, TR, DateDiff::ISOYearOperator>(left, right, result, count);
87468
87579
  break;
87469
87580
  case DatePartSpecifier::MICROSECONDS:
87470
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateDiff::MicrosecondsOperator>(left, right, result, count);
87581
+ DateDiff::BinaryExecute<TA, TB, TR, DateDiff::MicrosecondsOperator>(left, right, result, count);
87471
87582
  break;
87472
87583
  case DatePartSpecifier::MILLISECONDS:
87473
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateDiff::MillisecondsOperator>(left, right, result, count);
87584
+ DateDiff::BinaryExecute<TA, TB, TR, DateDiff::MillisecondsOperator>(left, right, result, count);
87474
87585
  break;
87475
87586
  case DatePartSpecifier::SECOND:
87476
87587
  case DatePartSpecifier::EPOCH:
87477
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateDiff::SecondsOperator>(left, right, result, count);
87588
+ DateDiff::BinaryExecute<TA, TB, TR, DateDiff::SecondsOperator>(left, right, result, count);
87478
87589
  break;
87479
87590
  case DatePartSpecifier::MINUTE:
87480
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateDiff::MinutesOperator>(left, right, result, count);
87591
+ DateDiff::BinaryExecute<TA, TB, TR, DateDiff::MinutesOperator>(left, right, result, count);
87481
87592
  break;
87482
87593
  case DatePartSpecifier::HOUR:
87483
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateDiff::HoursOperator>(left, right, result, count);
87594
+ DateDiff::BinaryExecute<TA, TB, TR, DateDiff::HoursOperator>(left, right, result, count);
87484
87595
  break;
87485
87596
  default:
87486
87597
  throw NotImplementedException("Specifier type not implemented for DATEDIFF");
@@ -87491,8 +87602,8 @@ template <typename T>
87491
87602
  static void DateDiffFunction(DataChunk &args, ExpressionState &state, Vector &result) {
87492
87603
  D_ASSERT(args.ColumnCount() == 3);
87493
87604
  auto &part_arg = args.data[0];
87494
- auto &startdate_arg = args.data[1];
87495
- auto &enddate_arg = args.data[2];
87605
+ auto &start_arg = args.data[1];
87606
+ auto &end_arg = args.data[2];
87496
87607
 
87497
87608
  if (part_arg.GetVectorType() == VectorType::CONSTANT_VECTOR) {
87498
87609
  // Common case of constant part.
@@ -87501,11 +87612,12 @@ static void DateDiffFunction(DataChunk &args, ExpressionState &state, Vector &re
87501
87612
  ConstantVector::SetNull(result, true);
87502
87613
  } else {
87503
87614
  const auto type = GetDatePartSpecifier(ConstantVector::GetData<string_t>(part_arg)->GetString());
87504
- DateDiffBinaryExecutor<T, T, int64_t>(type, startdate_arg, enddate_arg, result, args.size());
87615
+ DateDiffBinaryExecutor<T, T, int64_t>(type, start_arg, end_arg, result, args.size());
87505
87616
  }
87506
87617
  } else {
87507
- TernaryExecutor::Execute<string_t, T, T, int64_t>(part_arg, startdate_arg, enddate_arg, result, args.size(),
87508
- DateDiffTernaryOperator::Operation<string_t, T, T, int64_t>);
87618
+ TernaryExecutor::ExecuteWithNulls<string_t, T, T, int64_t>(
87619
+ part_arg, start_arg, end_arg, result, args.size(),
87620
+ DateDiffTernaryOperator::Operation<string_t, T, T, int64_t>);
87509
87621
  }
87510
87622
  }
87511
87623
 
@@ -87680,39 +87792,6 @@ DatePartSpecifier GetDateTypePartSpecifier(const string &specifier, LogicalType
87680
87792
  throw NotImplementedException("\"%s\" units \"%s\" not recognized", LogicalTypeIdToString(type.id()), specifier);
87681
87793
  }
87682
87794
 
87683
- template <class T>
87684
- static void LastYearFunction(DataChunk &args, ExpressionState &state, Vector &result) {
87685
- int32_t last_year = 0;
87686
- UnaryExecutor::Execute<T, int64_t>(args.data[0], result, args.size(),
87687
- [&](T input) { return Date::ExtractYear(input, &last_year); });
87688
- }
87689
-
87690
- template <class T, class OP>
87691
- static unique_ptr<BaseStatistics> PropagateDatePartStatistics(vector<unique_ptr<BaseStatistics>> &child_stats) {
87692
- // we can only propagate complex date part stats if the child has stats
87693
- if (!child_stats[0]) {
87694
- return nullptr;
87695
- }
87696
- auto &nstats = (NumericStatistics &)*child_stats[0];
87697
- if (nstats.min.IsNull() || nstats.max.IsNull()) {
87698
- return nullptr;
87699
- }
87700
- // run the operator on both the min and the max, this gives us the [min, max] bound
87701
- auto min = nstats.min.GetValueUnsafe<T>();
87702
- auto max = nstats.max.GetValueUnsafe<T>();
87703
- if (min > max) {
87704
- return nullptr;
87705
- }
87706
- auto min_part = OP::template Operation<T, int64_t>(min);
87707
- auto max_part = OP::template Operation<T, int64_t>(max);
87708
- auto result = make_unique<NumericStatistics>(LogicalType::BIGINT, Value::BIGINT(min_part), Value::BIGINT(max_part),
87709
- StatisticsType::LOCAL_STATS);
87710
- if (child_stats[0]->validity_stats) {
87711
- result->validity_stats = child_stats[0]->validity_stats->Copy();
87712
- }
87713
- return move(result);
87714
- }
87715
-
87716
87795
  template <int64_t MIN, int64_t MAX>
87717
87796
  static unique_ptr<BaseStatistics> PropagateSimpleDatePartStatistics(vector<unique_ptr<BaseStatistics>> &child_stats) {
87718
87797
  // we can always propagate simple date part statistics
@@ -87729,6 +87808,56 @@ static unique_ptr<BaseStatistics> PropagateSimpleDatePartStatistics(vector<uniqu
87729
87808
  }
87730
87809
 
87731
87810
  struct DatePart {
87811
+ template <class T, class OP>
87812
+ static unique_ptr<BaseStatistics> PropagateDatePartStatistics(vector<unique_ptr<BaseStatistics>> &child_stats) {
87813
+ // we can only propagate complex date part stats if the child has stats
87814
+ if (!child_stats[0]) {
87815
+ return nullptr;
87816
+ }
87817
+ auto &nstats = (NumericStatistics &)*child_stats[0];
87818
+ if (nstats.min.IsNull() || nstats.max.IsNull()) {
87819
+ return nullptr;
87820
+ }
87821
+ // run the operator on both the min and the max, this gives us the [min, max] bound
87822
+ auto min = nstats.min.GetValueUnsafe<T>();
87823
+ auto max = nstats.max.GetValueUnsafe<T>();
87824
+ if (min > max) {
87825
+ return nullptr;
87826
+ }
87827
+ // Infinities prevent us from computing generic ranges
87828
+ if (!Value::IsFinite(min) || !Value::IsFinite(max)) {
87829
+ return nullptr;
87830
+ }
87831
+ auto min_part = OP::template Operation<T, int64_t>(min);
87832
+ auto max_part = OP::template Operation<T, int64_t>(max);
87833
+ auto result = make_unique<NumericStatistics>(LogicalType::BIGINT, Value::BIGINT(min_part),
87834
+ Value::BIGINT(max_part), StatisticsType::LOCAL_STATS);
87835
+ if (child_stats[0]->validity_stats) {
87836
+ result->validity_stats = child_stats[0]->validity_stats->Copy();
87837
+ }
87838
+ return move(result);
87839
+ }
87840
+
87841
+ template <typename OP>
87842
+ struct PartOperator {
87843
+ template <class TA, class TR>
87844
+ static inline TR Operation(TA input, ValidityMask &mask, idx_t idx, void *dataptr) {
87845
+ if (Value::IsFinite(input)) {
87846
+ return OP::template Operation<TA, TR>(input);
87847
+ } else {
87848
+ mask.SetInvalid(idx);
87849
+ return TR();
87850
+ }
87851
+ }
87852
+ };
87853
+
87854
+ template <class TA, class TR, class OP>
87855
+ static void UnaryFunction(DataChunk &input, ExpressionState &state, Vector &result) {
87856
+ D_ASSERT(input.ColumnCount() >= 1);
87857
+ using IOP = PartOperator<OP>;
87858
+ UnaryExecutor::GenericExecute<TA, TR, IOP>(input.data[0], result, input.size(), nullptr, true);
87859
+ }
87860
+
87732
87861
  struct YearOperator {
87733
87862
  template <class TA, class TR>
87734
87863
  static inline TR Operation(TA input) {
@@ -88229,6 +88358,20 @@ struct DatePart {
88229
88358
  };
88230
88359
  };
88231
88360
 
88361
+ template <class T>
88362
+ static void LastYearFunction(DataChunk &args, ExpressionState &state, Vector &result) {
88363
+ int32_t last_year = 0;
88364
+ UnaryExecutor::ExecuteWithNulls<T, int64_t>(args.data[0], result, args.size(),
88365
+ [&](T input, ValidityMask &mask, idx_t idx) {
88366
+ if (Value::IsFinite(input)) {
88367
+ return Date::ExtractYear(input, &last_year);
88368
+ } else {
88369
+ mask.SetInvalid(idx);
88370
+ return 0;
88371
+ }
88372
+ });
88373
+ }
88374
+
88232
88375
  template <>
88233
88376
  int64_t DatePart::YearOperator::Operation(timestamp_t input) {
88234
88377
  return YearOperator::Operation<date_t, int64_t>(Timestamp::GetDate(input));
@@ -88728,21 +88871,21 @@ static int64_t ExtractElement(DatePartSpecifier type, T element) {
88728
88871
  }
88729
88872
  }
88730
88873
 
88731
- struct DatePartBinaryOperator {
88732
- template <class TA, class TB, class TR>
88733
- static inline TR Operation(TA specifier, TB date) {
88734
- return ExtractElement<TB>(GetDatePartSpecifier(specifier.GetString()), date);
88735
- }
88736
- };
88737
-
88738
88874
  template <typename T>
88739
88875
  static void DatePartFunction(DataChunk &args, ExpressionState &state, Vector &result) {
88740
88876
  D_ASSERT(args.ColumnCount() == 2);
88741
- auto &part_arg = args.data[0];
88877
+ auto &spec_arg = args.data[0];
88742
88878
  auto &date_arg = args.data[1];
88743
88879
 
88744
- BinaryExecutor::ExecuteStandard<string_t, T, int64_t, DatePartBinaryOperator>(part_arg, date_arg, result,
88745
- args.size());
88880
+ BinaryExecutor::ExecuteWithNulls<string_t, T, int64_t>(
88881
+ spec_arg, date_arg, result, args.size(), [&](string_t specifier, T date, ValidityMask &mask, idx_t idx) {
88882
+ if (Value::IsFinite(date)) {
88883
+ return ExtractElement<T>(GetDatePartSpecifier(specifier.GetString()), date);
88884
+ } else {
88885
+ mask.SetInvalid(idx);
88886
+ return int64_t(0);
88887
+ }
88888
+ });
88746
88889
  }
88747
88890
 
88748
88891
  void AddGenericDatePartOperator(BuiltinFunctions &set, const string &name, scalar_function_t date_func,
@@ -88759,8 +88902,8 @@ void AddGenericDatePartOperator(BuiltinFunctions &set, const string &name, scala
88759
88902
 
88760
88903
  template <class OP>
88761
88904
  static void AddDatePartOperator(BuiltinFunctions &set, string name) {
88762
- AddGenericDatePartOperator(set, name, ScalarFunction::UnaryFunction<date_t, int64_t, OP>,
88763
- ScalarFunction::UnaryFunction<timestamp_t, int64_t, OP>,
88905
+ AddGenericDatePartOperator(set, name, DatePart::UnaryFunction<date_t, int64_t, OP>,
88906
+ DatePart::UnaryFunction<timestamp_t, int64_t, OP>,
88764
88907
  ScalarFunction::UnaryFunction<interval_t, int64_t, OP>,
88765
88908
  OP::template PropagateStatistics<date_t>, OP::template PropagateStatistics<timestamp_t>);
88766
88909
  }
@@ -88783,10 +88926,10 @@ void AddGenericTimePartOperator(BuiltinFunctions &set, const string &name, scala
88783
88926
  template <class OP>
88784
88927
  static void AddTimePartOperator(BuiltinFunctions &set, string name) {
88785
88928
  AddGenericTimePartOperator(
88786
- set, name, ScalarFunction::UnaryFunction<date_t, int64_t, OP>,
88787
- ScalarFunction::UnaryFunction<timestamp_t, int64_t, OP>, ScalarFunction::UnaryFunction<interval_t, int64_t, OP>,
88788
- ScalarFunction::UnaryFunction<dtime_t, int64_t, OP>, OP::template PropagateStatistics<date_t>,
88789
- OP::template PropagateStatistics<timestamp_t>, OP::template PropagateStatistics<dtime_t>);
88929
+ set, name, DatePart::UnaryFunction<date_t, int64_t, OP>, DatePart::UnaryFunction<timestamp_t, int64_t, OP>,
88930
+ ScalarFunction::UnaryFunction<interval_t, int64_t, OP>, ScalarFunction::UnaryFunction<dtime_t, int64_t, OP>,
88931
+ OP::template PropagateStatistics<date_t>, OP::template PropagateStatistics<timestamp_t>,
88932
+ OP::template PropagateStatistics<dtime_t>);
88790
88933
  }
88791
88934
 
88792
88935
  struct LastDayOperator {
@@ -88914,7 +89057,13 @@ struct StructDatePart {
88914
89057
  }
88915
89058
  }
88916
89059
  auto tdata = ConstantVector::GetData<INPUT_TYPE>(input);
88917
- DatePart::StructOperator::Operation(part_values.data(), tdata[0], 0, part_mask);
89060
+ if (Value::IsFinite(tdata[0])) {
89061
+ DatePart::StructOperator::Operation(part_values.data(), tdata[0], 0, part_mask);
89062
+ } else {
89063
+ for (auto &child_entry : child_entries) {
89064
+ ConstantVector::SetNull(*child_entry, true);
89065
+ }
89066
+ }
88918
89067
  }
88919
89068
  } else {
88920
89069
  VectorData rdata;
@@ -88949,7 +89098,13 @@ struct StructDatePart {
88949
89098
  for (idx_t i = 0; i < count; ++i) {
88950
89099
  const auto idx = rdata.sel->get_index(i);
88951
89100
  if (arg_valid.RowIsValid(idx)) {
88952
- DatePart::StructOperator::Operation(part_values.data(), tdata[idx], idx, part_mask);
89101
+ if (Value::IsFinite(tdata[idx])) {
89102
+ DatePart::StructOperator::Operation(part_values.data(), tdata[idx], idx, part_mask);
89103
+ } else {
89104
+ for (auto &child_entry : child_entries) {
89105
+ FlatVector::Validity(*child_entry).SetInvalid(idx);
89106
+ }
89107
+ }
88953
89108
  } else {
88954
89109
  res_valid.SetInvalid(idx);
88955
89110
  for (auto &child_entry : child_entries) {
@@ -89018,25 +89173,25 @@ void DatePartFun::RegisterFunction(BuiltinFunctions &set) {
89018
89173
  // register the last_day function
89019
89174
  ScalarFunctionSet last_day("last_day");
89020
89175
  last_day.AddFunction(ScalarFunction({LogicalType::DATE}, LogicalType::DATE,
89021
- ScalarFunction::UnaryFunction<date_t, date_t, LastDayOperator>));
89176
+ DatePart::UnaryFunction<date_t, date_t, LastDayOperator>));
89022
89177
  last_day.AddFunction(ScalarFunction({LogicalType::TIMESTAMP}, LogicalType::DATE,
89023
- ScalarFunction::UnaryFunction<timestamp_t, date_t, LastDayOperator>));
89178
+ DatePart::UnaryFunction<timestamp_t, date_t, LastDayOperator>));
89024
89179
  set.AddFunction(last_day);
89025
89180
 
89026
89181
  // register the monthname function
89027
89182
  ScalarFunctionSet monthname("monthname");
89028
89183
  monthname.AddFunction(ScalarFunction({LogicalType::DATE}, LogicalType::VARCHAR,
89029
- ScalarFunction::UnaryFunction<date_t, string_t, MonthNameOperator>));
89184
+ DatePart::UnaryFunction<date_t, string_t, MonthNameOperator>));
89030
89185
  monthname.AddFunction(ScalarFunction({LogicalType::TIMESTAMP}, LogicalType::VARCHAR,
89031
- ScalarFunction::UnaryFunction<timestamp_t, string_t, MonthNameOperator>));
89186
+ DatePart::UnaryFunction<timestamp_t, string_t, MonthNameOperator>));
89032
89187
  set.AddFunction(monthname);
89033
89188
 
89034
89189
  // register the dayname function
89035
89190
  ScalarFunctionSet dayname("dayname");
89036
89191
  dayname.AddFunction(ScalarFunction({LogicalType::DATE}, LogicalType::VARCHAR,
89037
- ScalarFunction::UnaryFunction<date_t, string_t, DayNameOperator>));
89192
+ DatePart::UnaryFunction<date_t, string_t, DayNameOperator>));
89038
89193
  dayname.AddFunction(ScalarFunction({LogicalType::TIMESTAMP}, LogicalType::VARCHAR,
89039
- ScalarFunction::UnaryFunction<timestamp_t, string_t, DayNameOperator>));
89194
+ DatePart::UnaryFunction<timestamp_t, string_t, DayNameOperator>));
89040
89195
  set.AddFunction(dayname);
89041
89196
 
89042
89197
  // finally the actual date_part function
@@ -89077,6 +89232,19 @@ void DatePartFun::RegisterFunction(BuiltinFunctions &set) {
89077
89232
  namespace duckdb {
89078
89233
 
89079
89234
  struct DateSub {
89235
+ template <class TA, class TB, class TR, class OP>
89236
+ static inline void BinaryExecute(Vector &left, Vector &right, Vector &result, idx_t count) {
89237
+ BinaryExecutor::ExecuteWithNulls<TA, TB, TR>(
89238
+ left, right, result, count, [&](TA startdate, TB enddate, ValidityMask &mask, idx_t idx) {
89239
+ if (Value::IsFinite(startdate) && Value::IsFinite(enddate)) {
89240
+ return OP::template Operation<TA, TB, TR>(startdate, enddate);
89241
+ } else {
89242
+ mask.SetInvalid(idx);
89243
+ return TR();
89244
+ }
89245
+ });
89246
+ }
89247
+
89080
89248
  struct MonthOperator {
89081
89249
  template <class TA, class TB, class TR>
89082
89250
  static inline TR Operation(TA start_ts, TB end_ts) {
@@ -89403,8 +89571,13 @@ static int64_t SubtractDateParts(DatePartSpecifier type, TA startdate, TB enddat
89403
89571
 
89404
89572
  struct DateSubTernaryOperator {
89405
89573
  template <typename TS, typename TA, typename TB, typename TR>
89406
- static inline TR Operation(TS part, TA startdate, TB enddate) {
89407
- return SubtractDateParts<TA, TB, TR>(GetDatePartSpecifier(part.GetString()), startdate, enddate);
89574
+ static inline TR Operation(TS part, TA startdate, TB enddate, ValidityMask &mask, idx_t idx) {
89575
+ if (Value::IsFinite(startdate) && Value::IsFinite(enddate)) {
89576
+ return SubtractDateParts<TA, TB, TR>(GetDatePartSpecifier(part.GetString()), startdate, enddate);
89577
+ } else {
89578
+ mask.SetInvalid(idx);
89579
+ return TR();
89580
+ }
89408
89581
  }
89409
89582
  };
89410
89583
 
@@ -89413,48 +89586,48 @@ static void DateSubBinaryExecutor(DatePartSpecifier type, Vector &left, Vector &
89413
89586
  switch (type) {
89414
89587
  case DatePartSpecifier::YEAR:
89415
89588
  case DatePartSpecifier::ISOYEAR:
89416
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateSub::YearOperator>(left, right, result, count);
89589
+ DateSub::BinaryExecute<TA, TB, TR, DateSub::YearOperator>(left, right, result, count);
89417
89590
  break;
89418
89591
  case DatePartSpecifier::MONTH:
89419
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateSub::MonthOperator>(left, right, result, count);
89592
+ DateSub::BinaryExecute<TA, TB, TR, DateSub::MonthOperator>(left, right, result, count);
89420
89593
  break;
89421
89594
  case DatePartSpecifier::DAY:
89422
89595
  case DatePartSpecifier::DOW:
89423
89596
  case DatePartSpecifier::ISODOW:
89424
89597
  case DatePartSpecifier::DOY:
89425
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateSub::DayOperator>(left, right, result, count);
89598
+ DateSub::BinaryExecute<TA, TB, TR, DateSub::DayOperator>(left, right, result, count);
89426
89599
  break;
89427
89600
  case DatePartSpecifier::DECADE:
89428
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateSub::DecadeOperator>(left, right, result, count);
89601
+ DateSub::BinaryExecute<TA, TB, TR, DateSub::DecadeOperator>(left, right, result, count);
89429
89602
  break;
89430
89603
  case DatePartSpecifier::CENTURY:
89431
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateSub::CenturyOperator>(left, right, result, count);
89604
+ DateSub::BinaryExecute<TA, TB, TR, DateSub::CenturyOperator>(left, right, result, count);
89432
89605
  break;
89433
89606
  case DatePartSpecifier::MILLENNIUM:
89434
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateSub::MilleniumOperator>(left, right, result, count);
89607
+ DateSub::BinaryExecute<TA, TB, TR, DateSub::MilleniumOperator>(left, right, result, count);
89435
89608
  break;
89436
89609
  case DatePartSpecifier::QUARTER:
89437
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateSub::QuarterOperator>(left, right, result, count);
89610
+ DateSub::BinaryExecute<TA, TB, TR, DateSub::QuarterOperator>(left, right, result, count);
89438
89611
  break;
89439
89612
  case DatePartSpecifier::WEEK:
89440
89613
  case DatePartSpecifier::YEARWEEK:
89441
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateSub::WeekOperator>(left, right, result, count);
89614
+ DateSub::BinaryExecute<TA, TB, TR, DateSub::WeekOperator>(left, right, result, count);
89442
89615
  break;
89443
89616
  case DatePartSpecifier::MICROSECONDS:
89444
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateSub::MicrosecondsOperator>(left, right, result, count);
89617
+ DateSub::BinaryExecute<TA, TB, TR, DateSub::MicrosecondsOperator>(left, right, result, count);
89445
89618
  break;
89446
89619
  case DatePartSpecifier::MILLISECONDS:
89447
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateSub::MillisecondsOperator>(left, right, result, count);
89620
+ DateSub::BinaryExecute<TA, TB, TR, DateSub::MillisecondsOperator>(left, right, result, count);
89448
89621
  break;
89449
89622
  case DatePartSpecifier::SECOND:
89450
89623
  case DatePartSpecifier::EPOCH:
89451
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateSub::SecondsOperator>(left, right, result, count);
89624
+ DateSub::BinaryExecute<TA, TB, TR, DateSub::SecondsOperator>(left, right, result, count);
89452
89625
  break;
89453
89626
  case DatePartSpecifier::MINUTE:
89454
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateSub::MinutesOperator>(left, right, result, count);
89627
+ DateSub::BinaryExecute<TA, TB, TR, DateSub::MinutesOperator>(left, right, result, count);
89455
89628
  break;
89456
89629
  case DatePartSpecifier::HOUR:
89457
- BinaryExecutor::ExecuteStandard<TA, TB, TR, DateSub::HoursOperator>(left, right, result, count);
89630
+ DateSub::BinaryExecute<TA, TB, TR, DateSub::HoursOperator>(left, right, result, count);
89458
89631
  break;
89459
89632
  default:
89460
89633
  throw NotImplementedException("Specifier type not implemented for DATESUB");
@@ -89465,8 +89638,8 @@ template <typename T>
89465
89638
  static void DateSubFunction(DataChunk &args, ExpressionState &state, Vector &result) {
89466
89639
  D_ASSERT(args.ColumnCount() == 3);
89467
89640
  auto &part_arg = args.data[0];
89468
- auto &startdate_arg = args.data[1];
89469
- auto &enddate_arg = args.data[2];
89641
+ auto &start_arg = args.data[1];
89642
+ auto &end_arg = args.data[2];
89470
89643
 
89471
89644
  if (part_arg.GetVectorType() == VectorType::CONSTANT_VECTOR) {
89472
89645
  // Common case of constant part.
@@ -89475,11 +89648,12 @@ static void DateSubFunction(DataChunk &args, ExpressionState &state, Vector &res
89475
89648
  ConstantVector::SetNull(result, true);
89476
89649
  } else {
89477
89650
  const auto type = GetDatePartSpecifier(ConstantVector::GetData<string_t>(part_arg)->GetString());
89478
- DateSubBinaryExecutor<T, T, int64_t>(type, startdate_arg, enddate_arg, result, args.size());
89651
+ DateSubBinaryExecutor<T, T, int64_t>(type, start_arg, end_arg, result, args.size());
89479
89652
  }
89480
89653
  } else {
89481
- TernaryExecutor::Execute<string_t, T, T, int64_t>(part_arg, startdate_arg, enddate_arg, result, args.size(),
89482
- DateSubTernaryOperator::Operation<string_t, T, T, int64_t>);
89654
+ TernaryExecutor::ExecuteWithNulls<string_t, T, T, int64_t>(
89655
+ part_arg, start_arg, end_arg, result, args.size(),
89656
+ DateSubTernaryOperator::Operation<string_t, T, T, int64_t>);
89483
89657
  }
89484
89658
  }
89485
89659
 
@@ -89506,9 +89680,21 @@ void DateSubFun::RegisterFunction(BuiltinFunctions &set) {
89506
89680
 
89507
89681
 
89508
89682
 
89683
+
89684
+
89509
89685
  namespace duckdb {
89510
89686
 
89511
89687
  struct DateTrunc {
89688
+ template <class TA, class TR, class OP>
89689
+ static inline void UnaryExecute(Vector &left, Vector &result, idx_t count) {
89690
+ UnaryExecutor::Execute<TA, TR>(left, result, count, [&](TA input) {
89691
+ if (Value::IsFinite(input)) {
89692
+ return OP::template Operation<TA, TR>(input);
89693
+ } else {
89694
+ return Cast::template Operation<TA, TR>(input);
89695
+ }
89696
+ });
89697
+ }
89512
89698
 
89513
89699
  struct MillenniumOperator {
89514
89700
  template <class TA, class TR>
@@ -89813,6 +89999,10 @@ interval_t DateTrunc::MicrosecondOperator::Operation(interval_t input) {
89813
89999
 
89814
90000
  template <class TA, class TR>
89815
90001
  static TR TruncateElement(DatePartSpecifier type, TA element) {
90002
+ if (!Value::IsFinite(element)) {
90003
+ return Cast::template Operation<TA, TR>(element);
90004
+ }
90005
+
89816
90006
  switch (type) {
89817
90007
  case DatePartSpecifier::MILLENNIUM:
89818
90008
  return DateTrunc::MillenniumOperator::Operation<TA, TR>(element);
@@ -89863,51 +90053,51 @@ template <typename TA, typename TR>
89863
90053
  static void DateTruncUnaryExecutor(DatePartSpecifier type, Vector &left, Vector &result, idx_t count) {
89864
90054
  switch (type) {
89865
90055
  case DatePartSpecifier::MILLENNIUM:
89866
- UnaryExecutor::Execute<TA, TR, DateTrunc::MillenniumOperator>(left, result, count);
90056
+ DateTrunc::UnaryExecute<TA, TR, DateTrunc::MillenniumOperator>(left, result, count);
89867
90057
  break;
89868
90058
  case DatePartSpecifier::CENTURY:
89869
- UnaryExecutor::Execute<TA, TR, DateTrunc::CenturyOperator>(left, result, count);
90059
+ DateTrunc::UnaryExecute<TA, TR, DateTrunc::CenturyOperator>(left, result, count);
89870
90060
  break;
89871
90061
  case DatePartSpecifier::DECADE:
89872
- UnaryExecutor::Execute<TA, TR, DateTrunc::DecadeOperator>(left, result, count);
90062
+ DateTrunc::UnaryExecute<TA, TR, DateTrunc::DecadeOperator>(left, result, count);
89873
90063
  break;
89874
90064
  case DatePartSpecifier::YEAR:
89875
- UnaryExecutor::Execute<TA, TR, DateTrunc::YearOperator>(left, result, count);
90065
+ DateTrunc::UnaryExecute<TA, TR, DateTrunc::YearOperator>(left, result, count);
89876
90066
  break;
89877
90067
  case DatePartSpecifier::QUARTER:
89878
- UnaryExecutor::Execute<TA, TR, DateTrunc::QuarterOperator>(left, result, count);
90068
+ DateTrunc::UnaryExecute<TA, TR, DateTrunc::QuarterOperator>(left, result, count);
89879
90069
  break;
89880
90070
  case DatePartSpecifier::MONTH:
89881
- UnaryExecutor::Execute<TA, TR, DateTrunc::MonthOperator>(left, result, count);
90071
+ DateTrunc::UnaryExecute<TA, TR, DateTrunc::MonthOperator>(left, result, count);
89882
90072
  break;
89883
90073
  case DatePartSpecifier::WEEK:
89884
90074
  case DatePartSpecifier::YEARWEEK:
89885
- UnaryExecutor::Execute<TA, TR, DateTrunc::WeekOperator>(left, result, count);
90075
+ DateTrunc::UnaryExecute<TA, TR, DateTrunc::WeekOperator>(left, result, count);
89886
90076
  break;
89887
90077
  case DatePartSpecifier::ISOYEAR:
89888
- UnaryExecutor::Execute<TA, TR, DateTrunc::ISOYearOperator>(left, result, count);
90078
+ DateTrunc::UnaryExecute<TA, TR, DateTrunc::ISOYearOperator>(left, result, count);
89889
90079
  break;
89890
90080
  case DatePartSpecifier::DAY:
89891
90081
  case DatePartSpecifier::DOW:
89892
90082
  case DatePartSpecifier::ISODOW:
89893
90083
  case DatePartSpecifier::DOY:
89894
- UnaryExecutor::Execute<TA, TR, DateTrunc::DayOperator>(left, result, count);
90084
+ DateTrunc::UnaryExecute<TA, TR, DateTrunc::DayOperator>(left, result, count);
89895
90085
  break;
89896
90086
  case DatePartSpecifier::HOUR:
89897
- UnaryExecutor::Execute<TA, TR, DateTrunc::HourOperator>(left, result, count);
90087
+ DateTrunc::UnaryExecute<TA, TR, DateTrunc::HourOperator>(left, result, count);
89898
90088
  break;
89899
90089
  case DatePartSpecifier::MINUTE:
89900
- UnaryExecutor::Execute<TA, TR, DateTrunc::MinuteOperator>(left, result, count);
90090
+ DateTrunc::UnaryExecute<TA, TR, DateTrunc::MinuteOperator>(left, result, count);
89901
90091
  break;
89902
90092
  case DatePartSpecifier::SECOND:
89903
90093
  case DatePartSpecifier::EPOCH:
89904
- UnaryExecutor::Execute<TA, TR, DateTrunc::SecondOperator>(left, result, count);
90094
+ DateTrunc::UnaryExecute<TA, TR, DateTrunc::SecondOperator>(left, result, count);
89905
90095
  break;
89906
90096
  case DatePartSpecifier::MILLISECONDS:
89907
- UnaryExecutor::Execute<TA, TR, DateTrunc::MillisecondOperator>(left, result, count);
90097
+ DateTrunc::UnaryExecute<TA, TR, DateTrunc::MillisecondOperator>(left, result, count);
89908
90098
  break;
89909
90099
  case DatePartSpecifier::MICROSECONDS:
89910
- UnaryExecutor::Execute<TA, TR, DateTrunc::MicrosecondOperator>(left, result, count);
90100
+ DateTrunc::UnaryExecute<TA, TR, DateTrunc::MicrosecondOperator>(left, result, count);
89911
90101
  break;
89912
90102
  default:
89913
90103
  throw NotImplementedException("Specifier type not implemented for DATETRUNC");
@@ -90838,14 +91028,20 @@ static void StrfTimeFunctionDate(DataChunk &args, ExpressionState &state, Vector
90838
91028
  ConstantVector::SetNull(result, true);
90839
91029
  return;
90840
91030
  }
90841
- UnaryExecutor::Execute<date_t, string_t>(args.data[REVERSED ? 1 : 0], result, args.size(), [&](date_t input) {
90842
- dtime_t time(0);
90843
- idx_t len = info.format.GetLength(input, time, 0, nullptr);
90844
- string_t target = StringVector::EmptyString(result, len);
90845
- info.format.FormatString(input, time, target.GetDataWriteable());
90846
- target.Finalize();
90847
- return target;
90848
- });
91031
+ UnaryExecutor::ExecuteWithNulls<date_t, string_t>(
91032
+ args.data[REVERSED ? 1 : 0], result, args.size(), [&](date_t input, ValidityMask &mask, idx_t idx) {
91033
+ if (Date::IsFinite(input)) {
91034
+ dtime_t time(0);
91035
+ idx_t len = info.format.GetLength(input, time, 0, nullptr);
91036
+ string_t target = StringVector::EmptyString(result, len);
91037
+ info.format.FormatString(input, time, target.GetDataWriteable());
91038
+ target.Finalize();
91039
+ return target;
91040
+ } else {
91041
+ mask.SetInvalid(idx);
91042
+ return string_t();
91043
+ }
91044
+ });
90849
91045
  }
90850
91046
 
90851
91047
  template <bool REVERSED>
@@ -90859,17 +91055,22 @@ static void StrfTimeFunctionTimestamp(DataChunk &args, ExpressionState &state, V
90859
91055
  return;
90860
91056
  }
90861
91057
 
90862
- UnaryExecutor::Execute<timestamp_t, string_t>(args.data[REVERSED ? 1 : 0], result, args.size(),
90863
- [&](timestamp_t input) {
90864
- date_t date;
90865
- dtime_t time;
90866
- Timestamp::Convert(input, date, time);
90867
- idx_t len = info.format.GetLength(date, time, 0, nullptr);
90868
- string_t target = StringVector::EmptyString(result, len);
90869
- info.format.FormatString(date, time, target.GetDataWriteable());
90870
- target.Finalize();
90871
- return target;
90872
- });
91058
+ UnaryExecutor::ExecuteWithNulls<timestamp_t, string_t>(
91059
+ args.data[REVERSED ? 1 : 0], result, args.size(), [&](timestamp_t input, ValidityMask &mask, idx_t idx) {
91060
+ if (Timestamp::IsFinite(input)) {
91061
+ date_t date;
91062
+ dtime_t time;
91063
+ Timestamp::Convert(input, date, time);
91064
+ idx_t len = info.format.GetLength(date, time, 0, nullptr);
91065
+ string_t target = StringVector::EmptyString(result, len);
91066
+ info.format.FormatString(date, time, target.GetDataWriteable());
91067
+ target.Finalize();
91068
+ return target;
91069
+ } else {
91070
+ mask.SetInvalid(idx);
91071
+ return string_t();
91072
+ }
91073
+ });
90873
91074
  }
90874
91075
 
90875
91076
  void StrfTimeFun::RegisterFunction(BuiltinFunctions &set) {
@@ -94202,6 +94403,7 @@ void ListValueFun::RegisterFunction(BuiltinFunctions &set) {
94202
94403
 
94203
94404
 
94204
94405
 
94406
+
94205
94407
  namespace duckdb {
94206
94408
 
94207
94409
  struct NumericRangeInfo {
@@ -94260,6 +94462,11 @@ struct TimestampRangeInfo {
94260
94462
  // interval is 0: no result
94261
94463
  return 0;
94262
94464
  }
94465
+ // We don't allow infinite bounds because they generate errors or infinite loops
94466
+ if (!Timestamp::IsFinite(start_value) || !Timestamp::IsFinite(end_value)) {
94467
+ throw InvalidInputException("Interval infinite bounds not supported");
94468
+ }
94469
+
94263
94470
  if (is_negative && is_positive) {
94264
94471
  // we don't allow a mix of
94265
94472
  throw InvalidInputException("Interval with mix of negative/positive entries not supported");
@@ -96178,11 +96385,18 @@ interval_t AddOperator::Operation(interval_t left, interval_t right) {
96178
96385
 
96179
96386
  template <>
96180
96387
  date_t AddOperator::Operation(date_t left, int32_t right) {
96181
- int32_t result;
96182
- if (!TryAddOperator::Operation(left.days, right, result)) {
96388
+ if (!Value::IsFinite(left)) {
96389
+ return left;
96390
+ }
96391
+ int32_t days;
96392
+ if (!TryAddOperator::Operation(left.days, right, days)) {
96393
+ throw OutOfRangeException("Date out of range");
96394
+ }
96395
+ date_t result(days);
96396
+ if (!Value::IsFinite(result)) {
96183
96397
  throw OutOfRangeException("Date out of range");
96184
96398
  }
96185
- return date_t(result);
96399
+ return result;
96186
96400
  }
96187
96401
 
96188
96402
  template <>
@@ -96192,6 +96406,11 @@ date_t AddOperator::Operation(int32_t left, date_t right) {
96192
96406
 
96193
96407
  template <>
96194
96408
  timestamp_t AddOperator::Operation(date_t left, dtime_t right) {
96409
+ if (left == date_t::infinity()) {
96410
+ return timestamp_t::infinity();
96411
+ } else if (left == date_t::ninfinity()) {
96412
+ return timestamp_t::ninfinity();
96413
+ }
96195
96414
  timestamp_t result;
96196
96415
  if (!Timestamp::TryFromDatetime(left, right, result)) {
96197
96416
  throw OutOfRangeException("Timestamp out of range");
@@ -97750,6 +97969,7 @@ hugeint_t DecimalMultiplyOverflowCheck::Operation(hugeint_t left, hugeint_t righ
97750
97969
 
97751
97970
 
97752
97971
 
97972
+
97753
97973
  #include <limits>
97754
97974
 
97755
97975
  namespace duckdb {
@@ -97782,11 +98002,19 @@ int64_t SubtractOperator::Operation(date_t left, date_t right) {
97782
98002
 
97783
98003
  template <>
97784
98004
  date_t SubtractOperator::Operation(date_t left, int32_t right) {
97785
- int32_t result;
97786
- if (!TrySubtractOperator::Operation(left.days, right, result)) {
98005
+ if (!Date::IsFinite(left)) {
98006
+ return left;
98007
+ }
98008
+ int32_t days;
98009
+ if (!TrySubtractOperator::Operation(left.days, right, days)) {
97787
98010
  throw OutOfRangeException("Date out of range");
97788
98011
  }
97789
- return date_t(result);
98012
+
98013
+ date_t result(days);
98014
+ if (!Date::IsFinite(result)) {
98015
+ throw OutOfRangeException("Date out of range");
98016
+ }
98017
+ return result;
97790
98018
  }
97791
98019
 
97792
98020
  template <>
@@ -104810,6 +105038,7 @@ struct SummaryTableFunction {
104810
105038
 
104811
105039
 
104812
105040
 
105041
+
104813
105042
  namespace duckdb {
104814
105043
 
104815
105044
  //===--------------------------------------------------------------------===//
@@ -104954,6 +105183,11 @@ static unique_ptr<FunctionData> RangeDateTimeBind(ClientContext &context, TableF
104954
105183
  result->end = inputs[1].GetValue<timestamp_t>();
104955
105184
  result->increment = inputs[2].GetValue<interval_t>();
104956
105185
 
105186
+ // Infinities either cause errors or infinite loops, so just ban them
105187
+ if (!Timestamp::IsFinite(result->start) || !Timestamp::IsFinite(result->end)) {
105188
+ throw BinderException("RANGE with infinite bounds is not supported");
105189
+ }
105190
+
104957
105191
  if (result->increment.months == 0 && result->increment.days == 0 && result->increment.micros == 0) {
104958
105192
  throw BinderException("interval cannot be 0!");
104959
105193
  }
@@ -108125,6 +108359,8 @@ void PragmaTableInfo::RegisterFunction(BuiltinFunctions &set) {
108125
108359
  } // namespace duckdb
108126
108360
 
108127
108361
 
108362
+
108363
+
108128
108364
  #include <cmath>
108129
108365
  #include <limits>
108130
108366
 
@@ -108236,6 +108472,27 @@ static vector<TestType> GetTestTypes() {
108236
108472
  Value::DOUBLE(-std::numeric_limits<double>::infinity()), Value(LogicalType::DOUBLE), Value::DOUBLE(-42)});
108237
108473
  result.emplace_back(double_list_type, "double_array", empty_double_list, double_list);
108238
108474
 
108475
+ auto date_list_type = LogicalType::LIST(LogicalType::DATE);
108476
+ auto empty_date_list = Value::EMPTYLIST(LogicalType::DATE);
108477
+ auto date_list =
108478
+ Value::LIST({Value::DATE(date_t()), Value::DATE(date_t::infinity()), Value::DATE(date_t::ninfinity()),
108479
+ Value(LogicalType::DATE), Value::DATE(Date::FromString("2022-05-12"))});
108480
+ result.emplace_back(date_list_type, "date_array", empty_date_list, date_list);
108481
+
108482
+ auto timestamp_list_type = LogicalType::LIST(LogicalType::TIMESTAMP);
108483
+ auto empty_timestamp_list = Value::EMPTYLIST(LogicalType::TIMESTAMP);
108484
+ auto timestamp_list = Value::LIST({Value::TIMESTAMP(timestamp_t()), Value::TIMESTAMP(timestamp_t::infinity()),
108485
+ Value::TIMESTAMP(timestamp_t::ninfinity()), Value(LogicalType::TIMESTAMP),
108486
+ Value::TIMESTAMP(Timestamp::FromString("2022-05-12 16:23:45"))});
108487
+ result.emplace_back(timestamp_list_type, "timestamp_array", empty_timestamp_list, timestamp_list);
108488
+
108489
+ auto timestamptz_list_type = LogicalType::LIST(LogicalType::TIMESTAMP_TZ);
108490
+ auto empty_timestamptz_list = Value::EMPTYLIST(LogicalType::TIMESTAMP_TZ);
108491
+ auto timestamptz_list = Value::LIST({Value::TIMESTAMPTZ(timestamp_t()), Value::TIMESTAMPTZ(timestamp_t::infinity()),
108492
+ Value::TIMESTAMPTZ(timestamp_t::ninfinity()), Value(LogicalType::TIMESTAMP_TZ),
108493
+ Value::TIMESTAMPTZ(Timestamp::FromString("2022-05-12 16:23:45-07"))});
108494
+ result.emplace_back(timestamptz_list_type, "timestamptz_array", empty_timestamptz_list, timestamptz_list);
108495
+
108239
108496
  auto varchar_list_type = LogicalType::LIST(LogicalType::VARCHAR);
108240
108497
  auto empty_varchar_list = Value::EMPTYLIST(LogicalType::VARCHAR);
108241
108498
  auto varchar_list =