duckdb 0.6.2-dev1794.0 → 0.6.2-dev1830.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/catalog/catalog_entry/table_catalog_entry.cpp +2 -2
- package/src/duckdb/src/execution/index/art/art.cpp +146 -85
- package/src/duckdb/src/execution/index/art/leaf.cpp +58 -22
- package/src/duckdb/src/execution/index/art/node.cpp +148 -62
- package/src/duckdb/src/execution/index/art/node16.cpp +49 -20
- package/src/duckdb/src/execution/index/art/node256.cpp +40 -15
- package/src/duckdb/src/execution/index/art/node4.cpp +49 -19
- package/src/duckdb/src/execution/index/art/node48.cpp +53 -21
- package/src/duckdb/src/execution/index/art/prefix.cpp +24 -10
- package/src/duckdb/src/execution/index/art/swizzleable_pointer.cpp +3 -0
- package/src/duckdb/src/execution/operator/schema/physical_create_index.cpp +13 -11
- package/src/duckdb/src/execution/physical_plan/plan_create_index.cpp +3 -5
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +10 -12
- package/src/duckdb/src/include/duckdb/execution/index/art/leaf.hpp +17 -8
- package/src/duckdb/src/include/duckdb/execution/index/art/node.hpp +16 -6
- package/src/duckdb/src/include/duckdb/execution/index/art/node16.hpp +13 -3
- package/src/duckdb/src/include/duckdb/execution/index/art/node256.hpp +12 -3
- package/src/duckdb/src/include/duckdb/execution/index/art/node4.hpp +14 -6
- package/src/duckdb/src/include/duckdb/execution/index/art/node48.hpp +12 -3
- package/src/duckdb/src/include/duckdb/execution/index/art/prefix.hpp +23 -19
- package/src/duckdb/src/include/duckdb/execution/index/art/swizzleable_pointer.hpp +4 -4
- package/src/duckdb/src/include/duckdb/storage/buffer_manager.hpp +7 -0
- package/src/duckdb/src/include/duckdb/storage/index.hpp +16 -5
- package/src/duckdb/src/storage/buffer_manager.cpp +12 -0
- package/src/duckdb/src/storage/checkpoint_manager.cpp +1 -1
- package/src/duckdb/src/storage/index.cpp +7 -3
- package/src/duckdb/src/storage/local_storage.cpp +1 -1
package/package.json
CHANGED
|
@@ -65,10 +65,10 @@ void AddDataTableIndex(DataTable *storage, const ColumnList &columns, const vect
|
|
|
65
65
|
// create an adaptive radix tree around the expressions
|
|
66
66
|
if (index_block) {
|
|
67
67
|
art = make_unique<ART>(column_ids, TableIOManager::Get(*storage), std::move(unbound_expressions),
|
|
68
|
-
constraint_type, storage->db, index_block->block_id, index_block->offset);
|
|
68
|
+
constraint_type, storage->db, true, index_block->block_id, index_block->offset);
|
|
69
69
|
} else {
|
|
70
70
|
art = make_unique<ART>(column_ids, TableIOManager::Get(*storage), std::move(unbound_expressions),
|
|
71
|
-
constraint_type, storage->db);
|
|
71
|
+
constraint_type, storage->db, true);
|
|
72
72
|
if (!storage->IsRoot()) {
|
|
73
73
|
throw TransactionException("Transaction conflict: cannot add an index to a table that has been altered!");
|
|
74
74
|
}
|
|
@@ -15,66 +15,61 @@ namespace duckdb {
|
|
|
15
15
|
|
|
16
16
|
ART::ART(const vector<column_t> &column_ids, TableIOManager &table_io_manager,
|
|
17
17
|
const vector<unique_ptr<Expression>> &unbound_expressions, IndexConstraintType constraint_type,
|
|
18
|
-
AttachedDatabase &db, idx_t block_id, idx_t block_offset)
|
|
18
|
+
AttachedDatabase &db, bool track_memory, idx_t block_id, idx_t block_offset)
|
|
19
19
|
|
|
20
|
-
: Index(IndexType::ART, table_io_manager, column_ids, unbound_expressions, constraint_type
|
|
21
|
-
estimated_art_size(0), estimated_key_size(16) {
|
|
20
|
+
: Index(db, IndexType::ART, table_io_manager, column_ids, unbound_expressions, constraint_type, track_memory) {
|
|
22
21
|
|
|
23
22
|
if (!Radix::IsLittleEndian()) {
|
|
24
23
|
throw NotImplementedException("ART indexes are not supported on big endian architectures");
|
|
25
24
|
}
|
|
26
25
|
|
|
26
|
+
// set the root node of the tree
|
|
27
|
+
tree = nullptr;
|
|
27
28
|
if (block_id != DConstants::INVALID_INDEX) {
|
|
28
29
|
tree = Node::Deserialize(*this, block_id, block_offset);
|
|
29
|
-
|
|
30
|
-
tree = nullptr;
|
|
30
|
+
Verify();
|
|
31
31
|
}
|
|
32
|
-
|
|
33
32
|
serialized_data_pointer = BlockPointer(block_id, block_offset);
|
|
33
|
+
|
|
34
|
+
// validate the types of the key columns
|
|
34
35
|
for (idx_t i = 0; i < types.size(); i++) {
|
|
35
36
|
switch (types[i]) {
|
|
36
37
|
case PhysicalType::BOOL:
|
|
37
38
|
case PhysicalType::INT8:
|
|
38
|
-
case PhysicalType::UINT8:
|
|
39
|
-
estimated_key_size += sizeof(int8_t);
|
|
40
|
-
break;
|
|
41
39
|
case PhysicalType::INT16:
|
|
42
|
-
case PhysicalType::UINT16:
|
|
43
|
-
estimated_key_size += sizeof(int16_t);
|
|
44
|
-
break;
|
|
45
40
|
case PhysicalType::INT32:
|
|
46
|
-
case PhysicalType::UINT32:
|
|
47
|
-
case PhysicalType::FLOAT:
|
|
48
|
-
estimated_key_size += sizeof(int32_t);
|
|
49
|
-
break;
|
|
50
41
|
case PhysicalType::INT64:
|
|
42
|
+
case PhysicalType::INT128:
|
|
43
|
+
case PhysicalType::UINT8:
|
|
44
|
+
case PhysicalType::UINT16:
|
|
45
|
+
case PhysicalType::UINT32:
|
|
51
46
|
case PhysicalType::UINT64:
|
|
47
|
+
case PhysicalType::FLOAT:
|
|
52
48
|
case PhysicalType::DOUBLE:
|
|
53
|
-
estimated_key_size += sizeof(int64_t);
|
|
54
|
-
break;
|
|
55
|
-
case PhysicalType::INT128:
|
|
56
|
-
estimated_key_size += sizeof(hugeint_t);
|
|
57
|
-
break;
|
|
58
49
|
case PhysicalType::VARCHAR:
|
|
59
|
-
estimated_key_size += 16; // oh well
|
|
60
50
|
break;
|
|
61
51
|
default:
|
|
62
|
-
throw InvalidTypeException(logical_types[i], "Invalid type for index");
|
|
52
|
+
throw InvalidTypeException(logical_types[i], "Invalid type for index key.");
|
|
63
53
|
}
|
|
64
54
|
}
|
|
65
55
|
}
|
|
66
56
|
|
|
67
57
|
ART::~ART() {
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
estimated_art_size = 0;
|
|
58
|
+
if (!tree) {
|
|
59
|
+
return;
|
|
71
60
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
61
|
+
Verify();
|
|
62
|
+
if (track_memory) {
|
|
63
|
+
buffer_manager.DecreaseUsedMemory(memory_size);
|
|
75
64
|
}
|
|
65
|
+
Node::Delete(tree);
|
|
66
|
+
tree = nullptr;
|
|
76
67
|
}
|
|
77
68
|
|
|
69
|
+
//===--------------------------------------------------------------------===//
|
|
70
|
+
// Initialize Predicate Scans
|
|
71
|
+
//===--------------------------------------------------------------------===//
|
|
72
|
+
|
|
78
73
|
unique_ptr<IndexScanState> ART::InitializeScanSinglePredicate(Transaction &transaction, Value value,
|
|
79
74
|
ExpressionType expression_type) {
|
|
80
75
|
auto result = make_unique<ARTIndexScanState>();
|
|
@@ -230,7 +225,7 @@ void ART::GenerateKeys(ArenaAllocator &allocator, DataChunk &input, vector<Key>
|
|
|
230
225
|
}
|
|
231
226
|
|
|
232
227
|
//===--------------------------------------------------------------------===//
|
|
233
|
-
//
|
|
228
|
+
// Construct from sorted data
|
|
234
229
|
//===--------------------------------------------------------------------===//
|
|
235
230
|
|
|
236
231
|
struct KeySection {
|
|
@@ -256,7 +251,8 @@ void GetChildSections(vector<KeySection> &child_sections, vector<Key> &keys, Key
|
|
|
256
251
|
child_sections.emplace_back(child_start_idx, key_section.end, keys, key_section);
|
|
257
252
|
}
|
|
258
253
|
|
|
259
|
-
void Construct(vector<Key> &keys, row_t *row_ids, Node *&node, KeySection &key_section,
|
|
254
|
+
void Construct(ART &art, vector<Key> &keys, row_t *row_ids, Node *&node, KeySection &key_section,
|
|
255
|
+
bool &has_constraint) {
|
|
260
256
|
|
|
261
257
|
D_ASSERT(key_section.start < keys.size());
|
|
262
258
|
D_ASSERT(key_section.end < keys.size());
|
|
@@ -284,9 +280,11 @@ void Construct(vector<Key> &keys, row_t *row_ids, Node *&node, KeySection &key_s
|
|
|
284
280
|
|
|
285
281
|
if (single_row_id) {
|
|
286
282
|
node = Leaf::New(start_key, prefix_start, row_ids[key_section.start]);
|
|
283
|
+
art.memory_size += node->MemorySize(art, false);
|
|
287
284
|
return;
|
|
288
285
|
}
|
|
289
286
|
node = Leaf::New(start_key, prefix_start, row_ids + key_section.start, num_row_ids);
|
|
287
|
+
art.memory_size += node->MemorySize(art, false);
|
|
290
288
|
|
|
291
289
|
} else { // create a new node and recurse
|
|
292
290
|
|
|
@@ -299,12 +297,13 @@ void Construct(vector<Key> &keys, row_t *row_ids, Node *&node, KeySection &key_s
|
|
|
299
297
|
|
|
300
298
|
auto prefix_length = key_section.depth - prefix_start;
|
|
301
299
|
node->prefix = Prefix(start_key, prefix_start, prefix_length);
|
|
300
|
+
art.memory_size += node->MemorySize(art, false);
|
|
302
301
|
|
|
303
302
|
// recurse on each child section
|
|
304
303
|
for (auto &child_section : child_sections) {
|
|
305
304
|
Node *new_child = nullptr;
|
|
306
|
-
Construct(keys, row_ids, new_child, child_section, has_constraint);
|
|
307
|
-
Node::InsertChild(node, child_section.key_byte, new_child);
|
|
305
|
+
Construct(art, keys, row_ids, new_child, child_section, has_constraint);
|
|
306
|
+
Node::InsertChild(art, node, child_section.key_byte, new_child);
|
|
308
307
|
}
|
|
309
308
|
}
|
|
310
309
|
}
|
|
@@ -317,10 +316,15 @@ void ART::ConstructFromSorted(idx_t count, vector<Key> &keys, Vector &row_identi
|
|
|
317
316
|
|
|
318
317
|
auto key_section = KeySection(0, count - 1, 0, 0);
|
|
319
318
|
auto has_constraint = IsUnique();
|
|
320
|
-
Construct(keys, row_ids, this->tree, key_section, has_constraint);
|
|
319
|
+
Construct(*this, keys, row_ids, this->tree, key_section, has_constraint);
|
|
321
320
|
}
|
|
322
321
|
|
|
322
|
+
//===--------------------------------------------------------------------===//
|
|
323
|
+
// Insert
|
|
324
|
+
//===--------------------------------------------------------------------===//
|
|
325
|
+
|
|
323
326
|
bool ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) {
|
|
327
|
+
|
|
324
328
|
D_ASSERT(row_ids.GetType().InternalType() == ROW_TYPE);
|
|
325
329
|
D_ASSERT(logical_types[0] == input.data[0].GetType());
|
|
326
330
|
|
|
@@ -329,13 +333,13 @@ bool ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) {
|
|
|
329
333
|
vector<Key> keys(input.size());
|
|
330
334
|
GenerateKeys(arena_allocator, input, keys);
|
|
331
335
|
|
|
332
|
-
|
|
333
|
-
BufferManager::GetBufferManager(db).ReserveMemory(extra_memory);
|
|
334
|
-
estimated_art_size += extra_memory;
|
|
336
|
+
auto old_memory_size = this->memory_size;
|
|
335
337
|
|
|
336
|
-
//
|
|
338
|
+
// get the corresponding row IDs
|
|
337
339
|
row_ids.Flatten(input.size());
|
|
338
340
|
auto row_identifiers = FlatVector::GetData<row_t>(row_ids);
|
|
341
|
+
|
|
342
|
+
// now insert the elements into the index
|
|
339
343
|
idx_t failed_index = DConstants::INVALID_INDEX;
|
|
340
344
|
for (idx_t i = 0; i < input.size(); i++) {
|
|
341
345
|
if (keys[i].Empty()) {
|
|
@@ -359,8 +363,15 @@ bool ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) {
|
|
|
359
363
|
row_t row_id = row_identifiers[i];
|
|
360
364
|
Erase(tree, keys[i], 0, row_id);
|
|
361
365
|
}
|
|
366
|
+
// nothing changed, no need to update the buffer memory size
|
|
362
367
|
return false;
|
|
363
368
|
}
|
|
369
|
+
|
|
370
|
+
D_ASSERT(old_memory_size <= memory_size);
|
|
371
|
+
Verify();
|
|
372
|
+
if (track_memory) {
|
|
373
|
+
buffer_manager.IncreaseUsedMemory(memory_size - old_memory_size);
|
|
374
|
+
}
|
|
364
375
|
return true;
|
|
365
376
|
}
|
|
366
377
|
|
|
@@ -407,7 +418,7 @@ bool ART::InsertToLeaf(Leaf &leaf, row_t row_id) {
|
|
|
407
418
|
if (IsUnique() && leaf.count != 0) {
|
|
408
419
|
return false;
|
|
409
420
|
}
|
|
410
|
-
leaf.Insert(row_id);
|
|
421
|
+
leaf.Insert(*this, row_id);
|
|
411
422
|
return true;
|
|
412
423
|
}
|
|
413
424
|
|
|
@@ -416,23 +427,24 @@ bool ART::Insert(Node *&node, Key &key, idx_t depth, row_t row_id) {
|
|
|
416
427
|
if (!node) {
|
|
417
428
|
// node is currently empty, create a leaf here with the key
|
|
418
429
|
node = Leaf::New(key, depth, row_id);
|
|
430
|
+
this->memory_size += node->MemorySize(*this, false);
|
|
419
431
|
return true;
|
|
420
432
|
}
|
|
421
433
|
|
|
422
434
|
if (node->type == NodeType::NLeaf) {
|
|
423
|
-
//
|
|
435
|
+
// replace leaf with Node4 and store both leaves in it
|
|
436
|
+
// or add a row ID to a leaf, if they have the same key
|
|
424
437
|
auto leaf = (Leaf *)node;
|
|
425
|
-
|
|
426
|
-
auto &leaf_prefix = leaf->prefix;
|
|
427
438
|
uint32_t new_prefix_length = 0;
|
|
428
439
|
|
|
429
|
-
//
|
|
440
|
+
// FIXME: this code (if and while) can be optimized, less branching, see Construct
|
|
441
|
+
// leaf node is already there (its key matches the current key), update row_id vector
|
|
430
442
|
if (new_prefix_length == leaf->prefix.Size() && depth + leaf->prefix.Size() == key.len) {
|
|
431
443
|
return InsertToLeaf(*leaf, row_id);
|
|
432
444
|
}
|
|
433
|
-
while (
|
|
445
|
+
while (leaf->prefix[new_prefix_length] == key[depth + new_prefix_length]) {
|
|
434
446
|
new_prefix_length++;
|
|
435
|
-
//
|
|
447
|
+
// leaf node is already there (its key matches the current key), update row_id vector
|
|
436
448
|
if (new_prefix_length == leaf->prefix.Size() && depth + leaf->prefix.Size() == key.len) {
|
|
437
449
|
return InsertToLeaf(*leaf, row_id);
|
|
438
450
|
}
|
|
@@ -440,34 +452,44 @@ bool ART::Insert(Node *&node, Key &key, idx_t depth, row_t row_id) {
|
|
|
440
452
|
|
|
441
453
|
Node *new_node = Node4::New();
|
|
442
454
|
new_node->prefix = Prefix(key, depth, new_prefix_length);
|
|
443
|
-
|
|
444
|
-
|
|
455
|
+
this->memory_size += new_node->MemorySize(*this, false);
|
|
456
|
+
|
|
457
|
+
auto key_byte = node->prefix.Reduce(*this, new_prefix_length);
|
|
458
|
+
Node4::InsertChild(*this, new_node, key_byte, node);
|
|
459
|
+
|
|
445
460
|
Node *leaf_node = Leaf::New(key, depth + new_prefix_length + 1, row_id);
|
|
446
|
-
Node4::InsertChild(new_node, key[depth + new_prefix_length], leaf_node);
|
|
461
|
+
Node4::InsertChild(*this, new_node, key[depth + new_prefix_length], leaf_node);
|
|
462
|
+
this->memory_size += leaf_node->MemorySize(*this, false);
|
|
463
|
+
|
|
447
464
|
node = new_node;
|
|
448
465
|
return true;
|
|
449
466
|
}
|
|
450
467
|
|
|
451
|
-
//
|
|
468
|
+
// handle prefix of inner node
|
|
452
469
|
if (node->prefix.Size()) {
|
|
470
|
+
|
|
453
471
|
uint32_t mismatch_pos = node->prefix.KeyMismatchPosition(key, depth);
|
|
454
472
|
if (mismatch_pos != node->prefix.Size()) {
|
|
455
|
-
//
|
|
473
|
+
// prefix differs, create new node
|
|
456
474
|
Node *new_node = Node4::New();
|
|
457
475
|
new_node->prefix = Prefix(key, depth, mismatch_pos);
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
476
|
+
this->memory_size += new_node->MemorySize(*this, false);
|
|
477
|
+
|
|
478
|
+
// break up prefix
|
|
479
|
+
auto key_byte = node->prefix.Reduce(*this, mismatch_pos);
|
|
480
|
+
Node4::InsertChild(*this, new_node, key_byte, node);
|
|
461
481
|
|
|
462
482
|
Node *leaf_node = Leaf::New(key, depth + mismatch_pos + 1, row_id);
|
|
463
|
-
Node4::InsertChild(new_node, key[depth + mismatch_pos], leaf_node);
|
|
483
|
+
Node4::InsertChild(*this, new_node, key[depth + mismatch_pos], leaf_node);
|
|
484
|
+
this->memory_size += leaf_node->MemorySize(*this, false);
|
|
485
|
+
|
|
464
486
|
node = new_node;
|
|
465
487
|
return true;
|
|
466
488
|
}
|
|
467
489
|
depth += node->prefix.Size();
|
|
468
490
|
}
|
|
469
491
|
|
|
470
|
-
//
|
|
492
|
+
// recurse
|
|
471
493
|
D_ASSERT(depth < key.len);
|
|
472
494
|
idx_t pos = node->GetChildPos(key[depth]);
|
|
473
495
|
if (pos != DConstants::INVALID_INDEX) {
|
|
@@ -476,30 +498,32 @@ bool ART::Insert(Node *&node, Key &key, idx_t depth, row_t row_id) {
|
|
|
476
498
|
node->ReplaceChildPointer(pos, child);
|
|
477
499
|
return insertion_result;
|
|
478
500
|
}
|
|
479
|
-
|
|
480
|
-
Node::
|
|
501
|
+
|
|
502
|
+
Node *leaf_node = Leaf::New(key, depth + 1, row_id);
|
|
503
|
+
Node::InsertChild(*this, node, key[depth], leaf_node);
|
|
504
|
+
this->memory_size += leaf_node->MemorySize(*this, false);
|
|
481
505
|
return true;
|
|
482
506
|
}
|
|
483
507
|
|
|
484
508
|
//===--------------------------------------------------------------------===//
|
|
485
509
|
// Delete
|
|
486
510
|
//===--------------------------------------------------------------------===//
|
|
511
|
+
|
|
487
512
|
void ART::Delete(IndexLock &state, DataChunk &input, Vector &row_ids) {
|
|
513
|
+
|
|
488
514
|
DataChunk expression;
|
|
489
515
|
expression.Initialize(Allocator::DefaultAllocator(), logical_types);
|
|
490
516
|
|
|
491
517
|
// first resolve the expressions
|
|
492
518
|
ExecuteExpressions(input, expression);
|
|
493
519
|
|
|
494
|
-
idx_t released_memory = MinValue<idx_t>(estimated_art_size, estimated_key_size * input.size());
|
|
495
|
-
BufferManager::GetBufferManager(db).FreeReservedMemory(released_memory);
|
|
496
|
-
estimated_art_size -= released_memory;
|
|
497
|
-
|
|
498
520
|
// then generate the keys for the given input
|
|
499
521
|
ArenaAllocator arena_allocator(BufferAllocator::Get(db));
|
|
500
522
|
vector<Key> keys(expression.size());
|
|
501
523
|
GenerateKeys(arena_allocator, expression, keys);
|
|
502
524
|
|
|
525
|
+
auto old_memory_size = this->memory_size;
|
|
526
|
+
|
|
503
527
|
// now erase the elements from the database
|
|
504
528
|
row_ids.Flatten(input.size());
|
|
505
529
|
auto row_identifiers = FlatVector::GetData<row_t>(row_ids);
|
|
@@ -512,54 +536,66 @@ void ART::Delete(IndexLock &state, DataChunk &input, Vector &row_ids) {
|
|
|
512
536
|
#ifdef DEBUG
|
|
513
537
|
auto node = Lookup(tree, keys[i], 0);
|
|
514
538
|
if (node) {
|
|
515
|
-
auto leaf =
|
|
539
|
+
auto leaf = (Leaf *)node;
|
|
516
540
|
for (idx_t k = 0; k < leaf->count; k++) {
|
|
517
541
|
D_ASSERT(leaf->GetRowId(k) != row_identifiers[i]);
|
|
518
542
|
}
|
|
519
543
|
}
|
|
520
544
|
#endif
|
|
521
545
|
}
|
|
546
|
+
|
|
547
|
+
D_ASSERT(old_memory_size >= memory_size);
|
|
548
|
+
Verify();
|
|
549
|
+
if (track_memory) {
|
|
550
|
+
buffer_manager.DecreaseUsedMemory(old_memory_size - memory_size);
|
|
551
|
+
}
|
|
522
552
|
}
|
|
523
553
|
|
|
524
554
|
void ART::Erase(Node *&node, Key &key, idx_t depth, row_t row_id) {
|
|
555
|
+
|
|
525
556
|
if (!node) {
|
|
526
557
|
return;
|
|
527
558
|
}
|
|
528
|
-
|
|
559
|
+
|
|
560
|
+
// delete a leaf from a tree
|
|
529
561
|
if (node->type == NodeType::NLeaf) {
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
562
|
+
auto leaf = (Leaf *)node;
|
|
563
|
+
leaf->Remove(*this, row_id);
|
|
564
|
+
|
|
533
565
|
if (leaf->count == 0) {
|
|
566
|
+
D_ASSERT(this->memory_size >= leaf->MemorySize(*this, false));
|
|
567
|
+
this->memory_size -= leaf->MemorySize(*this, false);
|
|
534
568
|
Node::Delete(node);
|
|
535
569
|
node = nullptr;
|
|
536
570
|
}
|
|
537
|
-
|
|
538
571
|
return;
|
|
539
572
|
}
|
|
540
573
|
|
|
541
|
-
//
|
|
574
|
+
// handle prefix
|
|
542
575
|
if (node->prefix.Size()) {
|
|
543
576
|
if (node->prefix.KeyMismatchPosition(key, depth) != node->prefix.Size()) {
|
|
544
577
|
return;
|
|
545
578
|
}
|
|
546
579
|
depth += node->prefix.Size();
|
|
547
580
|
}
|
|
581
|
+
|
|
548
582
|
idx_t pos = node->GetChildPos(key[depth]);
|
|
549
583
|
if (pos != DConstants::INVALID_INDEX) {
|
|
550
584
|
auto child = node->GetChild(*this, pos);
|
|
551
585
|
D_ASSERT(child);
|
|
552
586
|
|
|
553
587
|
if (child->type == NodeType::NLeaf) {
|
|
554
|
-
//
|
|
588
|
+
// leaf found, remove entry
|
|
555
589
|
auto leaf = (Leaf *)child;
|
|
556
|
-
leaf->Remove(row_id);
|
|
590
|
+
leaf->Remove(*this, row_id);
|
|
591
|
+
|
|
557
592
|
if (leaf->count == 0) {
|
|
558
|
-
//
|
|
559
|
-
Node::EraseChild(node, pos
|
|
593
|
+
// leaf is empty, delete leaf, decrement node counter and maybe shrink node
|
|
594
|
+
Node::EraseChild(*this, node, pos);
|
|
560
595
|
}
|
|
596
|
+
|
|
561
597
|
} else {
|
|
562
|
-
//
|
|
598
|
+
// recurse
|
|
563
599
|
Erase(child, key, depth + 1, row_id);
|
|
564
600
|
node->ReplaceChildPointer(pos, child);
|
|
565
601
|
}
|
|
@@ -569,6 +605,7 @@ void ART::Erase(Node *&node, Key &key, idx_t depth, row_t row_id) {
|
|
|
569
605
|
//===--------------------------------------------------------------------===//
|
|
570
606
|
// Point Query
|
|
571
607
|
//===--------------------------------------------------------------------===//
|
|
608
|
+
|
|
572
609
|
static Key CreateKey(ArenaAllocator &allocator, PhysicalType type, Value &value) {
|
|
573
610
|
D_ASSERT(type == value.type().InternalType());
|
|
574
611
|
switch (type) {
|
|
@@ -605,7 +642,7 @@ static Key CreateKey(ArenaAllocator &allocator, PhysicalType type, Value &value)
|
|
|
605
642
|
|
|
606
643
|
bool ART::SearchEqual(Key &key, idx_t max_count, vector<row_t> &result_ids) {
|
|
607
644
|
|
|
608
|
-
auto leaf =
|
|
645
|
+
auto leaf = (Leaf *)(Lookup(tree, key, 0));
|
|
609
646
|
if (!leaf) {
|
|
610
647
|
return true;
|
|
611
648
|
}
|
|
@@ -666,6 +703,7 @@ Leaf *ART::Lookup(Node *node, Key &key, idx_t depth) {
|
|
|
666
703
|
// Returns: True (If found leaf >= key)
|
|
667
704
|
// False (Otherwise)
|
|
668
705
|
//===--------------------------------------------------------------------===//
|
|
706
|
+
|
|
669
707
|
bool ART::SearchGreater(ARTIndexScanState *state, Key &key, bool inclusive, idx_t max_count,
|
|
670
708
|
vector<row_t> &result_ids) {
|
|
671
709
|
|
|
@@ -689,6 +727,7 @@ bool ART::SearchGreater(ARTIndexScanState *state, Key &key, bool inclusive, idx_
|
|
|
689
727
|
//===--------------------------------------------------------------------===//
|
|
690
728
|
// Less Than
|
|
691
729
|
//===--------------------------------------------------------------------===//
|
|
730
|
+
|
|
692
731
|
bool ART::SearchLess(ARTIndexScanState *state, Key &upper_bound, bool inclusive, idx_t max_count,
|
|
693
732
|
vector<row_t> &result_ids) {
|
|
694
733
|
|
|
@@ -714,6 +753,7 @@ bool ART::SearchLess(ARTIndexScanState *state, Key &upper_bound, bool inclusive,
|
|
|
714
753
|
//===--------------------------------------------------------------------===//
|
|
715
754
|
// Closed Range Query
|
|
716
755
|
//===--------------------------------------------------------------------===//
|
|
756
|
+
|
|
717
757
|
bool ART::SearchCloseRange(ARTIndexScanState *state, Key &lower_bound, Key &upper_bound, bool left_inclusive,
|
|
718
758
|
bool right_inclusive, idx_t max_count, vector<row_t> &result_ids) {
|
|
719
759
|
|
|
@@ -820,18 +860,19 @@ string ART::GenerateErrorKeyName(DataChunk &input, idx_t row) {
|
|
|
820
860
|
string ART::GenerateConstraintErrorMessage(VerifyExistenceType verify_type, const string &key_name) {
|
|
821
861
|
switch (verify_type) {
|
|
822
862
|
case VerifyExistenceType::APPEND: {
|
|
823
|
-
//
|
|
863
|
+
// APPEND to PK/UNIQUE table, but node/key already exists in PK/UNIQUE table
|
|
824
864
|
string type = IsPrimary() ? "primary key" : "unique";
|
|
825
865
|
return StringUtil::Format("Duplicate key \"%s\" violates %s constraint", key_name, type);
|
|
826
866
|
}
|
|
827
867
|
case VerifyExistenceType::APPEND_FK: {
|
|
828
|
-
//
|
|
868
|
+
// APPEND_FK to FK table, node/key does not exist in PK/UNIQUE table
|
|
829
869
|
return StringUtil::Format(
|
|
830
|
-
"Violates foreign key constraint because key \"%s\" does not exist in referenced table", key_name);
|
|
870
|
+
"Violates foreign key constraint because key \"%s\" does not exist in the referenced table", key_name);
|
|
831
871
|
}
|
|
832
872
|
case VerifyExistenceType::DELETE_FK: {
|
|
833
|
-
//
|
|
834
|
-
return StringUtil::Format("Violates foreign key constraint because key \"%s\"
|
|
873
|
+
// DELETE_FK that still exists in a FK table, i.e., not a valid delete
|
|
874
|
+
return StringUtil::Format("Violates foreign key constraint because key \"%s\" is still referenced by a foreign "
|
|
875
|
+
"key in a different table",
|
|
835
876
|
key_name);
|
|
836
877
|
}
|
|
837
878
|
default:
|
|
@@ -840,13 +881,13 @@ string ART::GenerateConstraintErrorMessage(VerifyExistenceType verify_type, cons
|
|
|
840
881
|
}
|
|
841
882
|
|
|
842
883
|
void ART::LookupValues(DataChunk &input, ConflictManager &conflict_manager) {
|
|
843
|
-
DataChunk expression_chunk;
|
|
844
|
-
expression_chunk.Initialize(Allocator::DefaultAllocator(), logical_types);
|
|
845
884
|
|
|
846
|
-
//
|
|
885
|
+
// don't alter the index during constraint checking
|
|
847
886
|
lock_guard<mutex> l(lock);
|
|
848
887
|
|
|
849
888
|
// first resolve the expressions for the index
|
|
889
|
+
DataChunk expression_chunk;
|
|
890
|
+
expression_chunk.Initialize(Allocator::DefaultAllocator(), logical_types);
|
|
850
891
|
ExecuteExpressions(input, expression_chunk);
|
|
851
892
|
|
|
852
893
|
// generate the keys for the given input
|
|
@@ -890,6 +931,7 @@ void ART::LookupValues(DataChunk &input, ConflictManager &conflict_manager) {
|
|
|
890
931
|
//===--------------------------------------------------------------------===//
|
|
891
932
|
// Serialization
|
|
892
933
|
//===--------------------------------------------------------------------===//
|
|
934
|
+
|
|
893
935
|
BlockPointer ART::Serialize(duckdb::MetaBlockWriter &writer) {
|
|
894
936
|
lock_guard<mutex> l(lock);
|
|
895
937
|
if (tree) {
|
|
@@ -901,13 +943,15 @@ BlockPointer ART::Serialize(duckdb::MetaBlockWriter &writer) {
|
|
|
901
943
|
}
|
|
902
944
|
|
|
903
945
|
//===--------------------------------------------------------------------===//
|
|
904
|
-
//
|
|
946
|
+
// Merging
|
|
905
947
|
//===--------------------------------------------------------------------===//
|
|
948
|
+
|
|
906
949
|
bool ART::MergeIndexes(IndexLock &state, Index *other_index) {
|
|
950
|
+
|
|
907
951
|
auto other_art = (ART *)other_index;
|
|
908
|
-
|
|
909
|
-
other_art->estimated_art_size = 0;
|
|
952
|
+
|
|
910
953
|
if (!this->tree) {
|
|
954
|
+
this->memory_size += other_art->memory_size;
|
|
911
955
|
this->tree = other_art->tree;
|
|
912
956
|
other_art->tree = nullptr;
|
|
913
957
|
return true;
|
|
@@ -916,6 +960,10 @@ bool ART::MergeIndexes(IndexLock &state, Index *other_index) {
|
|
|
916
960
|
return Node::MergeARTs(this, other_art);
|
|
917
961
|
}
|
|
918
962
|
|
|
963
|
+
//===--------------------------------------------------------------------===//
|
|
964
|
+
// Utility
|
|
965
|
+
//===--------------------------------------------------------------------===//
|
|
966
|
+
|
|
919
967
|
string ART::ToString() {
|
|
920
968
|
if (tree) {
|
|
921
969
|
return tree->ToString(*this);
|
|
@@ -923,4 +971,17 @@ string ART::ToString() {
|
|
|
923
971
|
return "[empty]";
|
|
924
972
|
}
|
|
925
973
|
|
|
974
|
+
void ART::Verify() {
|
|
975
|
+
#ifdef DEBUG
|
|
976
|
+
idx_t current_mem_size = 0;
|
|
977
|
+
if (tree) {
|
|
978
|
+
current_mem_size = tree->MemorySize(*this, true);
|
|
979
|
+
}
|
|
980
|
+
if (memory_size != current_mem_size) {
|
|
981
|
+
throw InternalException("Memory_size value (%d) does not match actual memory size (%d).", memory_size,
|
|
982
|
+
current_mem_size);
|
|
983
|
+
}
|
|
984
|
+
#endif
|
|
985
|
+
}
|
|
986
|
+
|
|
926
987
|
} // namespace duckdb
|