| 1 | //===----------------------------------------------------------------------===// |
| 2 | // DuckDB |
| 3 | // |
| 4 | // duckdb/execution/index/art/prefix.hpp |
| 5 | // |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | #pragma once |
| 9 | |
| 10 | #include "duckdb/execution/index/art/node.hpp" |
| 11 | |
| 12 | namespace duckdb { |
| 13 | |
| 14 | // classes |
| 15 | class ARTKey; |
| 16 | class PrefixSegment; |
| 17 | |
| 18 | class Prefix { |
| 19 | public: |
| 20 | //! Number of bytes in this prefix |
| 21 | uint32_t count; |
| 22 | union { |
| 23 | //! Pointer to the head of the list of prefix segments |
| 24 | Node ptr; |
| 25 | //! Inlined prefix bytes |
| 26 | uint8_t inlined[Node::PREFIX_INLINE_BYTES]; |
| 27 | } data; |
| 28 | |
| 29 | public: |
| 30 | //! Delete all prefix segments (if not inlined) and reset all fields |
| 31 | void Free(ART &art); |
| 32 | //! Initializes all the fields of an empty prefix |
| 33 | inline void Initialize() { |
| 34 | count = 0; |
| 35 | } |
| 36 | //! Initialize a prefix from an ART key |
| 37 | void Initialize(ART &art, const ARTKey &key, const uint32_t depth, const uint32_t count_p); |
| 38 | //! Initialize a prefix from another prefix up to count |
| 39 | void Initialize(ART &art, const Prefix &other, const uint32_t count_p); |
| 40 | |
| 41 | //! Initializes a merge by incrementing the buffer IDs of the prefix segments |
| 42 | void InitializeMerge(ART &art, const idx_t buffer_count); |
| 43 | |
| 44 | //! Move a prefix into this prefix |
| 45 | inline void Move(Prefix &other) { |
| 46 | count = other.count; |
| 47 | data = other.data; |
| 48 | other.Initialize(); |
| 49 | } |
| 50 | //! Append a prefix to this prefix |
| 51 | void Append(ART &art, const Prefix &other); |
| 52 | //! Concatenate prefix with a partial key byte and another prefix: other.prefix + byte + this->prefix |
| 53 | void Concatenate(ART &art, const uint8_t byte, const Prefix &other); |
| 54 | //! Removes the first n bytes, and returns the new first byte |
| 55 | uint8_t Reduce(ART &art, const idx_t reduce_count); |
| 56 | |
| 57 | //! Get the byte at position |
| 58 | uint8_t GetByte(const ART &art, const idx_t position) const; |
| 59 | //! Compare the key with the prefix of the node, return the position where they mismatch |
| 60 | uint32_t KeyMismatchPosition(const ART &art, const ARTKey &key, const uint32_t depth) const; |
| 61 | //! Compare this prefix to another prefix, return the position where they mismatch, or count otherwise |
| 62 | uint32_t MismatchPosition(const ART &art, const Prefix &other) const; |
| 63 | |
| 64 | //! Serialize this prefix |
| 65 | void Serialize(const ART &art, MetaBlockWriter &writer) const; |
| 66 | //! Deserialize this prefix |
| 67 | void Deserialize(ART &art, MetaBlockReader &reader); |
| 68 | |
| 69 | //! Vacuum the prefix segments of a prefix, if not inlined |
| 70 | void Vacuum(ART &art); |
| 71 | |
| 72 | private: |
| 73 | //! Returns whether this prefix is inlined |
| 74 | inline bool IsInlined() const { |
| 75 | return count <= Node::PREFIX_INLINE_BYTES; |
| 76 | } |
| 77 | //! Moves all inlined bytes onto a prefix segment, does not change the size |
| 78 | //! so this will be an (temporarily) invalid prefix |
| 79 | PrefixSegment &MoveInlinedToSegment(ART &art); |
| 80 | //! Inlines up to eight bytes on the first prefix segment |
| 81 | void MoveSegmentToInlined(ART &art); |
| 82 | }; |
| 83 | |
| 84 | } // namespace duckdb |
| 85 | |