duckdb 0.7.2-dev2552.0 → 0.7.2-dev2699.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/binding.gyp +7 -7
- package/package.json +2 -2
- package/src/duckdb/extension/parquet/parquet_statistics.cpp +3 -0
- package/src/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp +2 -2
- package/src/duckdb/src/common/adbc/adbc.cpp +5 -2
- package/src/duckdb/src/common/radix_partitioning.cpp +1 -1
- package/src/duckdb/src/execution/index/art/art.cpp +286 -269
- package/src/duckdb/src/execution/index/art/art_key.cpp +22 -32
- package/src/duckdb/src/execution/index/art/fixed_size_allocator.cpp +224 -0
- package/src/duckdb/src/execution/index/art/iterator.cpp +142 -123
- package/src/duckdb/src/execution/index/art/leaf.cpp +319 -170
- package/src/duckdb/src/execution/index/art/leaf_segment.cpp +42 -0
- package/src/duckdb/src/execution/index/art/node.cpp +444 -379
- package/src/duckdb/src/execution/index/art/node16.cpp +178 -114
- package/src/duckdb/src/execution/index/art/node256.cpp +117 -79
- package/src/duckdb/src/execution/index/art/node4.cpp +169 -114
- package/src/duckdb/src/execution/index/art/node48.cpp +175 -105
- package/src/duckdb/src/execution/index/art/prefix.cpp +405 -127
- package/src/duckdb/src/execution/index/art/prefix_segment.cpp +42 -0
- package/src/duckdb/src/execution/index/art/swizzleable_pointer.cpp +10 -85
- package/src/duckdb/src/execution/operator/join/physical_index_join.cpp +2 -1
- package/src/duckdb/src/execution/operator/persistent/base_csv_reader.cpp +2 -2
- package/src/duckdb/src/execution/operator/persistent/csv_reader_options.cpp +2 -0
- package/src/duckdb/src/execution/operator/persistent/parallel_csv_reader.cpp +4 -0
- package/src/duckdb/src/execution/operator/schema/physical_create_index.cpp +11 -12
- package/src/duckdb/src/function/table/read_csv.cpp +5 -1
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/common/queue.hpp +1 -1
- package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +53 -45
- package/src/duckdb/src/include/duckdb/execution/index/art/art_key.hpp +29 -24
- package/src/duckdb/src/include/duckdb/execution/index/art/fixed_size_allocator.hpp +114 -0
- package/src/duckdb/src/include/duckdb/execution/index/art/iterator.hpp +26 -20
- package/src/duckdb/src/include/duckdb/execution/index/art/leaf.hpp +63 -39
- package/src/duckdb/src/include/duckdb/execution/index/art/leaf_segment.hpp +36 -0
- package/src/duckdb/src/include/duckdb/execution/index/art/node.hpp +98 -116
- package/src/duckdb/src/include/duckdb/execution/index/art/node16.hpp +48 -36
- package/src/duckdb/src/include/duckdb/execution/index/art/node256.hpp +52 -35
- package/src/duckdb/src/include/duckdb/execution/index/art/node4.hpp +46 -36
- package/src/duckdb/src/include/duckdb/execution/index/art/node48.hpp +57 -35
- package/src/duckdb/src/include/duckdb/execution/index/art/prefix.hpp +57 -50
- package/src/duckdb/src/include/duckdb/execution/index/art/prefix_segment.hpp +40 -0
- package/src/duckdb/src/include/duckdb/execution/index/art/swizzleable_pointer.hpp +38 -31
- package/src/duckdb/src/include/duckdb/execution/operator/persistent/csv_file_handle.hpp +2 -1
- package/src/duckdb/src/include/duckdb/execution/operator/persistent/csv_reader_options.hpp +2 -0
- package/src/duckdb/src/include/duckdb/main/query_result.hpp +1 -1
- package/src/duckdb/src/include/duckdb/parser/statement/insert_statement.hpp +4 -1
- package/src/duckdb/src/include/duckdb/parser/transformer.hpp +2 -1
- package/src/duckdb/src/include/duckdb/storage/buffer_manager.hpp +0 -5
- package/src/duckdb/src/include/duckdb/storage/index.hpp +13 -28
- package/src/duckdb/src/include/duckdb/storage/standard_buffer_manager.hpp +0 -2
- package/src/duckdb/src/include/duckdb/transaction/cleanup_state.hpp +5 -0
- package/src/duckdb/src/include/duckdb.h +26 -0
- package/src/duckdb/src/main/capi/helper-c.cpp +7 -0
- package/src/duckdb/src/main/client_context.cpp +1 -1
- package/src/duckdb/src/main/query_result.cpp +1 -1
- package/src/duckdb/src/parser/statement/insert_statement.cpp +15 -6
- package/src/duckdb/src/parser/transform/constraint/transform_constraint.cpp +1 -1
- package/src/duckdb/src/parser/transform/expression/transform_function.cpp +18 -5
- package/src/duckdb/src/parser/transform/statement/transform_insert.cpp +5 -7
- package/src/duckdb/src/planner/binder/statement/bind_create.cpp +20 -7
- package/src/duckdb/src/planner/binder/statement/bind_insert.cpp +14 -9
- package/src/duckdb/src/storage/checkpoint_manager.cpp +11 -9
- package/src/duckdb/src/storage/data_table.cpp +6 -3
- package/src/duckdb/src/storage/index.cpp +18 -6
- package/src/duckdb/src/storage/local_storage.cpp +8 -2
- package/src/duckdb/src/storage/standard_buffer_manager.cpp +0 -9
- package/src/duckdb/src/storage/wal_replay.cpp +1 -1
- package/src/duckdb/src/transaction/cleanup_state.cpp +6 -0
- package/src/duckdb/src/transaction/undo_buffer.cpp +8 -0
- package/src/duckdb/ub_extension_icu_third_party_icu_i18n.cpp +4 -4
- package/src/duckdb/ub_src_execution_index_art.cpp +7 -1
@@ -1,164 +1,219 @@
|
|
1
1
|
#include "duckdb/execution/index/art/node4.hpp"
|
2
2
|
|
3
3
|
#include "duckdb/execution/index/art/art.hpp"
|
4
|
+
#include "duckdb/execution/index/art/node.hpp"
|
4
5
|
#include "duckdb/execution/index/art/node16.hpp"
|
5
6
|
#include "duckdb/storage/meta_block_reader.hpp"
|
7
|
+
#include "duckdb/storage/meta_block_writer.hpp"
|
6
8
|
|
7
9
|
namespace duckdb {
|
8
10
|
|
9
|
-
Node4::
|
10
|
-
memset(key, 0, sizeof(key));
|
11
|
-
}
|
11
|
+
Node4 &Node4::New(ART &art, Node &node) {
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
}
|
17
|
-
return prefix.MemorySize() + sizeof(*this);
|
18
|
-
}
|
13
|
+
node.SetPtr(Node::GetAllocator(art, NType::NODE_4).New());
|
14
|
+
node.type = (uint8_t)NType::NODE_4;
|
15
|
+
auto &n4 = Node4::Get(art, node);
|
19
16
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
return pos;
|
24
|
-
}
|
25
|
-
}
|
26
|
-
return Node::GetChildPos(k);
|
17
|
+
n4.count = 0;
|
18
|
+
n4.prefix.Initialize();
|
19
|
+
return n4;
|
27
20
|
}
|
28
21
|
|
29
|
-
|
30
|
-
for (idx_t pos = 0; pos < count; pos++) {
|
31
|
-
if (key[pos] >= k) {
|
32
|
-
if (key[pos] == k) {
|
33
|
-
equal = true;
|
34
|
-
} else {
|
35
|
-
equal = false;
|
36
|
-
}
|
37
|
-
return pos;
|
38
|
-
}
|
39
|
-
}
|
40
|
-
return DConstants::INVALID_INDEX;
|
41
|
-
}
|
22
|
+
void Node4::Free(ART &art, Node &node) {
|
42
23
|
|
43
|
-
|
44
|
-
|
45
|
-
|
24
|
+
D_ASSERT(node.IsSet());
|
25
|
+
D_ASSERT(!node.IsSwizzled());
|
26
|
+
|
27
|
+
auto &n4 = Node4::Get(art, node);
|
46
28
|
|
47
|
-
|
48
|
-
|
49
|
-
|
29
|
+
// free all children
|
30
|
+
for (idx_t i = 0; i < n4.count; i++) {
|
31
|
+
Node::Free(art, n4.children[i]);
|
50
32
|
}
|
51
|
-
pos++;
|
52
|
-
return pos < count ? pos : DConstants::INVALID_INDEX;
|
53
33
|
}
|
54
34
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
35
|
+
Node4 &Node4::ShrinkNode16(ART &art, Node &node4, Node &node16) {
|
36
|
+
|
37
|
+
auto &n4 = Node4::New(art, node4);
|
38
|
+
auto &n16 = Node16::Get(art, node16);
|
39
|
+
|
40
|
+
n4.count = n16.count;
|
41
|
+
n4.prefix.Move(n16.prefix);
|
42
|
+
|
43
|
+
for (idx_t i = 0; i < n16.count; i++) {
|
44
|
+
n4.key[i] = n16.key[i];
|
45
|
+
n4.children[i] = n16.children[i];
|
64
46
|
}
|
65
|
-
return DConstants::INVALID_INDEX;
|
66
|
-
}
|
67
47
|
|
68
|
-
|
69
|
-
|
70
|
-
return
|
48
|
+
n16.count = 0;
|
49
|
+
Node::Free(art, node16);
|
50
|
+
return n4;
|
71
51
|
}
|
72
52
|
|
73
|
-
void Node4::
|
74
|
-
children[pos] = node;
|
75
|
-
}
|
53
|
+
void Node4::InitializeMerge(ART &art, const ARTFlags &flags) {
|
76
54
|
|
77
|
-
|
78
|
-
|
55
|
+
for (idx_t i = 0; i < count; i++) {
|
56
|
+
children[i].InitializeMerge(art, flags);
|
57
|
+
}
|
79
58
|
}
|
80
59
|
|
81
|
-
void Node4::InsertChild(ART &art, Node
|
82
|
-
|
60
|
+
void Node4::InsertChild(ART &art, Node &node, const uint8_t byte, const Node child) {
|
61
|
+
|
62
|
+
D_ASSERT(node.IsSet());
|
63
|
+
D_ASSERT(!node.IsSwizzled());
|
64
|
+
auto &n4 = Node4::Get(art, node);
|
65
|
+
|
66
|
+
// ensure that there is no other child at the same byte
|
67
|
+
for (idx_t i = 0; i < n4.count; i++) {
|
68
|
+
D_ASSERT(n4.key[i] != byte);
|
69
|
+
}
|
83
70
|
|
84
71
|
// insert new child node into node
|
85
|
-
if (
|
72
|
+
if (n4.count < Node::NODE_4_CAPACITY) {
|
86
73
|
// still space, just insert the child
|
87
|
-
idx_t
|
88
|
-
while (
|
89
|
-
|
74
|
+
idx_t child_pos = 0;
|
75
|
+
while (child_pos < n4.count && n4.key[child_pos] < byte) {
|
76
|
+
child_pos++;
|
90
77
|
}
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
}
|
78
|
+
// move children backwards to make space
|
79
|
+
for (idx_t i = n4.count; i > child_pos; i--) {
|
80
|
+
n4.key[i] = n4.key[i - 1];
|
81
|
+
n4.children[i] = n4.children[i - 1];
|
96
82
|
}
|
97
|
-
|
98
|
-
|
99
|
-
|
83
|
+
|
84
|
+
n4.key[child_pos] = byte;
|
85
|
+
n4.children[child_pos] = child;
|
86
|
+
n4.count++;
|
100
87
|
|
101
88
|
} else {
|
102
89
|
// node is full, grow to Node16
|
103
|
-
auto
|
104
|
-
|
105
|
-
|
106
|
-
new_node->prefix = std::move(node->prefix);
|
107
|
-
|
108
|
-
for (idx_t i = 0; i < n->count; i++) {
|
109
|
-
new_node->key[i] = n->key[i];
|
110
|
-
new_node->children[i] = n->children[i];
|
111
|
-
n->children[i] = nullptr;
|
112
|
-
}
|
113
|
-
n->count = 0;
|
114
|
-
|
115
|
-
art.DecreaseMemorySize(node->MemorySize(art, false));
|
116
|
-
Node::Delete(node);
|
117
|
-
node = new_node;
|
118
|
-
Node16::InsertChild(art, node, key_byte, new_child);
|
90
|
+
auto node4 = node;
|
91
|
+
Node16::GrowNode4(art, node, node4);
|
92
|
+
Node16::InsertChild(art, node, byte, child);
|
119
93
|
}
|
120
94
|
}
|
121
95
|
|
122
|
-
void Node4::
|
96
|
+
void Node4::DeleteChild(ART &art, Node &node, const uint8_t byte) {
|
123
97
|
|
124
|
-
|
125
|
-
D_ASSERT(
|
126
|
-
|
98
|
+
D_ASSERT(node.IsSet());
|
99
|
+
D_ASSERT(!node.IsSwizzled());
|
100
|
+
auto &n4 = Node4::Get(art, node);
|
127
101
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
102
|
+
idx_t child_pos = 0;
|
103
|
+
for (; child_pos < n4.count; child_pos++) {
|
104
|
+
if (n4.key[child_pos] == byte) {
|
105
|
+
break;
|
106
|
+
}
|
132
107
|
}
|
133
108
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
109
|
+
D_ASSERT(child_pos < n4.count);
|
110
|
+
D_ASSERT(n4.count > 1);
|
111
|
+
|
112
|
+
// free the child and decrease the count
|
113
|
+
Node::Free(art, n4.children[child_pos]);
|
114
|
+
n4.count--;
|
138
115
|
|
139
116
|
// potentially move any children backwards
|
140
|
-
for (;
|
141
|
-
|
142
|
-
|
143
|
-
}
|
144
|
-
// set any remaining nodes as nullptr
|
145
|
-
for (; pos < Node4::GetSize(); pos++) {
|
146
|
-
n->children[pos] = nullptr;
|
117
|
+
for (idx_t i = child_pos; i < n4.count; i++) {
|
118
|
+
n4.key[i] = n4.key[i + 1];
|
119
|
+
n4.children[i] = n4.children[i + 1];
|
147
120
|
}
|
148
121
|
|
149
122
|
// this is a one way node, compress
|
150
|
-
if (
|
123
|
+
if (n4.count == 1) {
|
151
124
|
|
152
125
|
// get only child and concatenate prefixes
|
153
|
-
auto
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
126
|
+
auto child = *n4.GetChild(n4.key[0]);
|
127
|
+
child.GetPrefix(art).Concatenate(art, n4.key[0], n4.prefix);
|
128
|
+
n4.count--;
|
129
|
+
|
130
|
+
Node::Free(art, node);
|
131
|
+
node = child;
|
132
|
+
}
|
133
|
+
}
|
158
134
|
|
159
|
-
|
160
|
-
|
161
|
-
|
135
|
+
void Node4::ReplaceChild(const uint8_t byte, const Node child) {
|
136
|
+
for (idx_t i = 0; i < count; i++) {
|
137
|
+
if (key[i] == byte) {
|
138
|
+
children[i] = child;
|
139
|
+
return;
|
140
|
+
}
|
162
141
|
}
|
163
142
|
}
|
143
|
+
|
144
|
+
optional_ptr<Node> Node4::GetChild(const uint8_t byte) {
|
145
|
+
|
146
|
+
for (idx_t i = 0; i < count; i++) {
|
147
|
+
if (key[i] == byte) {
|
148
|
+
return &children[i];
|
149
|
+
}
|
150
|
+
}
|
151
|
+
return nullptr;
|
152
|
+
}
|
153
|
+
|
154
|
+
optional_ptr<Node> Node4::GetNextChild(uint8_t &byte) {
|
155
|
+
|
156
|
+
for (idx_t i = 0; i < count; i++) {
|
157
|
+
if (key[i] >= byte) {
|
158
|
+
byte = key[i];
|
159
|
+
return &children[i];
|
160
|
+
}
|
161
|
+
}
|
162
|
+
return nullptr;
|
163
|
+
}
|
164
|
+
|
165
|
+
BlockPointer Node4::Serialize(ART &art, MetaBlockWriter &writer) {
|
166
|
+
|
167
|
+
// recurse into children and retrieve child block pointers
|
168
|
+
vector<BlockPointer> child_block_pointers;
|
169
|
+
for (idx_t i = 0; i < count; i++) {
|
170
|
+
child_block_pointers.push_back(children[i].Serialize(art, writer));
|
171
|
+
}
|
172
|
+
for (idx_t i = count; i < Node::NODE_4_CAPACITY; i++) {
|
173
|
+
child_block_pointers.emplace_back((block_id_t)DConstants::INVALID_INDEX, 0);
|
174
|
+
}
|
175
|
+
|
176
|
+
// get pointer and write fields
|
177
|
+
auto block_pointer = writer.GetBlockPointer();
|
178
|
+
writer.Write(NType::NODE_4);
|
179
|
+
writer.Write<uint8_t>(count);
|
180
|
+
prefix.Serialize(art, writer);
|
181
|
+
|
182
|
+
// write key values
|
183
|
+
for (idx_t i = 0; i < Node::NODE_4_CAPACITY; i++) {
|
184
|
+
writer.Write(key[i]);
|
185
|
+
}
|
186
|
+
|
187
|
+
// write child block pointers
|
188
|
+
for (auto &child_block_pointer : child_block_pointers) {
|
189
|
+
writer.Write(child_block_pointer.block_id);
|
190
|
+
writer.Write(child_block_pointer.offset);
|
191
|
+
}
|
192
|
+
|
193
|
+
return block_pointer;
|
194
|
+
}
|
195
|
+
|
196
|
+
void Node4::Deserialize(ART &art, MetaBlockReader &reader) {
|
197
|
+
|
198
|
+
count = reader.Read<uint8_t>();
|
199
|
+
prefix.Deserialize(art, reader);
|
200
|
+
|
201
|
+
// read key values
|
202
|
+
for (idx_t i = 0; i < Node::NODE_4_CAPACITY; i++) {
|
203
|
+
key[i] = reader.Read<uint8_t>();
|
204
|
+
}
|
205
|
+
|
206
|
+
// read child block pointers
|
207
|
+
for (idx_t i = 0; i < Node::NODE_4_CAPACITY; i++) {
|
208
|
+
children[i] = Node(reader);
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
void Node4::Vacuum(ART &art, const ARTFlags &flags) {
|
213
|
+
|
214
|
+
for (idx_t i = 0; i < count; i++) {
|
215
|
+
Node::Vacuum(art, children[i], flags);
|
216
|
+
}
|
217
|
+
}
|
218
|
+
|
164
219
|
} // namespace duckdb
|
@@ -1,160 +1,230 @@
|
|
1
1
|
#include "duckdb/execution/index/art/node48.hpp"
|
2
2
|
|
3
3
|
#include "duckdb/execution/index/art/art.hpp"
|
4
|
+
#include "duckdb/execution/index/art/node.hpp"
|
4
5
|
#include "duckdb/execution/index/art/node16.hpp"
|
5
6
|
#include "duckdb/execution/index/art/node256.hpp"
|
7
|
+
#include "duckdb/storage/meta_block_reader.hpp"
|
8
|
+
#include "duckdb/storage/meta_block_writer.hpp"
|
6
9
|
|
7
10
|
namespace duckdb {
|
8
11
|
|
9
|
-
Node48::
|
10
|
-
|
11
|
-
|
12
|
+
Node48 &Node48::New(ART &art, Node &node) {
|
13
|
+
|
14
|
+
node.SetPtr(Node::GetAllocator(art, NType::NODE_48).New());
|
15
|
+
node.type = (uint8_t)NType::NODE_48;
|
16
|
+
auto &n48 = Node48::Get(art, node);
|
17
|
+
|
18
|
+
n48.count = 0;
|
19
|
+
n48.prefix.Initialize();
|
20
|
+
|
21
|
+
for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
|
22
|
+
n48.child_index[i] = Node::EMPTY_MARKER;
|
12
23
|
}
|
13
|
-
}
|
14
24
|
|
15
|
-
|
16
|
-
|
17
|
-
|
25
|
+
// necessary for faster child insertion/deletion
|
26
|
+
for (idx_t i = 0; i < Node::NODE_48_CAPACITY; i++) {
|
27
|
+
n48.children[i].Reset();
|
18
28
|
}
|
19
|
-
|
29
|
+
|
30
|
+
return n48;
|
20
31
|
}
|
21
32
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
33
|
+
void Node48::Free(ART &art, Node &node) {
|
34
|
+
|
35
|
+
D_ASSERT(node.IsSet());
|
36
|
+
D_ASSERT(!node.IsSwizzled());
|
37
|
+
|
38
|
+
auto &n48 = Node48::Get(art, node);
|
39
|
+
|
40
|
+
if (!n48.count) {
|
41
|
+
return;
|
27
42
|
}
|
28
|
-
}
|
29
43
|
|
30
|
-
|
31
|
-
for (idx_t
|
32
|
-
if (child_index[
|
33
|
-
|
34
|
-
equal = true;
|
35
|
-
} else {
|
36
|
-
equal = false;
|
37
|
-
}
|
38
|
-
return pos;
|
44
|
+
// free all children
|
45
|
+
for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
|
46
|
+
if (n48.child_index[i] != Node::EMPTY_MARKER) {
|
47
|
+
Node::Free(art, n48.children[n48.child_index[i]]);
|
39
48
|
}
|
40
49
|
}
|
41
|
-
return DConstants::INVALID_INDEX;
|
42
50
|
}
|
43
51
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
52
|
+
Node48 &Node48::GrowNode16(ART &art, Node &node48, Node &node16) {
|
53
|
+
|
54
|
+
auto &n16 = Node16::Get(art, node16);
|
55
|
+
auto &n48 = Node48::New(art, node48);
|
56
|
+
|
57
|
+
n48.count = n16.count;
|
58
|
+
n48.prefix.Move(n16.prefix);
|
59
|
+
|
60
|
+
for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
|
61
|
+
n48.child_index[i] = Node::EMPTY_MARKER;
|
49
62
|
}
|
50
|
-
return DConstants::INVALID_INDEX;
|
51
|
-
}
|
52
63
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
64
|
+
for (idx_t i = 0; i < n16.count; i++) {
|
65
|
+
n48.child_index[n16.key[i]] = i;
|
66
|
+
n48.children[i] = n16.children[i];
|
67
|
+
}
|
68
|
+
|
69
|
+
// necessary for faster child insertion/deletion
|
70
|
+
for (idx_t i = n16.count; i < Node::NODE_48_CAPACITY; i++) {
|
71
|
+
n48.children[i].Reset();
|
59
72
|
}
|
60
|
-
|
73
|
+
|
74
|
+
n16.count = 0;
|
75
|
+
Node::Free(art, node16);
|
76
|
+
return n48;
|
61
77
|
}
|
62
78
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
79
|
+
Node48 &Node48::ShrinkNode256(ART &art, Node &node48, Node &node256) {
|
80
|
+
|
81
|
+
auto &n48 = Node48::New(art, node48);
|
82
|
+
auto &n256 = Node256::Get(art, node256);
|
83
|
+
|
84
|
+
n48.count = 0;
|
85
|
+
n48.prefix.Move(n256.prefix);
|
86
|
+
|
87
|
+
for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
|
88
|
+
if (n256.children[i].IsSet()) {
|
89
|
+
n48.child_index[i] = n48.count;
|
90
|
+
n48.children[n48.count] = n256.children[i];
|
91
|
+
n48.count++;
|
92
|
+
} else {
|
93
|
+
n48.child_index[i] = Node::EMPTY_MARKER;
|
69
94
|
}
|
70
95
|
}
|
71
|
-
return Node::GetNextPos(pos);
|
72
|
-
}
|
73
96
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
}
|
97
|
+
// necessary for faster child insertion/deletion
|
98
|
+
for (idx_t i = n48.count; i < Node::NODE_48_CAPACITY; i++) {
|
99
|
+
n48.children[i].Reset();
|
100
|
+
}
|
78
101
|
|
79
|
-
|
80
|
-
|
102
|
+
n256.count = 0;
|
103
|
+
Node::Free(art, node256);
|
104
|
+
return n48;
|
81
105
|
}
|
82
106
|
|
83
|
-
|
84
|
-
|
107
|
+
void Node48::InitializeMerge(ART &art, const ARTFlags &flags) {
|
108
|
+
|
109
|
+
for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
|
110
|
+
if (child_index[i] != Node::EMPTY_MARKER) {
|
111
|
+
children[child_index[i]].InitializeMerge(art, flags);
|
112
|
+
}
|
113
|
+
}
|
85
114
|
}
|
86
115
|
|
87
|
-
void Node48::InsertChild(ART &art, Node
|
88
|
-
|
116
|
+
void Node48::InsertChild(ART &art, Node &node, const uint8_t byte, const Node child) {
|
117
|
+
|
118
|
+
D_ASSERT(node.IsSet());
|
119
|
+
D_ASSERT(!node.IsSwizzled());
|
120
|
+
auto &n48 = Node48::Get(art, node);
|
121
|
+
|
122
|
+
// ensure that there is no other child at the same byte
|
123
|
+
D_ASSERT(n48.child_index[byte] == Node::EMPTY_MARKER);
|
89
124
|
|
90
125
|
// insert new child node into node
|
91
|
-
if (
|
126
|
+
if (n48.count < Node::NODE_48_CAPACITY) {
|
92
127
|
// still space, just insert the child
|
93
|
-
idx_t
|
94
|
-
if (
|
128
|
+
idx_t child_pos = n48.count;
|
129
|
+
if (n48.children[child_pos].IsSet()) {
|
95
130
|
// find an empty position in the node list if the current position is occupied
|
96
|
-
|
97
|
-
while (
|
98
|
-
|
131
|
+
child_pos = 0;
|
132
|
+
while (n48.children[child_pos].IsSet()) {
|
133
|
+
child_pos++;
|
99
134
|
}
|
100
135
|
}
|
101
|
-
|
102
|
-
|
103
|
-
|
136
|
+
n48.children[child_pos] = child;
|
137
|
+
n48.child_index[byte] = child_pos;
|
138
|
+
n48.count++;
|
104
139
|
|
105
140
|
} else {
|
106
141
|
// node is full, grow to Node256
|
107
|
-
auto
|
108
|
-
|
109
|
-
|
110
|
-
new_node->prefix = std::move(n->prefix);
|
111
|
-
|
112
|
-
for (idx_t i = 0; i < Node256::GetSize(); i++) {
|
113
|
-
if (n->child_index[i] != Node::EMPTY_MARKER) {
|
114
|
-
new_node->children[i] = n->children[n->child_index[i]];
|
115
|
-
n->children[n->child_index[i]] = nullptr;
|
116
|
-
}
|
117
|
-
}
|
118
|
-
|
119
|
-
art.DecreaseMemorySize(node->MemorySize(art, false));
|
120
|
-
Node::Delete(node);
|
121
|
-
node = new_node;
|
122
|
-
Node256::InsertChild(art, node, key_byte, new_child);
|
142
|
+
auto node48 = node;
|
143
|
+
Node256::GrowNode48(art, node, node48);
|
144
|
+
Node256::InsertChild(art, node, byte, child);
|
123
145
|
}
|
124
146
|
}
|
125
147
|
|
126
|
-
void Node48::
|
127
|
-
auto n = (Node48 *)(node);
|
148
|
+
void Node48::DeleteChild(ART &art, Node &node, const uint8_t byte) {
|
128
149
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
art.DecreaseMemorySize(child->MemorySize(art, true));
|
133
|
-
}
|
150
|
+
D_ASSERT(node.IsSet());
|
151
|
+
D_ASSERT(!node.IsSwizzled());
|
152
|
+
auto &n48 = Node48::Get(art, node);
|
134
153
|
|
135
|
-
//
|
136
|
-
|
137
|
-
|
138
|
-
|
154
|
+
// free the child and decrease the count
|
155
|
+
Node::Free(art, n48.children[n48.child_index[byte]]);
|
156
|
+
n48.child_index[byte] = Node::EMPTY_MARKER;
|
157
|
+
n48.count--;
|
139
158
|
|
140
159
|
// shrink node to Node16
|
141
|
-
if (
|
160
|
+
if (n48.count < Node::NODE_48_SHRINK_THRESHOLD) {
|
161
|
+
auto node48 = node;
|
162
|
+
Node16::ShrinkNode48(art, node, node48);
|
163
|
+
}
|
164
|
+
}
|
142
165
|
|
143
|
-
|
144
|
-
art.IncreaseMemorySize(new_node->MemorySize(art, false));
|
145
|
-
new_node->prefix = std::move(n->prefix);
|
166
|
+
optional_ptr<Node> Node48::GetNextChild(uint8_t &byte) {
|
146
167
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
n->children[n->child_index[i]] = nullptr;
|
152
|
-
}
|
168
|
+
for (idx_t i = byte; i < Node::NODE_256_CAPACITY; i++) {
|
169
|
+
if (child_index[i] != Node::EMPTY_MARKER) {
|
170
|
+
byte = i;
|
171
|
+
return &children[child_index[i]];
|
153
172
|
}
|
173
|
+
}
|
174
|
+
return nullptr;
|
175
|
+
}
|
176
|
+
|
177
|
+
BlockPointer Node48::Serialize(ART &art, MetaBlockWriter &writer) {
|
178
|
+
|
179
|
+
// recurse into children and retrieve child block pointers
|
180
|
+
vector<BlockPointer> child_block_pointers;
|
181
|
+
for (idx_t i = 0; i < Node::NODE_48_CAPACITY; i++) {
|
182
|
+
child_block_pointers.push_back(children[i].Serialize(art, writer));
|
183
|
+
}
|
184
|
+
|
185
|
+
// get pointer and write fields
|
186
|
+
auto block_pointer = writer.GetBlockPointer();
|
187
|
+
writer.Write(NType::NODE_48);
|
188
|
+
writer.Write<uint8_t>(count);
|
189
|
+
prefix.Serialize(art, writer);
|
190
|
+
|
191
|
+
// write key values
|
192
|
+
for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
|
193
|
+
writer.Write(child_index[i]);
|
194
|
+
}
|
195
|
+
|
196
|
+
// write child block pointers
|
197
|
+
for (auto &child_block_pointer : child_block_pointers) {
|
198
|
+
writer.Write(child_block_pointer.block_id);
|
199
|
+
writer.Write(child_block_pointer.offset);
|
200
|
+
}
|
201
|
+
|
202
|
+
return block_pointer;
|
203
|
+
}
|
204
|
+
|
205
|
+
void Node48::Deserialize(ART &art, MetaBlockReader &reader) {
|
206
|
+
|
207
|
+
count = reader.Read<uint8_t>();
|
208
|
+
prefix.Deserialize(art, reader);
|
209
|
+
|
210
|
+
// read key values
|
211
|
+
for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
|
212
|
+
child_index[i] = reader.Read<uint8_t>();
|
213
|
+
}
|
214
|
+
|
215
|
+
// read child block pointers
|
216
|
+
for (idx_t i = 0; i < Node::NODE_48_CAPACITY; i++) {
|
217
|
+
children[i] = Node(reader);
|
218
|
+
}
|
219
|
+
}
|
154
220
|
|
155
|
-
|
156
|
-
|
157
|
-
|
221
|
+
void Node48::Vacuum(ART &art, const ARTFlags &flags) {
|
222
|
+
|
223
|
+
for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
|
224
|
+
if (child_index[i] != Node::EMPTY_MARKER) {
|
225
|
+
Node::Vacuum(art, children[child_index[i]], flags);
|
226
|
+
}
|
158
227
|
}
|
159
228
|
}
|
229
|
+
|
160
230
|
} // namespace duckdb
|