duckdb 0.7.2-dev2552.0 → 0.7.2-dev2675.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.
Files changed (66) hide show
  1. package/binding.gyp +7 -7
  2. package/package.json +2 -2
  3. package/src/duckdb/extension/parquet/parquet_statistics.cpp +3 -0
  4. package/src/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp +2 -2
  5. package/src/duckdb/src/common/radix_partitioning.cpp +1 -1
  6. package/src/duckdb/src/execution/index/art/art.cpp +286 -269
  7. package/src/duckdb/src/execution/index/art/art_key.cpp +22 -32
  8. package/src/duckdb/src/execution/index/art/fixed_size_allocator.cpp +224 -0
  9. package/src/duckdb/src/execution/index/art/iterator.cpp +142 -123
  10. package/src/duckdb/src/execution/index/art/leaf.cpp +319 -170
  11. package/src/duckdb/src/execution/index/art/leaf_segment.cpp +42 -0
  12. package/src/duckdb/src/execution/index/art/node.cpp +444 -379
  13. package/src/duckdb/src/execution/index/art/node16.cpp +178 -114
  14. package/src/duckdb/src/execution/index/art/node256.cpp +117 -79
  15. package/src/duckdb/src/execution/index/art/node4.cpp +169 -114
  16. package/src/duckdb/src/execution/index/art/node48.cpp +175 -105
  17. package/src/duckdb/src/execution/index/art/prefix.cpp +405 -127
  18. package/src/duckdb/src/execution/index/art/prefix_segment.cpp +42 -0
  19. package/src/duckdb/src/execution/index/art/swizzleable_pointer.cpp +10 -85
  20. package/src/duckdb/src/execution/operator/join/physical_index_join.cpp +2 -1
  21. package/src/duckdb/src/execution/operator/persistent/base_csv_reader.cpp +2 -2
  22. package/src/duckdb/src/execution/operator/persistent/csv_reader_options.cpp +2 -0
  23. package/src/duckdb/src/execution/operator/schema/physical_create_index.cpp +11 -12
  24. package/src/duckdb/src/function/table/read_csv.cpp +5 -1
  25. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  26. package/src/duckdb/src/include/duckdb/common/queue.hpp +1 -1
  27. package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +53 -45
  28. package/src/duckdb/src/include/duckdb/execution/index/art/art_key.hpp +29 -24
  29. package/src/duckdb/src/include/duckdb/execution/index/art/fixed_size_allocator.hpp +114 -0
  30. package/src/duckdb/src/include/duckdb/execution/index/art/iterator.hpp +26 -20
  31. package/src/duckdb/src/include/duckdb/execution/index/art/leaf.hpp +63 -39
  32. package/src/duckdb/src/include/duckdb/execution/index/art/leaf_segment.hpp +36 -0
  33. package/src/duckdb/src/include/duckdb/execution/index/art/node.hpp +98 -116
  34. package/src/duckdb/src/include/duckdb/execution/index/art/node16.hpp +48 -36
  35. package/src/duckdb/src/include/duckdb/execution/index/art/node256.hpp +52 -35
  36. package/src/duckdb/src/include/duckdb/execution/index/art/node4.hpp +46 -36
  37. package/src/duckdb/src/include/duckdb/execution/index/art/node48.hpp +57 -35
  38. package/src/duckdb/src/include/duckdb/execution/index/art/prefix.hpp +57 -50
  39. package/src/duckdb/src/include/duckdb/execution/index/art/prefix_segment.hpp +40 -0
  40. package/src/duckdb/src/include/duckdb/execution/index/art/swizzleable_pointer.hpp +38 -31
  41. package/src/duckdb/src/include/duckdb/execution/operator/persistent/csv_file_handle.hpp +2 -1
  42. package/src/duckdb/src/include/duckdb/execution/operator/persistent/csv_reader_options.hpp +2 -0
  43. package/src/duckdb/src/include/duckdb/parser/statement/insert_statement.hpp +4 -1
  44. package/src/duckdb/src/include/duckdb/parser/transformer.hpp +2 -1
  45. package/src/duckdb/src/include/duckdb/storage/buffer_manager.hpp +0 -5
  46. package/src/duckdb/src/include/duckdb/storage/index.hpp +13 -28
  47. package/src/duckdb/src/include/duckdb/storage/standard_buffer_manager.hpp +0 -2
  48. package/src/duckdb/src/include/duckdb/transaction/cleanup_state.hpp +5 -0
  49. package/src/duckdb/src/include/duckdb.h +26 -0
  50. package/src/duckdb/src/main/capi/helper-c.cpp +7 -0
  51. package/src/duckdb/src/parser/statement/insert_statement.cpp +15 -6
  52. package/src/duckdb/src/parser/transform/constraint/transform_constraint.cpp +1 -1
  53. package/src/duckdb/src/parser/transform/expression/transform_function.cpp +18 -5
  54. package/src/duckdb/src/parser/transform/statement/transform_insert.cpp +5 -7
  55. package/src/duckdb/src/planner/binder/statement/bind_create.cpp +20 -7
  56. package/src/duckdb/src/planner/binder/statement/bind_insert.cpp +14 -9
  57. package/src/duckdb/src/storage/checkpoint_manager.cpp +11 -9
  58. package/src/duckdb/src/storage/data_table.cpp +6 -3
  59. package/src/duckdb/src/storage/index.cpp +18 -6
  60. package/src/duckdb/src/storage/local_storage.cpp +8 -2
  61. package/src/duckdb/src/storage/standard_buffer_manager.cpp +0 -9
  62. package/src/duckdb/src/storage/wal_replay.cpp +1 -1
  63. package/src/duckdb/src/transaction/cleanup_state.cpp +6 -0
  64. package/src/duckdb/src/transaction/undo_buffer.cpp +8 -0
  65. package/src/duckdb/ub_extension_icu_third_party_icu_i18n.cpp +4 -4
  66. 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::Node4() : Node(NodeType::N4) {
10
- memset(key, 0, sizeof(key));
11
- }
11
+ Node4 &Node4::New(ART &art, Node &node) {
12
12
 
13
- idx_t Node4::MemorySize(ART &art, const bool &recurse) {
14
- if (recurse) {
15
- return prefix.MemorySize() + sizeof(*this) + RecursiveMemorySize(art);
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
- idx_t Node4::GetChildPos(uint8_t k) {
21
- for (idx_t pos = 0; pos < count; pos++) {
22
- if (key[pos] == k) {
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
- idx_t Node4::GetChildGreaterEqual(uint8_t k, bool &equal) {
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
- idx_t Node4::GetMin() {
44
- return 0;
45
- }
24
+ D_ASSERT(node.IsSet());
25
+ D_ASSERT(!node.IsSwizzled());
26
+
27
+ auto &n4 = Node4::Get(art, node);
46
28
 
47
- idx_t Node4::GetNextPos(idx_t pos) {
48
- if (pos == DConstants::INVALID_INDEX) {
49
- return 0;
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
- idx_t Node4::GetNextPosAndByte(idx_t pos, uint8_t &byte) {
56
- if (pos == DConstants::INVALID_INDEX) {
57
- byte = key[0];
58
- return 0;
59
- }
60
- pos++;
61
- if (pos < count) {
62
- byte = key[pos];
63
- return pos;
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
- Node *Node4::GetChild(ART &art, idx_t pos) {
69
- D_ASSERT(pos < count);
70
- return children[pos].Unswizzle(art);
48
+ n16.count = 0;
49
+ Node::Free(art, node16);
50
+ return n4;
71
51
  }
72
52
 
73
- void Node4::ReplaceChildPointer(idx_t pos, Node *node) {
74
- children[pos] = node;
75
- }
53
+ void Node4::InitializeMerge(ART &art, const ARTFlags &flags) {
76
54
 
77
- bool Node4::ChildIsInMemory(idx_t pos) {
78
- return children[pos] && !children[pos].IsSwizzled();
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 *&node, uint8_t key_byte, Node *new_child) {
82
- Node4 *n = (Node4 *)node;
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 (node->count < Node4::GetSize()) {
72
+ if (n4.count < Node::NODE_4_CAPACITY) {
86
73
  // still space, just insert the child
87
- idx_t pos = 0;
88
- while ((pos < node->count) && (n->key[pos] < key_byte)) {
89
- pos++;
74
+ idx_t child_pos = 0;
75
+ while (child_pos < n4.count && n4.key[child_pos] < byte) {
76
+ child_pos++;
90
77
  }
91
- if (n->children[pos]) {
92
- for (idx_t i = n->count; i > pos; i--) {
93
- n->key[i] = n->key[i - 1];
94
- n->children[i] = n->children[i - 1];
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
- n->key[pos] = key_byte;
98
- n->children[pos] = new_child;
99
- n->count++;
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 new_node = Node16::New();
104
- art.IncreaseMemorySize(new_node->MemorySize(art, false));
105
- new_node->count = n->count;
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::EraseChild(ART &art, Node *&node, idx_t pos) {
96
+ void Node4::DeleteChild(ART &art, Node &node, const uint8_t byte) {
123
97
 
124
- Node4 *n = (Node4 *)node;
125
- D_ASSERT(pos < n->count);
126
- D_ASSERT(n->count > 1);
98
+ D_ASSERT(node.IsSet());
99
+ D_ASSERT(!node.IsSwizzled());
100
+ auto &n4 = Node4::Get(art, node);
127
101
 
128
- // adjust the ART size
129
- if (n->ChildIsInMemory(pos)) {
130
- auto child = n->GetChild(art, pos);
131
- art.DecreaseMemorySize(child->MemorySize(art, true));
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
- // erase the child and decrease the count
135
- n->children[pos].Reset();
136
- n->count--;
137
- D_ASSERT(n->count >= 1);
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 (; pos < n->count; pos++) {
141
- n->key[pos] = n->key[pos + 1];
142
- n->children[pos] = n->children[pos + 1];
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 (n->count == 1) {
123
+ if (n4.count == 1) {
151
124
 
152
125
  // get only child and concatenate prefixes
153
- auto child_ref = n->GetChild(art, 0);
154
- // concatenate prefixes
155
- child_ref->prefix.Concatenate(art, n->key[0], node->prefix);
156
- // ensure that when deleting the node, we do not delete the child (because we move it)
157
- n->children[0] = nullptr;
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
- art.DecreaseMemorySize(n->MemorySize(art, false));
160
- Node::Delete(node);
161
- node = child_ref;
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::Node48() : Node(NodeType::N48) {
10
- for (idx_t i = 0; i < 256; i++) {
11
- child_index[i] = Node::EMPTY_MARKER;
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
- idx_t Node48::MemorySize(ART &art, const bool &recurse) {
16
- if (recurse) {
17
- return prefix.MemorySize() + sizeof(*this) + RecursiveMemorySize(art);
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
- return prefix.MemorySize() + sizeof(*this);
29
+
30
+ return n48;
20
31
  }
21
32
 
22
- idx_t Node48::GetChildPos(uint8_t k) {
23
- if (child_index[k] == Node::EMPTY_MARKER) {
24
- return DConstants::INVALID_INDEX;
25
- } else {
26
- return k;
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
- idx_t Node48::GetChildGreaterEqual(uint8_t k, bool &equal) {
31
- for (idx_t pos = k; pos < Node256::GetSize(); pos++) {
32
- if (child_index[pos] != Node::EMPTY_MARKER) {
33
- if (pos == k) {
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
- idx_t Node48::GetMin() {
45
- for (idx_t i = 0; i < Node256::GetSize(); i++) {
46
- if (child_index[i] != Node::EMPTY_MARKER) {
47
- return i;
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
- idx_t Node48::GetNextPos(idx_t pos) {
54
- pos == DConstants::INVALID_INDEX ? pos = 0 : pos++;
55
- for (; pos < Node256::GetSize(); pos++) {
56
- if (child_index[pos] != Node::EMPTY_MARKER) {
57
- return pos;
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
- return Node::GetNextPos(pos);
73
+
74
+ n16.count = 0;
75
+ Node::Free(art, node16);
76
+ return n48;
61
77
  }
62
78
 
63
- idx_t Node48::GetNextPosAndByte(idx_t pos, uint8_t &byte) {
64
- pos == DConstants::INVALID_INDEX ? pos = 0 : pos++;
65
- for (; pos < Node256::GetSize(); pos++) {
66
- if (child_index[pos] != Node::EMPTY_MARKER) {
67
- byte = uint8_t(pos);
68
- return pos;
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
- Node *Node48::GetChild(ART &art, idx_t pos) {
75
- D_ASSERT(child_index[pos] != Node::EMPTY_MARKER);
76
- return children[child_index[pos]].Unswizzle(art);
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
- void Node48::ReplaceChildPointer(idx_t pos, Node *node) {
80
- children[child_index[pos]] = node;
102
+ n256.count = 0;
103
+ Node::Free(art, node256);
104
+ return n48;
81
105
  }
82
106
 
83
- bool Node48::ChildIsInMemory(idx_t pos) {
84
- return children[child_index[pos]] && !children[child_index[pos]].IsSwizzled();
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 *&node, uint8_t key_byte, Node *new_child) {
88
- auto n = (Node48 *)node;
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 (node->count < Node48::GetSize()) {
126
+ if (n48.count < Node::NODE_48_CAPACITY) {
92
127
  // still space, just insert the child
93
- idx_t pos = n->count;
94
- if (n->children[pos]) {
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
- pos = 0;
97
- while (n->children[pos]) {
98
- pos++;
131
+ child_pos = 0;
132
+ while (n48.children[child_pos].IsSet()) {
133
+ child_pos++;
99
134
  }
100
135
  }
101
- n->children[pos] = new_child;
102
- n->child_index[key_byte] = pos;
103
- n->count++;
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 new_node = Node256::New();
108
- art.IncreaseMemorySize(new_node->MemorySize(art, false));
109
- new_node->count = n->count;
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::EraseChild(ART &art, Node *&node, idx_t pos) {
127
- auto n = (Node48 *)(node);
148
+ void Node48::DeleteChild(ART &art, Node &node, const uint8_t byte) {
128
149
 
129
- // adjust the ART size
130
- if (n->ChildIsInMemory(pos)) {
131
- auto child = n->GetChild(art, pos);
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
- // erase the child and decrease the count
136
- n->children[n->child_index[pos]].Reset();
137
- n->child_index[pos] = Node::EMPTY_MARKER;
138
- n->count--;
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 (node->count < NODE_48_SHRINK_THRESHOLD) {
160
+ if (n48.count < Node::NODE_48_SHRINK_THRESHOLD) {
161
+ auto node48 = node;
162
+ Node16::ShrinkNode48(art, node, node48);
163
+ }
164
+ }
142
165
 
143
- auto new_node = Node16::New();
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
- for (idx_t i = 0; i < Node256::GetSize(); i++) {
148
- if (n->child_index[i] != Node::EMPTY_MARKER) {
149
- new_node->key[new_node->count] = i;
150
- new_node->children[new_node->count++] = n->children[n->child_index[i]];
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
- art.DecreaseMemorySize(node->MemorySize(art, false));
156
- Node::Delete(node);
157
- node = new_node;
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