duckdb 0.8.2-dev4025.0 → 0.8.2-dev4126.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 (63) hide show
  1. package/binding.gyp +1 -0
  2. package/package.json +1 -1
  3. package/src/duckdb/extension/json/buffered_json_reader.cpp +76 -74
  4. package/src/duckdb/extension/json/include/buffered_json_reader.hpp +35 -32
  5. package/src/duckdb/extension/json/include/json_scan.hpp +9 -6
  6. package/src/duckdb/extension/json/json_scan.cpp +124 -121
  7. package/src/duckdb/src/catalog/catalog_entry/duck_index_entry.cpp +5 -0
  8. package/src/duckdb/src/common/radix_partitioning.cpp +1 -1
  9. package/src/duckdb/src/common/sort/partition_state.cpp +5 -1
  10. package/src/duckdb/src/core_functions/aggregate/holistic/mode.cpp +1 -1
  11. package/src/duckdb/src/core_functions/function_list.cpp +7 -0
  12. package/src/duckdb/src/core_functions/scalar/list/list_cosine_similarity.cpp +78 -0
  13. package/src/duckdb/src/core_functions/scalar/list/list_distance.cpp +72 -0
  14. package/src/duckdb/src/core_functions/scalar/list/list_inner_product.cpp +70 -0
  15. package/src/duckdb/src/execution/index/art/art.cpp +111 -92
  16. package/src/duckdb/src/execution/index/art/iterator.cpp +21 -27
  17. package/src/duckdb/src/execution/index/art/leaf.cpp +72 -153
  18. package/src/duckdb/src/execution/index/art/node.cpp +109 -203
  19. package/src/duckdb/src/execution/index/art/node16.cpp +32 -64
  20. package/src/duckdb/src/execution/index/art/node256.cpp +38 -53
  21. package/src/duckdb/src/execution/index/art/node4.cpp +31 -62
  22. package/src/duckdb/src/execution/index/art/node48.cpp +43 -65
  23. package/src/duckdb/src/execution/index/art/prefix.cpp +70 -141
  24. package/src/duckdb/src/execution/index/fixed_size_allocator.cpp +345 -0
  25. package/src/duckdb/src/execution/index/fixed_size_buffer.cpp +74 -0
  26. package/src/duckdb/src/execution/operator/aggregate/physical_window.cpp +1 -1
  27. package/src/duckdb/src/execution/operator/schema/physical_create_art_index.cpp +1 -1
  28. package/src/duckdb/src/function/table/system/duckdb_columns.cpp +3 -1
  29. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  30. package/src/duckdb/src/include/duckdb/catalog/catalog_entry/duck_index_entry.hpp +2 -0
  31. package/src/duckdb/src/include/duckdb/common/optional_idx.hpp +1 -1
  32. package/src/duckdb/src/include/duckdb/core_functions/scalar/list_functions.hpp +51 -0
  33. package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +17 -7
  34. package/src/duckdb/src/include/duckdb/execution/index/art/iterator.hpp +5 -5
  35. package/src/duckdb/src/include/duckdb/execution/index/art/leaf.hpp +10 -16
  36. package/src/duckdb/src/include/duckdb/execution/index/art/node.hpp +38 -116
  37. package/src/duckdb/src/include/duckdb/execution/index/art/node16.hpp +17 -18
  38. package/src/duckdb/src/include/duckdb/execution/index/art/node256.hpp +17 -23
  39. package/src/duckdb/src/include/duckdb/execution/index/art/node4.hpp +17 -18
  40. package/src/duckdb/src/include/duckdb/execution/index/art/node48.hpp +17 -24
  41. package/src/duckdb/src/include/duckdb/execution/index/art/prefix.hpp +16 -22
  42. package/src/duckdb/src/include/duckdb/execution/index/fixed_size_allocator.hpp +126 -0
  43. package/src/duckdb/src/include/duckdb/execution/index/fixed_size_buffer.hpp +79 -0
  44. package/src/duckdb/src/include/duckdb/execution/index/index_pointer.hpp +96 -0
  45. package/src/duckdb/src/include/duckdb/parallel/task_scheduler.hpp +1 -1
  46. package/src/duckdb/src/include/duckdb/storage/block.hpp +1 -1
  47. package/src/duckdb/src/include/duckdb/storage/index.hpp +10 -8
  48. package/src/duckdb/src/include/duckdb/storage/metadata/metadata_writer.hpp +3 -0
  49. package/src/duckdb/src/planner/binder/expression/bind_function_expression.cpp +14 -5
  50. package/src/duckdb/src/storage/checkpoint/table_data_writer.cpp +2 -3
  51. package/src/duckdb/src/storage/checkpoint_manager.cpp +16 -21
  52. package/src/duckdb/src/storage/data_table.cpp +3 -3
  53. package/src/duckdb/src/storage/index.cpp +7 -1
  54. package/src/duckdb/src/storage/metadata/metadata_manager.cpp +21 -21
  55. package/src/duckdb/src/storage/standard_buffer_manager.cpp +0 -8
  56. package/src/duckdb/src/storage/storage_info.cpp +1 -1
  57. package/src/duckdb/src/storage/table_index_list.cpp +1 -1
  58. package/src/duckdb/src/transaction/commit_state.cpp +5 -1
  59. package/src/duckdb/ub_src_core_functions_scalar_list.cpp +6 -0
  60. package/src/duckdb/ub_src_execution_index.cpp +4 -0
  61. package/src/duckdb/ub_src_execution_index_art.cpp +0 -2
  62. package/src/duckdb/src/execution/index/art/fixed_size_allocator.cpp +0 -238
  63. package/src/duckdb/src/include/duckdb/execution/index/art/fixed_size_allocator.hpp +0 -115
@@ -2,16 +2,14 @@
2
2
 
3
3
  #include "duckdb/execution/index/art/node4.hpp"
4
4
  #include "duckdb/execution/index/art/node48.hpp"
5
- #include "duckdb/storage/metadata/metadata_reader.hpp"
6
- #include "duckdb/storage/metadata/metadata_writer.hpp"
7
5
 
8
6
  namespace duckdb {
9
7
 
10
8
  Node16 &Node16::New(ART &art, Node &node) {
11
9
 
12
10
  node = Node::GetAllocator(art, NType::NODE_16).New();
13
- node.SetType((uint8_t)NType::NODE_16);
14
- auto &n16 = Node16::Get(art, node);
11
+ node.SetMetadata(static_cast<uint8_t>(NType::NODE_16));
12
+ auto &n16 = Node::RefMutable<Node16>(art, node, NType::NODE_16);
15
13
 
16
14
  n16.count = 0;
17
15
  return n16;
@@ -19,10 +17,8 @@ Node16 &Node16::New(ART &art, Node &node) {
19
17
 
20
18
  void Node16::Free(ART &art, Node &node) {
21
19
 
22
- D_ASSERT(node.IsSet());
23
- D_ASSERT(!node.IsSerialized());
24
-
25
- auto &n16 = Node16::Get(art, node);
20
+ D_ASSERT(node.HasMetadata());
21
+ auto &n16 = Node::RefMutable<Node16>(art, node, NType::NODE_16);
26
22
 
27
23
  // free all children
28
24
  for (idx_t i = 0; i < n16.count; i++) {
@@ -32,8 +28,8 @@ void Node16::Free(ART &art, Node &node) {
32
28
 
33
29
  Node16 &Node16::GrowNode4(ART &art, Node &node16, Node &node4) {
34
30
 
35
- auto &n4 = Node4::Get(art, node4);
36
- auto &n16 = Node16::New(art, node16);
31
+ auto &n4 = Node::RefMutable<Node4>(art, node4, NType::NODE_4);
32
+ auto &n16 = New(art, node16);
37
33
 
38
34
  n16.count = n4.count;
39
35
  for (idx_t i = 0; i < n4.count; i++) {
@@ -48,8 +44,8 @@ Node16 &Node16::GrowNode4(ART &art, Node &node16, Node &node4) {
48
44
 
49
45
  Node16 &Node16::ShrinkNode48(ART &art, Node &node16, Node &node48) {
50
46
 
51
- auto &n16 = Node16::New(art, node16);
52
- auto &n48 = Node48::Get(art, node48);
47
+ auto &n16 = New(art, node16);
48
+ auto &n48 = Node::RefMutable<Node48>(art, node48, NType::NODE_48);
53
49
 
54
50
  n16.count = 0;
55
51
  for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
@@ -75,9 +71,8 @@ void Node16::InitializeMerge(ART &art, const ARTFlags &flags) {
75
71
 
76
72
  void Node16::InsertChild(ART &art, Node &node, const uint8_t byte, const Node child) {
77
73
 
78
- D_ASSERT(node.IsSet());
79
- D_ASSERT(!node.IsSerialized());
80
- auto &n16 = Node16::Get(art, node);
74
+ D_ASSERT(node.HasMetadata());
75
+ auto &n16 = Node::RefMutable<Node16>(art, node, NType::NODE_16);
81
76
 
82
77
  // ensure that there is no other child at the same byte
83
78
  for (idx_t i = 0; i < n16.count; i++) {
@@ -111,9 +106,8 @@ void Node16::InsertChild(ART &art, Node &node, const uint8_t byte, const Node ch
111
106
 
112
107
  void Node16::DeleteChild(ART &art, Node &node, const uint8_t byte) {
113
108
 
114
- D_ASSERT(node.IsSet());
115
- D_ASSERT(!node.IsSerialized());
116
- auto &n16 = Node16::Get(art, node);
109
+ D_ASSERT(node.HasMetadata());
110
+ auto &n16 = Node::RefMutable<Node16>(art, node, NType::NODE_16);
117
111
 
118
112
  idx_t child_pos = 0;
119
113
  for (; child_pos < n16.count; child_pos++) {
@@ -150,72 +144,46 @@ void Node16::ReplaceChild(const uint8_t byte, const Node child) {
150
144
  }
151
145
  }
152
146
 
153
- optional_ptr<Node> Node16::GetChild(const uint8_t byte) {
154
-
147
+ optional_ptr<const Node> Node16::GetChild(const uint8_t byte) const {
155
148
  for (idx_t i = 0; i < count; i++) {
156
149
  if (key[i] == byte) {
157
- D_ASSERT(children[i].IsSet());
150
+ D_ASSERT(children[i].HasMetadata());
158
151
  return &children[i];
159
152
  }
160
153
  }
161
154
  return nullptr;
162
155
  }
163
156
 
164
- optional_ptr<Node> Node16::GetNextChild(uint8_t &byte) {
165
-
157
+ optional_ptr<Node> Node16::GetChildMutable(const uint8_t byte) {
166
158
  for (idx_t i = 0; i < count; i++) {
167
- if (key[i] >= byte) {
168
- byte = key[i];
169
- D_ASSERT(children[i].IsSet());
159
+ if (key[i] == byte) {
160
+ D_ASSERT(children[i].HasMetadata());
170
161
  return &children[i];
171
162
  }
172
163
  }
173
164
  return nullptr;
174
165
  }
175
166
 
176
- BlockPointer Node16::Serialize(ART &art, MetadataWriter &writer) {
177
-
178
- // recurse into children and retrieve child block pointers
179
- vector<BlockPointer> child_block_pointers;
167
+ optional_ptr<const Node> Node16::GetNextChild(uint8_t &byte) const {
180
168
  for (idx_t i = 0; i < count; i++) {
181
- child_block_pointers.push_back(children[i].Serialize(art, writer));
182
- }
183
- for (idx_t i = count; i < Node::NODE_16_CAPACITY; i++) {
184
- child_block_pointers.emplace_back((block_id_t)DConstants::INVALID_INDEX, 0);
185
- }
186
-
187
- // get pointer and write fields
188
- auto block_pointer = writer.GetBlockPointer();
189
- writer.Write(NType::NODE_16);
190
- writer.Write<uint8_t>(count);
191
-
192
- // write key values
193
- for (idx_t i = 0; i < Node::NODE_16_CAPACITY; i++) {
194
- writer.Write(key[i]);
195
- }
196
-
197
- // write child block pointers
198
- for (auto &child_block_pointer : child_block_pointers) {
199
- writer.Write(child_block_pointer.block_id);
200
- writer.Write(child_block_pointer.offset);
169
+ if (key[i] >= byte) {
170
+ byte = key[i];
171
+ D_ASSERT(children[i].HasMetadata());
172
+ return &children[i];
173
+ }
201
174
  }
202
-
203
- return block_pointer;
175
+ return nullptr;
204
176
  }
205
177
 
206
- void Node16::Deserialize(MetadataReader &reader) {
207
-
208
- count = reader.Read<uint8_t>();
209
-
210
- // read key values
211
- for (idx_t i = 0; i < Node::NODE_16_CAPACITY; i++) {
212
- key[i] = reader.Read<uint8_t>();
213
- }
214
-
215
- // read child block pointers
216
- for (idx_t i = 0; i < Node::NODE_16_CAPACITY; i++) {
217
- children[i] = Node(reader);
178
+ optional_ptr<Node> Node16::GetNextChildMutable(uint8_t &byte) {
179
+ for (idx_t i = 0; i < count; i++) {
180
+ if (key[i] >= byte) {
181
+ byte = key[i];
182
+ D_ASSERT(children[i].HasMetadata());
183
+ return &children[i];
184
+ }
218
185
  }
186
+ return nullptr;
219
187
  }
220
188
 
221
189
  void Node16::Vacuum(ART &art, const ARTFlags &flags) {
@@ -1,20 +1,18 @@
1
1
  #include "duckdb/execution/index/art/node256.hpp"
2
2
 
3
3
  #include "duckdb/execution/index/art/node48.hpp"
4
- #include "duckdb/storage/metadata/metadata_reader.hpp"
5
- #include "duckdb/storage/metadata/metadata_writer.hpp"
6
4
 
7
5
  namespace duckdb {
8
6
 
9
7
  Node256 &Node256::New(ART &art, Node &node) {
10
8
 
11
9
  node = Node::GetAllocator(art, NType::NODE_256).New();
12
- node.SetType((uint8_t)NType::NODE_256);
13
- auto &n256 = Node256::Get(art, node);
10
+ node.SetMetadata(static_cast<uint8_t>(NType::NODE_256));
11
+ auto &n256 = Node::RefMutable<Node256>(art, node, NType::NODE_256);
14
12
 
15
13
  n256.count = 0;
16
14
  for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
17
- n256.children[i].Reset();
15
+ n256.children[i].Clear();
18
16
  }
19
17
 
20
18
  return n256;
@@ -22,10 +20,8 @@ Node256 &Node256::New(ART &art, Node &node) {
22
20
 
23
21
  void Node256::Free(ART &art, Node &node) {
24
22
 
25
- D_ASSERT(node.IsSet());
26
- D_ASSERT(!node.IsSerialized());
27
-
28
- auto &n256 = Node256::Get(art, node);
23
+ D_ASSERT(node.HasMetadata());
24
+ auto &n256 = Node::RefMutable<Node256>(art, node, NType::NODE_256);
29
25
 
30
26
  if (!n256.count) {
31
27
  return;
@@ -33,7 +29,7 @@ void Node256::Free(ART &art, Node &node) {
33
29
 
34
30
  // free all children
35
31
  for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
36
- if (n256.children[i].IsSet()) {
32
+ if (n256.children[i].HasMetadata()) {
37
33
  Node::Free(art, n256.children[i]);
38
34
  }
39
35
  }
@@ -41,15 +37,15 @@ void Node256::Free(ART &art, Node &node) {
41
37
 
42
38
  Node256 &Node256::GrowNode48(ART &art, Node &node256, Node &node48) {
43
39
 
44
- auto &n48 = Node48::Get(art, node48);
45
- auto &n256 = Node256::New(art, node256);
40
+ auto &n48 = Node::RefMutable<Node48>(art, node48, NType::NODE_48);
41
+ auto &n256 = New(art, node256);
46
42
 
47
43
  n256.count = n48.count;
48
44
  for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
49
45
  if (n48.child_index[i] != Node::EMPTY_MARKER) {
50
46
  n256.children[i] = n48.children[n48.child_index[i]];
51
47
  } else {
52
- n256.children[i].Reset();
48
+ n256.children[i].Clear();
53
49
  }
54
50
  }
55
51
 
@@ -61,7 +57,7 @@ Node256 &Node256::GrowNode48(ART &art, Node &node256, Node &node48) {
61
57
  void Node256::InitializeMerge(ART &art, const ARTFlags &flags) {
62
58
 
63
59
  for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
64
- if (children[i].IsSet()) {
60
+ if (children[i].HasMetadata()) {
65
61
  children[i].InitializeMerge(art, flags);
66
62
  }
67
63
  }
@@ -69,12 +65,11 @@ void Node256::InitializeMerge(ART &art, const ARTFlags &flags) {
69
65
 
70
66
  void Node256::InsertChild(ART &art, Node &node, const uint8_t byte, const Node child) {
71
67
 
72
- D_ASSERT(node.IsSet());
73
- D_ASSERT(!node.IsSerialized());
74
- auto &n256 = Node256::Get(art, node);
68
+ D_ASSERT(node.HasMetadata());
69
+ auto &n256 = Node::RefMutable<Node256>(art, node, NType::NODE_256);
75
70
 
76
71
  // ensure that there is no other child at the same byte
77
- D_ASSERT(!n256.children[byte].IsSet());
72
+ D_ASSERT(!n256.children[byte].HasMetadata());
78
73
 
79
74
  n256.count++;
80
75
  D_ASSERT(n256.count <= Node::NODE_256_CAPACITY);
@@ -83,9 +78,8 @@ void Node256::InsertChild(ART &art, Node &node, const uint8_t byte, const Node c
83
78
 
84
79
  void Node256::DeleteChild(ART &art, Node &node, const uint8_t byte) {
85
80
 
86
- D_ASSERT(node.IsSet());
87
- D_ASSERT(!node.IsSerialized());
88
- auto &n256 = Node256::Get(art, node);
81
+ D_ASSERT(node.HasMetadata());
82
+ auto &n256 = Node::RefMutable<Node256>(art, node, NType::NODE_256);
89
83
 
90
84
  // free the child and decrease the count
91
85
  Node::Free(art, n256.children[byte]);
@@ -98,53 +92,44 @@ void Node256::DeleteChild(ART &art, Node &node, const uint8_t byte) {
98
92
  }
99
93
  }
100
94
 
101
- optional_ptr<Node> Node256::GetNextChild(uint8_t &byte) {
102
-
103
- for (idx_t i = byte; i < Node::NODE_256_CAPACITY; i++) {
104
- if (children[i].IsSet()) {
105
- byte = i;
106
- return &children[i];
107
- }
95
+ optional_ptr<const Node> Node256::GetChild(const uint8_t byte) const {
96
+ if (children[byte].HasMetadata()) {
97
+ return &children[byte];
108
98
  }
109
99
  return nullptr;
110
100
  }
111
101
 
112
- BlockPointer Node256::Serialize(ART &art, MetadataWriter &writer) {
113
-
114
- // recurse into children and retrieve child block pointers
115
- vector<BlockPointer> child_block_pointers;
116
- for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
117
- child_block_pointers.push_back(children[i].Serialize(art, writer));
102
+ optional_ptr<Node> Node256::GetChildMutable(const uint8_t byte) {
103
+ if (children[byte].HasMetadata()) {
104
+ return &children[byte];
118
105
  }
106
+ return nullptr;
107
+ }
119
108
 
120
- // get pointer and write fields
121
- auto block_pointer = writer.GetBlockPointer();
122
- writer.Write(NType::NODE_256);
123
- writer.Write<uint16_t>(count);
124
-
125
- // write child block pointers
126
- for (auto &child_block_pointer : child_block_pointers) {
127
- writer.Write(child_block_pointer.block_id);
128
- writer.Write(child_block_pointer.offset);
109
+ optional_ptr<const Node> Node256::GetNextChild(uint8_t &byte) const {
110
+ for (idx_t i = byte; i < Node::NODE_256_CAPACITY; i++) {
111
+ if (children[i].HasMetadata()) {
112
+ byte = i;
113
+ return &children[i];
114
+ }
129
115
  }
130
-
131
- return block_pointer;
116
+ return nullptr;
132
117
  }
133
118
 
134
- void Node256::Deserialize(MetadataReader &reader) {
135
-
136
- count = reader.Read<uint16_t>();
137
-
138
- // read child block pointers
139
- for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
140
- children[i] = Node(reader);
119
+ optional_ptr<Node> Node256::GetNextChildMutable(uint8_t &byte) {
120
+ for (idx_t i = byte; i < Node::NODE_256_CAPACITY; i++) {
121
+ if (children[i].HasMetadata()) {
122
+ byte = i;
123
+ return &children[i];
124
+ }
141
125
  }
126
+ return nullptr;
142
127
  }
143
128
 
144
129
  void Node256::Vacuum(ART &art, const ARTFlags &flags) {
145
130
 
146
131
  for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
147
- if (children[i].IsSet()) {
132
+ if (children[i].HasMetadata()) {
148
133
  children[i].Vacuum(art, flags);
149
134
  }
150
135
  }
@@ -2,16 +2,14 @@
2
2
 
3
3
  #include "duckdb/execution/index/art/prefix.hpp"
4
4
  #include "duckdb/execution/index/art/node16.hpp"
5
- #include "duckdb/storage/metadata/metadata_reader.hpp"
6
- #include "duckdb/storage/metadata/metadata_writer.hpp"
7
5
 
8
6
  namespace duckdb {
9
7
 
10
8
  Node4 &Node4::New(ART &art, Node &node) {
11
9
 
12
10
  node = Node::GetAllocator(art, NType::NODE_4).New();
13
- node.SetType((uint8_t)NType::NODE_4);
14
- auto &n4 = Node4::Get(art, node);
11
+ node.SetMetadata(static_cast<uint8_t>(NType::NODE_4));
12
+ auto &n4 = Node::RefMutable<Node4>(art, node, NType::NODE_4);
15
13
 
16
14
  n4.count = 0;
17
15
  return n4;
@@ -19,10 +17,8 @@ Node4 &Node4::New(ART &art, Node &node) {
19
17
 
20
18
  void Node4::Free(ART &art, Node &node) {
21
19
 
22
- D_ASSERT(node.IsSet());
23
- D_ASSERT(!node.IsSerialized());
24
-
25
- auto &n4 = Node4::Get(art, node);
20
+ D_ASSERT(node.HasMetadata());
21
+ auto &n4 = Node::RefMutable<Node4>(art, node, NType::NODE_4);
26
22
 
27
23
  // free all children
28
24
  for (idx_t i = 0; i < n4.count; i++) {
@@ -32,8 +28,8 @@ void Node4::Free(ART &art, Node &node) {
32
28
 
33
29
  Node4 &Node4::ShrinkNode16(ART &art, Node &node4, Node &node16) {
34
30
 
35
- auto &n4 = Node4::New(art, node4);
36
- auto &n16 = Node16::Get(art, node16);
31
+ auto &n4 = New(art, node4);
32
+ auto &n16 = Node::RefMutable<Node16>(art, node16, NType::NODE_16);
37
33
 
38
34
  D_ASSERT(n16.count <= Node::NODE_4_CAPACITY);
39
35
  n4.count = n16.count;
@@ -56,9 +52,8 @@ void Node4::InitializeMerge(ART &art, const ARTFlags &flags) {
56
52
 
57
53
  void Node4::InsertChild(ART &art, Node &node, const uint8_t byte, const Node child) {
58
54
 
59
- D_ASSERT(node.IsSet());
60
- D_ASSERT(!node.IsSerialized());
61
- auto &n4 = Node4::Get(art, node);
55
+ D_ASSERT(node.HasMetadata());
56
+ auto &n4 = Node::RefMutable<Node4>(art, node, NType::NODE_4);
62
57
 
63
58
  // ensure that there is no other child at the same byte
64
59
  for (idx_t i = 0; i < n4.count; i++) {
@@ -92,9 +87,8 @@ void Node4::InsertChild(ART &art, Node &node, const uint8_t byte, const Node chi
92
87
 
93
88
  void Node4::DeleteChild(ART &art, Node &node, Node &prefix, const uint8_t byte) {
94
89
 
95
- D_ASSERT(node.IsSet());
96
- D_ASSERT(!node.IsSerialized());
97
- auto &n4 = Node4::Get(art, node);
90
+ D_ASSERT(node.HasMetadata());
91
+ auto &n4 = Node::RefMutable<Node4>(art, node, NType::NODE_4);
98
92
 
99
93
  idx_t child_pos = 0;
100
94
  for (; child_pos < n4.count; child_pos++) {
@@ -126,7 +120,7 @@ void Node4::DeleteChild(ART &art, Node &node, Node &prefix, const uint8_t byte)
126
120
  auto old_n4_node = node;
127
121
 
128
122
  // get only child and concatenate prefixes
129
- auto child = *n4.GetChild(n4.key[0]);
123
+ auto child = *n4.GetChildMutable(n4.key[0]);
130
124
  Prefix::Concatenate(art, prefix, n4.key[0], child);
131
125
 
132
126
  n4.count--;
@@ -143,71 +137,46 @@ void Node4::ReplaceChild(const uint8_t byte, const Node child) {
143
137
  }
144
138
  }
145
139
 
146
- optional_ptr<Node> Node4::GetChild(const uint8_t byte) {
147
-
140
+ optional_ptr<const Node> Node4::GetChild(const uint8_t byte) const {
148
141
  for (idx_t i = 0; i < count; i++) {
149
142
  if (key[i] == byte) {
150
- D_ASSERT(children[i].IsSet());
143
+ D_ASSERT(children[i].HasMetadata());
151
144
  return &children[i];
152
145
  }
153
146
  }
154
147
  return nullptr;
155
148
  }
156
149
 
157
- optional_ptr<Node> Node4::GetNextChild(uint8_t &byte) {
158
-
150
+ optional_ptr<Node> Node4::GetChildMutable(const uint8_t byte) {
159
151
  for (idx_t i = 0; i < count; i++) {
160
- if (key[i] >= byte) {
161
- byte = key[i];
162
- D_ASSERT(children[i].IsSet());
152
+ if (key[i] == byte) {
153
+ D_ASSERT(children[i].HasMetadata());
163
154
  return &children[i];
164
155
  }
165
156
  }
166
157
  return nullptr;
167
158
  }
168
159
 
169
- BlockPointer Node4::Serialize(ART &art, MetadataWriter &writer) {
170
-
171
- // recurse into children and retrieve child block pointers
172
- vector<BlockPointer> child_block_pointers;
160
+ optional_ptr<const Node> Node4::GetNextChild(uint8_t &byte) const {
173
161
  for (idx_t i = 0; i < count; i++) {
174
- child_block_pointers.push_back(children[i].Serialize(art, writer));
175
- }
176
- for (idx_t i = count; i < Node::NODE_4_CAPACITY; i++) {
177
- child_block_pointers.emplace_back((block_id_t)DConstants::INVALID_INDEX, 0);
178
- }
179
-
180
- // get pointer and write fields
181
- auto block_pointer = writer.GetBlockPointer();
182
- writer.Write(NType::NODE_4);
183
- writer.Write<uint8_t>(count);
184
-
185
- // write key values
186
- for (idx_t i = 0; i < Node::NODE_4_CAPACITY; i++) {
187
- writer.Write(key[i]);
188
- }
189
-
190
- // write child block pointers
191
- for (auto &child_block_pointer : child_block_pointers) {
192
- writer.Write(child_block_pointer.block_id);
193
- writer.Write(child_block_pointer.offset);
162
+ if (key[i] >= byte) {
163
+ byte = key[i];
164
+ D_ASSERT(children[i].HasMetadata());
165
+ return &children[i];
166
+ }
194
167
  }
195
-
196
- return block_pointer;
168
+ return nullptr;
197
169
  }
198
170
 
199
- void Node4::Deserialize(MetadataReader &reader) {
200
- count = reader.Read<uint8_t>();
201
-
202
- // read key values
203
- for (idx_t i = 0; i < Node::NODE_4_CAPACITY; i++) {
204
- key[i] = reader.Read<uint8_t>();
205
- }
206
-
207
- // read child block pointers
208
- for (idx_t i = 0; i < Node::NODE_4_CAPACITY; i++) {
209
- children[i] = Node(reader);
171
+ optional_ptr<Node> Node4::GetNextChildMutable(uint8_t &byte) {
172
+ for (idx_t i = 0; i < count; i++) {
173
+ if (key[i] >= byte) {
174
+ byte = key[i];
175
+ D_ASSERT(children[i].HasMetadata());
176
+ return &children[i];
177
+ }
210
178
  }
179
+ return nullptr;
211
180
  }
212
181
 
213
182
  void Node4::Vacuum(ART &art, const ARTFlags &flags) {