1#include "duckdb/execution/index/art/art_key.hpp"
2
3namespace duckdb {
4
5ARTKey::ARTKey() : len(0) {
6}
7
8ARTKey::ARTKey(const data_ptr_t &data, const uint32_t &len) : len(len), data(data) {
9}
10
11ARTKey::ARTKey(ArenaAllocator &allocator, const uint32_t &len) : len(len) {
12 data = allocator.Allocate(size: len);
13}
14
15template <>
16ARTKey ARTKey::CreateARTKey(ArenaAllocator &allocator, const LogicalType &type, string_t value) {
17 uint32_t len = value.GetSize() + 1;
18 auto data = allocator.Allocate(size: len);
19 memcpy(dest: data, src: value.GetData(), n: len - 1);
20
21 // FIXME: rethink this
22 if (type == LogicalType::BLOB || type == LogicalType::VARCHAR) {
23 // indexes cannot contain BLOBs (or BLOBs cast to VARCHARs) that contain null-terminated bytes
24 for (uint32_t i = 0; i < len - 1; i++) {
25 if (data[i] == '\0') {
26 throw NotImplementedException("Indexes cannot contain BLOBs that contain null-terminated bytes.");
27 }
28 }
29 }
30
31 data[len - 1] = '\0';
32 return ARTKey(data, len);
33}
34
35template <>
36ARTKey ARTKey::CreateARTKey(ArenaAllocator &allocator, const LogicalType &type, const char *value) {
37 return ARTKey::CreateARTKey(allocator, type, value: string_t(value, strlen(s: value)));
38}
39
40template <>
41void ARTKey::CreateARTKey(ArenaAllocator &allocator, const LogicalType &type, ARTKey &key, string_t value) {
42 key.len = value.GetSize() + 1;
43 key.data = allocator.Allocate(size: key.len);
44 memcpy(dest: key.data, src: value.GetData(), n: key.len - 1);
45
46 // FIXME: rethink this
47 if (type == LogicalType::BLOB || type == LogicalType::VARCHAR) {
48 // indexes cannot contain BLOBs (or BLOBs cast to VARCHARs) that contain null-terminated bytes
49 for (uint32_t i = 0; i < key.len - 1; i++) {
50 if (key.data[i] == '\0') {
51 throw NotImplementedException("Indexes cannot contain BLOBs that contain null-terminated bytes.");
52 }
53 }
54 }
55
56 key.data[key.len - 1] = '\0';
57}
58
59template <>
60void ARTKey::CreateARTKey(ArenaAllocator &allocator, const LogicalType &type, ARTKey &key, const char *value) {
61 ARTKey::CreateARTKey(allocator, type, key, value: string_t(value, strlen(s: value)));
62}
63
64bool ARTKey::operator>(const ARTKey &k) const {
65 for (uint32_t i = 0; i < MinValue<uint32_t>(a: len, b: k.len); i++) {
66 if (data[i] > k.data[i]) {
67 return true;
68 } else if (data[i] < k.data[i]) {
69 return false;
70 }
71 }
72 return len > k.len;
73}
74
75bool ARTKey::operator<(const ARTKey &k) const {
76 for (uint32_t i = 0; i < MinValue<uint32_t>(a: len, b: k.len); i++) {
77 if (data[i] < k.data[i]) {
78 return true;
79 } else if (data[i] > k.data[i]) {
80 return false;
81 }
82 }
83 return len < k.len;
84}
85
86bool ARTKey::operator>=(const ARTKey &k) const {
87 for (uint32_t i = 0; i < MinValue<uint32_t>(a: len, b: k.len); i++) {
88 if (data[i] > k.data[i]) {
89 return true;
90 } else if (data[i] < k.data[i]) {
91 return false;
92 }
93 }
94 return len >= k.len;
95}
96
97bool ARTKey::operator==(const ARTKey &k) const {
98 if (len != k.len) {
99 return false;
100 }
101 for (uint32_t i = 0; i < len; i++) {
102 if (data[i] != k.data[i]) {
103 return false;
104 }
105 }
106 return true;
107}
108
109void ARTKey::ConcatenateARTKey(ArenaAllocator &allocator, ARTKey &other_key) {
110
111 auto compound_data = allocator.Allocate(size: len + other_key.len);
112 memcpy(dest: compound_data, src: data, n: len);
113 memcpy(dest: compound_data + len, src: other_key.data, n: other_key.len);
114 len += other_key.len;
115 data = compound_data;
116}
117} // namespace duckdb
118