duckdb 0.8.2-dev1791.0 → 0.8.2-dev1859.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 (47) 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/version/pragma_version.cpp +2 -2
  23. package/src/duckdb/src/include/duckdb/common/constants.hpp +2 -0
  24. package/src/duckdb/src/include/duckdb/common/type_util.hpp +8 -0
  25. package/src/duckdb/src/include/duckdb/common/typedefs.hpp +8 -0
  26. package/src/duckdb/src/include/duckdb/core_functions/scalar/debug_functions.hpp +27 -0
  27. package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +1 -1
  28. package/src/duckdb/src/include/duckdb/execution/index/art/art_key.hpp +0 -1
  29. package/src/duckdb/src/include/duckdb/execution/index/art/fixed_size_allocator.hpp +22 -24
  30. package/src/duckdb/src/include/duckdb/execution/index/art/iterator.hpp +2 -2
  31. package/src/duckdb/src/include/duckdb/execution/index/art/leaf.hpp +43 -40
  32. package/src/duckdb/src/include/duckdb/execution/index/art/node.hpp +119 -40
  33. package/src/duckdb/src/include/duckdb/execution/index/art/node16.hpp +1 -0
  34. package/src/duckdb/src/include/duckdb/execution/index/art/node256.hpp +1 -0
  35. package/src/duckdb/src/include/duckdb/execution/index/art/node4.hpp +1 -0
  36. package/src/duckdb/src/include/duckdb/execution/index/art/node48.hpp +1 -0
  37. package/src/duckdb/src/include/duckdb/execution/index/art/prefix.hpp +4 -2
  38. package/src/duckdb/src/include/duckdb/execution/window_executor.hpp +313 -0
  39. package/src/duckdb/src/include/duckdb/execution/window_segment_tree.hpp +60 -53
  40. package/src/duckdb/src/storage/compression/rle.cpp +52 -12
  41. package/src/duckdb/ub_src_core_functions_scalar_debug.cpp +2 -0
  42. package/src/duckdb/ub_src_execution.cpp +2 -0
  43. package/src/duckdb/ub_src_execution_index_art.cpp +0 -4
  44. package/src/duckdb/src/execution/index/art/leaf_segment.cpp +0 -52
  45. package/src/duckdb/src/execution/index/art/swizzleable_pointer.cpp +0 -22
  46. package/src/duckdb/src/include/duckdb/execution/index/art/leaf_segment.hpp +0 -38
  47. package/src/duckdb/src/include/duckdb/execution/index/art/swizzleable_pointer.hpp +0 -58
@@ -8,16 +8,14 @@
8
8
 
9
9
  #pragma once
10
10
 
11
- #include "duckdb/common/unordered_set.hpp"
12
- #include "duckdb/common/constants.hpp"
13
- #include "duckdb/common/vector.hpp"
14
- #include "duckdb/common/assert.hpp"
15
11
  #include "duckdb/common/types/validity_mask.hpp"
12
+ #include "duckdb/common/unordered_set.hpp"
16
13
  #include "duckdb/storage/buffer_manager.hpp"
17
- #include "duckdb/execution/index/art/swizzleable_pointer.hpp"
14
+ #include "duckdb/execution/index/art/node.hpp"
18
15
 
19
16
  namespace duckdb {
20
17
 
18
+ // structs
21
19
  struct BufferEntry {
22
20
  BufferEntry(const data_ptr_t &ptr, const idx_t &allocation_count) : ptr(ptr), allocation_count(allocation_count) {
23
21
  }
@@ -26,7 +24,7 @@ struct BufferEntry {
26
24
  };
27
25
 
28
26
  //! The FixedSizeAllocator provides pointers to fixed-size sections of pre-allocated memory buffers.
29
- //! The pointers are SwizzleablePointers, and the leftmost byte (swizzle flag and type) must always be zero.
27
+ //! The pointers are Node pointers, and the leftmost byte (serialize flag and type) must always be zero.
30
28
  class FixedSizeAllocator {
31
29
  public:
32
30
  //! Fixed size of the buffers
@@ -65,17 +63,17 @@ public:
65
63
  Allocator &allocator;
66
64
 
67
65
  public:
68
- //! Get a new pointer to data, might cause a new buffer allocation
69
- SwizzleablePointer New();
70
- //! Free the data of the pointer
71
- void Free(const SwizzleablePointer ptr);
72
- //! Get the data of the pointer
66
+ //! Get a new Node pointer to data, might cause a new buffer allocation
67
+ Node New();
68
+ //! Free the data of the Node pointer
69
+ void Free(const Node ptr);
70
+ //! Get the data of the Node pointer
73
71
  template <class T>
74
- inline T *Get(const SwizzleablePointer ptr) const {
72
+ inline T *Get(const Node ptr) const {
75
73
  return (T *)Get(ptr);
76
74
  }
77
75
 
78
- //! Resets the allocator, which e.g. becomes necessary during DELETE FROM table
76
+ //! Resets the allocator, e.g., becomes necessary during DELETE FROM table
79
77
  void Reset();
80
78
 
81
79
  //! Returns the allocated memory size in bytes
@@ -83,32 +81,32 @@ public:
83
81
  return buffers.size() * BUFFER_ALLOC_SIZE;
84
82
  }
85
83
 
86
- //! Merge another FixedSizeAllocator with this allocator. Both must have the same allocation size
84
+ //! Merge another FixedSizeAllocator into this allocator. Both must have the same allocation size
87
85
  void Merge(FixedSizeAllocator &other);
88
86
 
89
87
  //! Initialize a vacuum operation, and return true, if the allocator needs a vacuum
90
88
  bool InitializeVacuum();
91
89
  //! Finalize a vacuum operation by freeing all buffers exceeding the min_vacuum_buffer_id
92
90
  void FinalizeVacuum();
93
- //! Returns true, if a pointer qualifies for a vacuum operation, and false otherwise
94
- inline bool NeedsVacuum(const SwizzleablePointer ptr) const {
95
- if (ptr.buffer_id >= min_vacuum_buffer_id) {
91
+ //! Returns true, if a Node pointer qualifies for a vacuum operation, and false otherwise
92
+ inline bool NeedsVacuum(const Node ptr) const {
93
+ if (ptr.GetBufferId() >= min_vacuum_buffer_id) {
96
94
  return true;
97
95
  }
98
96
  return false;
99
97
  }
100
- //! Vacuums a pointer
101
- SwizzleablePointer VacuumPointer(const SwizzleablePointer ptr);
98
+ //! Vacuums a Node pointer
99
+ Node VacuumPointer(const Node ptr);
102
100
 
103
101
  //! Verify that the allocation counts match the existing positions on the buffers
104
102
  void Verify() const;
105
103
 
106
104
  private:
107
- //! Returns the data_ptr_t of a pointer
108
- inline data_ptr_t Get(const SwizzleablePointer ptr) const {
109
- D_ASSERT(ptr.buffer_id < buffers.size());
110
- D_ASSERT(ptr.offset < allocations_per_buffer);
111
- return buffers[ptr.buffer_id].ptr + ptr.offset * allocation_size + allocation_offset;
105
+ //! Returns the data_ptr_t of a Node pointer
106
+ inline data_ptr_t Get(const Node ptr) const {
107
+ D_ASSERT(ptr.GetBufferId() < buffers.size());
108
+ D_ASSERT(ptr.GetOffset() < allocations_per_buffer);
109
+ return buffers[ptr.GetBufferId()].ptr + ptr.GetOffset() * allocation_size + allocation_offset;
112
110
  }
113
111
  //! Returns the first free offset in a bitmask
114
112
  uint32_t GetOffset(ValidityMask &mask, const idx_t allocation_count);
@@ -70,8 +70,8 @@ public:
70
70
  private:
71
71
  //! Stack of nodes from the root to the currently active node
72
72
  stack<IteratorEntry> nodes;
73
- //! Last visited leaf
74
- optional_ptr<Leaf> last_leaf = nullptr;
73
+ //! Last visited leaf node
74
+ Node last_leaf = Node();
75
75
 
76
76
  //! Goes to the next leaf in the ART and sets it as last_leaf,
77
77
  //! returns false if there is no next leaf
@@ -21,64 +21,67 @@ class MetaBlockReader;
21
21
  // structs
22
22
  struct BlockPointer;
23
23
 
24
+ //! The LEAF is a special node type that contains a count, up to LEAF_SIZE row IDs,
25
+ //! and a Node pointer. If this pointer is set, then it must point to another LEAF,
26
+ //! creating a chain of leaf nodes storing row IDs.
27
+ //! This class also contains functionality for nodes of type LEAF_INLINED, in which case we store the
28
+ //! row ID directly in the node pointer.
24
29
  class Leaf {
25
30
  public:
26
- //! Number of row IDs
27
- uint32_t count;
28
- union {
29
- //! The pointer to the head of the list of leaf segments
30
- Node ptr;
31
- //! Inlined row ID
32
- row_t inlined;
33
- } row_ids;
31
+ //! The number of row IDs in this leaf
32
+ uint8_t count;
33
+ //! Up to LEAF_SIZE row IDs
34
+ row_t row_ids[Node::LEAF_SIZE];
35
+ //! A pointer to the next LEAF node
36
+ Node ptr;
34
37
 
35
38
  public:
36
- //! Get a new leaf node, might cause a new buffer allocation, and initializes a leaf holding one row ID
37
- static Leaf &New(ART &art, Node &node, const row_t row_id);
38
- //! Get a new leaf node, might cause a new buffer allocation, and initializes a leaf holding n_row_ids row IDs
39
- static Leaf &New(ART &art, Node &node, const row_t *row_ids, const idx_t count);
40
- //! Free the leaf
39
+ //! Inline a row ID into a node pointer
40
+ static void New(Node &node, const row_t row_id);
41
+ //! Get a new chain of leaf nodes, might cause new buffer allocations,
42
+ //! with the node parameter holding the tail of the chain
43
+ static void New(ART &art, reference<Node> &node, const row_t *row_ids, idx_t count);
44
+ //! Free the leaf (chain)
41
45
  static void Free(ART &art, Node &node);
42
46
  //! Get a reference to the leaf
43
47
  static inline Leaf &Get(const ART &art, const Node ptr) {
48
+ D_ASSERT(!ptr.IsSerialized());
44
49
  return *Node::GetAllocator(art, NType::LEAF).Get<Leaf>(ptr);
45
50
  }
46
51
 
47
- //! Initializes a merge by incrementing the buffer IDs of the leaf segments
48
- void InitializeMerge(const ART &art, const idx_t buffer_count);
49
- //! Merge leaves
50
- void Merge(ART &art, Node &other);
52
+ //! Initializes a merge by incrementing the buffer IDs of the leaf
53
+ static void InitializeMerge(ART &art, Node &node, const ARTFlags &flags);
54
+ //! Merge leaves and free all copied leaf nodes
55
+ static void Merge(ART &art, Node &l_node, Node &r_node);
51
56
 
52
57
  //! Insert a row ID into a leaf
53
- void Insert(ART &art, const row_t row_id);
54
- //! Remove a row ID from a leaf
55
- void Remove(ART &art, const row_t row_id);
58
+ static void Insert(ART &art, Node &node, const row_t row_id);
59
+ //! Remove a row ID from a leaf. Returns true, if the leaf is empty after the removal
60
+ static bool Remove(ART &art, reference<Node> &node, const row_t row_id);
56
61
 
57
- //! Returns whether this leaf is inlined
58
- inline bool IsInlined() const {
59
- return count <= 1;
60
- }
61
- //! Get the row ID at the position
62
- row_t GetRowId(const ART &art, const idx_t position) const;
63
- //! Returns the position of a row ID, and an invalid index, if the leaf does not contain the row ID,
64
- //! and sets the ptr to point to the segment containing the row ID
65
- uint32_t FindRowId(const ART &art, Node &ptr, const row_t row_id) const;
62
+ //! Get the total count of row IDs in the chain of leaves
63
+ static idx_t TotalCount(ART &art, Node &node);
64
+ //! Fill the result_ids vector with the row IDs of this leaf chain, if the total count does not exceed max_count
65
+ static bool GetRowIds(ART &art, Node &node, vector<row_t> &result_ids, idx_t max_count);
66
+ //! Returns whether the leaf contains the row ID
67
+ static bool ContainsRowId(ART &art, Node &node, const row_t row_id);
66
68
 
67
- //! Returns the string representation of the node, or only traverses and verifies the node and its subtree
68
- string VerifyAndToString(const ART &art, const bool only_verify) const;
69
+ //! Returns the string representation of the leaf, or only traverses and verifies the leaf
70
+ static string VerifyAndToString(ART &art, Node &node);
69
71
 
70
- //! Serialize this leaf
71
- BlockPointer Serialize(const ART &art, MetaBlockWriter &writer) const;
72
- //! Deserialize this leaf
73
- void Deserialize(ART &art, MetaBlockReader &reader);
72
+ //! Serialize the leaf
73
+ static BlockPointer Serialize(ART &art, Node &node, MetaBlockWriter &writer);
74
+ //! Deserialize the leaf
75
+ static void Deserialize(ART &art, Node &node, MetaBlockReader &reader);
74
76
 
75
- //! Vacuum the leaf segments of a leaf, if not inlined
76
- void Vacuum(ART &art);
77
+ //! Vacuum the leaf
78
+ static void Vacuum(ART &art, Node &node);
77
79
 
78
80
  private:
79
- //! Moves the inlined row ID onto a leaf segment, does not change the size
80
- //! so this will be a (temporarily) invalid leaf
81
- void MoveInlinedToSegment(ART &art);
81
+ //! Moves the inlined row ID onto a leaf
82
+ static void MoveInlinedToLeaf(ART &art, Node &node);
83
+ //! Appends the row ID to this leaf, or creates a subsequent leaf, if this node is full
84
+ Leaf &Append(ART &art, const row_t row_id);
82
85
  };
83
86
 
84
87
  } // namespace duckdb
@@ -1,30 +1,32 @@
1
1
  //===----------------------------------------------------------------------===//
2
2
  // DuckDB
3
3
  //
4
- // duckdb/execution/index/art/art_node.hpp
4
+ // duckdb/execution/index/art/node.hpp
5
5
  //
6
6
  //
7
7
  //===----------------------------------------------------------------------===//
8
8
 
9
9
  #pragma once
10
10
 
11
- #include "duckdb/execution/index/art/fixed_size_allocator.hpp"
12
- #include "duckdb/execution/index/art/swizzleable_pointer.hpp"
11
+ #include "duckdb/common/assert.hpp"
12
+ #include "duckdb/common/optional_ptr.hpp"
13
+ #include "duckdb/common/to_string.hpp"
14
+ #include "duckdb/common/typedefs.hpp"
13
15
 
14
16
  namespace duckdb {
15
17
 
16
18
  // classes
17
19
  enum class NType : uint8_t {
18
20
  PREFIX = 1,
19
- LEAF_SEGMENT = 2,
20
- LEAF = 3,
21
- NODE_4 = 4,
22
- NODE_16 = 5,
23
- NODE_48 = 6,
24
- NODE_256 = 7
21
+ LEAF = 2,
22
+ NODE_4 = 3,
23
+ NODE_16 = 4,
24
+ NODE_48 = 5,
25
+ NODE_256 = 6,
26
+ LEAF_INLINED = 7,
25
27
  };
28
+ class FixedSizeAllocator;
26
29
  class ART;
27
- class Node;
28
30
  class Prefix;
29
31
  class MetaBlockReader;
30
32
  class MetaBlockWriter;
@@ -33,10 +35,10 @@ class MetaBlockWriter;
33
35
  struct BlockPointer;
34
36
  struct ARTFlags;
35
37
 
36
- //! The ARTNode is the swizzleable pointer class of the ART index.
37
- //! If the ARTNode pointer is not swizzled, then the leftmost byte identifies the NType.
38
- //! The remaining bytes are the position in the respective ART buffer.
39
- class Node : public SwizzleablePointer {
38
+ //! The Node is the pointer class of the ART index.
39
+ //! If the node is serialized, then the pointer points to a storage address (and has no type),
40
+ //! otherwise the pointer has a type and stores other information (e.g., a buffer location or a row ID).
41
+ class Node {
40
42
  public:
41
43
  //! Node thresholds
42
44
  static constexpr uint8_t NODE_48_SHRINK_THRESHOLD = 12;
@@ -46,42 +48,40 @@ public:
46
48
  static constexpr uint8_t NODE_16_CAPACITY = 16;
47
49
  static constexpr uint8_t NODE_48_CAPACITY = 48;
48
50
  static constexpr uint16_t NODE_256_CAPACITY = 256;
51
+ //! Bit-shifting
52
+ static constexpr uint64_t SHIFT_OFFSET = 32;
53
+ static constexpr uint64_t SHIFT_TYPE = 56;
54
+ static constexpr uint64_t SHIFT_SERIALIZED_FLAG = 63;
55
+ //! AND operations
56
+ static constexpr uint64_t AND_OFFSET = 0x0000000000FFFFFF;
57
+ static constexpr uint64_t AND_BUFFER_ID = 0x00000000FFFFFFFF;
58
+ static constexpr uint64_t AND_IS_SET = 0xFF00000000000000;
59
+ static constexpr uint64_t AND_RESET = 0x00FFFFFFFFFFFFFF;
60
+ //! OR operations
61
+ static constexpr uint64_t SET_SERIALIZED_FLAG = 0x8000000000000000;
49
62
  //! Other constants
50
63
  static constexpr uint8_t EMPTY_MARKER = 48;
51
- static constexpr uint32_t LEAF_SEGMENT_SIZE = 8;
64
+ static constexpr uint8_t LEAF_SIZE = 4;
52
65
  static constexpr uint8_t PREFIX_SIZE = 15;
53
66
 
54
67
  public:
55
- //! Constructs an empty ARTNode
56
- Node();
57
- //! Constructs a swizzled pointer from a block ID and an offset
68
+ //! Constructors
69
+
70
+ //! Constructs an empty Node
71
+ Node() : data(0) {};
72
+ //! Constructs a serialized Node pointer from a block ID and an offset
58
73
  explicit Node(MetaBlockReader &reader);
74
+ //! Constructs an in-memory Node from a buffer ID and an offset
75
+ Node(const uint32_t buffer_id, const uint32_t offset) : data(0) {
76
+ SetPtr(buffer_id, offset);
77
+ };
78
+
79
+ public:
59
80
  //! Get a new pointer to a node, might cause a new buffer allocation, and initialize it
60
81
  static void New(ART &art, Node &node, const NType type);
61
82
  //! Free the node (and its subtree)
62
83
  static void Free(ART &art, Node &node);
63
84
 
64
- inline bool operator==(const Node &node) const {
65
- return swizzle_flag == node.swizzle_flag && type == node.type && offset == node.offset &&
66
- buffer_id == node.buffer_id;
67
- }
68
-
69
- //! Retrieve the node type from the leftmost byte
70
- inline NType DecodeARTNodeType() const {
71
- D_ASSERT(!IsSwizzled());
72
- D_ASSERT(type >= (uint8_t)NType::PREFIX);
73
- D_ASSERT(type <= (uint8_t)NType::NODE_256);
74
- return NType(type);
75
- }
76
-
77
- //! Set the pointer
78
- inline void SetPtr(const SwizzleablePointer ptr) {
79
- swizzle_flag = ptr.swizzle_flag;
80
- type = ptr.type;
81
- offset = ptr.offset;
82
- buffer_id = ptr.buffer_id;
83
- }
84
-
85
85
  //! Replace the child node at the respective byte
86
86
  void ReplaceChild(const ART &art, const uint8_t byte, const Node child);
87
87
  //! Insert the child node at byte
@@ -118,7 +118,86 @@ public:
118
118
  bool MergeInternal(ART &art, Node &other);
119
119
 
120
120
  //! Vacuum all nodes that exceed their respective vacuum thresholds
121
- static void Vacuum(ART &art, Node &node, const ARTFlags &flags);
121
+ void Vacuum(ART &art, const ARTFlags &flags);
122
+
123
+ // Getters and Setters
124
+
125
+ //! Returns whether the node is serialized or not (zero bit)
126
+ inline bool IsSerialized() const {
127
+ return data >> Node::SHIFT_SERIALIZED_FLAG;
128
+ }
129
+ //! Get the type (1st to 7th bit)
130
+ inline NType GetType() const {
131
+ D_ASSERT(!IsSerialized());
132
+ auto type = data >> Node::SHIFT_TYPE;
133
+ D_ASSERT(type >= (uint8_t)NType::PREFIX);
134
+ D_ASSERT(type <= (uint8_t)NType::LEAF_INLINED);
135
+ return NType(type);
136
+ }
137
+ //! Get the offset (8th to 23rd bit)
138
+ inline idx_t GetOffset() const {
139
+ auto offset = data >> Node::SHIFT_OFFSET;
140
+ return offset & Node::AND_OFFSET;
141
+ }
142
+ //! Get the block/buffer ID (24th to 63rd bit)
143
+ inline idx_t GetBufferId() const {
144
+ return data & Node::AND_BUFFER_ID;
145
+ }
146
+ //! Get the row ID (8th to 63rd bit)
147
+ inline row_t GetRowId() const {
148
+ return data & Node::AND_RESET;
149
+ }
150
+
151
+ //! Set the serialized flag (zero bit)
152
+ inline void SetSerialized() {
153
+ data &= Node::AND_RESET;
154
+ data |= Node::SET_SERIALIZED_FLAG;
155
+ }
156
+ //! Set the type (1st to 7th bit)
157
+ inline void SetType(const uint8_t type) {
158
+ D_ASSERT(!IsSerialized());
159
+ data += (uint64_t)type << Node::SHIFT_TYPE;
160
+ }
161
+ //! Set the block/buffer ID (24th to 63rd bit) and offset (8th to 23rd bit)
162
+ inline void SetPtr(const uint32_t buffer_id, const uint32_t offset) {
163
+ D_ASSERT(!(data & Node::AND_RESET));
164
+ auto shifted_offset = ((uint64_t)offset) << Node::SHIFT_OFFSET;
165
+ data += shifted_offset;
166
+ data += buffer_id;
167
+ }
168
+ //! Set the row ID (8th to 63rd bit)
169
+ inline void SetRowId(const row_t row_id) {
170
+ D_ASSERT(!(data & Node::AND_RESET));
171
+ data += row_id;
172
+ }
173
+
174
+ //! Returns true, if neither the serialized flag is set nor the type
175
+ inline bool IsSet() const {
176
+ return data & Node::AND_IS_SET;
177
+ }
178
+ //! Reset the Node pointer by setting the node info to zero
179
+ inline void Reset() {
180
+ data = 0;
181
+ }
182
+
183
+ //! Comparison operator
184
+ inline bool operator==(const Node &node) const {
185
+ return data == node.data;
186
+ }
187
+
188
+ private:
189
+ //! Data holds all the information contained in a Node pointer
190
+ //! [0: serialized flag, 1 - 7: type,
191
+ //! 8 - 23: offset, 24 - 63: buffer/block ID OR
192
+ //! 8 - 63: row ID]
193
+ //! NOTE: a Node pointer can be either serialized OR have a type
194
+ //! NOTE: we do not use bit fields because when using bit fields Windows compiles
195
+ //! the Node class into 16 bytes instead of the intended 8 bytes, doubling the
196
+ //! space requirements
197
+ //! https://learn.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-170
198
+ uint64_t data;
122
199
  };
123
200
 
201
+ static_assert(sizeof(Node) == sizeof(uint64_t), "Invalid size for Node type.");
202
+
124
203
  } // namespace duckdb
@@ -31,6 +31,7 @@ public:
31
31
  static void Free(ART &art, Node &node);
32
32
  //! Get a reference to the node
33
33
  static inline Node16 &Get(const ART &art, const Node ptr) {
34
+ D_ASSERT(!ptr.IsSerialized());
34
35
  return *Node::GetAllocator(art, NType::NODE_16).Get<Node16>(ptr);
35
36
  }
36
37
  //! Initializes all the fields of the node while growing a Node4 to a Node16
@@ -29,6 +29,7 @@ public:
29
29
  static void Free(ART &art, Node &node);
30
30
  //! Get a reference to the node
31
31
  static inline Node256 &Get(const ART &art, const Node ptr) {
32
+ D_ASSERT(!ptr.IsSerialized());
32
33
  return *Node::GetAllocator(art, NType::NODE_256).Get<Node256>(ptr);
33
34
  }
34
35
  //! Initializes all the fields of the node while growing a Node48 to a Node256
@@ -31,6 +31,7 @@ public:
31
31
  static void Free(ART &art, Node &node);
32
32
  //! Get a reference to the node
33
33
  static inline Node4 &Get(const ART &art, const Node ptr) {
34
+ D_ASSERT(!ptr.IsSerialized());
34
35
  return *Node::GetAllocator(art, NType::NODE_4).Get<Node4>(ptr);
35
36
  }
36
37
  //! Initializes all fields of the node while shrinking a Node16 to a Node4
@@ -32,6 +32,7 @@ public:
32
32
  static void Free(ART &art, Node &node);
33
33
  //! Get a reference to the node
34
34
  static inline Node48 &Get(const ART &art, const Node ptr) {
35
+ D_ASSERT(!ptr.IsSerialized());
35
36
  return *Node::GetAllocator(art, NType::NODE_48).Get<Node48>(ptr);
36
37
  }
37
38
  //! Initializes all the fields of the node while growing a Node16 to a Node48
@@ -8,6 +8,7 @@
8
8
  #pragma once
9
9
 
10
10
  #include "duckdb/execution/index/art/art.hpp"
11
+ #include "duckdb/execution/index/art/fixed_size_allocator.hpp"
11
12
  #include "duckdb/execution/index/art/node.hpp"
12
13
 
13
14
  namespace duckdb {
@@ -37,6 +38,7 @@ public:
37
38
  static void Free(ART &art, Node &node);
38
39
  //! Get a reference to the prefix
39
40
  static inline Prefix &Get(const ART &art, const Node ptr) {
41
+ D_ASSERT(!ptr.IsSerialized());
40
42
  return *Node::GetAllocator(art, NType::PREFIX).Get<Prefix>(ptr);
41
43
  }
42
44
 
@@ -71,7 +73,7 @@ public:
71
73
  static void Split(ART &art, reference<Node> &prefix_node, Node &child_node, idx_t position);
72
74
 
73
75
  //! Returns the string representation of the node, or only traverses and verifies the node and its subtree
74
- string VerifyAndToString(ART &art, const bool only_verify);
76
+ static string VerifyAndToString(ART &art, Node &node, const bool only_verify);
75
77
 
76
78
  //! Serialize this node
77
79
  BlockPointer Serialize(ART &art, MetaBlockWriter &writer);
@@ -80,7 +82,7 @@ public:
80
82
 
81
83
  //! Vacuum the child of the node
82
84
  inline void Vacuum(ART &art, const ARTFlags &flags) {
83
- Node::Vacuum(art, ptr, flags);
85
+ ptr.Vacuum(art, flags);
84
86
  }
85
87
 
86
88
  private: