Repository: duckdb/duckdb
File: src/execution/index/art/base_leaf.cpp (C++)

Code before:
			break;
		}
	}
	n.count--;

	// Possibly move children backwards.
	for (uint8_t i = child_pos; i < n.count; i++) {
		n.key[i] = n.key[i + 1];
	}
	return handle;
}

//===--------------------------------------------------------------------===//
// Node7Leaf
//===--------------------------------------------------------------------===//

void Node7Leaf::InsertByte(ART &art, Node &node, const uint8_t byte) {
	// The node is full. Grow to Node15.
	NodeHandle<Node7Leaf> handle(art, node);
	auto &n7 = handle.Get();
	if (n7.count == CAPACITY) {
		auto node7 = node;
		Node15Leaf::GrowNode7Leaf(art, node, node7);
		Node15Leaf::InsertByte(art, node, byte);
		return;
	}
	InsertByteInternal(n7, byte);
}

void Node7Leaf::DeleteByte(ART &art, Node &node, Node &prefix, const uint8_t byte, const ARTKey &row_id) {
	auto n7_handle = DeleteByteInternal(art, node, byte);
	auto &n7 = n7_handle.Get();
	// Compress one-way nodes.
	if (n7.count == 1) {
		D_ASSERT(node.GetGateStatus() == GateStatus::GATE_NOT_SET);

		// Get the remaining row ID.
		auto remainder = UnsafeNumericCast<idx_t>(row_id.GetRowId()) & AND_LAST_BYTE;
		remainder |= UnsafeNumericCast<idx_t>(n7.key[0]);

		// Free the prefix (nodes) and inline the remainder.
		if (prefix.GetType() == NType::PREFIX) {
			Node::FreeTree(art, prefix);
			Leaf::New(prefix, UnsafeNumericCast<row_t>(remainder));
			return;
		}

		// Free the Node7Leaf and inline the remainder.
		Node::FreeNode(art, node);
		Leaf::New(node, UnsafeNumericCast<row_t>(remainder));
	}

Review comment (suggestion):
We likely need to change the logic here slightly, similar to what the `BaseNode` does (via `n7.count != CAPACITY`). If we look at `BaseNode::InsertChild`, the scope of the `NodeHandle` ends before growing the node. That way, we don't hold on to a node whose memory changes while growing. 

```cpp
{
		NodeHandle<Node4> handle(art, node);
		auto &n = handle.Get();

		if (n.count != CAPACITY) {
			InsertChildInternal(n, byte, child);
			return;
		}
	}
	// The node is full.
	// Grow to Node16.
	auto node4 = node;
	Node16::GrowNode4(art, node, node4);
	Node16::InsertChild(art, node, byte, child);
```



Code after:
			break;
		}
	}
	n.count--;

	// Possibly move children backwards.
	for (uint8_t i = child_pos; i < n.count; i++) {
		n.key[i] = n.key[i + 1];
	}
	return handle;
}

//===--------------------------------------------------------------------===//
// Node7Leaf
//===--------------------------------------------------------------------===//

void Node7Leaf::InsertByte(ART &art, Node &node, const uint8_t byte) {
	{
		NodeHandle<Node7Leaf> handle(art, node);
		auto &n7 = handle.Get();

		if (n7.count != CAPACITY) {
			InsertByteInternal(n7, byte);
			return;
		}
	}
	// The node is full. Grow to Node15.
	auto node7 = node;
	Node15Leaf::GrowNode7Leaf(art, node, node7);
	Node15Leaf::InsertByte(art, node, byte);
}

void Node7Leaf::DeleteByte(ART &art, Node &node, Node &prefix, const uint8_t byte, const ARTKey &row_id) {
	idx_t remainder;
	{
		auto n7_handle = DeleteByteInternal(art, node, byte);
		auto &n7 = n7_handle.Get();

		if (n7.count != 1) {
			return;
		}

		// Compress one-way nodes.
		D_ASSERT(node.GetGateStatus() == GateStatus::GATE_NOT_SET);

		// Get the remaining row ID.
		remainder = UnsafeNumericCast<idx_t>(row_id.GetRowId()) & AND_LAST_BYTE;
		remainder |= UnsafeNumericCast<idx_t>(n7.key[0]);

		// Free the prefix (nodes) and inline the remainder.
		if (prefix.GetType() == NType::PREFIX) {