duckdb 0.8.2-dev1791.0 → 0.8.2-dev1862.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 (48) hide show
  1. package/binding.gyp +1 -0
  2. package/package.json +1 -1
  3. package/src/duckdb/src/common/constants.cpp +2 -1
  4. package/src/duckdb/src/common/enum_util.cpp +5 -5
  5. package/src/duckdb/src/core_functions/function_list.cpp +2 -0
  6. package/src/duckdb/src/core_functions/scalar/debug/vector_type.cpp +23 -0
  7. package/src/duckdb/src/execution/index/art/art.cpp +49 -108
  8. package/src/duckdb/src/execution/index/art/art_key.cpp +0 -11
  9. package/src/duckdb/src/execution/index/art/fixed_size_allocator.cpp +10 -14
  10. package/src/duckdb/src/execution/index/art/iterator.cpp +13 -19
  11. package/src/duckdb/src/execution/index/art/leaf.cpp +290 -241
  12. package/src/duckdb/src/execution/index/art/node.cpp +104 -95
  13. package/src/duckdb/src/execution/index/art/node16.cpp +6 -6
  14. package/src/duckdb/src/execution/index/art/node256.cpp +6 -6
  15. package/src/duckdb/src/execution/index/art/node4.cpp +6 -6
  16. package/src/duckdb/src/execution/index/art/node48.cpp +6 -6
  17. package/src/duckdb/src/execution/index/art/prefix.cpp +49 -39
  18. package/src/duckdb/src/execution/operator/aggregate/physical_window.cpp +34 -1175
  19. package/src/duckdb/src/execution/operator/schema/physical_create_index.cpp +4 -14
  20. package/src/duckdb/src/execution/window_executor.cpp +1280 -0
  21. package/src/duckdb/src/execution/window_segment_tree.cpp +224 -117
  22. package/src/duckdb/src/function/table/read_csv.cpp +4 -3
  23. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  24. package/src/duckdb/src/include/duckdb/common/constants.hpp +2 -0
  25. package/src/duckdb/src/include/duckdb/common/type_util.hpp +8 -0
  26. package/src/duckdb/src/include/duckdb/common/typedefs.hpp +8 -0
  27. package/src/duckdb/src/include/duckdb/core_functions/scalar/debug_functions.hpp +27 -0
  28. package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +1 -1
  29. package/src/duckdb/src/include/duckdb/execution/index/art/art_key.hpp +0 -1
  30. package/src/duckdb/src/include/duckdb/execution/index/art/fixed_size_allocator.hpp +22 -24
  31. package/src/duckdb/src/include/duckdb/execution/index/art/iterator.hpp +2 -2
  32. package/src/duckdb/src/include/duckdb/execution/index/art/leaf.hpp +43 -40
  33. package/src/duckdb/src/include/duckdb/execution/index/art/node.hpp +119 -40
  34. package/src/duckdb/src/include/duckdb/execution/index/art/node16.hpp +1 -0
  35. package/src/duckdb/src/include/duckdb/execution/index/art/node256.hpp +1 -0
  36. package/src/duckdb/src/include/duckdb/execution/index/art/node4.hpp +1 -0
  37. package/src/duckdb/src/include/duckdb/execution/index/art/node48.hpp +1 -0
  38. package/src/duckdb/src/include/duckdb/execution/index/art/prefix.hpp +4 -2
  39. package/src/duckdb/src/include/duckdb/execution/window_executor.hpp +313 -0
  40. package/src/duckdb/src/include/duckdb/execution/window_segment_tree.hpp +60 -53
  41. package/src/duckdb/src/storage/compression/rle.cpp +52 -12
  42. package/src/duckdb/ub_src_core_functions_scalar_debug.cpp +2 -0
  43. package/src/duckdb/ub_src_execution.cpp +2 -0
  44. package/src/duckdb/ub_src_execution_index_art.cpp +0 -4
  45. package/src/duckdb/src/execution/index/art/leaf_segment.cpp +0 -52
  46. package/src/duckdb/src/execution/index/art/swizzleable_pointer.cpp +0 -22
  47. package/src/duckdb/src/include/duckdb/execution/index/art/leaf_segment.hpp +0 -38
  48. package/src/duckdb/src/include/duckdb/execution/index/art/swizzleable_pointer.hpp +0 -58
@@ -8,7 +8,6 @@
8
8
  #include "duckdb/execution/index/art/node16.hpp"
9
9
  #include "duckdb/execution/index/art/node4.hpp"
10
10
  #include "duckdb/execution/index/art/leaf.hpp"
11
- #include "duckdb/execution/index/art/leaf_segment.hpp"
12
11
  #include "duckdb/execution/index/art/prefix.hpp"
13
12
  #include "duckdb/storage/meta_block_reader.hpp"
14
13
  #include "duckdb/storage/meta_block_writer.hpp"
@@ -20,12 +19,24 @@ namespace duckdb {
20
19
  // Constructors / Destructors
21
20
  //===--------------------------------------------------------------------===//
22
21
 
23
- Node::Node() : SwizzleablePointer() {
24
- }
22
+ Node::Node(MetaBlockReader &reader) {
23
+
24
+ idx_t block_id = reader.Read<block_id_t>();
25
+ auto offset = reader.Read<uint32_t>();
26
+ Reset();
27
+
28
+ if (block_id == DConstants::INVALID_INDEX) {
29
+ return;
30
+ }
25
31
 
26
- Node::Node(MetaBlockReader &reader) : SwizzleablePointer(reader) {
32
+ SetSerialized();
33
+ SetPtr(block_id, offset);
27
34
  }
28
35
 
36
+ //===--------------------------------------------------------------------===//
37
+ // New / Free
38
+ //===--------------------------------------------------------------------===//
39
+
29
40
  void Node::New(ART &art, Node &node, const NType type) {
30
41
 
31
42
  // NOTE: leaves and prefixes should not pass through this function
@@ -50,22 +61,19 @@ void Node::New(ART &art, Node &node, const NType type) {
50
61
 
51
62
  void Node::Free(ART &art, Node &node) {
52
63
 
53
- // recursively free all nodes that are in-memory, and skip swizzled and empty nodes
64
+ // recursively free all nodes that are in-memory, and skip serialized and empty nodes
54
65
  if (!node.IsSet()) {
55
66
  return;
56
67
  }
57
68
 
58
- if (!node.IsSwizzled()) {
69
+ if (!node.IsSerialized()) {
59
70
 
60
71
  // free the children of the nodes
61
- auto type = node.DecodeARTNodeType();
72
+ auto type = node.GetType();
62
73
  switch (type) {
63
74
  case NType::PREFIX:
64
75
  Prefix::Free(art, node);
65
76
  break;
66
- case NType::LEAF_SEGMENT:
67
- LeafSegment::Free(art, node);
68
- break;
69
77
  case NType::LEAF:
70
78
  Leaf::Free(art, node);
71
79
  break;
@@ -81,6 +89,9 @@ void Node::Free(ART &art, Node &node) {
81
89
  case NType::NODE_256:
82
90
  Node256::Free(art, node);
83
91
  break;
92
+ case NType::LEAF_INLINED:
93
+ node.Reset();
94
+ return;
84
95
  }
85
96
 
86
97
  Node::GetAllocator(art, type).Free(node);
@@ -96,9 +107,9 @@ void Node::Free(ART &art, Node &node) {
96
107
 
97
108
  void Node::ReplaceChild(const ART &art, const uint8_t byte, const Node child) {
98
109
 
99
- D_ASSERT(!IsSwizzled());
110
+ D_ASSERT(!IsSerialized());
100
111
 
101
- switch (DecodeARTNodeType()) {
112
+ switch (GetType()) {
102
113
  case NType::NODE_4:
103
114
  return Node4::Get(art, *this).ReplaceChild(byte, child);
104
115
  case NType::NODE_16:
@@ -114,7 +125,7 @@ void Node::ReplaceChild(const ART &art, const uint8_t byte, const Node child) {
114
125
 
115
126
  void Node::InsertChild(ART &art, Node &node, const uint8_t byte, const Node child) {
116
127
 
117
- switch (node.DecodeARTNodeType()) {
128
+ switch (node.GetType()) {
118
129
  case NType::NODE_4:
119
130
  return Node4::InsertChild(art, node, byte, child);
120
131
  case NType::NODE_16:
@@ -134,7 +145,7 @@ void Node::InsertChild(ART &art, Node &node, const uint8_t byte, const Node chil
134
145
 
135
146
  void Node::DeleteChild(ART &art, Node &node, Node &prefix, const uint8_t byte) {
136
147
 
137
- switch (node.DecodeARTNodeType()) {
148
+ switch (node.GetType()) {
138
149
  case NType::NODE_4:
139
150
  return Node4::DeleteChild(art, node, prefix, byte);
140
151
  case NType::NODE_16:
@@ -154,10 +165,10 @@ void Node::DeleteChild(ART &art, Node &node, Node &prefix, const uint8_t byte) {
154
165
 
155
166
  optional_ptr<Node> Node::GetChild(ART &art, const uint8_t byte) const {
156
167
 
157
- D_ASSERT(IsSet() && !IsSwizzled());
168
+ D_ASSERT(IsSet() && !IsSerialized());
158
169
 
159
170
  optional_ptr<Node> child;
160
- switch (DecodeARTNodeType()) {
171
+ switch (GetType()) {
161
172
  case NType::NODE_4:
162
173
  child = Node4::Get(art, *this).GetChild(byte);
163
174
  break;
@@ -175,7 +186,7 @@ optional_ptr<Node> Node::GetChild(ART &art, const uint8_t byte) const {
175
186
  }
176
187
 
177
188
  // deserialize the ART node before returning it
178
- if (child && child->IsSwizzled()) {
189
+ if (child && child->IsSerialized()) {
179
190
  child->Deserialize(art);
180
191
  }
181
192
  return child;
@@ -183,10 +194,10 @@ optional_ptr<Node> Node::GetChild(ART &art, const uint8_t byte) const {
183
194
 
184
195
  optional_ptr<Node> Node::GetNextChild(ART &art, uint8_t &byte, const bool deserialize) const {
185
196
 
186
- D_ASSERT(IsSet() && !IsSwizzled());
197
+ D_ASSERT(IsSet() && !IsSerialized());
187
198
 
188
199
  optional_ptr<Node> child;
189
- switch (DecodeARTNodeType()) {
200
+ switch (GetType()) {
190
201
  case NType::NODE_4:
191
202
  child = Node4::Get(art, *this).GetNextChild(byte);
192
203
  break;
@@ -204,7 +215,7 @@ optional_ptr<Node> Node::GetNextChild(ART &art, uint8_t &byte, const bool deseri
204
215
  }
205
216
 
206
217
  // deserialize the ART node before returning it
207
- if (child && deserialize && child->IsSwizzled()) {
218
+ if (child && deserialize && child->IsSerialized()) {
208
219
  child->Deserialize(art);
209
220
  }
210
221
  return child;
@@ -219,15 +230,15 @@ BlockPointer Node::Serialize(ART &art, MetaBlockWriter &writer) {
219
230
  if (!IsSet()) {
220
231
  return {(block_id_t)DConstants::INVALID_INDEX, 0};
221
232
  }
222
- if (IsSwizzled()) {
233
+ if (IsSerialized()) {
223
234
  Deserialize(art);
224
235
  }
225
236
 
226
- switch (DecodeARTNodeType()) {
237
+ switch (GetType()) {
227
238
  case NType::PREFIX:
228
239
  return Prefix::Get(art, *this).Serialize(art, writer);
229
240
  case NType::LEAF:
230
- return Leaf::Get(art, *this).Serialize(art, writer);
241
+ return Leaf::Serialize(art, *this, writer);
231
242
  case NType::NODE_4:
232
243
  return Node4::Get(art, *this).Serialize(art, writer);
233
244
  case NType::NODE_16:
@@ -236,27 +247,35 @@ BlockPointer Node::Serialize(ART &art, MetaBlockWriter &writer) {
236
247
  return Node48::Get(art, *this).Serialize(art, writer);
237
248
  case NType::NODE_256:
238
249
  return Node256::Get(art, *this).Serialize(art, writer);
239
- default:
240
- throw InternalException("Invalid node type for Serialize.");
250
+ case NType::LEAF_INLINED:
251
+ return Leaf::Serialize(art, *this, writer);
241
252
  }
253
+ throw InternalException("Invalid node type for Serialize.");
242
254
  }
243
255
 
244
256
  void Node::Deserialize(ART &art) {
245
257
 
246
- MetaBlockReader reader(art.table_io_manager.GetIndexBlockManager(), buffer_id);
247
- reader.offset = offset;
248
- type = reader.Read<uint8_t>();
249
- swizzle_flag = 0;
258
+ D_ASSERT(IsSet() && IsSerialized());
259
+
260
+ MetaBlockReader reader(art.table_io_manager.GetIndexBlockManager(), GetBufferId());
261
+ reader.offset = GetOffset();
262
+ Reset();
263
+ SetType(reader.Read<uint8_t>());
264
+
265
+ auto decoded_type = GetType();
266
+ if (decoded_type == NType::LEAF_INLINED) {
267
+ SetRowId(reader.Read<row_t>());
268
+ return;
269
+ }
250
270
 
251
- auto decoded_type = DecodeARTNodeType();
252
- SetPtr(Node::GetAllocator(art, decoded_type).New());
253
- type = (uint8_t)decoded_type;
271
+ *this = Node::GetAllocator(art, decoded_type).New();
272
+ SetType((uint8_t)decoded_type);
254
273
 
255
274
  switch (decoded_type) {
256
275
  case NType::PREFIX:
257
276
  return Prefix::Get(art, *this).Deserialize(reader);
258
277
  case NType::LEAF:
259
- return Leaf::Get(art, *this).Deserialize(art, reader);
278
+ return Leaf::Deserialize(art, *this, reader);
260
279
  case NType::NODE_4:
261
280
  return Node4::Get(art, *this).Deserialize(reader);
262
281
  case NType::NODE_16:
@@ -277,32 +296,27 @@ void Node::Deserialize(ART &art) {
277
296
  string Node::VerifyAndToString(ART &art, const bool only_verify) {
278
297
 
279
298
  D_ASSERT(IsSet());
280
- if (IsSwizzled()) {
281
- return only_verify ? "" : "swizzled";
299
+ if (IsSerialized()) {
300
+ return only_verify ? "" : "serialized";
282
301
  }
283
302
 
284
- auto type = DecodeARTNodeType();
285
- if (type == NType::LEAF) {
286
- auto str = Leaf::Get(art, *this).VerifyAndToString(art, only_verify);
303
+ if (GetType() == NType::LEAF || GetType() == NType::LEAF_INLINED) {
304
+ auto str = Leaf::VerifyAndToString(art, *this);
287
305
  return only_verify ? "" : "\n" + str;
288
306
  }
289
- if (type == NType::PREFIX) {
290
- auto str = Prefix::Get(art, *this).VerifyAndToString(art, only_verify);
307
+ if (GetType() == NType::PREFIX) {
308
+ auto str = Prefix::Get(art, *this).VerifyAndToString(art, *this, only_verify);
291
309
  return only_verify ? "" : "\n" + str;
292
310
  }
293
311
 
294
312
  string str = "Node" + to_string(GetCapacity()) + ": [";
295
-
296
- idx_t child_count = 0;
297
313
  uint8_t byte = 0;
298
314
  auto child = GetNextChild(art, byte, false);
299
315
 
300
316
  while (child) {
301
-
302
- child_count++;
303
- if (child->IsSwizzled()) {
317
+ if (child->IsSerialized()) {
304
318
  if (!only_verify) {
305
- str += "(swizzled)";
319
+ str += "(serialized)";
306
320
  }
307
321
  } else {
308
322
  str += "(" + to_string(byte) + ", " + child->VerifyAndToString(art, only_verify) + ")";
@@ -315,17 +329,14 @@ string Node::VerifyAndToString(ART &art, const bool only_verify) {
315
329
  child = GetNextChild(art, byte, false);
316
330
  }
317
331
 
318
- (void)child_count;
319
- // ensure that the child count is at least two
320
- D_ASSERT(child_count > 1);
321
332
  return only_verify ? "" : "\n" + str + "]";
322
333
  }
323
334
 
324
335
  idx_t Node::GetCapacity() const {
325
336
 
326
- D_ASSERT(!IsSwizzled());
337
+ D_ASSERT(!IsSerialized());
327
338
 
328
- switch (DecodeARTNodeType()) {
339
+ switch (GetType()) {
329
340
  case NType::NODE_4:
330
341
  return Node::NODE_4_CAPACITY;
331
342
  case NType::NODE_16:
@@ -362,19 +373,14 @@ FixedSizeAllocator &Node::GetAllocator(const ART &art, NType type) {
362
373
  void Node::InitializeMerge(ART &art, const ARTFlags &flags) {
363
374
 
364
375
  // the index is fully in memory during CREATE [UNIQUE] INDEX statements
365
- D_ASSERT(IsSet() && !IsSwizzled());
376
+ D_ASSERT(IsSet() && !IsSerialized());
366
377
 
367
- auto type = DecodeARTNodeType();
368
- switch (type) {
378
+ switch (GetType()) {
369
379
  case NType::PREFIX:
370
380
  Prefix::Get(art, *this).InitializeMerge(art, flags);
371
381
  break;
372
382
  case NType::LEAF:
373
- // if not all leaves are inlined
374
- if (flags.merge_buffer_counts[(uint8_t)NType::LEAF_SEGMENT - 1] != 0) {
375
- // initialize leaf segments
376
- Leaf::Get(art, *this).InitializeMerge(art, flags.merge_buffer_counts[(uint8_t)NType::LEAF_SEGMENT - 1]);
377
- }
383
+ Leaf::InitializeMerge(art, *this, flags);
378
384
  break;
379
385
  case NType::NODE_4:
380
386
  Node4::Get(art, *this).InitializeMerge(art, flags);
@@ -388,11 +394,12 @@ void Node::InitializeMerge(ART &art, const ARTFlags &flags) {
388
394
  case NType::NODE_256:
389
395
  Node256::Get(art, *this).InitializeMerge(art, flags);
390
396
  break;
391
- default:
392
- throw InternalException("Invalid node type for InitializeMerge.");
397
+ case NType::LEAF_INLINED:
398
+ return;
393
399
  }
394
400
 
395
- buffer_id += flags.merge_buffer_counts[(uint8_t)type - 1];
401
+ // NOTE: this works because the rightmost 32 bits contain the buffer ID
402
+ data += flags.merge_buffer_counts[(uint8_t)GetType() - 1];
396
403
  }
397
404
 
398
405
  bool Node::Merge(ART &art, Node &other) {
@@ -412,7 +419,7 @@ bool MergePrefixContainsOtherPrefix(ART &art, reference<Node> &l_node, reference
412
419
  // r_node's prefix contains l_node's prefix
413
420
  // l_node cannot be a leaf, otherwise the key represented by l_node would be a subset of another key
414
421
  // which is not possible by our construction
415
- D_ASSERT(l_node.get().DecodeARTNodeType() != NType::LEAF);
422
+ D_ASSERT(l_node.get().GetType() != NType::LEAF && l_node.get().GetType() != NType::LEAF_INLINED);
416
423
 
417
424
  // test if the next byte (mismatch_position) in r_node (prefix) exists in l_node
418
425
  auto mismatch_byte = Prefix::GetByte(art, r_node, mismatch_position);
@@ -454,11 +461,10 @@ bool Node::ResolvePrefixes(ART &art, Node &other) {
454
461
 
455
462
  // NOTE: we always merge into the left ART
456
463
 
457
- D_ASSERT(IsSet());
458
- D_ASSERT(other.IsSet());
464
+ D_ASSERT(IsSet() && other.IsSet());
459
465
 
460
466
  // case 1: both nodes have no prefix
461
- if (DecodeARTNodeType() != NType::PREFIX && other.DecodeARTNodeType() != NType::PREFIX) {
467
+ if (GetType() != NType::PREFIX && other.GetType() != NType::PREFIX) {
462
468
  return MergeInternal(art, other);
463
469
  }
464
470
 
@@ -468,7 +474,7 @@ bool Node::ResolvePrefixes(ART &art, Node &other) {
468
474
  idx_t mismatch_position = DConstants::INVALID_INDEX;
469
475
 
470
476
  // traverse prefixes
471
- if (l_node.get().DecodeARTNodeType() == NType::PREFIX && r_node.get().DecodeARTNodeType() == NType::PREFIX) {
477
+ if (l_node.get().GetType() == NType::PREFIX && r_node.get().GetType() == NType::PREFIX) {
472
478
 
473
479
  if (!Prefix::Traverse(art, l_node, r_node, mismatch_position)) {
474
480
  return false;
@@ -481,7 +487,7 @@ bool Node::ResolvePrefixes(ART &art, Node &other) {
481
487
  } else {
482
488
 
483
489
  // l_prefix contains r_prefix
484
- if (l_node.get().DecodeARTNodeType() == NType::PREFIX) {
490
+ if (l_node.get().GetType() == NType::PREFIX) {
485
491
  swap(*this, other);
486
492
  }
487
493
  mismatch_position = 0;
@@ -489,7 +495,7 @@ bool Node::ResolvePrefixes(ART &art, Node &other) {
489
495
  D_ASSERT(mismatch_position != DConstants::INVALID_INDEX);
490
496
 
491
497
  // case 2: one prefix contains the other prefix
492
- if (l_node.get().DecodeARTNodeType() != NType::PREFIX && r_node.get().DecodeARTNodeType() == NType::PREFIX) {
498
+ if (l_node.get().GetType() != NType::PREFIX && r_node.get().GetType() == NType::PREFIX) {
493
499
  return MergePrefixContainsOtherPrefix(art, l_node, r_node, mismatch_position);
494
500
  }
495
501
 
@@ -501,13 +507,12 @@ bool Node::ResolvePrefixes(ART &art, Node &other) {
501
507
  bool Node::MergeInternal(ART &art, Node &other) {
502
508
 
503
509
  D_ASSERT(IsSet() && other.IsSet());
504
- D_ASSERT(DecodeARTNodeType() != NType::PREFIX && DecodeARTNodeType() != NType::LEAF_SEGMENT);
505
- D_ASSERT(other.DecodeARTNodeType() != NType::PREFIX && other.DecodeARTNodeType() != NType::LEAF_SEGMENT);
510
+ D_ASSERT(GetType() != NType::PREFIX && other.GetType() != NType::PREFIX);
506
511
 
507
512
  // always try to merge the smaller node into the bigger node
508
513
  // because maybe there is enough free space in the bigger node to fit the smaller one
509
514
  // without too much recursion
510
- if (DecodeARTNodeType() < other.DecodeARTNodeType()) {
515
+ if (GetType() < other.GetType()) {
511
516
  swap(*this, other);
512
517
  }
513
518
 
@@ -515,14 +520,14 @@ bool Node::MergeInternal(ART &art, Node &other) {
515
520
  auto &l_node = *this;
516
521
  auto &r_node = other;
517
522
 
518
- if (r_node.DecodeARTNodeType() == NType::LEAF) {
519
- D_ASSERT(l_node.DecodeARTNodeType() == NType::LEAF);
523
+ if (r_node.GetType() == NType::LEAF || r_node.GetType() == NType::LEAF_INLINED) {
524
+ D_ASSERT(l_node.GetType() == NType::LEAF || l_node.GetType() == NType::LEAF_INLINED);
520
525
 
521
526
  if (art.IsUnique()) {
522
527
  return false;
523
528
  }
524
529
 
525
- Leaf::Get(art, l_node).Merge(art, r_node);
530
+ Leaf::Merge(art, l_node, r_node);
526
531
  return true;
527
532
  }
528
533
 
@@ -559,38 +564,42 @@ bool Node::MergeInternal(ART &art, Node &other) {
559
564
  // Vacuum
560
565
  //===--------------------------------------------------------------------===//
561
566
 
562
- void Node::Vacuum(ART &art, Node &node, const ARTFlags &flags) {
567
+ void Node::Vacuum(ART &art, const ARTFlags &flags) {
563
568
 
564
- if (node.IsSwizzled()) {
569
+ D_ASSERT(IsSet());
570
+ if (IsSerialized()) {
565
571
  return;
566
572
  }
567
573
 
568
- auto type = node.DecodeARTNodeType();
569
- auto &allocator = Node::GetAllocator(art, type);
570
- auto needs_vacuum = flags.vacuum_flags[node.type - 1] && allocator.NeedsVacuum(node);
571
- if (needs_vacuum) {
572
- node.SetPtr(allocator.VacuumPointer(node));
573
- node.type = (uint8_t)type;
574
+ auto node_type = GetType();
575
+ if (node_type == NType::LEAF_INLINED) {
576
+ return;
574
577
  }
575
-
576
- switch (type) {
577
- case NType::PREFIX:
578
- return Prefix::Get(art, node).Vacuum(art, flags);
579
- case NType::LEAF: {
580
- // possibly vacuum leaf segments, if not all leaves are inlined
581
- if (flags.vacuum_flags[(uint8_t)NType::LEAF_SEGMENT - 1]) {
582
- Leaf::Get(art, node).Vacuum(art);
578
+ if (node_type == NType::LEAF) {
579
+ if (flags.vacuum_flags[(uint8_t)GetType() - 1]) {
580
+ Leaf::Vacuum(art, *this);
583
581
  }
584
582
  return;
585
583
  }
584
+
585
+ auto &allocator = Node::GetAllocator(art, node_type);
586
+ auto needs_vacuum = flags.vacuum_flags[(uint8_t)GetType() - 1] && allocator.NeedsVacuum(*this);
587
+ if (needs_vacuum) {
588
+ *this = allocator.VacuumPointer(*this);
589
+ SetType((uint8_t)node_type);
590
+ }
591
+
592
+ switch (node_type) {
593
+ case NType::PREFIX:
594
+ return Prefix::Get(art, *this).Vacuum(art, flags);
586
595
  case NType::NODE_4:
587
- return Node4::Get(art, node).Vacuum(art, flags);
596
+ return Node4::Get(art, *this).Vacuum(art, flags);
588
597
  case NType::NODE_16:
589
- return Node16::Get(art, node).Vacuum(art, flags);
598
+ return Node16::Get(art, *this).Vacuum(art, flags);
590
599
  case NType::NODE_48:
591
- return Node48::Get(art, node).Vacuum(art, flags);
600
+ return Node48::Get(art, *this).Vacuum(art, flags);
592
601
  case NType::NODE_256:
593
- return Node256::Get(art, node).Vacuum(art, flags);
602
+ return Node256::Get(art, *this).Vacuum(art, flags);
594
603
  default:
595
604
  throw InternalException("Invalid node type for Vacuum.");
596
605
  }
@@ -9,8 +9,8 @@ namespace duckdb {
9
9
 
10
10
  Node16 &Node16::New(ART &art, Node &node) {
11
11
 
12
- node.SetPtr(Node::GetAllocator(art, NType::NODE_16).New());
13
- node.type = (uint8_t)NType::NODE_16;
12
+ node = Node::GetAllocator(art, NType::NODE_16).New();
13
+ node.SetType((uint8_t)NType::NODE_16);
14
14
  auto &n16 = Node16::Get(art, node);
15
15
 
16
16
  n16.count = 0;
@@ -20,7 +20,7 @@ Node16 &Node16::New(ART &art, Node &node) {
20
20
  void Node16::Free(ART &art, Node &node) {
21
21
 
22
22
  D_ASSERT(node.IsSet());
23
- D_ASSERT(!node.IsSwizzled());
23
+ D_ASSERT(!node.IsSerialized());
24
24
 
25
25
  auto &n16 = Node16::Get(art, node);
26
26
 
@@ -76,7 +76,7 @@ void Node16::InitializeMerge(ART &art, const ARTFlags &flags) {
76
76
  void Node16::InsertChild(ART &art, Node &node, const uint8_t byte, const Node child) {
77
77
 
78
78
  D_ASSERT(node.IsSet());
79
- D_ASSERT(!node.IsSwizzled());
79
+ D_ASSERT(!node.IsSerialized());
80
80
  auto &n16 = Node16::Get(art, node);
81
81
 
82
82
  // ensure that there is no other child at the same byte
@@ -112,7 +112,7 @@ void Node16::InsertChild(ART &art, Node &node, const uint8_t byte, const Node ch
112
112
  void Node16::DeleteChild(ART &art, Node &node, const uint8_t byte) {
113
113
 
114
114
  D_ASSERT(node.IsSet());
115
- D_ASSERT(!node.IsSwizzled());
115
+ D_ASSERT(!node.IsSerialized());
116
116
  auto &n16 = Node16::Get(art, node);
117
117
 
118
118
  idx_t child_pos = 0;
@@ -221,7 +221,7 @@ void Node16::Deserialize(MetaBlockReader &reader) {
221
221
  void Node16::Vacuum(ART &art, const ARTFlags &flags) {
222
222
 
223
223
  for (idx_t i = 0; i < count; i++) {
224
- Node::Vacuum(art, children[i], flags);
224
+ children[i].Vacuum(art, flags);
225
225
  }
226
226
  }
227
227
 
@@ -8,8 +8,8 @@ namespace duckdb {
8
8
 
9
9
  Node256 &Node256::New(ART &art, Node &node) {
10
10
 
11
- node.SetPtr(Node::GetAllocator(art, NType::NODE_256).New());
12
- node.type = (uint8_t)NType::NODE_256;
11
+ node = Node::GetAllocator(art, NType::NODE_256).New();
12
+ node.SetType((uint8_t)NType::NODE_256);
13
13
  auto &n256 = Node256::Get(art, node);
14
14
 
15
15
  n256.count = 0;
@@ -23,7 +23,7 @@ Node256 &Node256::New(ART &art, Node &node) {
23
23
  void Node256::Free(ART &art, Node &node) {
24
24
 
25
25
  D_ASSERT(node.IsSet());
26
- D_ASSERT(!node.IsSwizzled());
26
+ D_ASSERT(!node.IsSerialized());
27
27
 
28
28
  auto &n256 = Node256::Get(art, node);
29
29
 
@@ -70,7 +70,7 @@ void Node256::InitializeMerge(ART &art, const ARTFlags &flags) {
70
70
  void Node256::InsertChild(ART &art, Node &node, const uint8_t byte, const Node child) {
71
71
 
72
72
  D_ASSERT(node.IsSet());
73
- D_ASSERT(!node.IsSwizzled());
73
+ D_ASSERT(!node.IsSerialized());
74
74
  auto &n256 = Node256::Get(art, node);
75
75
 
76
76
  // ensure that there is no other child at the same byte
@@ -84,7 +84,7 @@ void Node256::InsertChild(ART &art, Node &node, const uint8_t byte, const Node c
84
84
  void Node256::DeleteChild(ART &art, Node &node, const uint8_t byte) {
85
85
 
86
86
  D_ASSERT(node.IsSet());
87
- D_ASSERT(!node.IsSwizzled());
87
+ D_ASSERT(!node.IsSerialized());
88
88
  auto &n256 = Node256::Get(art, node);
89
89
 
90
90
  // free the child and decrease the count
@@ -145,7 +145,7 @@ void Node256::Vacuum(ART &art, const ARTFlags &flags) {
145
145
 
146
146
  for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
147
147
  if (children[i].IsSet()) {
148
- Node::Vacuum(art, children[i], flags);
148
+ children[i].Vacuum(art, flags);
149
149
  }
150
150
  }
151
151
  }
@@ -9,8 +9,8 @@ namespace duckdb {
9
9
 
10
10
  Node4 &Node4::New(ART &art, Node &node) {
11
11
 
12
- node.SetPtr(Node::GetAllocator(art, NType::NODE_4).New());
13
- node.type = (uint8_t)NType::NODE_4;
12
+ node = Node::GetAllocator(art, NType::NODE_4).New();
13
+ node.SetType((uint8_t)NType::NODE_4);
14
14
  auto &n4 = Node4::Get(art, node);
15
15
 
16
16
  n4.count = 0;
@@ -20,7 +20,7 @@ Node4 &Node4::New(ART &art, Node &node) {
20
20
  void Node4::Free(ART &art, Node &node) {
21
21
 
22
22
  D_ASSERT(node.IsSet());
23
- D_ASSERT(!node.IsSwizzled());
23
+ D_ASSERT(!node.IsSerialized());
24
24
 
25
25
  auto &n4 = Node4::Get(art, node);
26
26
 
@@ -57,7 +57,7 @@ void Node4::InitializeMerge(ART &art, const ARTFlags &flags) {
57
57
  void Node4::InsertChild(ART &art, Node &node, const uint8_t byte, const Node child) {
58
58
 
59
59
  D_ASSERT(node.IsSet());
60
- D_ASSERT(!node.IsSwizzled());
60
+ D_ASSERT(!node.IsSerialized());
61
61
  auto &n4 = Node4::Get(art, node);
62
62
 
63
63
  // ensure that there is no other child at the same byte
@@ -93,7 +93,7 @@ void Node4::InsertChild(ART &art, Node &node, const uint8_t byte, const Node chi
93
93
  void Node4::DeleteChild(ART &art, Node &node, Node &prefix, const uint8_t byte) {
94
94
 
95
95
  D_ASSERT(node.IsSet());
96
- D_ASSERT(!node.IsSwizzled());
96
+ D_ASSERT(!node.IsSerialized());
97
97
  auto &n4 = Node4::Get(art, node);
98
98
 
99
99
  idx_t child_pos = 0;
@@ -214,7 +214,7 @@ void Node4::Deserialize(MetaBlockReader &reader) {
214
214
  void Node4::Vacuum(ART &art, const ARTFlags &flags) {
215
215
 
216
216
  for (idx_t i = 0; i < count; i++) {
217
- Node::Vacuum(art, children[i], flags);
217
+ children[i].Vacuum(art, flags);
218
218
  }
219
219
  }
220
220
 
@@ -9,8 +9,8 @@ namespace duckdb {
9
9
 
10
10
  Node48 &Node48::New(ART &art, Node &node) {
11
11
 
12
- node.SetPtr(Node::GetAllocator(art, NType::NODE_48).New());
13
- node.type = (uint8_t)NType::NODE_48;
12
+ node = Node::GetAllocator(art, NType::NODE_48).New();
13
+ node.SetType((uint8_t)NType::NODE_48);
14
14
  auto &n48 = Node48::Get(art, node);
15
15
 
16
16
  n48.count = 0;
@@ -29,7 +29,7 @@ Node48 &Node48::New(ART &art, Node &node) {
29
29
  void Node48::Free(ART &art, Node &node) {
30
30
 
31
31
  D_ASSERT(node.IsSet());
32
- D_ASSERT(!node.IsSwizzled());
32
+ D_ASSERT(!node.IsSerialized());
33
33
 
34
34
  auto &n48 = Node48::Get(art, node);
35
35
 
@@ -109,7 +109,7 @@ void Node48::InitializeMerge(ART &art, const ARTFlags &flags) {
109
109
  void Node48::InsertChild(ART &art, Node &node, const uint8_t byte, const Node child) {
110
110
 
111
111
  D_ASSERT(node.IsSet());
112
- D_ASSERT(!node.IsSwizzled());
112
+ D_ASSERT(!node.IsSerialized());
113
113
  auto &n48 = Node48::Get(art, node);
114
114
 
115
115
  // ensure that there is no other child at the same byte
@@ -141,7 +141,7 @@ void Node48::InsertChild(ART &art, Node &node, const uint8_t byte, const Node ch
141
141
  void Node48::DeleteChild(ART &art, Node &node, const uint8_t byte) {
142
142
 
143
143
  D_ASSERT(node.IsSet());
144
- D_ASSERT(!node.IsSwizzled());
144
+ D_ASSERT(!node.IsSerialized());
145
145
  auto &n48 = Node48::Get(art, node);
146
146
 
147
147
  // free the child and decrease the count
@@ -214,7 +214,7 @@ void Node48::Vacuum(ART &art, const ARTFlags &flags) {
214
214
 
215
215
  for (idx_t i = 0; i < Node::NODE_256_CAPACITY; i++) {
216
216
  if (child_index[i] != Node::EMPTY_MARKER) {
217
- Node::Vacuum(art, children[child_index[i]], flags);
217
+ children[child_index[i]].Vacuum(art, flags);
218
218
  }
219
219
  }
220
220
  }