duckdb 0.7.1-dev240.0 → 0.7.1-dev284.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.cpp +15 -0
- package/src/duckdb/src/catalog/catalog_entry/index_catalog_entry.cpp +8 -7
- 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/function/pragma/pragma_queries.cpp +2 -2
- package/src/duckdb/src/function/table/read_csv.cpp +2 -1
- 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 +5 -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/enums/wal_type.hpp +3 -0
- 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/planner/binder.hpp +3 -0
- package/src/duckdb/src/include/duckdb/planner/expression_binder/index_binder.hpp +10 -3
- 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/write_ahead_log.hpp +7 -0
- package/src/duckdb/src/parser/parsed_data/create_index_info.cpp +3 -0
- package/src/duckdb/src/planner/binder/statement/bind_create_table.cpp +13 -0
- package/src/duckdb/src/planner/expression_binder/index_binder.cpp +32 -1
- 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_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/statement.cpp +46 -12
- package/test/prepare.test.ts +39 -1
- package/test/typescript_decls.test.ts +1 -1
|
@@ -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
|
|
|
@@ -299,16 +299,11 @@ Node *Node::Deserialize(ART &art, idx_t block_id, idx_t offset) {
|
|
|
299
299
|
NodeType node_type((NodeType)(n));
|
|
300
300
|
|
|
301
301
|
Node *deserialized_node = nullptr;
|
|
302
|
-
auto old_memory_size = art.memory_size;
|
|
303
302
|
switch (node_type) {
|
|
304
303
|
case NodeType::NLeaf: {
|
|
305
304
|
auto leaf = Leaf::New();
|
|
306
305
|
leaf->Deserialize(art, reader);
|
|
307
|
-
art.
|
|
308
|
-
D_ASSERT(art.memory_size >= old_memory_size);
|
|
309
|
-
if (art.track_memory) {
|
|
310
|
-
art.buffer_manager.IncreaseUsedMemory(art.memory_size - old_memory_size);
|
|
311
|
-
}
|
|
306
|
+
art.IncreaseMemorySize(leaf->MemorySize(art, false));
|
|
312
307
|
return leaf;
|
|
313
308
|
}
|
|
314
309
|
case NodeType::N4: {
|
|
@@ -331,11 +326,7 @@ Node *Node::Deserialize(ART &art, idx_t block_id, idx_t offset) {
|
|
|
331
326
|
throw InternalException("Unrecognized node type");
|
|
332
327
|
}
|
|
333
328
|
deserialized_node->DeserializeInternal(art, reader);
|
|
334
|
-
art.
|
|
335
|
-
D_ASSERT(art.memory_size >= old_memory_size);
|
|
336
|
-
if (art.track_memory) {
|
|
337
|
-
art.buffer_manager.IncreaseUsedMemory(art.memory_size - old_memory_size);
|
|
338
|
-
}
|
|
329
|
+
art.IncreaseMemorySize(deserialized_node->MemorySize(art, false));
|
|
339
330
|
return deserialized_node;
|
|
340
331
|
}
|
|
341
332
|
|
|
@@ -356,12 +347,10 @@ void SwapNodes(MergeInfo &info, ParentsOfNodes &parents) {
|
|
|
356
347
|
auto l_node_memory_size = info.l_node->MemorySize(*info.l_art, true);
|
|
357
348
|
auto r_node_memory_size = info.r_node->MemorySize(*info.r_art, true);
|
|
358
349
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
info.root_l_art->
|
|
362
|
-
info.root_r_art->
|
|
363
|
-
info.root_l_art->memory_size += r_node_memory_size;
|
|
364
|
-
info.root_r_art->memory_size += l_node_memory_size;
|
|
350
|
+
info.root_l_art->DecreaseMemorySize(l_node_memory_size);
|
|
351
|
+
info.root_r_art->DecreaseMemorySize(r_node_memory_size);
|
|
352
|
+
info.root_l_art->IncreaseMemorySize(r_node_memory_size);
|
|
353
|
+
info.root_r_art->IncreaseMemorySize(l_node_memory_size);
|
|
365
354
|
|
|
366
355
|
// actual swap
|
|
367
356
|
swap(info.l_art, info.r_art);
|
|
@@ -409,9 +398,8 @@ bool Merge(MergeInfo &info, ParentsOfNodes &parents) {
|
|
|
409
398
|
auto r_memory_size = r_child->MemorySize(*info.r_art, true);
|
|
410
399
|
Node::InsertChild(*info.root_l_art, info.l_node, key_byte, r_child);
|
|
411
400
|
|
|
412
|
-
info.root_l_art->
|
|
413
|
-
|
|
414
|
-
info.root_r_art->memory_size -= r_memory_size;
|
|
401
|
+
info.root_l_art->IncreaseMemorySize(r_memory_size);
|
|
402
|
+
info.root_r_art->DecreaseMemorySize(r_memory_size);
|
|
415
403
|
if (parents.l_parent) {
|
|
416
404
|
parents.l_parent->ReplaceChildPointer(parents.l_pos, info.l_node);
|
|
417
405
|
}
|
|
@@ -473,9 +461,8 @@ bool ResolvePrefixesAndMerge(MergeInfo &info, ParentsOfNodes &parents) {
|
|
|
473
461
|
auto r_memory_size = r_node->MemorySize(*info.r_art, true);
|
|
474
462
|
Node::InsertChild(*info.root_l_art, l_node, mismatch_byte, r_node);
|
|
475
463
|
|
|
476
|
-
info.root_l_art->
|
|
477
|
-
|
|
478
|
-
info.root_r_art->memory_size -= r_memory_size;
|
|
464
|
+
info.root_l_art->IncreaseMemorySize(r_memory_size);
|
|
465
|
+
info.root_r_art->DecreaseMemorySize(r_memory_size);
|
|
479
466
|
UpdateParentsOfNodes(l_node, null_parent, parents);
|
|
480
467
|
r_node = nullptr;
|
|
481
468
|
return true;
|
|
@@ -493,7 +480,7 @@ bool ResolvePrefixesAndMerge(MergeInfo &info, ParentsOfNodes &parents) {
|
|
|
493
480
|
// create new node
|
|
494
481
|
Node *new_node = Node4::New();
|
|
495
482
|
new_node->prefix = Prefix(l_node->prefix, mismatch_pos);
|
|
496
|
-
info.root_l_art->
|
|
483
|
+
info.root_l_art->IncreaseMemorySize(new_node->MemorySize(*info.l_art, false));
|
|
497
484
|
|
|
498
485
|
// insert l_node, break up prefix of l_node
|
|
499
486
|
auto key_byte = l_node->prefix.Reduce(*info.root_l_art, mismatch_pos);
|
|
@@ -504,9 +491,8 @@ bool ResolvePrefixesAndMerge(MergeInfo &info, ParentsOfNodes &parents) {
|
|
|
504
491
|
auto r_memory_size = r_node->MemorySize(*info.r_art, true);
|
|
505
492
|
Node4::InsertChild(*info.root_l_art, new_node, key_byte, r_node);
|
|
506
493
|
|
|
507
|
-
info.root_l_art->
|
|
508
|
-
|
|
509
|
-
info.root_r_art->memory_size -= r_memory_size;
|
|
494
|
+
info.root_l_art->IncreaseMemorySize(r_memory_size);
|
|
495
|
+
info.root_r_art->DecreaseMemorySize(r_memory_size);
|
|
510
496
|
|
|
511
497
|
l_node = new_node;
|
|
512
498
|
UpdateParentsOfNodes(l_node, null_parent, parents);
|
|
@@ -104,7 +104,7 @@ void Node16::InsertChild(ART &art, Node *&node, uint8_t key_byte, Node *new_chil
|
|
|
104
104
|
} else {
|
|
105
105
|
// node is full, grow to Node48
|
|
106
106
|
auto new_node = Node48::New();
|
|
107
|
-
art.
|
|
107
|
+
art.IncreaseMemorySize(new_node->MemorySize(art, false));
|
|
108
108
|
new_node->count = node->count;
|
|
109
109
|
new_node->prefix = std::move(n->prefix);
|
|
110
110
|
|
|
@@ -114,8 +114,7 @@ void Node16::InsertChild(ART &art, Node *&node, uint8_t key_byte, Node *new_chil
|
|
|
114
114
|
n->children[i] = nullptr;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
|
|
118
|
-
art.memory_size -= node->MemorySize(art, false);
|
|
117
|
+
art.DecreaseMemorySize(node->MemorySize(art, false));
|
|
119
118
|
Node::Delete(node);
|
|
120
119
|
node = new_node;
|
|
121
120
|
Node48::InsertChild(art, node, key_byte, new_child);
|
|
@@ -130,8 +129,7 @@ void Node16::EraseChild(ART &art, Node *&node, idx_t pos) {
|
|
|
130
129
|
// adjust the ART size
|
|
131
130
|
if (n->ChildIsInMemory(pos)) {
|
|
132
131
|
auto child = n->GetChild(art, pos);
|
|
133
|
-
|
|
134
|
-
art.memory_size -= child->MemorySize(art, true);
|
|
132
|
+
art.DecreaseMemorySize(child->MemorySize(art, true));
|
|
135
133
|
}
|
|
136
134
|
|
|
137
135
|
// erase the child and decrease the count
|
|
@@ -155,7 +153,7 @@ void Node16::EraseChild(ART &art, Node *&node, idx_t pos) {
|
|
|
155
153
|
if (node->count < Node4::GetSize()) {
|
|
156
154
|
|
|
157
155
|
auto new_node = Node4::New();
|
|
158
|
-
art.
|
|
156
|
+
art.IncreaseMemorySize(new_node->MemorySize(art, false));
|
|
159
157
|
new_node->prefix = std::move(n->prefix);
|
|
160
158
|
|
|
161
159
|
for (idx_t i = 0; i < n->count; i++) {
|
|
@@ -164,8 +162,7 @@ void Node16::EraseChild(ART &art, Node *&node, idx_t pos) {
|
|
|
164
162
|
n->children[i] = nullptr;
|
|
165
163
|
}
|
|
166
164
|
|
|
167
|
-
|
|
168
|
-
art.memory_size -= node->MemorySize(art, false);
|
|
165
|
+
art.DecreaseMemorySize(node->MemorySize(art, false));
|
|
169
166
|
Node::Delete(node);
|
|
170
167
|
node = new_node;
|
|
171
168
|
}
|
|
@@ -92,8 +92,7 @@ void Node256::EraseChild(ART &art, Node *&node, idx_t pos) {
|
|
|
92
92
|
// adjust the ART size
|
|
93
93
|
if (n->ChildIsInMemory(pos)) {
|
|
94
94
|
auto child = n->GetChild(art, pos);
|
|
95
|
-
|
|
96
|
-
art.memory_size -= child->MemorySize(art, true);
|
|
95
|
+
art.DecreaseMemorySize(child->MemorySize(art, true));
|
|
97
96
|
}
|
|
98
97
|
|
|
99
98
|
// erase the child and decrease the count
|
|
@@ -104,7 +103,7 @@ void Node256::EraseChild(ART &art, Node *&node, idx_t pos) {
|
|
|
104
103
|
if (node->count <= NODE_256_SHRINK_THRESHOLD) {
|
|
105
104
|
|
|
106
105
|
auto new_node = Node48::New();
|
|
107
|
-
art.
|
|
106
|
+
art.IncreaseMemorySize(new_node->MemorySize(art, false));
|
|
108
107
|
new_node->prefix = std::move(n->prefix);
|
|
109
108
|
|
|
110
109
|
for (idx_t i = 0; i < Node256::GetSize(); i++) {
|
|
@@ -115,8 +114,7 @@ void Node256::EraseChild(ART &art, Node *&node, idx_t pos) {
|
|
|
115
114
|
}
|
|
116
115
|
}
|
|
117
116
|
|
|
118
|
-
|
|
119
|
-
art.memory_size -= node->MemorySize(art, false);
|
|
117
|
+
art.DecreaseMemorySize(node->MemorySize(art, false));
|
|
120
118
|
Node::Delete(node);
|
|
121
119
|
node = new_node;
|
|
122
120
|
}
|
|
@@ -101,7 +101,7 @@ void Node4::InsertChild(ART &art, Node *&node, uint8_t key_byte, Node *new_child
|
|
|
101
101
|
} else {
|
|
102
102
|
// node is full, grow to Node16
|
|
103
103
|
auto new_node = Node16::New();
|
|
104
|
-
art.
|
|
104
|
+
art.IncreaseMemorySize(new_node->MemorySize(art, false));
|
|
105
105
|
new_node->count = n->count;
|
|
106
106
|
new_node->prefix = std::move(node->prefix);
|
|
107
107
|
|
|
@@ -112,8 +112,7 @@ void Node4::InsertChild(ART &art, Node *&node, uint8_t key_byte, Node *new_child
|
|
|
112
112
|
}
|
|
113
113
|
n->count = 0;
|
|
114
114
|
|
|
115
|
-
|
|
116
|
-
art.memory_size -= node->MemorySize(art, false);
|
|
115
|
+
art.DecreaseMemorySize(node->MemorySize(art, false));
|
|
117
116
|
Node::Delete(node);
|
|
118
117
|
node = new_node;
|
|
119
118
|
Node16::InsertChild(art, node, key_byte, new_child);
|
|
@@ -129,8 +128,7 @@ void Node4::EraseChild(ART &art, Node *&node, idx_t pos) {
|
|
|
129
128
|
// adjust the ART size
|
|
130
129
|
if (n->ChildIsInMemory(pos)) {
|
|
131
130
|
auto child = n->GetChild(art, pos);
|
|
132
|
-
|
|
133
|
-
art.memory_size -= child->MemorySize(art, true);
|
|
131
|
+
art.DecreaseMemorySize(child->MemorySize(art, true));
|
|
134
132
|
}
|
|
135
133
|
|
|
136
134
|
// erase the child and decrease the count
|
|
@@ -158,8 +156,7 @@ void Node4::EraseChild(ART &art, Node *&node, idx_t pos) {
|
|
|
158
156
|
// ensure that when deleting the node, we do not delete the child (because we move it)
|
|
159
157
|
n->children[0] = nullptr;
|
|
160
158
|
|
|
161
|
-
|
|
162
|
-
art.memory_size -= n->MemorySize(art, false);
|
|
159
|
+
art.DecreaseMemorySize(n->MemorySize(art, false));
|
|
163
160
|
Node::Delete(node);
|
|
164
161
|
node = child_ref;
|
|
165
162
|
}
|
|
@@ -105,7 +105,7 @@ void Node48::InsertChild(ART &art, Node *&node, uint8_t key_byte, Node *new_chil
|
|
|
105
105
|
} else {
|
|
106
106
|
// node is full, grow to Node256
|
|
107
107
|
auto new_node = Node256::New();
|
|
108
|
-
art.
|
|
108
|
+
art.IncreaseMemorySize(new_node->MemorySize(art, false));
|
|
109
109
|
new_node->count = n->count;
|
|
110
110
|
new_node->prefix = std::move(n->prefix);
|
|
111
111
|
|
|
@@ -116,8 +116,7 @@ void Node48::InsertChild(ART &art, Node *&node, uint8_t key_byte, Node *new_chil
|
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
|
|
120
|
-
art.memory_size -= node->MemorySize(art, false);
|
|
119
|
+
art.DecreaseMemorySize(node->MemorySize(art, false));
|
|
121
120
|
Node::Delete(node);
|
|
122
121
|
node = new_node;
|
|
123
122
|
Node256::InsertChild(art, node, key_byte, new_child);
|
|
@@ -130,8 +129,7 @@ void Node48::EraseChild(ART &art, Node *&node, idx_t pos) {
|
|
|
130
129
|
// adjust the ART size
|
|
131
130
|
if (n->ChildIsInMemory(pos)) {
|
|
132
131
|
auto child = n->GetChild(art, pos);
|
|
133
|
-
|
|
134
|
-
art.memory_size -= child->MemorySize(art, true);
|
|
132
|
+
art.DecreaseMemorySize(child->MemorySize(art, true));
|
|
135
133
|
}
|
|
136
134
|
|
|
137
135
|
// erase the child and decrease the count
|
|
@@ -143,7 +141,7 @@ void Node48::EraseChild(ART &art, Node *&node, idx_t pos) {
|
|
|
143
141
|
if (node->count < NODE_48_SHRINK_THRESHOLD) {
|
|
144
142
|
|
|
145
143
|
auto new_node = Node16::New();
|
|
146
|
-
art.
|
|
144
|
+
art.IncreaseMemorySize(new_node->MemorySize(art, false));
|
|
147
145
|
new_node->prefix = std::move(n->prefix);
|
|
148
146
|
|
|
149
147
|
for (idx_t i = 0; i < Node256::GetSize(); i++) {
|
|
@@ -154,8 +152,7 @@ void Node48::EraseChild(ART &art, Node *&node, idx_t pos) {
|
|
|
154
152
|
}
|
|
155
153
|
}
|
|
156
154
|
|
|
157
|
-
|
|
158
|
-
art.memory_size -= node->MemorySize(art, false);
|
|
155
|
+
art.DecreaseMemorySize(node->MemorySize(art, false));
|
|
159
156
|
Node::Delete(node);
|
|
160
157
|
node = new_node;
|
|
161
158
|
}
|
|
@@ -113,7 +113,7 @@ void Prefix::Overwrite(uint32_t new_size, uint8_t *data) {
|
|
|
113
113
|
|
|
114
114
|
void Prefix::Concatenate(ART &art, uint8_t key, Prefix &other) {
|
|
115
115
|
auto new_size = size + 1 + other.size;
|
|
116
|
-
art.
|
|
116
|
+
art.IncreaseMemorySize((new_size - size) * sizeof(uint8_t));
|
|
117
117
|
// have to allocate space in our prefix array
|
|
118
118
|
auto new_prefix = AllocateArray<uint8_t>(new_size);
|
|
119
119
|
idx_t new_prefix_idx = 0;
|
|
@@ -136,8 +136,7 @@ void Prefix::Concatenate(ART &art, uint8_t key, Prefix &other) {
|
|
|
136
136
|
|
|
137
137
|
uint8_t Prefix::Reduce(ART &art, uint32_t n) {
|
|
138
138
|
auto new_size = size - n - 1;
|
|
139
|
-
|
|
140
|
-
art.memory_size -= (size - new_size) * sizeof(uint8_t);
|
|
139
|
+
art.DecreaseMemorySize((size - new_size) * sizeof(uint8_t));
|
|
141
140
|
auto prefix = GetPrefixData();
|
|
142
141
|
auto partial_key = prefix[n];
|
|
143
142
|
|
|
@@ -22,8 +22,8 @@ string PragmaShowTablesExpanded(ClientContext &context, const FunctionParameters
|
|
|
22
22
|
return R"(
|
|
23
23
|
SELECT
|
|
24
24
|
t.table_name,
|
|
25
|
-
LIST(c.column_name order by c.
|
|
26
|
-
LIST(c.data_type order by c.
|
|
25
|
+
LIST(c.column_name order by c.column_index) AS column_names,
|
|
26
|
+
LIST(c.data_type order by c.column_index) AS column_types,
|
|
27
27
|
FIRST(t.temporary) AS temporary
|
|
28
28
|
FROM duckdb_tables t
|
|
29
29
|
JOIN duckdb_columns c
|
|
@@ -312,7 +312,7 @@ public:
|
|
|
312
312
|
progress = double(bytes_read) / double(file_size);
|
|
313
313
|
}
|
|
314
314
|
// now get the total percentage of files read
|
|
315
|
-
double percentage = double(file_index) / total_files;
|
|
315
|
+
double percentage = double(file_index - 1) / total_files;
|
|
316
316
|
percentage += (double(1) / double(total_files)) * progress;
|
|
317
317
|
return percentage * 100;
|
|
318
318
|
}
|
|
@@ -584,6 +584,7 @@ struct SingleThreadedCSVState : public GlobalTableFunctionState {
|
|
|
584
584
|
{
|
|
585
585
|
lock_guard<mutex> l(csv_lock);
|
|
586
586
|
if (initial_reader) {
|
|
587
|
+
total_size = initial_reader->file_handle ? initial_reader->file_handle->FileSize() : 0;
|
|
587
588
|
return std::move(initial_reader);
|
|
588
589
|
}
|
|
589
590
|
if (next_file >= total_files) {
|
|
@@ -287,9 +287,12 @@ void TableScanPushdownComplexFilter(ClientContext &context, LogicalGet &get, Fun
|
|
|
287
287
|
// behold
|
|
288
288
|
storage.info->indexes.Scan([&](Index &index) {
|
|
289
289
|
// first rewrite the index expression so the ColumnBindings align with the column bindings of the current table
|
|
290
|
+
|
|
290
291
|
if (index.unbound_expressions.size() > 1) {
|
|
292
|
+
// NOTE: index scans are not (yet) supported for compound index keys
|
|
291
293
|
return false;
|
|
292
294
|
}
|
|
295
|
+
|
|
293
296
|
auto index_expression = index.unbound_expressions[0]->Copy();
|
|
294
297
|
bool rewrite_possible = true;
|
|
295
298
|
RewriteIndexExpression(index, get, *index_expression, rewrite_possible);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#ifndef DUCKDB_VERSION
|
|
2
|
-
#define DUCKDB_VERSION "0.7.1-
|
|
2
|
+
#define DUCKDB_VERSION "0.7.1-dev284"
|
|
3
3
|
#endif
|
|
4
4
|
#ifndef DUCKDB_SOURCE_ID
|
|
5
|
-
#define DUCKDB_SOURCE_ID "
|
|
5
|
+
#define DUCKDB_SOURCE_ID "6b7362d2ca"
|
|
6
6
|
#endif
|
|
7
7
|
#include "duckdb/function/table/system_functions.hpp"
|
|
8
8
|
#include "duckdb/main/database.hpp"
|
|
@@ -29,6 +29,7 @@ struct CreateFunctionInfo;
|
|
|
29
29
|
struct CreateViewInfo;
|
|
30
30
|
struct CreateSequenceInfo;
|
|
31
31
|
struct CreateCollationInfo;
|
|
32
|
+
struct CreateIndexInfo;
|
|
32
33
|
struct CreateTypeInfo;
|
|
33
34
|
struct CreateTableInfo;
|
|
34
35
|
struct DatabaseSize;
|
|
@@ -137,6 +138,9 @@ public:
|
|
|
137
138
|
//! Creates a collation in the catalog
|
|
138
139
|
DUCKDB_API CatalogEntry *CreateCollation(CatalogTransaction transaction, CreateCollationInfo *info);
|
|
139
140
|
DUCKDB_API CatalogEntry *CreateCollation(ClientContext &context, CreateCollationInfo *info);
|
|
141
|
+
//! Creates an index in the catalog
|
|
142
|
+
DUCKDB_API CatalogEntry *CreateIndex(CatalogTransaction transaction, CreateIndexInfo *info);
|
|
143
|
+
DUCKDB_API CatalogEntry *CreateIndex(ClientContext &context, CreateIndexInfo *info);
|
|
140
144
|
|
|
141
145
|
//! Creates a table in the catalog.
|
|
142
146
|
DUCKDB_API CatalogEntry *CreateTable(CatalogTransaction transaction, SchemaCatalogEntry *schema,
|
|
@@ -153,7 +157,7 @@ public:
|
|
|
153
157
|
//! Create a scalar or aggregate function in the catalog
|
|
154
158
|
DUCKDB_API CatalogEntry *CreateFunction(CatalogTransaction transaction, SchemaCatalogEntry *schema,
|
|
155
159
|
CreateFunctionInfo *info);
|
|
156
|
-
//! Creates a
|
|
160
|
+
//! Creates a view in the catalog
|
|
157
161
|
DUCKDB_API CatalogEntry *CreateView(CatalogTransaction transaction, SchemaCatalogEntry *schema,
|
|
158
162
|
CreateViewInfo *info);
|
|
159
163
|
//! Creates a table in the catalog.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//===----------------------------------------------------------------------===//
|
|
2
2
|
// DuckDB
|
|
3
3
|
//
|
|
4
|
-
// duckdb/catalog/catalog_entry/
|
|
4
|
+
// duckdb/catalog/catalog_entry/duck_index_entry.hpp
|
|
5
5
|
//
|
|
6
6
|
//
|
|
7
7
|
//===----------------------------------------------------------------------===//
|
|
@@ -34,7 +34,7 @@ public:
|
|
|
34
34
|
|
|
35
35
|
public:
|
|
36
36
|
string ToSQL() override;
|
|
37
|
-
void Serialize(
|
|
37
|
+
void Serialize(Serializer &serializer);
|
|
38
38
|
static unique_ptr<CreateIndexInfo> Deserialize(Deserializer &source, ClientContext &context);
|
|
39
39
|
|
|
40
40
|
virtual string GetSchemaName() = 0;
|
|
@@ -29,24 +29,21 @@ namespace duckdb {
|
|
|
29
29
|
class ConflictManager;
|
|
30
30
|
|
|
31
31
|
struct ARTIndexScanState : public IndexScanState {
|
|
32
|
-
ARTIndexScanState() : checked(false), result_index(0) {
|
|
33
|
-
}
|
|
34
32
|
|
|
33
|
+
//! Scan predicates (single predicate scan or range scan)
|
|
35
34
|
Value values[2];
|
|
35
|
+
//! Expressions of the scan predicates
|
|
36
36
|
ExpressionType expressions[2];
|
|
37
|
-
bool checked;
|
|
37
|
+
bool checked = false;
|
|
38
|
+
//! All scanned row IDs
|
|
38
39
|
vector<row_t> result_ids;
|
|
39
40
|
Iterator iterator;
|
|
40
|
-
//! Stores the current leaf
|
|
41
|
-
Leaf *cur_leaf = nullptr;
|
|
42
|
-
//! Offset to leaf
|
|
43
|
-
idx_t result_index = 0;
|
|
44
41
|
};
|
|
45
42
|
|
|
46
43
|
enum class VerifyExistenceType : uint8_t {
|
|
47
|
-
APPEND = 0, //
|
|
48
|
-
APPEND_FK = 1, //
|
|
49
|
-
DELETE_FK = 2 //
|
|
44
|
+
APPEND = 0, // appends to a table
|
|
45
|
+
APPEND_FK = 1, // appends to a table that has a foreign key
|
|
46
|
+
DELETE_FK = 2 // delete from a table that has a foreign key
|
|
50
47
|
};
|
|
51
48
|
|
|
52
49
|
class ART : public Index {
|
|
@@ -62,47 +59,44 @@ public:
|
|
|
62
59
|
Node *tree;
|
|
63
60
|
|
|
64
61
|
public:
|
|
65
|
-
//! Initialize a scan on the index with the given expression and column
|
|
66
|
-
//! to fetch from the base table for a single predicate
|
|
62
|
+
//! Initialize a single predicate scan on the index with the given expression and column IDs
|
|
67
63
|
unique_ptr<IndexScanState> InitializeScanSinglePredicate(const Transaction &transaction, const Value &value,
|
|
68
64
|
ExpressionType expression_type) override;
|
|
69
|
-
|
|
70
|
-
//! Initialize a scan on the index with the given expression and column ids
|
|
71
|
-
//! to fetch from the base table for two predicates
|
|
65
|
+
//! Initialize a two predicate scan on the index with the given expression and column IDs
|
|
72
66
|
unique_ptr<IndexScanState> InitializeScanTwoPredicates(Transaction &transaction, const Value &low_value,
|
|
73
67
|
ExpressionType low_expression_type, const Value &high_value,
|
|
74
68
|
ExpressionType high_expression_type) override;
|
|
75
|
-
|
|
76
|
-
//!
|
|
69
|
+
//! Performs a lookup on the index, fetching up to max_count result IDs. Returns true if all row IDs were fetched,
|
|
70
|
+
//! and false otherwise
|
|
77
71
|
bool Scan(Transaction &transaction, DataTable &table, IndexScanState &state, idx_t max_count,
|
|
78
72
|
vector<row_t> &result_ids) override;
|
|
79
|
-
|
|
73
|
+
|
|
74
|
+
//! Called when data is appended to the index. The lock obtained from InitializeLock must be held
|
|
80
75
|
bool Append(IndexLock &lock, DataChunk &entries, Vector &row_identifiers) override;
|
|
81
|
-
//! Verify that data can be appended to the index
|
|
76
|
+
//! Verify that data can be appended to the index without a constraint violation
|
|
82
77
|
void VerifyAppend(DataChunk &chunk) override;
|
|
83
|
-
//! Verify that data can be appended to the index
|
|
78
|
+
//! Verify that data can be appended to the index without a constraint violation using the conflict manager
|
|
84
79
|
void VerifyAppend(DataChunk &chunk, ConflictManager &conflict_manager) override;
|
|
85
|
-
//!
|
|
86
|
-
void VerifyAppendForeignKey(DataChunk &chunk) override;
|
|
87
|
-
//! Verify that data can be delete from the index for foreign key constraint
|
|
88
|
-
void VerifyDeleteForeignKey(DataChunk &chunk) override;
|
|
89
|
-
//! Delete entries in the index
|
|
80
|
+
//! Delete a chunk of entries from the index. The lock obtained from InitializeLock must be held
|
|
90
81
|
void Delete(IndexLock &lock, DataChunk &entries, Vector &row_identifiers) override;
|
|
91
|
-
//! Insert
|
|
82
|
+
//! Insert a chunk of entries into the index
|
|
92
83
|
bool Insert(IndexLock &lock, DataChunk &data, Vector &row_ids) override;
|
|
93
84
|
|
|
94
85
|
//! Construct an ART from a vector of sorted keys
|
|
95
86
|
bool ConstructFromSorted(idx_t count, vector<Key> &keys, Vector &row_identifiers);
|
|
96
87
|
|
|
97
|
-
//! Search
|
|
88
|
+
//! Search equal values and fetches the row IDs
|
|
98
89
|
bool SearchEqual(Key &key, idx_t max_count, vector<row_t> &result_ids);
|
|
99
|
-
//! Search
|
|
90
|
+
//! Search equal values used for joins that do not need to fetch data
|
|
100
91
|
void SearchEqualJoinNoFetch(Key &key, idx_t &result_size);
|
|
101
|
-
|
|
92
|
+
|
|
93
|
+
//! Serializes the index and returns the pair of block_id offset positions
|
|
102
94
|
BlockPointer Serialize(duckdb::MetaBlockWriter &writer) override;
|
|
103
95
|
|
|
104
|
-
//! Merge
|
|
96
|
+
//! Merge another index into this index. The lock obtained from InitializeLock must be held, and the other
|
|
97
|
+
//! index must also be locked during the merge
|
|
105
98
|
bool MergeIndexes(IndexLock &state, Index *other_index) override;
|
|
99
|
+
|
|
106
100
|
//! Generate ART keys for an input chunk
|
|
107
101
|
static void GenerateKeys(ArenaAllocator &allocator, DataChunk &input, vector<Key> &keys);
|
|
108
102
|
|
|
@@ -110,30 +104,32 @@ public:
|
|
|
110
104
|
string GenerateErrorKeyName(DataChunk &input, idx_t row);
|
|
111
105
|
//! Generate the matching error message for a constraint violation
|
|
112
106
|
string GenerateConstraintErrorMessage(VerifyExistenceType verify_type, const string &key_name);
|
|
107
|
+
//! Performs constraint checking for a chunk of input data
|
|
108
|
+
void CheckConstraintsForChunk(DataChunk &input, ConflictManager &conflict_manager) override;
|
|
113
109
|
|
|
114
110
|
//! Returns the string representation of an ART
|
|
115
111
|
string ToString() override;
|
|
116
|
-
//! Verifies that the
|
|
112
|
+
//! Verifies that the in-memory size value of the index matches its actual size
|
|
117
113
|
void Verify() override;
|
|
114
|
+
//! Increases the memory size by the difference between the old size and the current size
|
|
115
|
+
//! and performs verifications
|
|
116
|
+
void IncreaseAndVerifyMemorySize(idx_t old_memory_size) override;
|
|
118
117
|
|
|
119
118
|
private:
|
|
120
|
-
//! Insert a row
|
|
119
|
+
//! Insert a row ID into a leaf
|
|
121
120
|
bool InsertToLeaf(Leaf &leaf, row_t row_id);
|
|
122
|
-
//! Insert
|
|
121
|
+
//! Insert a key into the tree
|
|
123
122
|
bool Insert(Node *&node, Key &key, idx_t depth, row_t row_id);
|
|
124
|
-
|
|
125
|
-
//! Erase element from leaf (if leaf has more than one value) or eliminate the leaf itself
|
|
123
|
+
//! Erase a key from the tree (if a leaf has more than one value) or erase the leaf itself
|
|
126
124
|
void Erase(Node *&node, Key &key, idx_t depth, row_t row_id);
|
|
127
|
-
|
|
128
|
-
//! Perform 'Lookup' for an entire chunk, marking which succeeded
|
|
129
|
-
void LookupValues(DataChunk &input, ConflictManager &conflict_manager) final override;
|
|
130
|
-
|
|
131
|
-
//! Find the node with a matching key, optimistic version
|
|
125
|
+
//! Find the node with a matching key, or return nullptr if not found
|
|
132
126
|
Leaf *Lookup(Node *node, Key &key, idx_t depth);
|
|
133
|
-
|
|
127
|
+
//! Returns all row IDs belonging to a key greater (or equal) than the search key
|
|
134
128
|
bool SearchGreater(ARTIndexScanState *state, Key &key, bool inclusive, idx_t max_count, vector<row_t> &result_ids);
|
|
129
|
+
//! Returns all row IDs belonging to a key less (or equal) than the upper_bound
|
|
135
130
|
bool SearchLess(ARTIndexScanState *state, Key &upper_bound, bool inclusive, idx_t max_count,
|
|
136
131
|
vector<row_t> &result_ids);
|
|
132
|
+
//! Returns all row IDs belonging to a key within the range of lower_bound and upper_bound
|
|
137
133
|
bool SearchCloseRange(ARTIndexScanState *state, Key &lower_bound, Key &upper_bound, bool left_inclusive,
|
|
138
134
|
bool right_inclusive, idx_t max_count, vector<row_t> &result_ids);
|
|
139
135
|
};
|