duckdb 0.8.2-dev5080.0 → 0.8.2-dev5120.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 CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "duckdb",
3
3
  "main": "./lib/duckdb.js",
4
4
  "types": "./lib/duckdb.d.ts",
5
- "version": "0.8.2-dev5080.0",
5
+ "version": "0.8.2-dev5120.0",
6
6
  "description": "DuckDB node.js API",
7
7
  "gypfile": true,
8
8
  "dependencies": {
@@ -288,12 +288,40 @@ struct QuantileCompare {
288
288
  }
289
289
  };
290
290
 
291
+ // Avoid using naked Values in inner loops...
292
+ struct QuantileValue {
293
+ explicit QuantileValue(const Value &v) : val(v), dbl(v.GetValue<double>()) {
294
+ const auto &type = val.type();
295
+ switch (type.id()) {
296
+ case LogicalTypeId::DECIMAL: {
297
+ integral = IntegralValue::Get(v);
298
+ scaling = Hugeint::POWERS_OF_TEN[DecimalType::GetScale(type)];
299
+ break;
300
+ }
301
+ default:
302
+ break;
303
+ }
304
+ }
305
+
306
+ Value val;
307
+
308
+ // DOUBLE
309
+ double dbl;
310
+
311
+ // DECIMAL
312
+ hugeint_t integral;
313
+ hugeint_t scaling;
314
+ };
315
+
316
+ bool operator==(const QuantileValue &x, const QuantileValue &y) {
317
+ return x.val == y.val;
318
+ }
319
+
291
320
  // Continuous interpolation
292
321
  template <bool DISCRETE>
293
322
  struct Interpolator {
294
- Interpolator(const Value &q, const idx_t n_p, const bool desc_p)
295
- : desc(desc_p), RN((double)(n_p - 1) * q.GetValue<double>()), FRN(floor(RN)), CRN(ceil(RN)), begin(0),
296
- end(n_p) {
323
+ Interpolator(const QuantileValue &q, const idx_t n_p, const bool desc_p)
324
+ : desc(desc_p), RN((double)(n_p - 1) * q.dbl), FRN(floor(RN)), CRN(ceil(RN)), begin(0), end(n_p) {
297
325
  }
298
326
 
299
327
  template <class INPUT_TYPE, class TARGET_TYPE, typename ACCESSOR = QuantileDirect<INPUT_TYPE>>
@@ -336,21 +364,20 @@ struct Interpolator {
336
364
  // Discrete "interpolation"
337
365
  template <>
338
366
  struct Interpolator<true> {
339
- static inline idx_t Index(const Value &q, const idx_t n) {
367
+ static inline idx_t Index(const QuantileValue &q, const idx_t n) {
340
368
  idx_t floored;
341
- const auto &type = q.type();
342
- switch (type.id()) {
369
+ switch (q.val.type().id()) {
343
370
  case LogicalTypeId::DECIMAL: {
344
371
  // Integer arithmetic for accuracy
345
- const auto integral = IntegralValue::Get(q);
346
- const auto scaling = Hugeint::POWERS_OF_TEN[DecimalType::GetScale(type)];
372
+ const auto integral = q.integral;
373
+ const auto scaling = q.scaling;
347
374
  const auto scaled_q = DecimalMultiplyOverflowCheck::Operation<hugeint_t, hugeint_t, hugeint_t>(n, integral);
348
375
  const auto scaled_n = DecimalMultiplyOverflowCheck::Operation<hugeint_t, hugeint_t, hugeint_t>(n, scaling);
349
376
  floored = Cast::Operation<hugeint_t, idx_t>((scaled_n - scaled_q) / scaling);
350
377
  break;
351
378
  }
352
379
  default:
353
- const auto scaled_q = (double)(n * q.GetValue<double>());
380
+ const auto scaled_q = (double)(n * q.dbl);
354
381
  floored = floor(n - scaled_q);
355
382
  break;
356
383
  }
@@ -358,7 +385,7 @@ struct Interpolator<true> {
358
385
  return MaxValue<idx_t>(1, n - floored) - 1;
359
386
  }
360
387
 
361
- Interpolator(const Value &q, const idx_t n_p, bool desc_p)
388
+ Interpolator(const QuantileValue &q, const idx_t n_p, bool desc_p)
362
389
  : desc(desc_p), FRN(Index(q, n_p)), CRN(FRN), begin(0), end(n_p) {
363
390
  }
364
391
 
@@ -420,17 +447,18 @@ struct QuantileBindData : public FunctionData {
420
447
  }
421
448
 
422
449
  explicit QuantileBindData(const Value &quantile_p)
423
- : quantiles(1, QuantileAbs(quantile_p)), order(1, 0), desc(quantile_p < 0) {
450
+ : quantiles(1, QuantileValue(QuantileAbs(quantile_p))), order(1, 0), desc(quantile_p < 0) {
424
451
  }
425
452
 
426
453
  explicit QuantileBindData(const vector<Value> &quantiles_p) {
454
+ vector<Value> normalised;
427
455
  size_t pos = 0;
428
456
  size_t neg = 0;
429
457
  for (idx_t i = 0; i < quantiles_p.size(); ++i) {
430
458
  const auto &q = quantiles_p[i];
431
459
  pos += (q > 0);
432
460
  neg += (q < 0);
433
- quantiles.emplace_back(QuantileAbs(q));
461
+ normalised.emplace_back(QuantileAbs(q));
434
462
  order.push_back(i);
435
463
  }
436
464
  if (pos && neg) {
@@ -438,8 +466,12 @@ struct QuantileBindData : public FunctionData {
438
466
  }
439
467
  desc = (neg > 0);
440
468
 
441
- IndirectLess<Value> lt(quantiles.data());
469
+ IndirectLess<Value> lt(normalised.data());
442
470
  std::sort(order.begin(), order.end(), lt);
471
+
472
+ for (const auto &q : normalised) {
473
+ quantiles.emplace_back(QuantileValue(q));
474
+ }
443
475
  }
444
476
 
445
477
  QuantileBindData(const QuantileBindData &other) : order(other.order), desc(other.desc) {
@@ -460,16 +492,24 @@ struct QuantileBindData : public FunctionData {
460
492
  static void Serialize(Serializer &serializer, const optional_ptr<FunctionData> bind_data_p,
461
493
  const AggregateFunction &function) {
462
494
  auto &bind_data = bind_data_p->Cast<QuantileBindData>();
463
- serializer.WriteProperty(100, "quantiles", bind_data.quantiles);
495
+ vector<Value> raw;
496
+ for (const auto &q : bind_data.quantiles) {
497
+ raw.emplace_back(q.val);
498
+ }
499
+ serializer.WriteProperty(100, "quantiles", raw);
464
500
  serializer.WriteProperty(101, "order", bind_data.order);
465
501
  serializer.WriteProperty(102, "desc", bind_data.desc);
466
502
  }
467
503
 
468
504
  static unique_ptr<FunctionData> Deserialize(Deserializer &deserializer, AggregateFunction &function) {
469
505
  auto result = make_uniq<QuantileBindData>();
470
- deserializer.ReadProperty(100, "quantiles", result->quantiles);
506
+ vector<Value> raw;
507
+ deserializer.ReadProperty(100, "quantiles", raw);
471
508
  deserializer.ReadProperty(101, "order", result->order);
472
509
  deserializer.ReadProperty(102, "desc", result->desc);
510
+ for (const auto &r : raw) {
511
+ result->quantiles.emplace_back(QuantileValue(r));
512
+ }
473
513
  return std::move(result);
474
514
  }
475
515
 
@@ -478,7 +518,7 @@ struct QuantileBindData : public FunctionData {
478
518
  throw NotImplementedException("FIXME: serializing quantiles with decimals is not supported right now");
479
519
  }
480
520
 
481
- vector<Value> quantiles;
521
+ vector<QuantileValue> quantiles;
482
522
  vector<idx_t> order;
483
523
  bool desc;
484
524
  };
@@ -566,7 +606,7 @@ struct QuantileScalarOperation : public QuantileOperation {
566
606
  auto &bind_data = aggr_input_data.bind_data->Cast<QuantileBindData>();
567
607
 
568
608
  // Find the two positions needed
569
- const auto q = bind_data.quantiles[0];
609
+ const auto &q = bind_data.quantiles[0];
570
610
 
571
611
  bool replace = false;
572
612
  if (frame.start == prev.start + 1 && frame.end == prev.end + 1) {
@@ -1041,7 +1081,11 @@ struct MedianAbsoluteDeviationOperation : public QuantileOperation {
1041
1081
  return;
1042
1082
  }
1043
1083
  using SAVE_TYPE = typename STATE::SaveType;
1044
- Interpolator<false> interp(0.5, state.v.size(), false);
1084
+ D_ASSERT(finalize_data.input.bind_data);
1085
+ auto &bind_data = finalize_data.input.bind_data->Cast<QuantileBindData>();
1086
+ D_ASSERT(bind_data.quantiles.size() == 1);
1087
+ const auto &q = bind_data.quantiles[0];
1088
+ Interpolator<false> interp(q, state.v.size(), false);
1045
1089
  const auto med = interp.template Operation<SAVE_TYPE, MEDIAN_TYPE>(state.v.data(), finalize_data.result);
1046
1090
 
1047
1091
  MadAccessor<SAVE_TYPE, T, MEDIAN_TYPE> accessor(med);
@@ -1050,8 +1094,8 @@ struct MedianAbsoluteDeviationOperation : public QuantileOperation {
1050
1094
 
1051
1095
  template <class STATE, class INPUT_TYPE, class RESULT_TYPE>
1052
1096
  static void Window(const INPUT_TYPE *data, const ValidityMask &fmask, const ValidityMask &dmask,
1053
- AggregateInputData &, STATE &state, const FrameBounds &frame, const FrameBounds &prev,
1054
- Vector &result, idx_t ridx, idx_t bias) {
1097
+ AggregateInputData &aggr_input_data, STATE &state, const FrameBounds &frame,
1098
+ const FrameBounds &prev, Vector &result, idx_t ridx, idx_t bias) {
1055
1099
  auto rdata = FlatVector::GetData<RESULT_TYPE>(result);
1056
1100
  auto &rmask = FlatVector::Validity(result);
1057
1101
 
@@ -1079,7 +1123,10 @@ struct MedianAbsoluteDeviationOperation : public QuantileOperation {
1079
1123
  std::partition(index2, index2 + state.pos, included);
1080
1124
 
1081
1125
  // Find the two positions needed for the median
1082
- const float q = 0.5;
1126
+ D_ASSERT(aggr_input_data.bind_data);
1127
+ auto &bind_data = aggr_input_data.bind_data->Cast<QuantileBindData>();
1128
+ D_ASSERT(bind_data.quantiles.size() == 1);
1129
+ const auto &q = bind_data.quantiles[0];
1083
1130
 
1084
1131
  bool replace = false;
1085
1132
  if (frame.start == prev.start + 1 && frame.end == prev.end + 1) {
@@ -1124,12 +1171,18 @@ struct MedianAbsoluteDeviationOperation : public QuantileOperation {
1124
1171
  }
1125
1172
  };
1126
1173
 
1174
+ unique_ptr<FunctionData> BindMedian(ClientContext &context, AggregateFunction &function,
1175
+ vector<unique_ptr<Expression>> &arguments) {
1176
+ return make_uniq<QuantileBindData>(Value::DECIMAL(int16_t(5), 2, 1));
1177
+ }
1178
+
1127
1179
  template <typename INPUT_TYPE, typename MEDIAN_TYPE, typename TARGET_TYPE>
1128
1180
  AggregateFunction GetTypedMedianAbsoluteDeviationAggregateFunction(const LogicalType &input_type,
1129
1181
  const LogicalType &target_type) {
1130
1182
  using STATE = QuantileState<INPUT_TYPE>;
1131
1183
  using OP = MedianAbsoluteDeviationOperation<MEDIAN_TYPE>;
1132
1184
  auto fun = AggregateFunction::UnaryAggregateDestructor<STATE, INPUT_TYPE, TARGET_TYPE, OP>(input_type, target_type);
1185
+ fun.bind = BindMedian;
1133
1186
  fun.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT;
1134
1187
  fun.window = AggregateFunction::UnaryWindow<STATE, INPUT_TYPE, TARGET_TYPE, OP>;
1135
1188
  return fun;
@@ -1173,11 +1226,6 @@ AggregateFunction GetMedianAbsoluteDeviationAggregateFunction(const LogicalType
1173
1226
  }
1174
1227
  }
1175
1228
 
1176
- unique_ptr<FunctionData> BindMedian(ClientContext &context, AggregateFunction &function,
1177
- vector<unique_ptr<Expression>> &arguments) {
1178
- return make_uniq<QuantileBindData>(Value::DECIMAL(int16_t(5), 2, 1));
1179
- }
1180
-
1181
1229
  unique_ptr<FunctionData> BindMedianDecimal(ClientContext &context, AggregateFunction &function,
1182
1230
  vector<unique_ptr<Expression>> &arguments) {
1183
1231
  auto bind_data = BindMedian(context, function, arguments);
@@ -1195,7 +1243,7 @@ unique_ptr<FunctionData> BindMedianAbsoluteDeviationDecimal(ClientContext &conte
1195
1243
  function = GetMedianAbsoluteDeviationAggregateFunction(arguments[0]->return_type);
1196
1244
  function.name = "mad";
1197
1245
  function.order_dependent = AggregateOrderDependent::NOT_ORDER_DEPENDENT;
1198
- return nullptr;
1246
+ return BindMedian(context, function, arguments);
1199
1247
  }
1200
1248
 
1201
1249
  static const Value &CheckQuantile(const Value &quantile_val) {
@@ -281,7 +281,7 @@ static StaticFunctionDefinition internal_functions[] = {
281
281
  DUCKDB_SCALAR_FUNCTION(RightFun),
282
282
  DUCKDB_SCALAR_FUNCTION(RightGraphemeFun),
283
283
  DUCKDB_SCALAR_FUNCTION_SET(RoundFun),
284
- DUCKDB_SCALAR_FUNCTION_ALIAS(RowFun),
284
+ DUCKDB_SCALAR_FUNCTION(RowFun),
285
285
  DUCKDB_SCALAR_FUNCTION(RpadFun),
286
286
  DUCKDB_SCALAR_FUNCTION_SET(RtrimFun),
287
287
  DUCKDB_SCALAR_FUNCTION_SET(SecondsFun),
@@ -30,6 +30,7 @@ static void StructPackFunction(DataChunk &args, ExpressionState &state, Vector &
30
30
  result.Verify(args.size());
31
31
  }
32
32
 
33
+ template <bool IS_STRUCT_PACK>
33
34
  static unique_ptr<FunctionData> StructPackBind(ClientContext &context, ScalarFunction &bound_function,
34
35
  vector<unique_ptr<Expression>> &arguments) {
35
36
  case_insensitive_set_t name_collision_set;
@@ -39,25 +40,20 @@ static unique_ptr<FunctionData> StructPackBind(ClientContext &context, ScalarFun
39
40
  throw Exception("Can't pack nothing into a struct");
40
41
  }
41
42
  child_list_t<LogicalType> struct_children;
42
- bool unnamed = false;
43
43
  for (idx_t i = 0; i < arguments.size(); i++) {
44
44
  auto &child = arguments[i];
45
- if (child->alias.empty()) {
46
- if (bound_function.name == "struct_pack") {
45
+ string alias;
46
+ if (IS_STRUCT_PACK) {
47
+ if (child->alias.empty()) {
47
48
  throw BinderException("Need named argument for struct pack, e.g. STRUCT_PACK(a := b)");
48
- } else {
49
- D_ASSERT(bound_function.name == "row");
50
- if (i > 1) {
51
- D_ASSERT(unnamed);
52
- }
53
- unnamed = true;
54
49
  }
50
+ alias = child->alias;
51
+ if (name_collision_set.find(alias) != name_collision_set.end()) {
52
+ throw BinderException("Duplicate struct entry name \"%s\"", alias);
53
+ }
54
+ name_collision_set.insert(alias);
55
55
  }
56
- if (!child->alias.empty() && name_collision_set.find(child->alias) != name_collision_set.end()) {
57
- throw BinderException("Duplicate struct entry name \"%s\"", child->alias);
58
- }
59
- name_collision_set.insert(child->alias);
60
- struct_children.push_back(make_pair(child->alias, arguments[i]->return_type));
56
+ struct_children.push_back(make_pair(alias, arguments[i]->return_type));
61
57
  }
62
58
 
63
59
  // this is more for completeness reasons
@@ -75,10 +71,10 @@ unique_ptr<BaseStatistics> StructPackStats(ClientContext &context, FunctionStati
75
71
  return struct_stats.ToUnique();
76
72
  }
77
73
 
78
- ScalarFunction StructPackFun::GetFunction() {
79
- // the arguments and return types are actually set in the binder function
80
- ScalarFunction fun("struct_pack", {}, LogicalTypeId::STRUCT, StructPackFunction, StructPackBind, nullptr,
81
- StructPackStats);
74
+ template <bool IS_STRUCT_PACK>
75
+ ScalarFunction GetStructPackFunction() {
76
+ ScalarFunction fun(IS_STRUCT_PACK ? "struct_pack" : "row", {}, LogicalTypeId::STRUCT, StructPackFunction,
77
+ StructPackBind<IS_STRUCT_PACK>, nullptr, StructPackStats);
82
78
  fun.varargs = LogicalType::ANY;
83
79
  fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING;
84
80
  fun.serialize = VariableReturnBindData::Serialize;
@@ -86,4 +82,12 @@ ScalarFunction StructPackFun::GetFunction() {
86
82
  return fun;
87
83
  }
88
84
 
85
+ ScalarFunction StructPackFun::GetFunction() {
86
+ return GetStructPackFunction<true>();
87
+ }
88
+
89
+ ScalarFunction RowFun::GetFunction() {
90
+ return GetStructPackFunction<false>();
91
+ }
92
+
89
93
  } // namespace duckdb
@@ -1,8 +1,8 @@
1
1
  #ifndef DUCKDB_VERSION
2
- #define DUCKDB_VERSION "0.8.2-dev5080"
2
+ #define DUCKDB_VERSION "0.8.2-dev5120"
3
3
  #endif
4
4
  #ifndef DUCKDB_SOURCE_ID
5
- #define DUCKDB_SOURCE_ID "e07b94a748"
5
+ #define DUCKDB_SOURCE_ID "fc2e4b26a6"
6
6
  #endif
7
7
  #include "duckdb/function/table/system_functions.hpp"
8
8
  #include "duckdb/main/database.hpp"
@@ -34,9 +34,12 @@ struct StructPackFun {
34
34
  };
35
35
 
36
36
  struct RowFun {
37
- using ALIAS = StructPackFun;
38
-
39
37
  static constexpr const char *Name = "row";
38
+ static constexpr const char *Parameters = "any";
39
+ static constexpr const char *Description = "Creates an unnamed STRUCT containing the argument values.";
40
+ static constexpr const char *Example = "row(4, 'hello')";
41
+
42
+ static ScalarFunction GetFunction();
40
43
  };
41
44
 
42
45
  } // namespace duckdb
@@ -39,6 +39,7 @@ class CompressionFunction;
39
39
  class TableFunctionRef;
40
40
  class OperatorExtension;
41
41
  class StorageExtension;
42
+ class ExtensionCallback;
42
43
 
43
44
  struct CompressionFunctionSet;
44
45
  struct DBConfig;
@@ -212,6 +213,8 @@ public:
212
213
  case_insensitive_map_t<duckdb::unique_ptr<StorageExtension>> storage_extensions;
213
214
  //! A buffer pool can be shared across multiple databases (if desired).
214
215
  shared_ptr<BufferPool> buffer_pool;
216
+ //! Set of callbacks that can be installed by extensions
217
+ vector<unique_ptr<ExtensionCallback>> extension_callbacks;
215
218
 
216
219
  public:
217
220
  DUCKDB_API static DBConfig &GetConfig(ClientContext &context);
@@ -0,0 +1,26 @@
1
+ //===----------------------------------------------------------------------===//
2
+ // DuckDB
3
+ //
4
+ // duckdb/planner/extension_callback.hpp
5
+ //
6
+ //
7
+ //===----------------------------------------------------------------------===//
8
+
9
+ #pragma once
10
+
11
+ #include "duckdb/common/common.hpp"
12
+
13
+ namespace duckdb {
14
+ class DatabaseInstance;
15
+
16
+ class ExtensionCallback {
17
+ public:
18
+ virtual ~ExtensionCallback() {
19
+ }
20
+
21
+ //! Called after an extension is finished loading
22
+ virtual void OnExtensionLoaded(DatabaseInstance &db, const string &name) {
23
+ }
24
+ };
25
+
26
+ } // namespace duckdb
@@ -19,6 +19,7 @@
19
19
  #include "duckdb/storage/storage_extension.hpp"
20
20
  #include "duckdb/storage/storage_manager.hpp"
21
21
  #include "duckdb/transaction/transaction_manager.hpp"
22
+ #include "duckdb/planner/extension_callback.hpp"
22
23
 
23
24
  #ifndef DUCKDB_NO_THREADS
24
25
  #include "duckdb/common/thread.hpp"
@@ -381,6 +382,11 @@ bool DuckDB::ExtensionIsLoaded(const std::string &name) {
381
382
  void DatabaseInstance::SetExtensionLoaded(const std::string &name) {
382
383
  auto extension_name = ExtensionHelper::GetExtensionName(name);
383
384
  loaded_extensions.insert(extension_name);
385
+
386
+ auto &callbacks = DBConfig::GetConfig(*this).extension_callbacks;
387
+ for (auto &callback : callbacks) {
388
+ callback->OnExtensionLoaded(*this, name);
389
+ }
384
390
  }
385
391
 
386
392
  bool DatabaseInstance::TryGetCurrentSetting(const std::string &key, Value &result) {
@@ -21,6 +21,10 @@ namespace duckdb {
21
21
  // Access Mode
22
22
  //===--------------------------------------------------------------------===//
23
23
  void AccessModeSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) {
24
+ if (db) {
25
+ throw InvalidInputException("Cannot change access_mode setting while database is running - it must be set when "
26
+ "opening or attaching the database");
27
+ }
24
28
  auto parameter = StringUtil::Lower(input.ToString());
25
29
  if (parameter == "automatic") {
26
30
  config.options.access_mode = AccessMode::AUTOMATIC;
@@ -8,6 +8,7 @@
8
8
  #include "duckdb/storage/metadata/metadata_writer.hpp"
9
9
  #include "duckdb/storage/buffer_manager.hpp"
10
10
  #include "duckdb/main/config.hpp"
11
+ #include "duckdb/main/database.hpp"
11
12
 
12
13
  #include <algorithm>
13
14
  #include <cstring>
@@ -16,12 +17,22 @@ namespace duckdb {
16
17
 
17
18
  const char MainHeader::MAGIC_BYTES[] = "DUCK";
18
19
 
20
+ void SerializeVersionNumber(WriteStream &ser, const string &version_str) {
21
+ constexpr const idx_t MAX_VERSION_SIZE = 32;
22
+ data_t version[MAX_VERSION_SIZE];
23
+ memset(version, 0, MAX_VERSION_SIZE);
24
+ memcpy(version, version_str.c_str(), MinValue<idx_t>(version_str.size(), MAX_VERSION_SIZE));
25
+ ser.WriteData(version, MAX_VERSION_SIZE);
26
+ }
27
+
19
28
  void MainHeader::Write(WriteStream &ser) {
20
29
  ser.WriteData(const_data_ptr_cast(MAGIC_BYTES), MAGIC_BYTE_SIZE);
21
30
  ser.Write<uint64_t>(version_number);
22
31
  for (idx_t i = 0; i < FLAG_COUNT; i++) {
23
32
  ser.Write<uint64_t>(flags[i]);
24
33
  }
34
+ SerializeVersionNumber(ser, DuckDB::LibraryVersion());
35
+ SerializeVersionNumber(ser, DuckDB::SourceID());
25
36
  }
26
37
 
27
38
  void MainHeader::CheckMagicBytes(FileHandle &handle) {