Coverage Report

Created: 2025-08-28 07:58

/src/duckdb/src/execution/index/art/base_leaf.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "duckdb/execution/index/art/base_leaf.hpp"
2
3
#include "duckdb/execution/index/art/art_key.hpp"
4
#include "duckdb/execution/index/art/base_node.hpp"
5
#include "duckdb/execution/index/art/leaf.hpp"
6
#include "duckdb/execution/index/art/prefix.hpp"
7
#include "duckdb/execution/index/art/node256_leaf.hpp"
8
9
namespace duckdb {
10
11
//===--------------------------------------------------------------------===//
12
// BaseLeaf
13
//===--------------------------------------------------------------------===//
14
15
template <uint8_t CAPACITY, NType TYPE>
16
0
void BaseLeaf<CAPACITY, TYPE>::InsertByteInternal(BaseLeaf &n, const uint8_t byte) {
17
  // Still space. Insert the child.
18
0
  uint8_t child_pos = 0;
19
0
  while (child_pos < n.count && n.key[child_pos] < byte) {
20
0
    child_pos++;
21
0
  }
22
23
  // Move children backwards to make space.
24
0
  for (uint8_t i = n.count; i > child_pos; i--) {
25
0
    n.key[i] = n.key[i - 1];
26
0
  }
27
28
0
  n.key[child_pos] = byte;
29
0
  n.count++;
30
0
}
Unexecuted instantiation: duckdb::BaseLeaf<(unsigned char)7, (duckdb::NType)8>::InsertByteInternal(duckdb::BaseLeaf<(unsigned char)7, (duckdb::NType)8>&, unsigned char)
Unexecuted instantiation: duckdb::BaseLeaf<(unsigned char)15, (duckdb::NType)9>::InsertByteInternal(duckdb::BaseLeaf<(unsigned char)15, (duckdb::NType)9>&, unsigned char)
31
32
template <uint8_t CAPACITY, NType TYPE>
33
0
BaseLeaf<CAPACITY, TYPE> &BaseLeaf<CAPACITY, TYPE>::DeleteByteInternal(ART &art, Node &node, const uint8_t byte) {
34
0
  auto &n = Node::Ref<BaseLeaf>(art, node, node.GetType());
35
0
  uint8_t child_pos = 0;
36
37
0
  for (; child_pos < n.count; child_pos++) {
38
0
    if (n.key[child_pos] == byte) {
39
0
      break;
40
0
    }
41
0
  }
42
0
  n.count--;
43
44
  // Possibly move children backwards.
45
0
  for (uint8_t i = child_pos; i < n.count; i++) {
46
0
    n.key[i] = n.key[i + 1];
47
0
  }
48
0
  return n;
49
0
}
Unexecuted instantiation: duckdb::BaseLeaf<(unsigned char)7, (duckdb::NType)8>::DeleteByteInternal(duckdb::ART&, duckdb::Node&, unsigned char)
Unexecuted instantiation: duckdb::BaseLeaf<(unsigned char)15, (duckdb::NType)9>::DeleteByteInternal(duckdb::ART&, duckdb::Node&, unsigned char)
50
51
//===--------------------------------------------------------------------===//
52
// Node7Leaf
53
//===--------------------------------------------------------------------===//
54
55
0
void Node7Leaf::InsertByte(ART &art, Node &node, const uint8_t byte) {
56
  // The node is full. Grow to Node15.
57
0
  auto &n7 = Node::Ref<Node7Leaf>(art, node, NODE_7_LEAF);
58
0
  if (n7.count == CAPACITY) {
59
0
    auto node7 = node;
60
0
    Node15Leaf::GrowNode7Leaf(art, node, node7);
61
0
    Node15Leaf::InsertByte(art, node, byte);
62
0
    return;
63
0
  }
64
65
0
  InsertByteInternal(n7, byte);
66
0
}
67
68
0
void Node7Leaf::DeleteByte(ART &art, Node &node, Node &prefix, const uint8_t byte, const ARTKey &row_id) {
69
0
  auto &n7 = DeleteByteInternal(art, node, byte);
70
71
  // Compress one-way nodes.
72
0
  if (n7.count == 1) {
73
0
    D_ASSERT(node.GetGateStatus() == GateStatus::GATE_NOT_SET);
74
75
    // Get the remaining row ID.
76
0
    auto remainder = UnsafeNumericCast<idx_t>(row_id.GetRowId()) & AND_LAST_BYTE;
77
0
    remainder |= UnsafeNumericCast<idx_t>(n7.key[0]);
78
79
    // Free the prefix (nodes) and inline the remainder.
80
0
    if (prefix.GetType() == NType::PREFIX) {
81
0
      Node::FreeTree(art, prefix);
82
0
      Leaf::New(prefix, UnsafeNumericCast<row_t>(remainder));
83
0
      return;
84
0
    }
85
86
    // Free the Node7Leaf and inline the remainder.
87
0
    Node::FreeNode(art, node);
88
0
    Leaf::New(node, UnsafeNumericCast<row_t>(remainder));
89
0
  }
90
0
}
91
92
0
void Node7Leaf::ShrinkNode15Leaf(ART &art, Node &node7_leaf, Node &node15_leaf) {
93
0
  auto &n7 = New(art, node7_leaf);
94
0
  auto &n15 = Node::Ref<Node15Leaf>(art, node15_leaf, NType::NODE_15_LEAF);
95
0
  node7_leaf.SetGateStatus(node15_leaf.GetGateStatus());
96
97
0
  n7.count = n15.count;
98
0
  for (uint8_t i = 0; i < n15.count; i++) {
99
0
    n7.key[i] = n15.key[i];
100
0
  }
101
102
0
  Node::FreeNode(art, node15_leaf);
103
0
}
104
105
//===--------------------------------------------------------------------===//
106
// Node15Leaf
107
//===--------------------------------------------------------------------===//
108
109
0
void Node15Leaf::InsertByte(ART &art, Node &node, const uint8_t byte) {
110
  // The node is full. Grow to Node256Leaf.
111
0
  auto &n15 = Node::Ref<Node15Leaf>(art, node, NODE_15_LEAF);
112
0
  if (n15.count == CAPACITY) {
113
0
    auto node15 = node;
114
0
    Node256Leaf::GrowNode15Leaf(art, node, node15);
115
0
    Node256Leaf::InsertByte(art, node, byte);
116
0
    return;
117
0
  }
118
119
0
  InsertByteInternal(n15, byte);
120
0
}
121
122
0
void Node15Leaf::DeleteByte(ART &art, Node &node, const uint8_t byte) {
123
0
  auto &n15 = DeleteByteInternal(art, node, byte);
124
125
  // Shrink node to Node7.
126
0
  if (n15.count < Node7Leaf::CAPACITY) {
127
0
    auto node15 = node;
128
0
    Node7Leaf::ShrinkNode15Leaf(art, node, node15);
129
0
  }
130
0
}
131
132
0
void Node15Leaf::GrowNode7Leaf(ART &art, Node &node15_leaf, Node &node7_leaf) {
133
0
  auto &n7 = Node::Ref<Node7Leaf>(art, node7_leaf, NType::NODE_7_LEAF);
134
0
  auto &n15 = New(art, node15_leaf);
135
0
  node15_leaf.SetGateStatus(node7_leaf.GetGateStatus());
136
137
0
  n15.count = n7.count;
138
0
  for (uint8_t i = 0; i < n7.count; i++) {
139
0
    n15.key[i] = n7.key[i];
140
0
  }
141
142
0
  Node::FreeNode(art, node7_leaf);
143
0
}
144
145
0
void Node15Leaf::ShrinkNode256Leaf(ART &art, Node &node15_leaf, Node &node256_leaf) {
146
0
  auto &n15 = New(art, node15_leaf);
147
0
  auto &n256 = Node::Ref<Node256Leaf>(art, node256_leaf, NType::NODE_256_LEAF);
148
0
  node15_leaf.SetGateStatus(node256_leaf.GetGateStatus());
149
150
0
  ValidityMask mask(&n256.mask[0], Node256::CAPACITY);
151
0
  for (uint16_t i = 0; i < Node256::CAPACITY; i++) {
152
0
    if (mask.RowIsValid(i)) {
153
0
      n15.key[n15.count] = UnsafeNumericCast<uint8_t>(i);
154
0
      n15.count++;
155
0
    }
156
0
  }
157
158
0
  Node::FreeNode(art, node256_leaf);
159
0
}
160
161
} // namespace duckdb