duckdb 0.8.2-dev3092.0 → 0.8.2-dev3190.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/package.json +1 -1
- package/src/duckdb/extension/icu/icu-datepart.cpp +151 -32
- package/src/duckdb/extension/icu/icu-datesub.cpp +1 -0
- package/src/duckdb/extension/icu/icu-datetrunc.cpp +1 -0
- package/src/duckdb/src/common/enum_util.cpp +5 -0
- package/src/duckdb/src/common/enums/date_part_specifier.cpp +2 -0
- package/src/duckdb/src/common/types/date.cpp +6 -0
- package/src/duckdb/src/common/types/timestamp.cpp +7 -0
- package/src/duckdb/src/core_functions/function_list.cpp +1 -0
- package/src/duckdb/src/core_functions/scalar/date/date_diff.cpp +2 -0
- package/src/duckdb/src/core_functions/scalar/date/date_part.cpp +227 -102
- package/src/duckdb/src/core_functions/scalar/date/date_sub.cpp +2 -0
- package/src/duckdb/src/core_functions/scalar/date/date_trunc.cpp +4 -0
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/common/enums/date_part_specifier.hpp +9 -1
- package/src/duckdb/src/include/duckdb/common/types/date.hpp +2 -0
- package/src/duckdb/src/include/duckdb/common/types/timestamp.hpp +2 -0
- package/src/duckdb/src/include/duckdb/core_functions/scalar/date_functions.hpp +9 -0
- package/src/duckdb/src/main/extension/extension_load.cpp +16 -5
- package/src/duckdb/src/planner/expression/bound_cast_expression.cpp +0 -2
- package/src/duckdb/third_party/mbedtls/include/mbedtls_wrapper.hpp +10 -0
- package/src/duckdb/third_party/mbedtls/mbedtls_wrapper.cpp +31 -1
package/package.json
CHANGED
@@ -14,7 +14,8 @@
|
|
14
14
|
namespace duckdb {
|
15
15
|
|
16
16
|
struct ICUDatePart : public ICUDateFunc {
|
17
|
-
typedef int64_t (*
|
17
|
+
typedef int64_t (*part_bigint_t)(icu::Calendar *calendar, const uint64_t micros);
|
18
|
+
typedef double (*part_double_t)(icu::Calendar *calendar, const uint64_t micros);
|
18
19
|
|
19
20
|
// Date part adapters
|
20
21
|
static int64_t ExtractEra(icu::Calendar *calendar, const uint64_t micros) {
|
@@ -129,7 +130,26 @@ struct ICUDatePart : public ICUDateFunc {
|
|
129
130
|
return (secs % Interval::SECS_PER_HOUR) / Interval::SECS_PER_MINUTE;
|
130
131
|
}
|
131
132
|
|
132
|
-
|
133
|
+
// PG uses doubles for JDs so we can only use them with other double types
|
134
|
+
static double ExtractJulianDay(icu::Calendar *calendar, const uint64_t micros) {
|
135
|
+
// We need days + fraction
|
136
|
+
auto days = ExtractField(calendar, UCAL_JULIAN_DAY);
|
137
|
+
auto frac = ExtractHour(calendar, micros);
|
138
|
+
|
139
|
+
frac *= Interval::MINS_PER_HOUR;
|
140
|
+
frac += ExtractMinute(calendar, micros);
|
141
|
+
|
142
|
+
frac *= Interval::MICROS_PER_MINUTE;
|
143
|
+
frac += ExtractMicrosecond(calendar, micros);
|
144
|
+
|
145
|
+
double result = frac;
|
146
|
+
result /= Interval::MICROS_PER_DAY;
|
147
|
+
result += days;
|
148
|
+
|
149
|
+
return result;
|
150
|
+
}
|
151
|
+
|
152
|
+
static part_bigint_t PartCodeBigintFactory(DatePartSpecifier part) {
|
133
153
|
switch (part) {
|
134
154
|
case DatePartSpecifier::YEAR:
|
135
155
|
return ExtractYear;
|
@@ -178,7 +198,16 @@ struct ICUDatePart : public ICUDateFunc {
|
|
178
198
|
case DatePartSpecifier::TIMEZONE_MINUTE:
|
179
199
|
return ExtractTimezoneMinute;
|
180
200
|
default:
|
181
|
-
throw Exception("Unsupported ICU
|
201
|
+
throw Exception("Unsupported ICU BIGINT extractor");
|
202
|
+
}
|
203
|
+
}
|
204
|
+
|
205
|
+
static part_double_t PartCodeDoubleFactory(DatePartSpecifier part) {
|
206
|
+
switch (part) {
|
207
|
+
case DatePartSpecifier::JULIAN_DAY:
|
208
|
+
return ExtractJulianDay;
|
209
|
+
default:
|
210
|
+
throw Exception("Unsupported ICU DOUBLE extractor");
|
182
211
|
}
|
183
212
|
}
|
184
213
|
|
@@ -208,7 +237,7 @@ struct ICUDatePart : public ICUDateFunc {
|
|
208
237
|
static string_t MonthName(icu::Calendar *calendar, const uint64_t micros) {
|
209
238
|
const auto mm = ExtractMonth(calendar, micros) - 1;
|
210
239
|
if (mm == 12) {
|
211
|
-
return "
|
240
|
+
return "Undecimber";
|
212
241
|
}
|
213
242
|
return Date::MONTH_NAMES[mm];
|
214
243
|
}
|
@@ -282,7 +311,7 @@ struct ICUDatePart : public ICUDateFunc {
|
|
282
311
|
[&](string_t specifier, INPUT_TYPE input, ValidityMask &mask, idx_t idx) {
|
283
312
|
if (Timestamp::IsFinite(input)) {
|
284
313
|
const auto micros = SetTime(calendar, input);
|
285
|
-
auto adapter =
|
314
|
+
auto adapter = PartCodeBigintFactory(GetDatePartSpecifier(specifier.GetString()));
|
286
315
|
return adapter(calendar, micros);
|
287
316
|
} else {
|
288
317
|
mask.SetInvalid(idx);
|
@@ -291,11 +320,37 @@ struct ICUDatePart : public ICUDateFunc {
|
|
291
320
|
});
|
292
321
|
}
|
293
322
|
|
323
|
+
struct BindStructData : public BindData {
|
324
|
+
using part_codes_t = vector<DatePartSpecifier>;
|
325
|
+
using bigints_t = vector<part_bigint_t>;
|
326
|
+
using doubles_t = vector<part_double_t>;
|
327
|
+
|
328
|
+
BindStructData(ClientContext &context, part_codes_t &part_codes_p, bigints_t &bigints_p, doubles_t &doubles_p)
|
329
|
+
: BindData(context), part_codes(part_codes_p), bigints(bigints_p), doubles(doubles_p) {
|
330
|
+
}
|
331
|
+
BindStructData(const BindStructData &other)
|
332
|
+
: BindData(other), part_codes(other.part_codes), bigints(other.bigints), doubles(other.doubles) {
|
333
|
+
}
|
334
|
+
|
335
|
+
part_codes_t part_codes;
|
336
|
+
bigints_t bigints;
|
337
|
+
doubles_t doubles;
|
338
|
+
|
339
|
+
bool Equals(const FunctionData &other_p) const override {
|
340
|
+
const auto &other = other_p.Cast<BindStructData>();
|
341
|
+
return BindData::Equals(other_p) && part_codes == other.part_codes && bigints == other.bigints &&
|
342
|
+
doubles == other.doubles;
|
343
|
+
}
|
344
|
+
|
345
|
+
duckdb::unique_ptr<FunctionData> Copy() const override {
|
346
|
+
return make_uniq<BindStructData>(*this);
|
347
|
+
}
|
348
|
+
};
|
349
|
+
|
294
350
|
template <typename INPUT_TYPE>
|
295
351
|
static void StructFunction(DataChunk &args, ExpressionState &state, Vector &result) {
|
296
|
-
using BIND_TYPE = BindAdapterData<int64_t>;
|
297
352
|
auto &func_expr = state.expr.Cast<BoundFunctionExpression>();
|
298
|
-
auto &info = func_expr.bind_info->Cast<
|
353
|
+
auto &info = func_expr.bind_info->Cast<BindStructData>();
|
299
354
|
CalendarPtr calendar_ptr(info.calendar->clone());
|
300
355
|
auto calendar = calendar_ptr.get();
|
301
356
|
|
@@ -318,9 +373,15 @@ struct ICUDatePart : public ICUDateFunc {
|
|
318
373
|
auto &child_entry = child_entries[col];
|
319
374
|
if (is_finite) {
|
320
375
|
ConstantVector::SetNull(*child_entry, false);
|
321
|
-
|
322
|
-
|
323
|
-
|
376
|
+
if (IsBigintDatepart(info.part_codes[col])) {
|
377
|
+
auto pdata = ConstantVector::GetData<int64_t>(*child_entry);
|
378
|
+
auto adapter = info.bigints[col];
|
379
|
+
pdata[0] = adapter(calendar, micros);
|
380
|
+
} else {
|
381
|
+
auto pdata = ConstantVector::GetData<double>(*child_entry);
|
382
|
+
auto adapter = info.doubles[col];
|
383
|
+
pdata[0] = adapter(calendar, micros);
|
384
|
+
}
|
324
385
|
} else {
|
325
386
|
ConstantVector::SetNull(*child_entry, true);
|
326
387
|
}
|
@@ -350,9 +411,15 @@ struct ICUDatePart : public ICUDateFunc {
|
|
350
411
|
auto &child_entry = child_entries[col];
|
351
412
|
if (is_finite) {
|
352
413
|
FlatVector::Validity(*child_entry).SetValid(i);
|
353
|
-
|
354
|
-
|
355
|
-
|
414
|
+
if (IsBigintDatepart(info.part_codes[col])) {
|
415
|
+
auto pdata = ConstantVector::GetData<int64_t>(*child_entry);
|
416
|
+
auto adapter = info.bigints[col];
|
417
|
+
pdata[i] = adapter(calendar, micros);
|
418
|
+
} else {
|
419
|
+
auto pdata = ConstantVector::GetData<double>(*child_entry);
|
420
|
+
auto adapter = info.doubles[col];
|
421
|
+
pdata[i] = adapter(calendar, micros);
|
422
|
+
}
|
356
423
|
} else {
|
357
424
|
FlatVector::Validity(*child_entry).SetInvalid(i);
|
358
425
|
}
|
@@ -376,19 +443,54 @@ struct ICUDatePart : public ICUDateFunc {
|
|
376
443
|
return make_uniq<BIND_TYPE>(context, adapter);
|
377
444
|
}
|
378
445
|
|
379
|
-
static duckdb::unique_ptr<FunctionData>
|
380
|
-
|
446
|
+
static duckdb::unique_ptr<FunctionData> BindUnaryDatePart(ClientContext &context, ScalarFunction &bound_function,
|
447
|
+
vector<duckdb::unique_ptr<Expression>> &arguments) {
|
448
|
+
const auto part_code = GetDatePartSpecifier(bound_function.name);
|
449
|
+
if (IsBigintDatepart(part_code)) {
|
450
|
+
using data_t = BindAdapterData<int64_t>;
|
451
|
+
auto adapter = PartCodeBigintFactory(part_code);
|
452
|
+
return BindAdapter<data_t>(context, bound_function, arguments, adapter);
|
453
|
+
} else {
|
454
|
+
using data_t = BindAdapterData<double>;
|
455
|
+
auto adapter = PartCodeDoubleFactory(part_code);
|
456
|
+
return BindAdapter<data_t>(context, bound_function, arguments, adapter);
|
457
|
+
}
|
458
|
+
}
|
459
|
+
|
460
|
+
static duckdb::unique_ptr<FunctionData> BindBinaryDatePart(ClientContext &context, ScalarFunction &bound_function,
|
461
|
+
vector<duckdb::unique_ptr<Expression>> &arguments) {
|
462
|
+
// If we are only looking for Julian Days, then patch in the unary function.
|
463
|
+
do {
|
464
|
+
if (arguments[0]->HasParameter() || !arguments[0]->IsFoldable()) {
|
465
|
+
break;
|
466
|
+
}
|
467
|
+
|
468
|
+
Value part_value = ExpressionExecutor::EvaluateScalar(context, *arguments[0]);
|
469
|
+
if (part_value.IsNull()) {
|
470
|
+
break;
|
471
|
+
}
|
472
|
+
|
473
|
+
const auto part_name = part_value.ToString();
|
474
|
+
const auto part_code = GetDatePartSpecifier(part_name);
|
475
|
+
if (IsBigintDatepart(part_code)) {
|
476
|
+
break;
|
477
|
+
}
|
478
|
+
|
479
|
+
arguments.erase(arguments.begin());
|
480
|
+
bound_function.arguments.erase(bound_function.arguments.begin());
|
481
|
+
bound_function.name = part_name;
|
482
|
+
bound_function.return_type = LogicalType::DOUBLE;
|
483
|
+
bound_function.function = UnaryTimestampFunction<timestamp_t, double>;
|
484
|
+
|
485
|
+
return BindUnaryDatePart(context, bound_function, arguments);
|
486
|
+
} while (false);
|
487
|
+
|
381
488
|
using data_t = BindAdapterData<int64_t>;
|
382
|
-
|
383
|
-
(arguments.size() == 1) ? PartCodeAdapterFactory(GetDatePartSpecifier(bound_function.name)) : nullptr;
|
384
|
-
return BindAdapter<data_t>(context, bound_function, arguments, adapter);
|
489
|
+
return BindAdapter<data_t>(context, bound_function, arguments, nullptr);
|
385
490
|
}
|
386
491
|
|
387
492
|
static duckdb::unique_ptr<FunctionData> BindStruct(ClientContext &context, ScalarFunction &bound_function,
|
388
493
|
vector<duckdb::unique_ptr<Expression>> &arguments) {
|
389
|
-
using data_t = BindAdapterData<int64_t>;
|
390
|
-
using adapters_t = data_t::adapters_t;
|
391
|
-
|
392
494
|
// collect names and deconflict, construct return type
|
393
495
|
if (arguments[0]->HasParameter()) {
|
394
496
|
throw ParameterNotResolvedException();
|
@@ -399,7 +501,9 @@ struct ICUDatePart : public ICUDateFunc {
|
|
399
501
|
|
400
502
|
case_insensitive_set_t name_collision_set;
|
401
503
|
child_list_t<LogicalType> struct_children;
|
402
|
-
|
504
|
+
BindStructData::part_codes_t part_codes;
|
505
|
+
BindStructData::bigints_t bigints;
|
506
|
+
BindStructData::doubles_t doubles;
|
403
507
|
|
404
508
|
Value parts_list = ExpressionExecutor::EvaluateScalar(context, *arguments[0]);
|
405
509
|
if (parts_list.type().id() == LogicalTypeId::LIST) {
|
@@ -407,7 +511,11 @@ struct ICUDatePart : public ICUDateFunc {
|
|
407
511
|
if (list_children.empty()) {
|
408
512
|
throw BinderException("%s requires non-empty lists of part names", bound_function.name);
|
409
513
|
}
|
410
|
-
|
514
|
+
|
515
|
+
bigints.resize(list_children.size(), nullptr);
|
516
|
+
doubles.resize(list_children.size(), nullptr);
|
517
|
+
for (size_t col = 0; col < list_children.size(); ++col) {
|
518
|
+
const auto &part_value = list_children[col];
|
411
519
|
if (part_value.IsNull()) {
|
412
520
|
throw BinderException("NULL struct entry name in %s", bound_function.name);
|
413
521
|
}
|
@@ -417,8 +525,14 @@ struct ICUDatePart : public ICUDateFunc {
|
|
417
525
|
throw BinderException("Duplicate struct entry name \"%s\" in %s", part_name, bound_function.name);
|
418
526
|
}
|
419
527
|
name_collision_set.insert(part_name);
|
420
|
-
|
421
|
-
|
528
|
+
part_codes.emplace_back(part_code);
|
529
|
+
if (IsBigintDatepart(part_code)) {
|
530
|
+
bigints[col] = PartCodeBigintFactory(part_code);
|
531
|
+
struct_children.emplace_back(make_pair(part_name, LogicalType::BIGINT));
|
532
|
+
} else {
|
533
|
+
doubles[col] = PartCodeDoubleFactory(part_code);
|
534
|
+
struct_children.emplace_back(make_pair(part_name, LogicalType::DOUBLE));
|
535
|
+
}
|
422
536
|
}
|
423
537
|
} else {
|
424
538
|
throw BinderException("%s can only take constant lists of part names", bound_function.name);
|
@@ -426,7 +540,7 @@ struct ICUDatePart : public ICUDateFunc {
|
|
426
540
|
|
427
541
|
Function::EraseArgument(bound_function, arguments, 0);
|
428
542
|
bound_function.return_type = LogicalType::STRUCT(std::move(struct_children));
|
429
|
-
return make_uniq<
|
543
|
+
return make_uniq<BindStructData>(context, part_codes, bigints, doubles);
|
430
544
|
}
|
431
545
|
|
432
546
|
static void SerializeFunction(FieldWriter &writer, const FunctionData *bind_data_p,
|
@@ -440,15 +554,18 @@ struct ICUDatePart : public ICUDateFunc {
|
|
440
554
|
}
|
441
555
|
|
442
556
|
template <typename INPUT_TYPE, typename RESULT_TYPE>
|
443
|
-
static ScalarFunction GetUnaryPartCodeFunction(const LogicalType &temporal_type
|
444
|
-
|
445
|
-
|
557
|
+
static ScalarFunction GetUnaryPartCodeFunction(const LogicalType &temporal_type,
|
558
|
+
const LogicalType &result_type = LogicalType::BIGINT) {
|
559
|
+
return ScalarFunction({temporal_type}, result_type, UnaryTimestampFunction<INPUT_TYPE, RESULT_TYPE>,
|
560
|
+
BindUnaryDatePart);
|
446
561
|
}
|
447
562
|
|
448
|
-
|
563
|
+
template <typename RESULT_TYPE = int64_t>
|
564
|
+
static void AddUnaryPartCodeFunctions(const string &name, ClientContext &context,
|
565
|
+
const LogicalType &result_type = LogicalType::BIGINT) {
|
449
566
|
auto &catalog = Catalog::GetSystemCatalog(context);
|
450
567
|
ScalarFunctionSet set(name);
|
451
|
-
set.AddFunction(GetUnaryPartCodeFunction<timestamp_t,
|
568
|
+
set.AddFunction(GetUnaryPartCodeFunction<timestamp_t, RESULT_TYPE>(LogicalType::TIMESTAMP_TZ, result_type));
|
452
569
|
CreateScalarFunctionInfo func_info(set);
|
453
570
|
catalog.AddFunction(context, func_info);
|
454
571
|
}
|
@@ -456,7 +573,7 @@ struct ICUDatePart : public ICUDateFunc {
|
|
456
573
|
template <typename INPUT_TYPE, typename RESULT_TYPE>
|
457
574
|
static ScalarFunction GetBinaryPartCodeFunction(const LogicalType &temporal_type) {
|
458
575
|
return ScalarFunction({LogicalType::VARCHAR, temporal_type}, LogicalType::BIGINT,
|
459
|
-
BinaryTimestampFunction<INPUT_TYPE, RESULT_TYPE>,
|
576
|
+
BinaryTimestampFunction<INPUT_TYPE, RESULT_TYPE>, BindBinaryDatePart);
|
460
577
|
}
|
461
578
|
|
462
579
|
template <typename INPUT_TYPE>
|
@@ -561,6 +678,8 @@ void RegisterICUDatePartFunctions(ClientContext &context) {
|
|
561
678
|
ICUDatePart::AddUnaryPartCodeFunctions("timezone_hour", context);
|
562
679
|
ICUDatePart::AddUnaryPartCodeFunctions("timezone_minute", context);
|
563
680
|
|
681
|
+
ICUDatePart::AddUnaryPartCodeFunctions<double>("julian", context, LogicalType::DOUBLE);
|
682
|
+
|
564
683
|
// register combinations
|
565
684
|
ICUDatePart::AddUnaryPartCodeFunctions("yearweek", context); // Note this is ISO year and week
|
566
685
|
|
@@ -171,6 +171,7 @@ ICUDateFunc::part_sub_t ICUDateFunc::SubtractFactory(DatePartSpecifier type) {
|
|
171
171
|
case DatePartSpecifier::DOW:
|
172
172
|
case DatePartSpecifier::ISODOW:
|
173
173
|
case DatePartSpecifier::DOY:
|
174
|
+
case DatePartSpecifier::JULIAN_DAY:
|
174
175
|
return ICUCalendarSub::SubtractDay;
|
175
176
|
case DatePartSpecifier::HOUR:
|
176
177
|
return ICUCalendarSub::SubtractHour;
|
@@ -175,6 +175,7 @@ ICUDateFunc::part_trunc_t ICUDateFunc::TruncationFactory(DatePartSpecifier type)
|
|
175
175
|
case DatePartSpecifier::DOW:
|
176
176
|
case DatePartSpecifier::ISODOW:
|
177
177
|
case DatePartSpecifier::DOY:
|
178
|
+
case DatePartSpecifier::JULIAN_DAY:
|
178
179
|
return ICUDateTrunc::TruncDay;
|
179
180
|
case DatePartSpecifier::HOUR:
|
180
181
|
return ICUDateTrunc::TruncHour;
|
@@ -1154,6 +1154,8 @@ const char* EnumUtil::ToChars<DatePartSpecifier>(DatePartSpecifier value) {
|
|
1154
1154
|
return "TIMEZONE_HOUR";
|
1155
1155
|
case DatePartSpecifier::TIMEZONE_MINUTE:
|
1156
1156
|
return "TIMEZONE_MINUTE";
|
1157
|
+
case DatePartSpecifier::JULIAN_DAY:
|
1158
|
+
return "JULIAN_DAY";
|
1157
1159
|
default:
|
1158
1160
|
throw NotImplementedException(StringUtil::Format("Enum value: '%d' not implemented", value));
|
1159
1161
|
}
|
@@ -1230,6 +1232,9 @@ DatePartSpecifier EnumUtil::FromString<DatePartSpecifier>(const char *value) {
|
|
1230
1232
|
if (StringUtil::Equals(value, "TIMEZONE_MINUTE")) {
|
1231
1233
|
return DatePartSpecifier::TIMEZONE_MINUTE;
|
1232
1234
|
}
|
1235
|
+
if (StringUtil::Equals(value, "JULIAN_DAY")) {
|
1236
|
+
return DatePartSpecifier::JULIAN_DAY;
|
1237
|
+
}
|
1233
1238
|
throw NotImplementedException(StringUtil::Format("Enum value: '%s' not implemented", value));
|
1234
1239
|
}
|
1235
1240
|
|
@@ -65,6 +65,8 @@ bool TryGetDatePartSpecifier(const string &specifier_p, DatePartSpecifier &resul
|
|
65
65
|
result = DatePartSpecifier::TIMEZONE_HOUR;
|
66
66
|
} else if (specifier == "timezone_minute") {
|
67
67
|
result = DatePartSpecifier::TIMEZONE_MINUTE;
|
68
|
+
} else if (specifier == "julian" || specifier == "jd") {
|
69
|
+
result = DatePartSpecifier::JULIAN_DAY;
|
68
70
|
} else {
|
69
71
|
return false;
|
70
72
|
}
|
@@ -490,6 +490,12 @@ int32_t Date::ExtractDayOfTheYear(date_t date) {
|
|
490
490
|
return date.days - Date::CUMULATIVE_YEAR_DAYS[year_offset] + 1;
|
491
491
|
}
|
492
492
|
|
493
|
+
int64_t Date::ExtractJulianDay(date_t date) {
|
494
|
+
// Julian Day 0 is (-4713, 11, 24) in the proleptic Gregorian calendar.
|
495
|
+
static const auto JULIAN_EPOCH = -2440588;
|
496
|
+
return date.days - JULIAN_EPOCH;
|
497
|
+
}
|
498
|
+
|
493
499
|
int32_t Date::ExtractISODayOfTheWeek(date_t date) {
|
494
500
|
// date of 0 is 1970-01-01, which was a Thursday (4)
|
495
501
|
// -7 = 4
|
@@ -341,4 +341,11 @@ int64_t Timestamp::GetEpochNanoSeconds(timestamp_t timestamp) {
|
|
341
341
|
return result;
|
342
342
|
}
|
343
343
|
|
344
|
+
double Timestamp::GetJulianDay(timestamp_t timestamp) {
|
345
|
+
double result = Timestamp::GetTime(timestamp).micros;
|
346
|
+
result /= Interval::MICROS_PER_DAY;
|
347
|
+
result += Date::ExtractJulianDay(Timestamp::GetDate(timestamp));
|
348
|
+
return result;
|
349
|
+
}
|
350
|
+
|
344
351
|
} // namespace duckdb
|
@@ -182,6 +182,7 @@ static StaticFunctionDefinition internal_functions[] = {
|
|
182
182
|
DUCKDB_SCALAR_FUNCTION(JaccardFun),
|
183
183
|
DUCKDB_SCALAR_FUNCTION(JaroSimilarityFun),
|
184
184
|
DUCKDB_SCALAR_FUNCTION(JaroWinklerSimilarityFun),
|
185
|
+
DUCKDB_SCALAR_FUNCTION_SET(JulianDayFun),
|
185
186
|
DUCKDB_AGGREGATE_FUNCTION(KahanSumFun),
|
186
187
|
DUCKDB_AGGREGATE_FUNCTION(KurtosisFun),
|
187
188
|
DUCKDB_SCALAR_FUNCTION_SET(LastDayFun),
|
@@ -304,6 +304,7 @@ static int64_t DifferenceDates(DatePartSpecifier type, TA startdate, TB enddate)
|
|
304
304
|
case DatePartSpecifier::DOW:
|
305
305
|
case DatePartSpecifier::ISODOW:
|
306
306
|
case DatePartSpecifier::DOY:
|
307
|
+
case DatePartSpecifier::JULIAN_DAY:
|
307
308
|
return DateDiff::DayOperator::template Operation<TA, TB, TR>(startdate, enddate);
|
308
309
|
case DatePartSpecifier::DECADE:
|
309
310
|
return DateDiff::DecadeOperator::template Operation<TA, TB, TR>(startdate, enddate);
|
@@ -359,6 +360,7 @@ static void DateDiffBinaryExecutor(DatePartSpecifier type, Vector &left, Vector
|
|
359
360
|
case DatePartSpecifier::DOW:
|
360
361
|
case DatePartSpecifier::ISODOW:
|
361
362
|
case DatePartSpecifier::DOY:
|
363
|
+
case DatePartSpecifier::JULIAN_DAY:
|
362
364
|
DateDiff::BinaryExecute<TA, TB, TR, DateDiff::DayOperator>(left, right, result, count);
|
363
365
|
break;
|
364
366
|
case DatePartSpecifier::DECADE:
|
@@ -37,6 +37,7 @@ DatePartSpecifier GetDateTypePartSpecifier(const string &specifier, LogicalType
|
|
37
37
|
case DatePartSpecifier::DOY:
|
38
38
|
case DatePartSpecifier::YEARWEEK:
|
39
39
|
case DatePartSpecifier::ERA:
|
40
|
+
case DatePartSpecifier::JULIAN_DAY:
|
40
41
|
return part;
|
41
42
|
default:
|
42
43
|
break;
|
@@ -97,8 +98,9 @@ static unique_ptr<BaseStatistics> PropagateSimpleDatePartStatistics(vector<BaseS
|
|
97
98
|
}
|
98
99
|
|
99
100
|
struct DatePart {
|
100
|
-
template <class T, class OP>
|
101
|
-
static unique_ptr<BaseStatistics> PropagateDatePartStatistics(vector<BaseStatistics> &child_stats
|
101
|
+
template <class T, class OP, class TR = int64_t>
|
102
|
+
static unique_ptr<BaseStatistics> PropagateDatePartStatistics(vector<BaseStatistics> &child_stats,
|
103
|
+
const LogicalType &stats_type = LogicalType::BIGINT) {
|
102
104
|
// we can only propagate complex date part stats if the child has stats
|
103
105
|
auto &nstats = child_stats[0];
|
104
106
|
if (!NumericStats::HasMinMax(nstats)) {
|
@@ -114,11 +116,11 @@ struct DatePart {
|
|
114
116
|
if (!Value::IsFinite(min) || !Value::IsFinite(max)) {
|
115
117
|
return nullptr;
|
116
118
|
}
|
117
|
-
|
118
|
-
|
119
|
-
auto result = NumericStats::CreateEmpty(
|
120
|
-
NumericStats::SetMin(result, Value
|
121
|
-
NumericStats::SetMax(result, Value
|
119
|
+
TR min_part = OP::template Operation<T, TR>(min);
|
120
|
+
TR max_part = OP::template Operation<T, TR>(max);
|
121
|
+
auto result = NumericStats::CreateEmpty(stats_type);
|
122
|
+
NumericStats::SetMin(result, Value(min_part));
|
123
|
+
NumericStats::SetMax(result, Value(max_part));
|
122
124
|
result.CopyValidity(child_stats[0]);
|
123
125
|
return result.ToUnique();
|
124
126
|
}
|
@@ -499,6 +501,18 @@ struct DatePart {
|
|
499
501
|
}
|
500
502
|
};
|
501
503
|
|
504
|
+
struct JulianDayOperator {
|
505
|
+
template <class TA, class TR>
|
506
|
+
static inline TR Operation(TA input) {
|
507
|
+
return Timestamp::GetJulianDay(input);
|
508
|
+
}
|
509
|
+
|
510
|
+
template <class T>
|
511
|
+
static unique_ptr<BaseStatistics> PropagateStatistics(ClientContext &context, FunctionStatisticsInput &input) {
|
512
|
+
return PropagateDatePartStatistics<T, JulianDayOperator, double>(input.child_stats, LogicalType::DOUBLE);
|
513
|
+
}
|
514
|
+
};
|
515
|
+
|
502
516
|
// These are all zero and have the same restrictions
|
503
517
|
using TimezoneHourOperator = TimezoneOperator;
|
504
518
|
using TimezoneMinuteOperator = TimezoneOperator;
|
@@ -514,7 +528,8 @@ struct DatePart {
|
|
514
528
|
EPOCH = 1 << 3,
|
515
529
|
TIME = 1 << 4,
|
516
530
|
ZONE = 1 << 5,
|
517
|
-
ISO = 1 << 6
|
531
|
+
ISO = 1 << 6,
|
532
|
+
JD = 1 << 7
|
518
533
|
};
|
519
534
|
|
520
535
|
static part_mask_t GetMask(const part_codes_t &part_codes) {
|
@@ -546,6 +561,9 @@ struct DatePart {
|
|
546
561
|
case DatePartSpecifier::EPOCH:
|
547
562
|
mask |= EPOCH;
|
548
563
|
break;
|
564
|
+
case DatePartSpecifier::JULIAN_DAY:
|
565
|
+
mask |= JD;
|
566
|
+
break;
|
549
567
|
case DatePartSpecifier::MICROSECONDS:
|
550
568
|
case DatePartSpecifier::MILLISECONDS:
|
551
569
|
case DatePartSpecifier::SECOND:
|
@@ -564,63 +582,73 @@ struct DatePart {
|
|
564
582
|
}
|
565
583
|
|
566
584
|
template <typename P>
|
567
|
-
static inline P HasPartValue(P
|
568
|
-
|
585
|
+
static inline P HasPartValue(vector<P> part_values, DatePartSpecifier part) {
|
586
|
+
static const auto BEGIN_DOUBLE = size_t(DatePartSpecifier::JULIAN_DAY);
|
587
|
+
auto idx = size_t(part);
|
588
|
+
if (IsBigintDatepart(part)) {
|
589
|
+
return part_values[idx];
|
590
|
+
} else {
|
591
|
+
return part_values[idx - BEGIN_DOUBLE];
|
592
|
+
}
|
569
593
|
}
|
570
594
|
|
571
|
-
|
572
|
-
|
573
|
-
|
595
|
+
using bigint_vec = vector<int64_t *>;
|
596
|
+
using double_vec = vector<double *>;
|
597
|
+
|
598
|
+
template <class TA>
|
599
|
+
static inline void Operation(bigint_vec &bigint_values, double_vec &double_values, const TA &input,
|
600
|
+
const idx_t idx, const part_mask_t mask) {
|
601
|
+
int64_t *bigint_data;
|
574
602
|
// YMD calculations
|
575
603
|
int32_t yyyy = 1970;
|
576
604
|
int32_t mm = 0;
|
577
605
|
int32_t dd = 1;
|
578
606
|
if (mask & YMD) {
|
579
607
|
Date::Convert(input, yyyy, mm, dd);
|
580
|
-
|
581
|
-
if (
|
582
|
-
|
608
|
+
bigint_data = HasPartValue(bigint_values, DatePartSpecifier::YEAR);
|
609
|
+
if (bigint_data) {
|
610
|
+
bigint_data[idx] = yyyy;
|
583
611
|
}
|
584
|
-
|
585
|
-
if (
|
586
|
-
|
612
|
+
bigint_data = HasPartValue(bigint_values, DatePartSpecifier::MONTH);
|
613
|
+
if (bigint_data) {
|
614
|
+
bigint_data[idx] = mm;
|
587
615
|
}
|
588
|
-
|
589
|
-
if (
|
590
|
-
|
616
|
+
bigint_data = HasPartValue(bigint_values, DatePartSpecifier::DAY);
|
617
|
+
if (bigint_data) {
|
618
|
+
bigint_data[idx] = dd;
|
591
619
|
}
|
592
|
-
|
593
|
-
if (
|
594
|
-
|
620
|
+
bigint_data = HasPartValue(bigint_values, DatePartSpecifier::DECADE);
|
621
|
+
if (bigint_data) {
|
622
|
+
bigint_data[idx] = DecadeOperator::DecadeFromYear(yyyy);
|
595
623
|
}
|
596
|
-
|
597
|
-
if (
|
598
|
-
|
624
|
+
bigint_data = HasPartValue(bigint_values, DatePartSpecifier::CENTURY);
|
625
|
+
if (bigint_data) {
|
626
|
+
bigint_data[idx] = CenturyOperator::CenturyFromYear(yyyy);
|
599
627
|
}
|
600
|
-
|
601
|
-
if (
|
602
|
-
|
628
|
+
bigint_data = HasPartValue(bigint_values, DatePartSpecifier::MILLENNIUM);
|
629
|
+
if (bigint_data) {
|
630
|
+
bigint_data[idx] = MillenniumOperator::MillenniumFromYear(yyyy);
|
603
631
|
}
|
604
|
-
|
605
|
-
if (
|
606
|
-
|
632
|
+
bigint_data = HasPartValue(bigint_values, DatePartSpecifier::QUARTER);
|
633
|
+
if (bigint_data) {
|
634
|
+
bigint_data[idx] = QuarterOperator::QuarterFromMonth(mm);
|
607
635
|
}
|
608
|
-
|
609
|
-
if (
|
610
|
-
|
636
|
+
bigint_data = HasPartValue(bigint_values, DatePartSpecifier::ERA);
|
637
|
+
if (bigint_data) {
|
638
|
+
bigint_data[idx] = EraOperator::EraFromYear(yyyy);
|
611
639
|
}
|
612
640
|
}
|
613
641
|
|
614
642
|
// Week calculations
|
615
643
|
if (mask & DOW) {
|
616
644
|
auto isodow = Date::ExtractISODayOfTheWeek(input);
|
617
|
-
|
618
|
-
if (
|
619
|
-
|
645
|
+
bigint_data = HasPartValue(bigint_values, DatePartSpecifier::DOW);
|
646
|
+
if (bigint_data) {
|
647
|
+
bigint_data[idx] = DayOfWeekOperator::DayOfWeekFromISO(isodow);
|
620
648
|
}
|
621
|
-
|
622
|
-
if (
|
623
|
-
|
649
|
+
bigint_data = HasPartValue(bigint_values, DatePartSpecifier::ISODOW);
|
650
|
+
if (bigint_data) {
|
651
|
+
bigint_data[idx] = isodow;
|
624
652
|
}
|
625
653
|
}
|
626
654
|
|
@@ -629,30 +657,36 @@ struct DatePart {
|
|
629
657
|
int32_t ww = 0;
|
630
658
|
int32_t iyyy = 0;
|
631
659
|
Date::ExtractISOYearWeek(input, iyyy, ww);
|
632
|
-
|
633
|
-
if (
|
634
|
-
|
660
|
+
bigint_data = HasPartValue(bigint_values, DatePartSpecifier::WEEK);
|
661
|
+
if (bigint_data) {
|
662
|
+
bigint_data[idx] = ww;
|
635
663
|
}
|
636
|
-
|
637
|
-
if (
|
638
|
-
|
664
|
+
bigint_data = HasPartValue(bigint_values, DatePartSpecifier::ISOYEAR);
|
665
|
+
if (bigint_data) {
|
666
|
+
bigint_data[idx] = iyyy;
|
639
667
|
}
|
640
|
-
|
641
|
-
if (
|
642
|
-
|
668
|
+
bigint_data = HasPartValue(bigint_values, DatePartSpecifier::YEARWEEK);
|
669
|
+
if (bigint_data) {
|
670
|
+
bigint_data[idx] = YearWeekOperator::YearWeekFromParts(iyyy, ww);
|
643
671
|
}
|
644
672
|
}
|
645
673
|
|
646
674
|
if (mask & EPOCH) {
|
647
|
-
|
648
|
-
if (
|
649
|
-
|
675
|
+
bigint_data = HasPartValue(bigint_values, DatePartSpecifier::EPOCH);
|
676
|
+
if (bigint_data) {
|
677
|
+
bigint_data[idx] = Date::Epoch(input);
|
650
678
|
}
|
651
679
|
}
|
652
680
|
if (mask & DOY) {
|
653
|
-
|
654
|
-
if (
|
655
|
-
|
681
|
+
bigint_data = HasPartValue(bigint_values, DatePartSpecifier::DOY);
|
682
|
+
if (bigint_data) {
|
683
|
+
bigint_data[idx] = Date::ExtractDayOfTheYear(input);
|
684
|
+
}
|
685
|
+
}
|
686
|
+
if (mask & JD) {
|
687
|
+
auto double_data = HasPartValue(double_values, DatePartSpecifier::JULIAN_DAY);
|
688
|
+
if (double_data) {
|
689
|
+
double_data[idx] = Date::ExtractJulianDay(input);
|
656
690
|
}
|
657
691
|
}
|
658
692
|
}
|
@@ -1046,35 +1080,50 @@ int64_t DatePart::TimezoneOperator::Operation(dtime_t input) {
|
|
1046
1080
|
}
|
1047
1081
|
|
1048
1082
|
template <>
|
1049
|
-
|
1050
|
-
|
1083
|
+
double DatePart::JulianDayOperator::Operation(date_t input) {
|
1084
|
+
return Date::ExtractJulianDay(input);
|
1085
|
+
}
|
1086
|
+
|
1087
|
+
template <>
|
1088
|
+
double DatePart::JulianDayOperator::Operation(interval_t input) {
|
1089
|
+
throw NotImplementedException("interval units \"julian\" not recognized");
|
1090
|
+
}
|
1091
|
+
|
1092
|
+
template <>
|
1093
|
+
double DatePart::JulianDayOperator::Operation(dtime_t input) {
|
1094
|
+
throw NotImplementedException("\"time\" units \"julian\" not recognized");
|
1095
|
+
}
|
1096
|
+
|
1097
|
+
template <>
|
1098
|
+
void DatePart::StructOperator::Operation(bigint_vec &bigint_values, double_vec &double_values, const dtime_t &input,
|
1099
|
+
const idx_t idx, const part_mask_t mask) {
|
1051
1100
|
int64_t *part_data;
|
1052
1101
|
if (mask & TIME) {
|
1053
1102
|
const auto micros = MicrosecondsOperator::Operation<dtime_t, int64_t>(input);
|
1054
|
-
part_data = HasPartValue(
|
1103
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::MICROSECONDS);
|
1055
1104
|
if (part_data) {
|
1056
1105
|
part_data[idx] = micros;
|
1057
1106
|
}
|
1058
|
-
part_data = HasPartValue(
|
1107
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::MILLISECONDS);
|
1059
1108
|
if (part_data) {
|
1060
1109
|
part_data[idx] = micros / Interval::MICROS_PER_MSEC;
|
1061
1110
|
}
|
1062
|
-
part_data = HasPartValue(
|
1111
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::SECOND);
|
1063
1112
|
if (part_data) {
|
1064
1113
|
part_data[idx] = micros / Interval::MICROS_PER_SEC;
|
1065
1114
|
}
|
1066
|
-
part_data = HasPartValue(
|
1115
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::MINUTE);
|
1067
1116
|
if (part_data) {
|
1068
1117
|
part_data[idx] = MinutesOperator::Operation<dtime_t, int64_t>(input);
|
1069
1118
|
}
|
1070
|
-
part_data = HasPartValue(
|
1119
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::HOUR);
|
1071
1120
|
if (part_data) {
|
1072
1121
|
part_data[idx] = HoursOperator::Operation<dtime_t, int64_t>(input);
|
1073
1122
|
}
|
1074
1123
|
}
|
1075
1124
|
|
1076
1125
|
if (mask & EPOCH) {
|
1077
|
-
part_data = HasPartValue(
|
1126
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::EPOCH);
|
1078
1127
|
if (part_data) {
|
1079
1128
|
part_data[idx] = EpochOperator::Operation<dtime_t, int64_t>(input);
|
1080
1129
|
;
|
@@ -1082,15 +1131,15 @@ void DatePart::StructOperator::Operation(int64_t **part_values, const dtime_t &i
|
|
1082
1131
|
}
|
1083
1132
|
|
1084
1133
|
if (mask & ZONE) {
|
1085
|
-
part_data = HasPartValue(
|
1134
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::TIMEZONE);
|
1086
1135
|
if (part_data) {
|
1087
1136
|
part_data[idx] = 0;
|
1088
1137
|
}
|
1089
|
-
part_data = HasPartValue(
|
1138
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::TIMEZONE_HOUR);
|
1090
1139
|
if (part_data) {
|
1091
1140
|
part_data[idx] = 0;
|
1092
1141
|
}
|
1093
|
-
part_data = HasPartValue(
|
1142
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::TIMEZONE_MINUTE);
|
1094
1143
|
if (part_data) {
|
1095
1144
|
part_data[idx] = 0;
|
1096
1145
|
}
|
@@ -1098,56 +1147,63 @@ void DatePart::StructOperator::Operation(int64_t **part_values, const dtime_t &i
|
|
1098
1147
|
}
|
1099
1148
|
|
1100
1149
|
template <>
|
1101
|
-
void DatePart::StructOperator::Operation(
|
1102
|
-
const part_mask_t mask) {
|
1150
|
+
void DatePart::StructOperator::Operation(bigint_vec &bigint_values, double_vec &double_values, const timestamp_t &input,
|
1151
|
+
const idx_t idx, const part_mask_t mask) {
|
1103
1152
|
date_t d;
|
1104
1153
|
dtime_t t;
|
1105
1154
|
Timestamp::Convert(input, d, t);
|
1106
1155
|
|
1107
1156
|
// Both define epoch, and the correct value is the sum.
|
1108
1157
|
// So mask it out and compute it separately.
|
1109
|
-
Operation(
|
1110
|
-
Operation(
|
1158
|
+
Operation(bigint_values, double_values, d, idx, mask & ~EPOCH);
|
1159
|
+
Operation(bigint_values, double_values, t, idx, mask & ~EPOCH);
|
1111
1160
|
|
1112
1161
|
if (mask & EPOCH) {
|
1113
|
-
auto part_data = HasPartValue(
|
1162
|
+
auto part_data = HasPartValue(bigint_values, DatePartSpecifier::EPOCH);
|
1114
1163
|
if (part_data) {
|
1115
1164
|
part_data[idx] = EpochOperator::Operation<timestamp_t, int64_t>(input);
|
1116
1165
|
}
|
1117
1166
|
}
|
1167
|
+
|
1168
|
+
if (mask & JD) {
|
1169
|
+
auto part_data = HasPartValue(double_values, DatePartSpecifier::JULIAN_DAY);
|
1170
|
+
if (part_data) {
|
1171
|
+
part_data[idx] = JulianDayOperator::Operation<timestamp_t, double>(input);
|
1172
|
+
}
|
1173
|
+
}
|
1118
1174
|
}
|
1119
1175
|
|
1120
1176
|
template <>
|
1121
|
-
void DatePart::StructOperator::Operation(
|
1122
|
-
const part_mask_t mask) {
|
1177
|
+
void DatePart::StructOperator::Operation(bigint_vec &bigint_values, double_vec &double_values, const interval_t &input,
|
1178
|
+
const idx_t idx, const part_mask_t mask) {
|
1123
1179
|
int64_t *part_data;
|
1124
1180
|
if (mask & YMD) {
|
1125
1181
|
const auto mm = input.months % Interval::MONTHS_PER_YEAR;
|
1126
|
-
part_data = HasPartValue(
|
1182
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::YEAR);
|
1127
1183
|
if (part_data) {
|
1128
1184
|
part_data[idx] = input.months / Interval::MONTHS_PER_YEAR;
|
1129
1185
|
}
|
1130
|
-
part_data = HasPartValue(
|
1186
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::MONTH);
|
1131
1187
|
if (part_data) {
|
1132
1188
|
part_data[idx] = mm;
|
1133
1189
|
}
|
1134
|
-
part_data = HasPartValue(
|
1190
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::DAY);
|
1135
1191
|
if (part_data) {
|
1136
1192
|
part_data[idx] = input.days;
|
1137
1193
|
}
|
1138
|
-
part_data = HasPartValue(
|
1194
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::DECADE);
|
1139
1195
|
if (part_data) {
|
1140
1196
|
part_data[idx] = input.months / Interval::MONTHS_PER_DECADE;
|
1141
1197
|
}
|
1142
|
-
part_data = HasPartValue(
|
1198
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::CENTURY);
|
1143
1199
|
if (part_data) {
|
1144
1200
|
part_data[idx] = input.months / Interval::MONTHS_PER_CENTURY;
|
1145
1201
|
}
|
1146
|
-
part_data = HasPartValue(
|
1202
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::MILLENNIUM);
|
1147
1203
|
if (part_data) {
|
1148
1204
|
part_data[idx] = input.months / Interval::MONTHS_PER_MILLENIUM;
|
1149
1205
|
}
|
1150
|
-
part_data = HasPartValue(
|
1206
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::QUARTER);
|
1151
1207
|
if (part_data) {
|
1152
1208
|
part_data[idx] = mm / Interval::MONTHS_PER_QUARTER + 1;
|
1153
1209
|
}
|
@@ -1155,30 +1211,30 @@ void DatePart::StructOperator::Operation(int64_t **part_values, const interval_t
|
|
1155
1211
|
|
1156
1212
|
if (mask & TIME) {
|
1157
1213
|
const auto micros = MicrosecondsOperator::Operation<interval_t, int64_t>(input);
|
1158
|
-
part_data = HasPartValue(
|
1214
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::MICROSECONDS);
|
1159
1215
|
if (part_data) {
|
1160
1216
|
part_data[idx] = micros;
|
1161
1217
|
}
|
1162
|
-
part_data = HasPartValue(
|
1218
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::MILLISECONDS);
|
1163
1219
|
if (part_data) {
|
1164
1220
|
part_data[idx] = micros / Interval::MICROS_PER_MSEC;
|
1165
1221
|
}
|
1166
|
-
part_data = HasPartValue(
|
1222
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::SECOND);
|
1167
1223
|
if (part_data) {
|
1168
1224
|
part_data[idx] = micros / Interval::MICROS_PER_SEC;
|
1169
1225
|
}
|
1170
|
-
part_data = HasPartValue(
|
1226
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::MINUTE);
|
1171
1227
|
if (part_data) {
|
1172
1228
|
part_data[idx] = MinutesOperator::Operation<interval_t, int64_t>(input);
|
1173
1229
|
}
|
1174
|
-
part_data = HasPartValue(
|
1230
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::HOUR);
|
1175
1231
|
if (part_data) {
|
1176
1232
|
part_data[idx] = HoursOperator::Operation<interval_t, int64_t>(input);
|
1177
1233
|
}
|
1178
1234
|
}
|
1179
1235
|
|
1180
1236
|
if (mask & EPOCH) {
|
1181
|
-
part_data = HasPartValue(
|
1237
|
+
part_data = HasPartValue(bigint_values, DatePartSpecifier::EPOCH);
|
1182
1238
|
if (part_data) {
|
1183
1239
|
part_data[idx] = EpochOperator::Operation<interval_t, int64_t>(input);
|
1184
1240
|
}
|
@@ -1254,6 +1310,45 @@ static void DatePartFunction(DataChunk &args, ExpressionState &state, Vector &re
|
|
1254
1310
|
});
|
1255
1311
|
}
|
1256
1312
|
|
1313
|
+
static unique_ptr<FunctionData> DatePartBind(ClientContext &context, ScalarFunction &bound_function,
|
1314
|
+
vector<unique_ptr<Expression>> &arguments) {
|
1315
|
+
// If we are only looking for Julian Days for timestamps,
|
1316
|
+
// then return doubles.
|
1317
|
+
if (arguments[0]->HasParameter() || !arguments[0]->IsFoldable()) {
|
1318
|
+
return nullptr;
|
1319
|
+
}
|
1320
|
+
|
1321
|
+
Value part_value = ExpressionExecutor::EvaluateScalar(context, *arguments[0]);
|
1322
|
+
if (part_value.IsNull()) {
|
1323
|
+
return nullptr;
|
1324
|
+
}
|
1325
|
+
const auto part_name = part_value.ToString();
|
1326
|
+
switch (GetDatePartSpecifier(part_name)) {
|
1327
|
+
case DatePartSpecifier::JULIAN_DAY:
|
1328
|
+
arguments.erase(arguments.begin());
|
1329
|
+
bound_function.arguments.erase(bound_function.arguments.begin());
|
1330
|
+
bound_function.name = "julian";
|
1331
|
+
bound_function.return_type = LogicalType::DOUBLE;
|
1332
|
+
switch (arguments[0]->return_type.id()) {
|
1333
|
+
case LogicalType::TIMESTAMP:
|
1334
|
+
bound_function.function = DatePart::UnaryFunction<timestamp_t, double, DatePart::JulianDayOperator>;
|
1335
|
+
bound_function.statistics = DatePart::JulianDayOperator::template PropagateStatistics<timestamp_t>;
|
1336
|
+
break;
|
1337
|
+
case LogicalType::DATE:
|
1338
|
+
bound_function.function = DatePart::UnaryFunction<date_t, double, DatePart::JulianDayOperator>;
|
1339
|
+
bound_function.statistics = DatePart::JulianDayOperator::template PropagateStatistics<date_t>;
|
1340
|
+
break;
|
1341
|
+
default:
|
1342
|
+
throw BinderException("%s can only take DATE or TIMESTAMP arguments", bound_function.name);
|
1343
|
+
}
|
1344
|
+
break;
|
1345
|
+
default:
|
1346
|
+
break;
|
1347
|
+
}
|
1348
|
+
|
1349
|
+
return nullptr;
|
1350
|
+
}
|
1351
|
+
|
1257
1352
|
ScalarFunctionSet GetGenericDatePartFunction(scalar_function_t date_func, scalar_function_t ts_func,
|
1258
1353
|
scalar_function_t interval_func, function_statistics_t date_stats,
|
1259
1354
|
function_statistics_t ts_stats) {
|
@@ -1332,6 +1427,10 @@ struct DayNameOperator {
|
|
1332
1427
|
struct StructDatePart {
|
1333
1428
|
using part_codes_t = vector<DatePartSpecifier>;
|
1334
1429
|
|
1430
|
+
static const auto BEGIN_BIGINT = size_t(DatePartSpecifier::YEAR);
|
1431
|
+
static const auto BEGIN_DOUBLE = size_t(DatePartSpecifier::JULIAN_DAY);
|
1432
|
+
static const auto BEGIN_INVALID = size_t(DatePartSpecifier::JULIAN_DAY) + 1;
|
1433
|
+
|
1335
1434
|
struct BindData : public VariableReturnBindData {
|
1336
1435
|
part_codes_t part_codes;
|
1337
1436
|
|
@@ -1375,7 +1474,8 @@ struct StructDatePart {
|
|
1375
1474
|
}
|
1376
1475
|
name_collision_set.insert(part_name);
|
1377
1476
|
part_codes.emplace_back(part_code);
|
1378
|
-
|
1477
|
+
const auto part_type = IsBigintDatepart(part_code) ? LogicalType::BIGINT : LogicalType::DOUBLE;
|
1478
|
+
struct_children.emplace_back(make_pair(part_name, part_type));
|
1379
1479
|
}
|
1380
1480
|
} else {
|
1381
1481
|
throw BinderException("%s can only take constant lists of part names", bound_function.name);
|
@@ -1394,14 +1494,15 @@ struct StructDatePart {
|
|
1394
1494
|
|
1395
1495
|
const auto count = args.size();
|
1396
1496
|
Vector &input = args.data[0];
|
1397
|
-
|
1497
|
+
DatePart::StructOperator::bigint_vec bigint_values(size_t(BEGIN_DOUBLE), nullptr);
|
1498
|
+
DatePart::StructOperator::double_vec double_values(BEGIN_INVALID - size_t(BEGIN_DOUBLE), nullptr);
|
1398
1499
|
const auto part_mask = DatePart::StructOperator::GetMask(info.part_codes);
|
1399
1500
|
|
1400
1501
|
auto &child_entries = StructVector::GetEntries(result);
|
1401
1502
|
|
1402
1503
|
// The first computer of a part "owns" it
|
1403
1504
|
// and other requestors just reference the owner
|
1404
|
-
vector<size_t> owners(int(DatePartSpecifier::
|
1505
|
+
vector<size_t> owners(int(DatePartSpecifier::JULIAN_DAY) + 1, child_entries.size());
|
1405
1506
|
for (size_t col = 0; col < child_entries.size(); ++col) {
|
1406
1507
|
const auto part_index = size_t(info.part_codes[col]);
|
1407
1508
|
if (owners[part_index] == child_entries.size()) {
|
@@ -1421,12 +1522,16 @@ struct StructDatePart {
|
|
1421
1522
|
ConstantVector::SetNull(*child_entry, false);
|
1422
1523
|
const auto part_index = size_t(info.part_codes[col]);
|
1423
1524
|
if (owners[part_index] == col) {
|
1424
|
-
|
1525
|
+
if (IsBigintDatepart(info.part_codes[col])) {
|
1526
|
+
bigint_values[part_index - BEGIN_BIGINT] = ConstantVector::GetData<int64_t>(*child_entry);
|
1527
|
+
} else {
|
1528
|
+
double_values[part_index - BEGIN_DOUBLE] = ConstantVector::GetData<double>(*child_entry);
|
1529
|
+
}
|
1425
1530
|
}
|
1426
1531
|
}
|
1427
1532
|
auto tdata = ConstantVector::GetData<INPUT_TYPE>(input);
|
1428
1533
|
if (Value::IsFinite(tdata[0])) {
|
1429
|
-
DatePart::StructOperator::Operation(
|
1534
|
+
DatePart::StructOperator::Operation(bigint_values, double_values, tdata[0], 0, part_mask);
|
1430
1535
|
} else {
|
1431
1536
|
for (auto &child_entry : child_entries) {
|
1432
1537
|
ConstantVector::SetNull(*child_entry, true);
|
@@ -1459,7 +1564,11 @@ struct StructDatePart {
|
|
1459
1564
|
// Pre-multiplex
|
1460
1565
|
const auto part_index = size_t(info.part_codes[col]);
|
1461
1566
|
if (owners[part_index] == col) {
|
1462
|
-
|
1567
|
+
if (IsBigintDatepart(info.part_codes[col])) {
|
1568
|
+
bigint_values[part_index - BEGIN_BIGINT] = FlatVector::GetData<int64_t>(*child_entry);
|
1569
|
+
} else {
|
1570
|
+
double_values[part_index - BEGIN_DOUBLE] = FlatVector::GetData<double>(*child_entry);
|
1571
|
+
}
|
1463
1572
|
}
|
1464
1573
|
}
|
1465
1574
|
|
@@ -1467,7 +1576,7 @@ struct StructDatePart {
|
|
1467
1576
|
const auto idx = rdata.sel->get_index(i);
|
1468
1577
|
if (arg_valid.RowIsValid(idx)) {
|
1469
1578
|
if (Value::IsFinite(tdata[idx])) {
|
1470
|
-
DatePart::StructOperator::Operation(
|
1579
|
+
DatePart::StructOperator::Operation(bigint_values, double_values, tdata[idx], i, part_mask);
|
1471
1580
|
} else {
|
1472
1581
|
for (auto &child_entry : child_entries) {
|
1473
1582
|
FlatVector::Validity(*child_entry).SetInvalid(i);
|
@@ -1695,16 +1804,32 @@ ScalarFunctionSet DayNameFun::GetFunctions() {
|
|
1695
1804
|
return dayname;
|
1696
1805
|
}
|
1697
1806
|
|
1807
|
+
ScalarFunctionSet JulianDayFun::GetFunctions() {
|
1808
|
+
using OP = DatePart::JulianDayOperator;
|
1809
|
+
|
1810
|
+
ScalarFunctionSet operator_set;
|
1811
|
+
auto date_func = DatePart::UnaryFunction<date_t, double, OP>;
|
1812
|
+
auto date_stats = OP::template PropagateStatistics<date_t>;
|
1813
|
+
operator_set.AddFunction(
|
1814
|
+
ScalarFunction({LogicalType::DATE}, LogicalType::DOUBLE, date_func, nullptr, nullptr, date_stats));
|
1815
|
+
auto ts_func = DatePart::UnaryFunction<timestamp_t, double, OP>;
|
1816
|
+
auto ts_stats = OP::template PropagateStatistics<timestamp_t>;
|
1817
|
+
operator_set.AddFunction(
|
1818
|
+
ScalarFunction({LogicalType::TIMESTAMP}, LogicalType::DOUBLE, ts_func, nullptr, nullptr, ts_stats));
|
1819
|
+
|
1820
|
+
return operator_set;
|
1821
|
+
}
|
1822
|
+
|
1698
1823
|
ScalarFunctionSet DatePartFun::GetFunctions() {
|
1699
1824
|
ScalarFunctionSet date_part;
|
1700
|
-
date_part.AddFunction(
|
1701
|
-
|
1825
|
+
date_part.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::DATE}, LogicalType::BIGINT,
|
1826
|
+
DatePartFunction<date_t>, DatePartBind));
|
1702
1827
|
date_part.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::TIMESTAMP}, LogicalType::BIGINT,
|
1703
|
-
DatePartFunction<timestamp_t
|
1704
|
-
date_part.AddFunction(
|
1705
|
-
|
1828
|
+
DatePartFunction<timestamp_t>, DatePartBind));
|
1829
|
+
date_part.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::TIME}, LogicalType::BIGINT,
|
1830
|
+
DatePartFunction<dtime_t>, DatePartBind));
|
1706
1831
|
date_part.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::INTERVAL}, LogicalType::BIGINT,
|
1707
|
-
DatePartFunction<interval_t
|
1832
|
+
DatePartFunction<interval_t>, DatePartBind));
|
1708
1833
|
|
1709
1834
|
// struct variants
|
1710
1835
|
date_part.AddFunction(StructDatePart::GetFunction<date_t>(LogicalType::DATE));
|
@@ -322,6 +322,7 @@ static int64_t SubtractDateParts(DatePartSpecifier type, TA startdate, TB enddat
|
|
322
322
|
case DatePartSpecifier::DOW:
|
323
323
|
case DatePartSpecifier::ISODOW:
|
324
324
|
case DatePartSpecifier::DOY:
|
325
|
+
case DatePartSpecifier::JULIAN_DAY:
|
325
326
|
return DateSub::DayOperator::template Operation<TA, TB, TR>(startdate, enddate);
|
326
327
|
case DatePartSpecifier::DECADE:
|
327
328
|
return DateSub::DecadeOperator::template Operation<TA, TB, TR>(startdate, enddate);
|
@@ -376,6 +377,7 @@ static void DateSubBinaryExecutor(DatePartSpecifier type, Vector &left, Vector &
|
|
376
377
|
case DatePartSpecifier::DOW:
|
377
378
|
case DatePartSpecifier::ISODOW:
|
378
379
|
case DatePartSpecifier::DOY:
|
380
|
+
case DatePartSpecifier::JULIAN_DAY:
|
379
381
|
DateSub::BinaryExecute<TA, TB, TR, DateSub::DayOperator>(left, right, result, count);
|
380
382
|
break;
|
381
383
|
case DatePartSpecifier::DECADE:
|
@@ -485,6 +485,7 @@ static TR TruncateElement(DatePartSpecifier type, TA element) {
|
|
485
485
|
case DatePartSpecifier::DOW:
|
486
486
|
case DatePartSpecifier::ISODOW:
|
487
487
|
case DatePartSpecifier::DOY:
|
488
|
+
case DatePartSpecifier::JULIAN_DAY:
|
488
489
|
return DateTrunc::DayOperator::Operation<TA, TR>(element);
|
489
490
|
case DatePartSpecifier::HOUR:
|
490
491
|
return DateTrunc::HourOperator::Operation<TA, TR>(element);
|
@@ -541,6 +542,7 @@ static void DateTruncUnaryExecutor(DatePartSpecifier type, Vector &left, Vector
|
|
541
542
|
case DatePartSpecifier::DOW:
|
542
543
|
case DatePartSpecifier::ISODOW:
|
543
544
|
case DatePartSpecifier::DOY:
|
545
|
+
case DatePartSpecifier::JULIAN_DAY:
|
544
546
|
DateTrunc::UnaryExecute<TA, TR, DateTrunc::DayOperator>(left, result, count);
|
545
547
|
break;
|
546
548
|
case DatePartSpecifier::HOUR:
|
@@ -641,6 +643,7 @@ static function_statistics_t DateTruncStats(DatePartSpecifier type) {
|
|
641
643
|
case DatePartSpecifier::DOW:
|
642
644
|
case DatePartSpecifier::ISODOW:
|
643
645
|
case DatePartSpecifier::DOY:
|
646
|
+
case DatePartSpecifier::JULIAN_DAY:
|
644
647
|
return PropagateDateTruncStatistics<TA, TR, DateTrunc::DayOperator>;
|
645
648
|
case DatePartSpecifier::HOUR:
|
646
649
|
return PropagateDateTruncStatistics<TA, TR, DateTrunc::HourOperator>;
|
@@ -685,6 +688,7 @@ static unique_ptr<FunctionData> DateTruncBind(ClientContext &context, ScalarFunc
|
|
685
688
|
case DatePartSpecifier::DOW:
|
686
689
|
case DatePartSpecifier::ISODOW:
|
687
690
|
case DatePartSpecifier::DOY:
|
691
|
+
case DatePartSpecifier::JULIAN_DAY:
|
688
692
|
switch (bound_function.arguments[1].id()) {
|
689
693
|
case LogicalType::TIMESTAMP:
|
690
694
|
bound_function.function = DateTruncFunction<timestamp_t, date_t>;
|
@@ -1,8 +1,8 @@
|
|
1
1
|
#ifndef DUCKDB_VERSION
|
2
|
-
#define DUCKDB_VERSION "0.8.2-
|
2
|
+
#define DUCKDB_VERSION "0.8.2-dev3190"
|
3
3
|
#endif
|
4
4
|
#ifndef DUCKDB_SOURCE_ID
|
5
|
-
#define DUCKDB_SOURCE_ID "
|
5
|
+
#define DUCKDB_SOURCE_ID "3196df79ce"
|
6
6
|
#endif
|
7
7
|
#include "duckdb/function/table/system_functions.hpp"
|
8
8
|
#include "duckdb/main/database.hpp"
|
@@ -13,6 +13,7 @@
|
|
13
13
|
namespace duckdb {
|
14
14
|
|
15
15
|
enum class DatePartSpecifier : uint8_t {
|
16
|
+
// BIGINT values
|
16
17
|
YEAR,
|
17
18
|
MONTH,
|
18
19
|
DAY,
|
@@ -35,9 +36,16 @@ enum class DatePartSpecifier : uint8_t {
|
|
35
36
|
ERA,
|
36
37
|
TIMEZONE,
|
37
38
|
TIMEZONE_HOUR,
|
38
|
-
TIMEZONE_MINUTE
|
39
|
+
TIMEZONE_MINUTE,
|
40
|
+
|
41
|
+
// DOUBLE values
|
42
|
+
JULIAN_DAY
|
39
43
|
};
|
40
44
|
|
45
|
+
inline bool IsBigintDatepart(DatePartSpecifier part_code) {
|
46
|
+
return size_t(part_code) < size_t(DatePartSpecifier::JULIAN_DAY);
|
47
|
+
}
|
48
|
+
|
41
49
|
DUCKDB_API bool TryGetDatePartSpecifier(const string &specifier, DatePartSpecifier &result);
|
42
50
|
DUCKDB_API DatePartSpecifier GetDatePartSpecifier(const string &specifier);
|
43
51
|
|
@@ -181,6 +181,8 @@ public:
|
|
181
181
|
DUCKDB_API static int32_t ExtractISODayOfTheWeek(date_t date);
|
182
182
|
//! Extract the day of the year
|
183
183
|
DUCKDB_API static int32_t ExtractDayOfTheYear(date_t date);
|
184
|
+
//! Extract the day of the year
|
185
|
+
DUCKDB_API static int64_t ExtractJulianDay(date_t date);
|
184
186
|
//! Extract the ISO week number
|
185
187
|
//! ISO weeks start on Monday and the first week of a year
|
186
188
|
//! contains January 4 of that year.
|
@@ -151,6 +151,8 @@ public:
|
|
151
151
|
DUCKDB_API static int64_t GetEpochMicroSeconds(timestamp_t timestamp);
|
152
152
|
//! Convert a timestamp to epoch (in nanoseconds)
|
153
153
|
DUCKDB_API static int64_t GetEpochNanoSeconds(timestamp_t timestamp);
|
154
|
+
//! Convert a timestamp to a Julian Day
|
155
|
+
DUCKDB_API static double GetJulianDay(timestamp_t timestamp);
|
154
156
|
|
155
157
|
DUCKDB_API static bool TryParseUTCOffset(const char *str, idx_t &pos, idx_t len, int &hour_offset,
|
156
158
|
int &minute_offset);
|
@@ -264,6 +264,15 @@ struct ISOYearFun {
|
|
264
264
|
static ScalarFunctionSet GetFunctions();
|
265
265
|
};
|
266
266
|
|
267
|
+
struct JulianDayFun {
|
268
|
+
static constexpr const char *Name = "julian";
|
269
|
+
static constexpr const char *Parameters = "ts";
|
270
|
+
static constexpr const char *Description = "Extract the Julian Day number from a date or timestamp";
|
271
|
+
static constexpr const char *Example = "julian(timestamp '2006-01-01 12:00')";
|
272
|
+
|
273
|
+
static ScalarFunctionSet GetFunctions();
|
274
|
+
};
|
275
|
+
|
267
276
|
struct LastDayFun {
|
268
277
|
static constexpr const char *Name = "last_day";
|
269
278
|
static constexpr const char *Parameters = "ts";
|
@@ -37,12 +37,23 @@ static void ComputeSHA256String(const std::string &to_hash, std::string *res) {
|
|
37
37
|
}
|
38
38
|
|
39
39
|
static void ComputeSHA256FileSegment(FileHandle *handle, const idx_t start, const idx_t end, std::string *res) {
|
40
|
-
|
41
|
-
|
42
|
-
file_content.resize(len);
|
43
|
-
handle->Read((void *)file_content.data(), len, start);
|
40
|
+
idx_t iter = start;
|
41
|
+
const idx_t segment_size = 1024 * 8;
|
44
42
|
|
45
|
-
|
43
|
+
duckdb_mbedtls::MbedTlsWrapper::SHA256State state;
|
44
|
+
|
45
|
+
std::string to_hash;
|
46
|
+
while (iter < end) {
|
47
|
+
idx_t len = std::min(end - iter, segment_size);
|
48
|
+
to_hash.resize(len);
|
49
|
+
handle->Read((void *)to_hash.data(), len, iter);
|
50
|
+
|
51
|
+
state.AddString(to_hash);
|
52
|
+
|
53
|
+
iter += segment_size;
|
54
|
+
}
|
55
|
+
|
56
|
+
*res = state.Finalize();
|
46
57
|
}
|
47
58
|
#endif
|
48
59
|
|
@@ -142,12 +142,10 @@ bool BoundCastExpression::CastIsInvertible(const LogicalType &source_type, const
|
|
142
142
|
}
|
143
143
|
if (source_type.id() == LogicalTypeId::VARCHAR) {
|
144
144
|
switch (target_type.id()) {
|
145
|
-
case LogicalTypeId::TIME:
|
146
145
|
case LogicalTypeId::TIMESTAMP:
|
147
146
|
case LogicalTypeId::TIMESTAMP_NS:
|
148
147
|
case LogicalTypeId::TIMESTAMP_MS:
|
149
148
|
case LogicalTypeId::TIMESTAMP_SEC:
|
150
|
-
case LogicalTypeId::TIME_TZ:
|
151
149
|
case LogicalTypeId::TIMESTAMP_TZ:
|
152
150
|
return true;
|
153
151
|
default:
|
@@ -19,5 +19,15 @@ public:
|
|
19
19
|
static void Hmac256(const char* key, size_t key_len, const char* message, size_t message_len, char* out);
|
20
20
|
|
21
21
|
static constexpr size_t SHA256_HASH_BYTES = 32;
|
22
|
+
|
23
|
+
class SHA256State {
|
24
|
+
public:
|
25
|
+
SHA256State();
|
26
|
+
~SHA256State();
|
27
|
+
void AddString(const std::string & str);
|
28
|
+
std::string Finalize();
|
29
|
+
private:
|
30
|
+
void *sha_context;
|
31
|
+
};
|
22
32
|
};
|
23
33
|
}
|
@@ -81,4 +81,34 @@ void MbedTlsWrapper::Hmac256(const char* key, size_t key_len, const char* messag
|
|
81
81
|
throw runtime_error("HMAC256 Error");
|
82
82
|
}
|
83
83
|
mbedtls_md_free(&hmac_ctx);
|
84
|
-
}
|
84
|
+
}
|
85
|
+
|
86
|
+
MbedTlsWrapper::SHA256State::SHA256State() : sha_context(new mbedtls_sha256_context()) {
|
87
|
+
mbedtls_sha256_init((mbedtls_sha256_context*)sha_context);
|
88
|
+
|
89
|
+
if (mbedtls_sha256_starts((mbedtls_sha256_context*)sha_context, false)) {
|
90
|
+
throw std::runtime_error("SHA256 Error");
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
MbedTlsWrapper::SHA256State::~SHA256State() {
|
95
|
+
mbedtls_sha256_free((mbedtls_sha256_context*)sha_context);
|
96
|
+
delete (mbedtls_sha256_context*)sha_context;
|
97
|
+
}
|
98
|
+
|
99
|
+
void MbedTlsWrapper::SHA256State::AddString(const std::string & str) {
|
100
|
+
if (mbedtls_sha256_update((mbedtls_sha256_context*)sha_context, (unsigned char*)str.data(), str.size())) {
|
101
|
+
throw std::runtime_error("SHA256 Error");
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
std::string MbedTlsWrapper::SHA256State::Finalize() {
|
106
|
+
string hash;
|
107
|
+
hash.resize(MbedTlsWrapper::SHA256_HASH_BYTES);
|
108
|
+
|
109
|
+
if (mbedtls_sha256_finish((mbedtls_sha256_context*)sha_context, (unsigned char*)hash.data())) {
|
110
|
+
throw std::runtime_error("SHA256 Error");
|
111
|
+
}
|
112
|
+
|
113
|
+
return hash;
|
114
|
+
}
|