duckdb 0.7.1-dev37.0 → 0.7.1-dev407.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/README.md +1 -1
- package/binding.gyp +7 -7
- package/package.json +3 -3
- package/src/duckdb/extension/json/buffered_json_reader.cpp +50 -9
- package/src/duckdb/extension/json/include/buffered_json_reader.hpp +7 -2
- package/src/duckdb/extension/json/include/json_scan.hpp +45 -10
- package/src/duckdb/extension/json/json_functions/copy_json.cpp +35 -22
- package/src/duckdb/extension/json/json_functions/json_create.cpp +8 -8
- package/src/duckdb/extension/json/json_functions/json_structure.cpp +8 -3
- package/src/duckdb/extension/json/json_functions/json_transform.cpp +54 -10
- package/src/duckdb/extension/json/json_functions/read_json.cpp +104 -49
- package/src/duckdb/extension/json/json_functions/read_json_objects.cpp +5 -3
- package/src/duckdb/extension/json/json_functions.cpp +7 -0
- package/src/duckdb/extension/json/json_scan.cpp +144 -37
- package/src/duckdb/extension/parquet/column_reader.cpp +7 -0
- package/src/duckdb/extension/parquet/include/column_reader.hpp +1 -0
- package/src/duckdb/extension/parquet/parquet-extension.cpp +2 -9
- package/src/duckdb/src/catalog/catalog.cpp +62 -13
- package/src/duckdb/src/catalog/catalog_entry/index_catalog_entry.cpp +8 -7
- package/src/duckdb/src/catalog/default/default_views.cpp +1 -1
- package/src/duckdb/src/common/bind_helpers.cpp +55 -0
- package/src/duckdb/src/common/enums/logical_operator_type.cpp +2 -0
- package/src/duckdb/src/common/enums/physical_operator_type.cpp +2 -0
- package/src/duckdb/src/common/enums/statement_type.cpp +2 -0
- package/src/duckdb/src/common/file_system.cpp +28 -0
- package/src/duckdb/src/common/hive_partitioning.cpp +1 -0
- package/src/duckdb/src/common/local_file_system.cpp +4 -4
- package/src/duckdb/src/common/operator/cast_operators.cpp +10 -4
- package/src/duckdb/src/common/types/partitioned_column_data.cpp +1 -0
- package/src/duckdb/src/common/types/time.cpp +1 -1
- package/src/duckdb/src/common/types/timestamp.cpp +35 -4
- package/src/duckdb/src/common/types.cpp +37 -11
- package/src/duckdb/src/execution/column_binding_resolver.cpp +5 -2
- package/src/duckdb/src/execution/index/art/art.cpp +117 -67
- package/src/duckdb/src/execution/index/art/art_key.cpp +24 -12
- package/src/duckdb/src/execution/index/art/leaf.cpp +7 -8
- package/src/duckdb/src/execution/index/art/node.cpp +13 -27
- package/src/duckdb/src/execution/index/art/node16.cpp +5 -8
- package/src/duckdb/src/execution/index/art/node256.cpp +3 -5
- package/src/duckdb/src/execution/index/art/node4.cpp +4 -7
- package/src/duckdb/src/execution/index/art/node48.cpp +5 -8
- package/src/duckdb/src/execution/index/art/prefix.cpp +2 -3
- package/src/duckdb/src/execution/operator/aggregate/physical_window.cpp +6 -27
- package/src/duckdb/src/execution/operator/helper/physical_reset.cpp +1 -9
- package/src/duckdb/src/execution/operator/helper/physical_set.cpp +1 -9
- package/src/duckdb/src/execution/operator/join/physical_iejoin.cpp +7 -9
- package/src/duckdb/src/execution/operator/persistent/base_csv_reader.cpp +6 -11
- package/src/duckdb/src/execution/operator/persistent/buffered_csv_reader.cpp +13 -13
- package/src/duckdb/src/execution/operator/schema/physical_detach.cpp +37 -0
- package/src/duckdb/src/execution/operator/schema/physical_drop.cpp +0 -5
- package/src/duckdb/src/execution/physical_operator.cpp +6 -6
- package/src/duckdb/src/execution/physical_plan/plan_simple.cpp +4 -0
- package/src/duckdb/src/execution/physical_plan_generator.cpp +1 -0
- package/src/duckdb/src/function/pragma/pragma_queries.cpp +38 -11
- package/src/duckdb/src/function/scalar/generic/current_setting.cpp +2 -2
- package/src/duckdb/src/function/scalar/map/map.cpp +69 -21
- package/src/duckdb/src/function/table/read_csv.cpp +17 -5
- package/src/duckdb/src/function/table/system/duckdb_temporary_files.cpp +59 -0
- package/src/duckdb/src/function/table/system_functions.cpp +1 -0
- package/src/duckdb/src/function/table/table_scan.cpp +3 -0
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/catalog/catalog.hpp +7 -1
- package/src/duckdb/src/include/duckdb/catalog/catalog_entry/duck_index_entry.hpp +1 -1
- package/src/duckdb/src/include/duckdb/catalog/catalog_entry/index_catalog_entry.hpp +1 -1
- package/src/duckdb/src/include/duckdb/common/bind_helpers.hpp +2 -0
- package/src/duckdb/src/include/duckdb/common/enums/logical_operator_type.hpp +1 -0
- package/src/duckdb/src/include/duckdb/common/enums/physical_operator_type.hpp +1 -0
- package/src/duckdb/src/include/duckdb/common/enums/statement_type.hpp +3 -2
- package/src/duckdb/src/include/duckdb/common/enums/wal_type.hpp +3 -0
- package/src/duckdb/src/include/duckdb/common/exception.hpp +10 -0
- package/src/duckdb/src/include/duckdb/common/file_system.hpp +1 -0
- package/src/duckdb/src/include/duckdb/common/hive_partitioning.hpp +9 -1
- package/src/duckdb/src/include/duckdb/common/radix_partitioning.hpp +4 -4
- package/src/duckdb/src/include/duckdb/common/types/timestamp.hpp +5 -1
- package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +37 -41
- package/src/duckdb/src/include/duckdb/execution/index/art/art_key.hpp +8 -11
- package/src/duckdb/src/include/duckdb/execution/operator/persistent/base_csv_reader.hpp +1 -3
- package/src/duckdb/src/include/duckdb/execution/operator/persistent/buffered_csv_reader.hpp +0 -2
- package/src/duckdb/src/include/duckdb/execution/operator/persistent/csv_reader_options.hpp +2 -0
- package/src/duckdb/src/include/duckdb/execution/operator/schema/physical_detach.hpp +32 -0
- package/src/duckdb/src/include/duckdb/function/table/system_functions.hpp +4 -0
- package/src/duckdb/src/include/duckdb/main/client_data.hpp +2 -2
- package/src/duckdb/src/include/duckdb/main/config.hpp +2 -3
- package/src/duckdb/src/include/duckdb/main/{extension_functions.hpp → extension_entries.hpp} +26 -5
- package/src/duckdb/src/include/duckdb/main/extension_helper.hpp +3 -0
- package/src/duckdb/src/include/duckdb/main/settings.hpp +9 -0
- package/src/duckdb/src/include/duckdb/parallel/pipeline_executor.hpp +0 -7
- package/src/duckdb/src/include/duckdb/parser/parsed_data/create_database_info.hpp +0 -4
- package/src/duckdb/src/include/duckdb/parser/parsed_data/detach_info.hpp +32 -0
- package/src/duckdb/src/include/duckdb/parser/query_node/select_node.hpp +1 -1
- package/src/duckdb/src/include/duckdb/parser/sql_statement.hpp +2 -2
- package/src/duckdb/src/include/duckdb/parser/statement/copy_statement.hpp +1 -1
- package/src/duckdb/src/include/duckdb/parser/statement/detach_statement.hpp +29 -0
- package/src/duckdb/src/include/duckdb/parser/statement/list.hpp +1 -0
- package/src/duckdb/src/include/duckdb/parser/statement/select_statement.hpp +3 -3
- package/src/duckdb/src/include/duckdb/parser/tableref/subqueryref.hpp +1 -1
- package/src/duckdb/src/include/duckdb/parser/tokens.hpp +1 -0
- package/src/duckdb/src/include/duckdb/parser/transformer.hpp +1 -0
- package/src/duckdb/src/include/duckdb/planner/binder.hpp +4 -0
- package/src/duckdb/src/include/duckdb/planner/expression_binder/index_binder.hpp +10 -3
- package/src/duckdb/src/include/duckdb/planner/operator/logical_execute.hpp +1 -5
- package/src/duckdb/src/include/duckdb/planner/operator/logical_show.hpp +1 -2
- package/src/duckdb/src/include/duckdb/storage/buffer_manager.hpp +8 -0
- package/src/duckdb/src/include/duckdb/storage/data_table.hpp +7 -1
- package/src/duckdb/src/include/duckdb/storage/index.hpp +47 -38
- package/src/duckdb/src/include/duckdb/storage/storage_extension.hpp +7 -0
- package/src/duckdb/src/include/duckdb/storage/table/update_segment.hpp +2 -0
- package/src/duckdb/src/include/duckdb/storage/write_ahead_log.hpp +7 -0
- package/src/duckdb/src/main/client_context.cpp +2 -0
- package/src/duckdb/src/main/config.cpp +1 -0
- package/src/duckdb/src/main/database.cpp +14 -5
- package/src/duckdb/src/main/extension/extension_alias.cpp +2 -1
- package/src/duckdb/src/main/extension/extension_install.cpp +43 -9
- package/src/duckdb/src/main/extension/extension_load.cpp +29 -5
- package/src/duckdb/src/main/settings/settings.cpp +16 -0
- package/src/duckdb/src/optimizer/statistics/operator/propagate_join.cpp +2 -6
- package/src/duckdb/src/parallel/pipeline_executor.cpp +1 -55
- package/src/duckdb/src/parser/parsed_data/create_index_info.cpp +3 -0
- package/src/duckdb/src/parser/statement/copy_statement.cpp +2 -13
- package/src/duckdb/src/parser/statement/delete_statement.cpp +3 -0
- package/src/duckdb/src/parser/statement/detach_statement.cpp +15 -0
- package/src/duckdb/src/parser/statement/insert_statement.cpp +9 -0
- package/src/duckdb/src/parser/statement/update_statement.cpp +3 -0
- package/src/duckdb/src/parser/transform/expression/transform_case.cpp +3 -3
- package/src/duckdb/src/parser/transform/statement/transform_create_database.cpp +0 -1
- package/src/duckdb/src/parser/transform/statement/transform_detach.cpp +19 -0
- package/src/duckdb/src/parser/transformer.cpp +2 -0
- package/src/duckdb/src/planner/binder/expression/bind_aggregate_expression.cpp +3 -0
- package/src/duckdb/src/planner/binder/statement/bind_copy.cpp +7 -14
- package/src/duckdb/src/planner/binder/statement/bind_create.cpp +16 -14
- package/src/duckdb/src/planner/binder/statement/bind_create_table.cpp +13 -0
- package/src/duckdb/src/planner/binder/statement/bind_detach.cpp +19 -0
- package/src/duckdb/src/planner/binder/statement/bind_drop.cpp +29 -4
- package/src/duckdb/src/planner/binder/statement/bind_insert.cpp +22 -1
- package/src/duckdb/src/planner/binder.cpp +2 -0
- package/src/duckdb/src/planner/expression_binder/index_binder.cpp +32 -1
- package/src/duckdb/src/planner/logical_operator.cpp +4 -0
- package/src/duckdb/src/planner/planner.cpp +1 -0
- package/src/duckdb/src/storage/buffer_manager.cpp +105 -26
- package/src/duckdb/src/storage/compression/bitpacking.cpp +16 -7
- package/src/duckdb/src/storage/data_table.cpp +66 -3
- package/src/duckdb/src/storage/index.cpp +1 -1
- package/src/duckdb/src/storage/local_storage.cpp +1 -1
- package/src/duckdb/src/storage/table/column_data.cpp +4 -2
- package/src/duckdb/src/storage/table/update_segment.cpp +15 -0
- package/src/duckdb/src/storage/table_index_list.cpp +1 -2
- package/src/duckdb/src/storage/wal_replay.cpp +68 -0
- package/src/duckdb/src/storage/write_ahead_log.cpp +21 -1
- package/src/duckdb/src/transaction/commit_state.cpp +5 -2
- package/src/duckdb/third_party/concurrentqueue/blockingconcurrentqueue.h +2 -2
- package/src/duckdb/third_party/fmt/include/fmt/core.h +1 -2
- package/src/duckdb/third_party/libpg_query/include/nodes/nodes.hpp +1 -0
- package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +14 -0
- package/src/duckdb/third_party/libpg_query/include/parser/gram.hpp +530 -1006
- package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +17659 -17626
- package/src/duckdb/ub_extension_icu_third_party_icu_i18n.cpp +4 -4
- package/src/duckdb/ub_src_execution_operator_schema.cpp +2 -0
- package/src/duckdb/ub_src_function_table_system.cpp +2 -0
- package/src/duckdb/ub_src_parser_statement.cpp +2 -0
- package/src/duckdb/ub_src_parser_transform_statement.cpp +2 -0
- package/src/duckdb/ub_src_planner_binder_statement.cpp +2 -0
- package/src/statement.cpp +46 -12
- package/test/arrow.test.ts +3 -3
- package/test/prepare.test.ts +39 -1
- package/test/typescript_decls.test.ts +1 -1
- package/src/duckdb/src/include/duckdb/function/create_database_extension.hpp +0 -37
|
@@ -27,7 +27,10 @@ ART::ART(const vector<column_t> &column_ids, TableIOManager &table_io_manager,
|
|
|
27
27
|
tree = nullptr;
|
|
28
28
|
if (block_id != DConstants::INVALID_INDEX) {
|
|
29
29
|
tree = Node::Deserialize(*this, block_id, block_offset);
|
|
30
|
-
|
|
30
|
+
Verify();
|
|
31
|
+
if (track_memory) {
|
|
32
|
+
buffer_manager.IncreaseUsedMemory(memory_size);
|
|
33
|
+
}
|
|
31
34
|
}
|
|
32
35
|
serialized_data_pointer = BlockPointer(block_id, block_offset);
|
|
33
36
|
|
|
@@ -58,7 +61,7 @@ ART::~ART() {
|
|
|
58
61
|
if (!tree) {
|
|
59
62
|
return;
|
|
60
63
|
}
|
|
61
|
-
|
|
64
|
+
Verify();
|
|
62
65
|
if (track_memory) {
|
|
63
66
|
buffer_manager.DecreaseUsedMemory(memory_size);
|
|
64
67
|
}
|
|
@@ -72,6 +75,7 @@ ART::~ART() {
|
|
|
72
75
|
|
|
73
76
|
unique_ptr<IndexScanState> ART::InitializeScanSinglePredicate(const Transaction &transaction, const Value &value,
|
|
74
77
|
ExpressionType expression_type) {
|
|
78
|
+
// initialize point lookup
|
|
75
79
|
auto result = make_unique<ARTIndexScanState>();
|
|
76
80
|
result->values[0] = value;
|
|
77
81
|
result->expressions[0] = expression_type;
|
|
@@ -81,6 +85,7 @@ unique_ptr<IndexScanState> ART::InitializeScanSinglePredicate(const Transaction
|
|
|
81
85
|
unique_ptr<IndexScanState> ART::InitializeScanTwoPredicates(Transaction &transaction, const Value &low_value,
|
|
82
86
|
ExpressionType low_expression_type, const Value &high_value,
|
|
83
87
|
ExpressionType high_expression_type) {
|
|
88
|
+
// initialize range lookup
|
|
84
89
|
auto result = make_unique<ARTIndexScanState>();
|
|
85
90
|
result->values[0] = low_value;
|
|
86
91
|
result->expressions[0] = low_expression_type;
|
|
@@ -103,7 +108,7 @@ static void TemplatedGenerateKeys(ArenaAllocator &allocator, Vector &input, idx_
|
|
|
103
108
|
for (idx_t i = 0; i < count; i++) {
|
|
104
109
|
auto idx = idata.sel->get_index(i);
|
|
105
110
|
if (idata.validity.RowIsValid(idx)) {
|
|
106
|
-
Key::CreateKey<T>(allocator, keys[i], input_data[idx]);
|
|
111
|
+
Key::CreateKey<T>(allocator, input.GetType(), keys[i], input_data[idx]);
|
|
107
112
|
}
|
|
108
113
|
}
|
|
109
114
|
}
|
|
@@ -123,7 +128,7 @@ static void ConcatenateKeys(ArenaAllocator &allocator, Vector &input, idx_t coun
|
|
|
123
128
|
// this column entry is NULL, set whole key to NULL
|
|
124
129
|
keys[i] = Key();
|
|
125
130
|
} else {
|
|
126
|
-
auto other_key = Key::CreateKey<T>(allocator, input_data[idx]);
|
|
131
|
+
auto other_key = Key::CreateKey<T>(allocator, input.GetType(), input_data[idx]);
|
|
127
132
|
keys[i].ConcatenateKey(allocator, other_key);
|
|
128
133
|
}
|
|
129
134
|
}
|
|
@@ -225,7 +230,7 @@ void ART::GenerateKeys(ArenaAllocator &allocator, DataChunk &input, vector<Key>
|
|
|
225
230
|
}
|
|
226
231
|
|
|
227
232
|
//===--------------------------------------------------------------------===//
|
|
228
|
-
// Construct from sorted data
|
|
233
|
+
// Construct from sorted data (only during CREATE (UNIQUE) INDEX statements)
|
|
229
234
|
//===--------------------------------------------------------------------===//
|
|
230
235
|
|
|
231
236
|
struct KeySection {
|
|
@@ -283,7 +288,7 @@ bool Construct(ART &art, vector<Key> &keys, row_t *row_ids, Node *&node, KeySect
|
|
|
283
288
|
} else {
|
|
284
289
|
node = Leaf::New(start_key, prefix_start, row_ids + key_section.start, num_row_ids);
|
|
285
290
|
}
|
|
286
|
-
art.
|
|
291
|
+
art.IncreaseMemorySize(node->MemorySize(art, false));
|
|
287
292
|
return true;
|
|
288
293
|
}
|
|
289
294
|
// create a new node and recurse
|
|
@@ -297,7 +302,7 @@ bool Construct(ART &art, vector<Key> &keys, row_t *row_ids, Node *&node, KeySect
|
|
|
297
302
|
|
|
298
303
|
auto prefix_length = key_section.depth - prefix_start;
|
|
299
304
|
node->prefix = Prefix(start_key, prefix_start, prefix_length);
|
|
300
|
-
art.
|
|
305
|
+
art.IncreaseMemorySize(node->MemorySize(art, false));
|
|
301
306
|
|
|
302
307
|
// recurse on each child section
|
|
303
308
|
for (auto &child_section : child_sections) {
|
|
@@ -323,7 +328,7 @@ bool ART::ConstructFromSorted(idx_t count, vector<Key> &keys, Vector &row_identi
|
|
|
323
328
|
}
|
|
324
329
|
|
|
325
330
|
//===--------------------------------------------------------------------===//
|
|
326
|
-
// Insert
|
|
331
|
+
// Insert / Verification / Constraint Checking
|
|
327
332
|
//===--------------------------------------------------------------------===//
|
|
328
333
|
|
|
329
334
|
bool ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) {
|
|
@@ -331,13 +336,13 @@ bool ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) {
|
|
|
331
336
|
D_ASSERT(row_ids.GetType().InternalType() == ROW_TYPE);
|
|
332
337
|
D_ASSERT(logical_types[0] == input.data[0].GetType());
|
|
333
338
|
|
|
339
|
+
auto old_memory_size = memory_size;
|
|
340
|
+
|
|
334
341
|
// generate the keys for the given input
|
|
335
342
|
ArenaAllocator arena_allocator(BufferAllocator::Get(db));
|
|
336
343
|
vector<Key> keys(input.size());
|
|
337
344
|
GenerateKeys(arena_allocator, input, keys);
|
|
338
345
|
|
|
339
|
-
auto old_memory_size = this->memory_size;
|
|
340
|
-
|
|
341
346
|
// get the corresponding row IDs
|
|
342
347
|
row_ids.Flatten(input.size());
|
|
343
348
|
auto row_identifiers = FlatVector::GetData<row_t>(row_ids);
|
|
@@ -356,9 +361,9 @@ bool ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) {
|
|
|
356
361
|
break;
|
|
357
362
|
}
|
|
358
363
|
}
|
|
359
|
-
if (failed_index != DConstants::INVALID_INDEX) {
|
|
360
364
|
|
|
361
|
-
|
|
365
|
+
// failed to insert because of constraint violation: remove previously inserted entries
|
|
366
|
+
if (failed_index != DConstants::INVALID_INDEX) {
|
|
362
367
|
for (idx_t i = 0; i < failed_index; i++) {
|
|
363
368
|
if (keys[i].Empty()) {
|
|
364
369
|
continue;
|
|
@@ -366,14 +371,11 @@ bool ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) {
|
|
|
366
371
|
row_t row_id = row_identifiers[i];
|
|
367
372
|
Erase(tree, keys[i], 0, row_id);
|
|
368
373
|
}
|
|
369
|
-
// nothing changed, no need to update the buffer memory size
|
|
370
|
-
return false;
|
|
371
374
|
}
|
|
372
375
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
buffer_manager.IncreaseUsedMemory(memory_size - old_memory_size);
|
|
376
|
+
IncreaseAndVerifyMemorySize(old_memory_size);
|
|
377
|
+
if (failed_index != DConstants::INVALID_INDEX) {
|
|
378
|
+
return false;
|
|
377
379
|
}
|
|
378
380
|
return true;
|
|
379
381
|
}
|
|
@@ -391,25 +393,12 @@ bool ART::Append(IndexLock &lock, DataChunk &appended_data, Vector &row_identifi
|
|
|
391
393
|
|
|
392
394
|
void ART::VerifyAppend(DataChunk &chunk) {
|
|
393
395
|
ConflictManager conflict_manager(VerifyExistenceType::APPEND, chunk.size());
|
|
394
|
-
|
|
396
|
+
CheckConstraintsForChunk(chunk, conflict_manager);
|
|
395
397
|
}
|
|
396
398
|
|
|
397
399
|
void ART::VerifyAppend(DataChunk &chunk, ConflictManager &conflict_manager) {
|
|
398
400
|
D_ASSERT(conflict_manager.LookupType() == VerifyExistenceType::APPEND);
|
|
399
|
-
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
void ART::VerifyAppendForeignKey(DataChunk &chunk) {
|
|
403
|
-
ConflictManager conflict_manager(VerifyExistenceType::APPEND_FK, chunk.size());
|
|
404
|
-
LookupValues(chunk, conflict_manager);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
void ART::VerifyDeleteForeignKey(DataChunk &chunk) {
|
|
408
|
-
if (!IsUnique()) {
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
ConflictManager conflict_manager(VerifyExistenceType::DELETE_FK, chunk.size());
|
|
412
|
-
LookupValues(chunk, conflict_manager);
|
|
401
|
+
CheckConstraintsForChunk(chunk, conflict_manager);
|
|
413
402
|
}
|
|
414
403
|
|
|
415
404
|
bool ART::InsertToLeaf(Leaf &leaf, row_t row_id) {
|
|
@@ -430,7 +419,7 @@ bool ART::Insert(Node *&node, Key &key, idx_t depth, row_t row_id) {
|
|
|
430
419
|
if (!node) {
|
|
431
420
|
// node is currently empty, create a leaf here with the key
|
|
432
421
|
node = Leaf::New(key, depth, row_id);
|
|
433
|
-
|
|
422
|
+
IncreaseMemorySize(node->MemorySize(*this, false));
|
|
434
423
|
return true;
|
|
435
424
|
}
|
|
436
425
|
|
|
@@ -455,14 +444,14 @@ bool ART::Insert(Node *&node, Key &key, idx_t depth, row_t row_id) {
|
|
|
455
444
|
|
|
456
445
|
Node *new_node = Node4::New();
|
|
457
446
|
new_node->prefix = Prefix(key, depth, new_prefix_length);
|
|
458
|
-
|
|
447
|
+
IncreaseMemorySize(new_node->MemorySize(*this, false));
|
|
459
448
|
|
|
460
449
|
auto key_byte = node->prefix.Reduce(*this, new_prefix_length);
|
|
461
450
|
Node4::InsertChild(*this, new_node, key_byte, node);
|
|
462
451
|
|
|
463
452
|
Node *leaf_node = Leaf::New(key, depth + new_prefix_length + 1, row_id);
|
|
464
453
|
Node4::InsertChild(*this, new_node, key[depth + new_prefix_length], leaf_node);
|
|
465
|
-
|
|
454
|
+
IncreaseMemorySize(leaf_node->MemorySize(*this, false));
|
|
466
455
|
|
|
467
456
|
node = new_node;
|
|
468
457
|
return true;
|
|
@@ -476,7 +465,7 @@ bool ART::Insert(Node *&node, Key &key, idx_t depth, row_t row_id) {
|
|
|
476
465
|
// prefix differs, create new node
|
|
477
466
|
Node *new_node = Node4::New();
|
|
478
467
|
new_node->prefix = Prefix(key, depth, mismatch_pos);
|
|
479
|
-
|
|
468
|
+
IncreaseMemorySize(new_node->MemorySize(*this, false));
|
|
480
469
|
|
|
481
470
|
// break up prefix
|
|
482
471
|
auto key_byte = node->prefix.Reduce(*this, mismatch_pos);
|
|
@@ -484,7 +473,7 @@ bool ART::Insert(Node *&node, Key &key, idx_t depth, row_t row_id) {
|
|
|
484
473
|
|
|
485
474
|
Node *leaf_node = Leaf::New(key, depth + mismatch_pos + 1, row_id);
|
|
486
475
|
Node4::InsertChild(*this, new_node, key[depth + mismatch_pos], leaf_node);
|
|
487
|
-
|
|
476
|
+
IncreaseMemorySize(leaf_node->MemorySize(*this, false));
|
|
488
477
|
|
|
489
478
|
node = new_node;
|
|
490
479
|
return true;
|
|
@@ -504,7 +493,7 @@ bool ART::Insert(Node *&node, Key &key, idx_t depth, row_t row_id) {
|
|
|
504
493
|
|
|
505
494
|
Node *leaf_node = Leaf::New(key, depth + 1, row_id);
|
|
506
495
|
Node::InsertChild(*this, node, key[depth], leaf_node);
|
|
507
|
-
|
|
496
|
+
IncreaseMemorySize(leaf_node->MemorySize(*this, false));
|
|
508
497
|
return true;
|
|
509
498
|
}
|
|
510
499
|
|
|
@@ -525,7 +514,7 @@ void ART::Delete(IndexLock &state, DataChunk &input, Vector &row_ids) {
|
|
|
525
514
|
vector<Key> keys(expression.size());
|
|
526
515
|
GenerateKeys(arena_allocator, expression, keys);
|
|
527
516
|
|
|
528
|
-
auto old_memory_size =
|
|
517
|
+
auto old_memory_size = memory_size;
|
|
529
518
|
|
|
530
519
|
// now erase the elements from the database
|
|
531
520
|
row_ids.Flatten(input.size());
|
|
@@ -547,10 +536,13 @@ void ART::Delete(IndexLock &state, DataChunk &input, Vector &row_ids) {
|
|
|
547
536
|
#endif
|
|
548
537
|
}
|
|
549
538
|
|
|
550
|
-
|
|
539
|
+
// if we deserialize nodes while erasing, then we might end up with more
|
|
540
|
+
// memory afterwards, so we have to either increase or decrease the used memory
|
|
551
541
|
Verify();
|
|
552
|
-
if (track_memory) {
|
|
542
|
+
if (track_memory && old_memory_size >= memory_size) {
|
|
553
543
|
buffer_manager.DecreaseUsedMemory(old_memory_size - memory_size);
|
|
544
|
+
} else if (track_memory) {
|
|
545
|
+
buffer_manager.IncreaseUsedMemory(memory_size - old_memory_size);
|
|
554
546
|
}
|
|
555
547
|
}
|
|
556
548
|
|
|
@@ -566,8 +558,7 @@ void ART::Erase(Node *&node, Key &key, idx_t depth, row_t row_id) {
|
|
|
566
558
|
leaf->Remove(*this, row_id);
|
|
567
559
|
|
|
568
560
|
if (leaf->count == 0) {
|
|
569
|
-
|
|
570
|
-
this->memory_size -= leaf->MemorySize(*this, false);
|
|
561
|
+
DecreaseMemorySize(leaf->MemorySize(*this, false));
|
|
571
562
|
Node::Delete(node);
|
|
572
563
|
node = nullptr;
|
|
573
564
|
}
|
|
@@ -606,38 +597,38 @@ void ART::Erase(Node *&node, Key &key, idx_t depth, row_t row_id) {
|
|
|
606
597
|
}
|
|
607
598
|
|
|
608
599
|
//===--------------------------------------------------------------------===//
|
|
609
|
-
// Point Query
|
|
600
|
+
// Point Query (Equal)
|
|
610
601
|
//===--------------------------------------------------------------------===//
|
|
611
602
|
|
|
612
603
|
static Key CreateKey(ArenaAllocator &allocator, PhysicalType type, Value &value) {
|
|
613
604
|
D_ASSERT(type == value.type().InternalType());
|
|
614
605
|
switch (type) {
|
|
615
606
|
case PhysicalType::BOOL:
|
|
616
|
-
return Key::CreateKey<bool>(allocator, value);
|
|
607
|
+
return Key::CreateKey<bool>(allocator, value.type(), value);
|
|
617
608
|
case PhysicalType::INT8:
|
|
618
|
-
return Key::CreateKey<int8_t>(allocator, value);
|
|
609
|
+
return Key::CreateKey<int8_t>(allocator, value.type(), value);
|
|
619
610
|
case PhysicalType::INT16:
|
|
620
|
-
return Key::CreateKey<int16_t>(allocator, value);
|
|
611
|
+
return Key::CreateKey<int16_t>(allocator, value.type(), value);
|
|
621
612
|
case PhysicalType::INT32:
|
|
622
|
-
return Key::CreateKey<int32_t>(allocator, value);
|
|
613
|
+
return Key::CreateKey<int32_t>(allocator, value.type(), value);
|
|
623
614
|
case PhysicalType::INT64:
|
|
624
|
-
return Key::CreateKey<int64_t>(allocator, value);
|
|
615
|
+
return Key::CreateKey<int64_t>(allocator, value.type(), value);
|
|
625
616
|
case PhysicalType::UINT8:
|
|
626
|
-
return Key::CreateKey<uint8_t>(allocator, value);
|
|
617
|
+
return Key::CreateKey<uint8_t>(allocator, value.type(), value);
|
|
627
618
|
case PhysicalType::UINT16:
|
|
628
|
-
return Key::CreateKey<uint16_t>(allocator, value);
|
|
619
|
+
return Key::CreateKey<uint16_t>(allocator, value.type(), value);
|
|
629
620
|
case PhysicalType::UINT32:
|
|
630
|
-
return Key::CreateKey<uint32_t>(allocator, value);
|
|
621
|
+
return Key::CreateKey<uint32_t>(allocator, value.type(), value);
|
|
631
622
|
case PhysicalType::UINT64:
|
|
632
|
-
return Key::CreateKey<uint64_t>(allocator, value);
|
|
623
|
+
return Key::CreateKey<uint64_t>(allocator, value.type(), value);
|
|
633
624
|
case PhysicalType::INT128:
|
|
634
|
-
return Key::CreateKey<hugeint_t>(allocator, value);
|
|
625
|
+
return Key::CreateKey<hugeint_t>(allocator, value.type(), value);
|
|
635
626
|
case PhysicalType::FLOAT:
|
|
636
|
-
return Key::CreateKey<float>(allocator, value);
|
|
627
|
+
return Key::CreateKey<float>(allocator, value.type(), value);
|
|
637
628
|
case PhysicalType::DOUBLE:
|
|
638
|
-
return Key::CreateKey<double>(allocator, value);
|
|
629
|
+
return Key::CreateKey<double>(allocator, value.type(), value);
|
|
639
630
|
case PhysicalType::VARCHAR:
|
|
640
|
-
return Key::CreateKey<string_t>(allocator, value);
|
|
631
|
+
return Key::CreateKey<string_t>(allocator, value.type(), value);
|
|
641
632
|
default:
|
|
642
633
|
throw InternalException("Invalid type for index");
|
|
643
634
|
}
|
|
@@ -645,7 +636,10 @@ static Key CreateKey(ArenaAllocator &allocator, PhysicalType type, Value &value)
|
|
|
645
636
|
|
|
646
637
|
bool ART::SearchEqual(Key &key, idx_t max_count, vector<row_t> &result_ids) {
|
|
647
638
|
|
|
639
|
+
auto old_memory_size = memory_size;
|
|
648
640
|
auto leaf = (Leaf *)(Lookup(tree, key, 0));
|
|
641
|
+
IncreaseAndVerifyMemorySize(old_memory_size);
|
|
642
|
+
|
|
649
643
|
if (!leaf) {
|
|
650
644
|
return true;
|
|
651
645
|
}
|
|
@@ -662,19 +656,28 @@ bool ART::SearchEqual(Key &key, idx_t max_count, vector<row_t> &result_ids) {
|
|
|
662
656
|
void ART::SearchEqualJoinNoFetch(Key &key, idx_t &result_size) {
|
|
663
657
|
|
|
664
658
|
// we need to look for a leaf
|
|
659
|
+
auto old_memory_size = memory_size;
|
|
665
660
|
auto leaf = Lookup(tree, key, 0);
|
|
661
|
+
IncreaseAndVerifyMemorySize(old_memory_size);
|
|
662
|
+
|
|
666
663
|
if (!leaf) {
|
|
667
664
|
return;
|
|
668
665
|
}
|
|
669
666
|
result_size = leaf->count;
|
|
670
667
|
}
|
|
671
668
|
|
|
669
|
+
//===--------------------------------------------------------------------===//
|
|
670
|
+
// Lookup
|
|
671
|
+
//===--------------------------------------------------------------------===//
|
|
672
|
+
|
|
672
673
|
Leaf *ART::Lookup(Node *node, Key &key, idx_t depth) {
|
|
674
|
+
|
|
673
675
|
while (node) {
|
|
674
676
|
if (node->type == NodeType::NLeaf) {
|
|
675
677
|
auto leaf = (Leaf *)node;
|
|
676
678
|
auto &leaf_prefix = leaf->prefix;
|
|
677
|
-
|
|
679
|
+
|
|
680
|
+
// check if leaf contains key
|
|
678
681
|
for (idx_t i = 0; i < leaf->prefix.Size(); i++) {
|
|
679
682
|
if (leaf_prefix[i] != key[i + depth]) {
|
|
680
683
|
return nullptr;
|
|
@@ -682,22 +685,29 @@ Leaf *ART::Lookup(Node *node, Key &key, idx_t depth) {
|
|
|
682
685
|
}
|
|
683
686
|
return (Leaf *)node;
|
|
684
687
|
}
|
|
688
|
+
|
|
685
689
|
if (node->prefix.Size()) {
|
|
686
690
|
for (idx_t pos = 0; pos < node->prefix.Size(); pos++) {
|
|
687
691
|
if (key[depth + pos] != node->prefix[pos]) {
|
|
692
|
+
// prefix mismatch, does not contain key
|
|
688
693
|
return nullptr;
|
|
689
694
|
}
|
|
690
695
|
}
|
|
691
696
|
depth += node->prefix.Size();
|
|
692
697
|
}
|
|
698
|
+
|
|
699
|
+
// prefix matches key, but no child at byte, does not contain key
|
|
693
700
|
idx_t pos = node->GetChildPos(key[depth]);
|
|
694
701
|
if (pos == DConstants::INVALID_INDEX) {
|
|
695
702
|
return nullptr;
|
|
696
703
|
}
|
|
704
|
+
|
|
705
|
+
// recurse into child
|
|
697
706
|
node = node->GetChild(*this, pos);
|
|
698
707
|
D_ASSERT(node);
|
|
699
708
|
depth++;
|
|
700
709
|
}
|
|
710
|
+
|
|
701
711
|
return nullptr;
|
|
702
712
|
}
|
|
703
713
|
|
|
@@ -710,6 +720,7 @@ Leaf *ART::Lookup(Node *node, Key &key, idx_t depth) {
|
|
|
710
720
|
bool ART::SearchGreater(ARTIndexScanState *state, Key &key, bool inclusive, idx_t max_count,
|
|
711
721
|
vector<row_t> &result_ids) {
|
|
712
722
|
|
|
723
|
+
auto old_memory_size = memory_size;
|
|
713
724
|
Iterator *it = &state->iterator;
|
|
714
725
|
|
|
715
726
|
// greater than scan: first set the iterator to the node at which we will start our scan by finding the lowest node
|
|
@@ -718,13 +729,16 @@ bool ART::SearchGreater(ARTIndexScanState *state, Key &key, bool inclusive, idx_
|
|
|
718
729
|
it->art = this;
|
|
719
730
|
bool found = it->LowerBound(tree, key, inclusive);
|
|
720
731
|
if (!found) {
|
|
732
|
+
IncreaseAndVerifyMemorySize(old_memory_size);
|
|
721
733
|
return true;
|
|
722
734
|
}
|
|
723
735
|
}
|
|
724
736
|
// after that we continue the scan; we don't need to check the bounds as any value following this value is
|
|
725
737
|
// automatically bigger and hence satisfies our predicate
|
|
726
738
|
Key empty_key = Key();
|
|
727
|
-
|
|
739
|
+
auto success = it->Scan(empty_key, max_count, result_ids, false);
|
|
740
|
+
IncreaseAndVerifyMemorySize(old_memory_size);
|
|
741
|
+
return success;
|
|
728
742
|
}
|
|
729
743
|
|
|
730
744
|
//===--------------------------------------------------------------------===//
|
|
@@ -738,6 +752,7 @@ bool ART::SearchLess(ARTIndexScanState *state, Key &upper_bound, bool inclusive,
|
|
|
738
752
|
return true;
|
|
739
753
|
}
|
|
740
754
|
|
|
755
|
+
auto old_memory_size = memory_size;
|
|
741
756
|
Iterator *it = &state->iterator;
|
|
742
757
|
|
|
743
758
|
if (!it->art) {
|
|
@@ -746,11 +761,14 @@ bool ART::SearchLess(ARTIndexScanState *state, Key &upper_bound, bool inclusive,
|
|
|
746
761
|
it->FindMinimum(*tree);
|
|
747
762
|
// early out min value higher than upper bound query
|
|
748
763
|
if (it->cur_key > upper_bound) {
|
|
764
|
+
IncreaseAndVerifyMemorySize(old_memory_size);
|
|
749
765
|
return true;
|
|
750
766
|
}
|
|
751
767
|
}
|
|
752
768
|
// now continue the scan until we reach the upper bound
|
|
753
|
-
|
|
769
|
+
auto success = it->Scan(upper_bound, max_count, result_ids, inclusive);
|
|
770
|
+
IncreaseAndVerifyMemorySize(old_memory_size);
|
|
771
|
+
return success;
|
|
754
772
|
}
|
|
755
773
|
|
|
756
774
|
//===--------------------------------------------------------------------===//
|
|
@@ -760,6 +778,7 @@ bool ART::SearchLess(ARTIndexScanState *state, Key &upper_bound, bool inclusive,
|
|
|
760
778
|
bool ART::SearchCloseRange(ARTIndexScanState *state, Key &lower_bound, Key &upper_bound, bool left_inclusive,
|
|
761
779
|
bool right_inclusive, idx_t max_count, vector<row_t> &result_ids) {
|
|
762
780
|
|
|
781
|
+
auto old_memory_size = memory_size;
|
|
763
782
|
Iterator *it = &state->iterator;
|
|
764
783
|
|
|
765
784
|
// first find the first node that satisfies the left predicate
|
|
@@ -767,11 +786,14 @@ bool ART::SearchCloseRange(ARTIndexScanState *state, Key &lower_bound, Key &uppe
|
|
|
767
786
|
it->art = this;
|
|
768
787
|
bool found = it->LowerBound(tree, lower_bound, left_inclusive);
|
|
769
788
|
if (!found) {
|
|
789
|
+
IncreaseAndVerifyMemorySize(old_memory_size);
|
|
770
790
|
return true;
|
|
771
791
|
}
|
|
772
792
|
}
|
|
773
793
|
// now continue the scan until we reach the upper bound
|
|
774
|
-
|
|
794
|
+
auto success = it->Scan(upper_bound, max_count, result_ids, right_inclusive);
|
|
795
|
+
IncreaseAndVerifyMemorySize(old_memory_size);
|
|
796
|
+
return success;
|
|
775
797
|
}
|
|
776
798
|
|
|
777
799
|
bool ART::Scan(Transaction &transaction, DataTable &table, IndexScanState &table_state, idx_t max_count,
|
|
@@ -844,8 +866,15 @@ bool ART::Scan(Transaction &transaction, DataTable &table, IndexScanState &table
|
|
|
844
866
|
return true;
|
|
845
867
|
}
|
|
846
868
|
|
|
869
|
+
//===--------------------------------------------------------------------===//
|
|
870
|
+
// More Verification / Constraint Checking
|
|
871
|
+
//===--------------------------------------------------------------------===//
|
|
872
|
+
|
|
847
873
|
string ART::GenerateErrorKeyName(DataChunk &input, idx_t row) {
|
|
848
|
-
|
|
874
|
+
|
|
875
|
+
// FIXME: why exactly can we not pass the expression_chunk as an argument to this
|
|
876
|
+
// FIXME: function instead of re-executing?
|
|
877
|
+
// re-executing the expressions is not very fast, but we're going to throw, so we don't care
|
|
849
878
|
DataChunk expression_chunk;
|
|
850
879
|
expression_chunk.Initialize(Allocator::DefaultAllocator(), logical_types);
|
|
851
880
|
ExecuteExpressions(input, expression_chunk);
|
|
@@ -883,11 +912,13 @@ string ART::GenerateConstraintErrorMessage(VerifyExistenceType verify_type, cons
|
|
|
883
912
|
}
|
|
884
913
|
}
|
|
885
914
|
|
|
886
|
-
void ART::
|
|
915
|
+
void ART::CheckConstraintsForChunk(DataChunk &input, ConflictManager &conflict_manager) {
|
|
887
916
|
|
|
888
917
|
// don't alter the index during constraint checking
|
|
889
918
|
lock_guard<mutex> l(lock);
|
|
890
919
|
|
|
920
|
+
auto old_memory_size = memory_size;
|
|
921
|
+
|
|
891
922
|
// first resolve the expressions for the index
|
|
892
923
|
DataChunk expression_chunk;
|
|
893
924
|
expression_chunk.Initialize(Allocator::DefaultAllocator(), logical_types);
|
|
@@ -900,12 +931,14 @@ void ART::LookupValues(DataChunk &input, ConflictManager &conflict_manager) {
|
|
|
900
931
|
|
|
901
932
|
idx_t found_conflict = DConstants::INVALID_INDEX;
|
|
902
933
|
for (idx_t i = 0; found_conflict == DConstants::INVALID_INDEX && i < input.size(); i++) {
|
|
934
|
+
|
|
903
935
|
if (keys[i].Empty()) {
|
|
904
936
|
if (conflict_manager.AddNull(i)) {
|
|
905
937
|
found_conflict = i;
|
|
906
938
|
}
|
|
907
939
|
continue;
|
|
908
940
|
}
|
|
941
|
+
|
|
909
942
|
Leaf *leaf_ptr = Lookup(tree, keys[i], 0);
|
|
910
943
|
if (leaf_ptr == nullptr) {
|
|
911
944
|
if (conflict_manager.AddMiss(i)) {
|
|
@@ -913,6 +946,7 @@ void ART::LookupValues(DataChunk &input, ConflictManager &conflict_manager) {
|
|
|
913
946
|
}
|
|
914
947
|
continue;
|
|
915
948
|
}
|
|
949
|
+
|
|
916
950
|
// When we find a node, we need to update the 'matches' and 'row_ids'
|
|
917
951
|
// NOTE: Leafs can have more than one row_id, but for UNIQUE/PRIMARY KEY they will only have one
|
|
918
952
|
D_ASSERT(leaf_ptr->count == 1);
|
|
@@ -921,11 +955,15 @@ void ART::LookupValues(DataChunk &input, ConflictManager &conflict_manager) {
|
|
|
921
955
|
found_conflict = i;
|
|
922
956
|
}
|
|
923
957
|
}
|
|
958
|
+
|
|
924
959
|
conflict_manager.FinishLookup();
|
|
960
|
+
IncreaseAndVerifyMemorySize(old_memory_size);
|
|
961
|
+
|
|
925
962
|
if (found_conflict == DConstants::INVALID_INDEX) {
|
|
926
963
|
// No conflicts detected
|
|
927
964
|
return;
|
|
928
965
|
}
|
|
966
|
+
|
|
929
967
|
auto key_name = GenerateErrorKeyName(input, found_conflict);
|
|
930
968
|
auto exception_msg = GenerateConstraintErrorMessage(conflict_manager.LookupType(), key_name);
|
|
931
969
|
throw ConstraintException(exception_msg);
|
|
@@ -935,13 +973,15 @@ void ART::LookupValues(DataChunk &input, ConflictManager &conflict_manager) {
|
|
|
935
973
|
// Serialization
|
|
936
974
|
//===--------------------------------------------------------------------===//
|
|
937
975
|
|
|
938
|
-
BlockPointer ART::Serialize(
|
|
976
|
+
BlockPointer ART::Serialize(MetaBlockWriter &writer) {
|
|
939
977
|
lock_guard<mutex> l(lock);
|
|
978
|
+
auto old_memory_size = memory_size;
|
|
940
979
|
if (tree) {
|
|
941
980
|
serialized_data_pointer = tree->Serialize(*this, writer);
|
|
942
981
|
} else {
|
|
943
982
|
serialized_data_pointer = {(block_id_t)DConstants::INVALID_INDEX, (uint32_t)DConstants::INVALID_INDEX};
|
|
944
983
|
}
|
|
984
|
+
IncreaseAndVerifyMemorySize(old_memory_size);
|
|
945
985
|
return serialized_data_pointer;
|
|
946
986
|
}
|
|
947
987
|
|
|
@@ -954,8 +994,8 @@ bool ART::MergeIndexes(IndexLock &state, Index *other_index) {
|
|
|
954
994
|
auto other_art = (ART *)other_index;
|
|
955
995
|
|
|
956
996
|
if (!this->tree) {
|
|
957
|
-
|
|
958
|
-
|
|
997
|
+
IncreaseMemorySize(other_art->memory_size);
|
|
998
|
+
tree = other_art->tree;
|
|
959
999
|
other_art->tree = nullptr;
|
|
960
1000
|
return true;
|
|
961
1001
|
}
|
|
@@ -987,4 +1027,14 @@ void ART::Verify() {
|
|
|
987
1027
|
#endif
|
|
988
1028
|
}
|
|
989
1029
|
|
|
1030
|
+
void ART::IncreaseAndVerifyMemorySize(idx_t old_memory_size) {
|
|
1031
|
+
// since we lazily deserialize ART nodes, it is possible that its in-memory size
|
|
1032
|
+
// increased during lookups
|
|
1033
|
+
Verify();
|
|
1034
|
+
D_ASSERT(memory_size >= old_memory_size);
|
|
1035
|
+
if (track_memory) {
|
|
1036
|
+
buffer_manager.IncreaseUsedMemory(memory_size - old_memory_size);
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
|
|
990
1040
|
} // namespace duckdb
|
|
@@ -15,40 +15,52 @@ Key::Key(ArenaAllocator &allocator, idx_t len) : len(len) {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
template <>
|
|
18
|
-
Key Key::CreateKey(ArenaAllocator &allocator, string_t value) {
|
|
18
|
+
Key Key::CreateKey(ArenaAllocator &allocator, const LogicalType &type, string_t value) {
|
|
19
19
|
idx_t len = value.GetSize() + 1;
|
|
20
20
|
auto data = allocator.Allocate(len);
|
|
21
21
|
memcpy(data, value.GetDataUnsafe(), len - 1);
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
// FIXME: rethink this
|
|
24
|
+
if (type == LogicalType::BLOB || type == LogicalType::VARCHAR) {
|
|
25
|
+
// indexes cannot contain BLOBs (or BLOBs cast to VARCHARs) that contain null-terminated bytes
|
|
26
|
+
for (idx_t i = 0; i < len - 1; i++) {
|
|
27
|
+
if (data[i] == '\0') {
|
|
28
|
+
throw NotImplementedException("Indexes cannot contain BLOBs that contain null-terminated bytes.");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
26
31
|
}
|
|
32
|
+
|
|
27
33
|
data[len - 1] = '\0';
|
|
28
34
|
return Key(data, len);
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
template <>
|
|
32
|
-
Key Key::CreateKey(ArenaAllocator &allocator, const char *value) {
|
|
33
|
-
return Key::CreateKey(allocator, string_t(value, strlen(value)));
|
|
38
|
+
Key Key::CreateKey(ArenaAllocator &allocator, const LogicalType &type, const char *value) {
|
|
39
|
+
return Key::CreateKey(allocator, type, string_t(value, strlen(value)));
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
template <>
|
|
37
|
-
void Key::CreateKey(ArenaAllocator &allocator, Key &key, string_t value) {
|
|
43
|
+
void Key::CreateKey(ArenaAllocator &allocator, const LogicalType &type, Key &key, string_t value) {
|
|
38
44
|
key.len = value.GetSize() + 1;
|
|
39
45
|
key.data = allocator.Allocate(key.len);
|
|
40
46
|
memcpy(key.data, value.GetDataUnsafe(), key.len - 1);
|
|
41
47
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
// FIXME: rethink this
|
|
49
|
+
if (type == LogicalType::BLOB || type == LogicalType::VARCHAR) {
|
|
50
|
+
// indexes cannot contain BLOBs (or BLOBs cast to VARCHARs) that contain null-terminated bytes
|
|
51
|
+
for (idx_t i = 0; i < key.len - 1; i++) {
|
|
52
|
+
if (key.data[i] == '\0') {
|
|
53
|
+
throw NotImplementedException("Indexes cannot contain BLOBs that contain null-terminated bytes.");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
45
56
|
}
|
|
57
|
+
|
|
46
58
|
key.data[key.len - 1] = '\0';
|
|
47
59
|
}
|
|
48
60
|
|
|
49
61
|
template <>
|
|
50
|
-
void Key::CreateKey(ArenaAllocator &allocator, Key &key, const char *value) {
|
|
51
|
-
Key::CreateKey(allocator, key, string_t(value, strlen(value)));
|
|
62
|
+
void Key::CreateKey(ArenaAllocator &allocator, const LogicalType &type, Key &key, const char *value) {
|
|
63
|
+
Key::CreateKey(allocator, type, key, string_t(value, strlen(value)));
|
|
52
64
|
}
|
|
53
65
|
|
|
54
66
|
bool Key::operator>(const Key &k) const {
|
|
@@ -109,9 +109,9 @@ void Leaf::Insert(ART &art, row_t row_id) {
|
|
|
109
109
|
if (count == capacity) {
|
|
110
110
|
// grow array
|
|
111
111
|
if (IsInlined()) {
|
|
112
|
-
art.
|
|
112
|
+
art.IncreaseMemorySize((capacity + 1) * sizeof(row_t));
|
|
113
113
|
} else {
|
|
114
|
-
art.
|
|
114
|
+
art.IncreaseMemorySize(capacity * sizeof(row_t));
|
|
115
115
|
}
|
|
116
116
|
row_ids = Resize(row_ids, count, capacity * 2);
|
|
117
117
|
}
|
|
@@ -143,6 +143,7 @@ void Leaf::Remove(ART &art, row_t row_id) {
|
|
|
143
143
|
return;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
auto capacity = GetCapacity();
|
|
146
147
|
count--;
|
|
147
148
|
if (count == 1) {
|
|
148
149
|
// after erasing we can now inline the leaf
|
|
@@ -150,18 +151,16 @@ void Leaf::Remove(ART &art, row_t row_id) {
|
|
|
150
151
|
auto remaining_row_id = row_ids[0] == row_id ? row_ids[1] : row_ids[0];
|
|
151
152
|
DeleteArray<row_t>(rowids.ptr, rowids.ptr[0] + 1);
|
|
152
153
|
rowids.inlined = remaining_row_id;
|
|
153
|
-
|
|
154
|
-
art.memory_size -= 2 * sizeof(row_t);
|
|
154
|
+
art.DecreaseMemorySize(capacity * sizeof(row_t));
|
|
155
155
|
return;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
// shrink array, if less than half full
|
|
159
|
-
|
|
159
|
+
capacity = GetCapacity();
|
|
160
160
|
if (capacity > 2 && count < capacity / 2) {
|
|
161
161
|
|
|
162
162
|
auto new_capacity = capacity / 2;
|
|
163
|
-
|
|
164
|
-
art.memory_size -= (capacity - new_capacity) * sizeof(row_t);
|
|
163
|
+
art.DecreaseMemorySize((capacity - new_capacity) * sizeof(row_t));
|
|
165
164
|
|
|
166
165
|
auto new_allocation = AllocateArray<row_t>(new_capacity + 1);
|
|
167
166
|
new_allocation[0] = new_capacity;
|
|
@@ -200,7 +199,7 @@ void Leaf::Merge(ART &art, Node *&l_node, Node *&r_node) {
|
|
|
200
199
|
if (l_n->count + r_n->count > l_capacity) {
|
|
201
200
|
auto capacity = l_n->GetCapacity();
|
|
202
201
|
auto new_capacity = NextPowerOfTwo(l_n->count + r_n->count);
|
|
203
|
-
art.
|
|
202
|
+
art.IncreaseMemorySize(sizeof(row_t) * (new_capacity - capacity));
|
|
204
203
|
l_row_ids = l_n->Resize(l_row_ids, l_n->count, new_capacity);
|
|
205
204
|
}
|
|
206
205
|
|