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 +1 -1
- package/src/duckdb/src/core_functions/aggregate/holistic/quantile.cpp +75 -27
- package/src/duckdb/src/core_functions/function_list.cpp +1 -1
- package/src/duckdb/src/core_functions/scalar/struct/struct_pack.cpp +22 -18
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/core_functions/scalar/struct_functions.hpp +5 -2
- package/src/duckdb/src/include/duckdb/main/config.hpp +3 -0
- package/src/duckdb/src/include/duckdb/planner/extension_callback.hpp +26 -0
- package/src/duckdb/src/main/database.cpp +6 -0
- package/src/duckdb/src/main/settings/settings.cpp +4 -0
- package/src/duckdb/src/storage/single_file_block_manager.cpp +11 -0
package/package.json
CHANGED
@@ -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
|
295
|
-
: desc(desc_p), RN((double)(n_p - 1) * q.
|
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
|
367
|
+
static inline idx_t Index(const QuantileValue &q, const idx_t n) {
|
340
368
|
idx_t floored;
|
341
|
-
|
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 =
|
346
|
-
const auto scaling =
|
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.
|
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
|
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
|
-
|
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(
|
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
|
-
|
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
|
-
|
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<
|
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
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
46
|
-
|
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
|
-
|
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
|
-
|
79
|
-
|
80
|
-
ScalarFunction fun("struct_pack", {}, LogicalTypeId::STRUCT, StructPackFunction,
|
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-
|
2
|
+
#define DUCKDB_VERSION "0.8.2-dev5120"
|
3
3
|
#endif
|
4
4
|
#ifndef DUCKDB_SOURCE_ID
|
5
|
-
#define DUCKDB_SOURCE_ID "
|
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) {
|