/Users/deen/code/yugabyte-db/src/yb/docdb/value_type.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) YugaByte, Inc. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
4 | | // in compliance with the License. You may obtain a copy of the License at |
5 | | // |
6 | | // http://www.apache.org/licenses/LICENSE-2.0 |
7 | | // |
8 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
9 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
10 | | // or implied. See the License for the specific language governing permissions and limitations |
11 | | // under the License. |
12 | | // |
13 | | |
14 | | #ifndef YB_DOCDB_VALUE_TYPE_H_ |
15 | | #define YB_DOCDB_VALUE_TYPE_H_ |
16 | | |
17 | | #include <bitset> |
18 | | #include <string> |
19 | | |
20 | | #include <boost/preprocessor/seq/for_each.hpp> |
21 | | |
22 | | #include "yb/util/enums.h" |
23 | | #include "yb/util/math_util.h" |
24 | | #include "yb/util/slice.h" |
25 | | |
26 | | namespace yb { |
27 | | namespace docdb { |
28 | | |
29 | | #define DOCDB_VALUE_TYPES \ |
30 | | /* This ValueType is used as -infinity for scanning purposes only. */\ |
31 | | ((kLowest, 0)) \ |
32 | | /* Prefix for transaction apply state records. */ \ |
33 | | ((kTransactionApplyState, 7)) \ |
34 | | /* Externally received transaction id */ \ |
35 | | ((kExternalTransactionId, 8)) \ |
36 | | /* Obsolete intent prefix. Should be deleted when DBs in old format are gone. */ \ |
37 | | ((kObsoleteIntentPrefix, 10)) \ |
38 | | /* We use ASCII code 13 in order to have it before all other value types which can occur in */ \ |
39 | | /* key, so intents will be written in the same order as original keys for which intents are */ \ |
40 | | /* written. */ \ |
41 | | ((kIntentTypeSet, 13)) \ |
42 | | /* Obsolete intent prefix. Should be deleted when DBs in old format are gone. */ \ |
43 | | /* It has different values to intent type set entries, that was not optimised for RocksDB */ \ |
44 | | /* lookup. */ \ |
45 | | /* I.e. strong/weak and read/write bits are swapped. */ \ |
46 | | ((kObsoleteIntentTypeSet, 15)) \ |
47 | | /* Obsolete intent prefix. Should be deleted when DBs in old format are gone. */ \ |
48 | | /* Old intent type had 6 different types of intents, one for each possible intent. */ \ |
49 | | /* Intent type set has 4 different types of intents, but allow their combinations. */ \ |
50 | | ((kObsoleteIntentType, 20)) \ |
51 | | /* Value type that is greater than any of intent types. */ \ |
52 | | /* It is NOT stored in DB, so should be updated if we add new intent value type */ \ |
53 | | ((kGreaterThanIntentType, 21)) \ |
54 | | /* This indicates the end of the "hashed" or "range" group of components of the primary */ \ |
55 | | /* key. This needs to sort before all other value types, so that a DocKey that has a prefix */ \ |
56 | | /* of the sequence of components of another key sorts before the other key. kGroupEnd is */ \ |
57 | | /* also used as the end marker for a frozen value. */ \ |
58 | | ((kGroupEnd, '!')) /* ASCII code 33 -- we pick the lowest code graphic character. */ \ |
59 | | /* HybridTime must be lower than all other primitive types (other than kGroupEnd) so that */ \ |
60 | | /* SubDocKeys that have fewer subkeys within a document sort above those that have all the */ \ |
61 | | /* same subkeys and more. In our MVCC document model layout the hybrid time always appears */ \ |
62 | | /* at the end of the key. */ \ |
63 | | ((kHybridTime, '#')) /* ASCII code 35 (34 is double quote, which would be a bit confusing */ \ |
64 | | /* here). */ \ |
65 | | /* Primitive value types */ \ |
66 | | \ |
67 | | /* Null must be lower than the other primitive types so that it compares as smaller than */ \ |
68 | | /* them. It is used for frozen CQL user-defined types (which can contain null elements) on */ \ |
69 | | /* ASC columns. */ \ |
70 | | ((kNullLow, '$')) /* ASCII code 36 */ \ |
71 | | /* Counter to check cardinality. */ \ |
72 | | ((kCounter, '%')) /* ASCII code 37 */ \ |
73 | | /* Forward and reverse mappings for sorted sets. */ \ |
74 | | ((kSSForward, '&')) /* ASCII code 38 */ \ |
75 | | ((kSSReverse, '\'')) /* ASCII code 39 */ \ |
76 | | ((kRedisSet, '(')) /* ASCII code 40 */ \ |
77 | | ((kRedisList, ')')) /* ASCII code 41*/ \ |
78 | | /* This is the redis timeseries type. */ \ |
79 | | ((kRedisTS, '+')) /* ASCII code 43 */ \ |
80 | | ((kRedisSortedSet, ',')) /* ASCII code 44 */ \ |
81 | | ((kInetaddress, '-')) /* ASCII code 45 */ \ |
82 | | ((kInetaddressDescending, '.')) /* ASCII code 46 */ \ |
83 | | ((kColocationId, '0')) /* ASCII code 48 */ \ |
84 | | ((kJsonb, '2')) /* ASCII code 50 */ \ |
85 | | ((kFrozen, '<')) /* ASCII code 60 */ \ |
86 | | ((kFrozenDescending, '>')) /* ASCII code 62 */ \ |
87 | | ((kArray, 'A')) /* ASCII code 65 */ \ |
88 | | ((kVarInt, 'B')) /* ASCII code 66 */ \ |
89 | | ((kFloat, 'C')) /* ASCII code 67 */ \ |
90 | | ((kDouble, 'D')) /* ASCII code 68 */ \ |
91 | | ((kDecimal, 'E')) /* ASCII code 69 */ \ |
92 | | ((kFalse, 'F')) /* ASCII code 70 */ \ |
93 | | ((kUInt16Hash, 'G')) /* ASCII code 71 */ \ |
94 | | ((kInt32, 'H')) /* ASCII code 72 */ \ |
95 | | ((kInt64, 'I')) /* ASCII code 73 */ \ |
96 | | ((kSystemColumnId, 'J')) /* ASCII code 74 */ \ |
97 | | ((kColumnId, 'K')) /* ASCII code 75 */ \ |
98 | | ((kDoubleDescending, 'L')) /* ASCII code 76 */ \ |
99 | | ((kFloatDescending, 'M')) /* ASCII code 77 */ \ |
100 | | ((kUInt32, 'O')) /* ASCII code 79 */ \ |
101 | | ((kString, 'S')) /* ASCII code 83 */ \ |
102 | | ((kTrue, 'T')) /* ASCII code 84 */ \ |
103 | | ((kUInt64, 'U')) /* ASCII code 85 */ \ |
104 | | ((kTombstone, 'X')) /* ASCII code 88 */ \ |
105 | | ((kExternalIntents, 'Z')) /* ASCII code 90 */ \ |
106 | | ((kArrayIndex, '[')) /* ASCII code 91 */ \ |
107 | | ((kCollString, '\\')) /* ASCII code 92 */ \ |
108 | | ((kCollStringDescending, ']')) /* ASCII code 93 */ \ |
109 | | \ |
110 | | /* We allow putting a 32-bit hash in front of the document key. This hash is computed based */ \ |
111 | | /* on the "hashed" components of the document key that precede "range" components. */ \ |
112 | | \ |
113 | | ((kUuid, '_')) /* ASCII code 95 */ \ |
114 | | ((kUuidDescending, '`')) /* ASCII code 96 */ \ |
115 | | ((kStringDescending, 'a')) /* ASCII code 97 */ \ |
116 | | ((kInt64Descending, 'b')) /* ASCII code 98 */ \ |
117 | | ((kTimestampDescending, 'c')) /* ASCII code 99 */ \ |
118 | | ((kDecimalDescending, 'd')) /* ASCII code 100 */ \ |
119 | | ((kInt32Descending, 'e')) /* ASCII code 101 */ \ |
120 | | ((kVarIntDescending, 'f')) /* ASCII code 102 */ \ |
121 | | ((kUInt32Descending, 'g')) /* ASCII code 103 */ \ |
122 | | ((kTrueDescending, 'h')) /* ASCII code 104 */ \ |
123 | | ((kFalseDescending, 'i')) /* ASCII code 105 */ \ |
124 | | ((kUInt64Descending, 'j')) /* ASCII code 106 */ \ |
125 | | \ |
126 | | /* Flag type for merge record flags */ \ |
127 | | ((kMergeFlags, 'k')) /* ASCII code 107 */ \ |
128 | | /* Indicator for whether an intent is for a row lock. */ \ |
129 | | ((kRowLock, 'l')) /* ASCII code 108 */ \ |
130 | | ((kBitSet, 'm')) /* ASCII code 109 */ \ |
131 | | ((kSubTransactionId, 'n')) /* ASCII code 110 */ \ |
132 | | /* Timestamp value in microseconds */ \ |
133 | | ((kTimestamp, 's')) /* ASCII code 115 */ \ |
134 | | /* TTL value in milliseconds, optionally present at the start of a value. */ \ |
135 | | ((kTtl, 't')) /* ASCII code 116 */ \ |
136 | | ((kUserTimestamp, 'u')) /* ASCII code 117 */ \ |
137 | | ((kGinNull, 'v')) /* ASCII code 118 */ \ |
138 | | ((kWriteId, 'w')) /* ASCII code 119 */ \ |
139 | | ((kTransactionId, 'x')) /* ASCII code 120 */ \ |
140 | | ((kTableId, 'y')) /* ASCII code 121 */ \ |
141 | | \ |
142 | | ((kObject, '{')) /* ASCII code 123 */ \ |
143 | | \ |
144 | | /* Null desc must be higher than the other descending primitive types so that it compares */ \ |
145 | | /* as bigger than them. It is used for frozen CQL user-defined types (which can contain */ \ |
146 | | /* null elements) on DESC columns. */ \ |
147 | | ((kNullHigh, '|')) /* ASCII code 124 */ \ |
148 | | \ |
149 | | /* This is only needed when used as the end marker for a frozen value on a DESC column. */ \ |
150 | | ((kGroupEndDescending, '}')) /* ASCII code 125 -- we pick the highest value below kHighest. */ \ |
151 | | \ |
152 | | /* This ValueType is used as +infinity for scanning purposes only. */ \ |
153 | | ((kHighest, '~')) /* ASCII code 126 */ \ |
154 | | \ |
155 | | /* This is used for sanity checking. */ \ |
156 | | ((kInvalid, 127)) \ |
157 | | \ |
158 | | /* ValueType which lexicographically higher than any other byte and is not used for */ \ |
159 | | /* encoding value type. */ \ |
160 | | ((kMaxByte, '\xff')) |
161 | | |
162 | | YB_DEFINE_ENUM(ValueType, DOCDB_VALUE_TYPES); |
163 | | |
164 | | #define DOCDB_VALUE_TYPE_AS_CHAR_IMPL(name, value) static constexpr char name = value; |
165 | | #define DOCDB_VALUE_TYPE_AS_CHAR(i, data, entry) DOCDB_VALUE_TYPE_AS_CHAR_IMPL entry |
166 | | |
167 | | struct ValueTypeAsChar { |
168 | | BOOST_PP_SEQ_FOR_EACH(DOCDB_VALUE_TYPE_AS_CHAR, ~, DOCDB_VALUE_TYPES) |
169 | | }; |
170 | | |
171 | | // All primitive value types fall into this range, but not all value types in this range are |
172 | | // primitive (e.g. object and tombstone are not). |
173 | | |
174 | | constexpr ValueType kMinPrimitiveValueType = ValueType::kNullLow; |
175 | | constexpr ValueType kMaxPrimitiveValueType = ValueType::kNullHigh; |
176 | | |
177 | | // kArray is handled slightly differently and hence we only have |
178 | | // kObject, kRedisTS, kRedisSet, and kRedisList. |
179 | 9.87G | constexpr inline bool IsObjectType(const ValueType value_type) { |
180 | 9.87G | return value_type == ValueType::kRedisTS || value_type == ValueType::kObject9.87G || |
181 | 9.87G | value_type == ValueType::kRedisSet5.36G || value_type == ValueType::kRedisSortedSet5.36G || |
182 | 9.87G | value_type == ValueType::kSSForward5.36G || value_type == ValueType::kSSReverse5.36G || |
183 | 9.87G | value_type == ValueType::kRedisList5.35G ; |
184 | 9.87G | } |
185 | | |
186 | 6.32G | constexpr inline bool IsCollectionType(const ValueType value_type) { |
187 | 6.32G | return IsObjectType(value_type) || value_type == ValueType::kArray5.36G ; |
188 | 6.32G | } |
189 | | |
190 | 115M | constexpr inline bool IsRegulaDBInternalRecordKeyType(const ValueType value_type) { |
191 | | // For regular db: |
192 | | // - transaction apply state records. |
193 | 115M | return value_type == ValueType::kTransactionApplyState; |
194 | 115M | } |
195 | | |
196 | 115M | constexpr inline bool IsIntentsDBInternalRecordKeyType(const ValueType value_type) { |
197 | | // For intents db: |
198 | | // - reverse index from transaction id to keys of write intents belonging to that transaction. |
199 | | // - external transaction records (transactions that originated on a CDC producer). |
200 | 115M | return value_type == ValueType::kExternalTransactionId || |
201 | 115M | value_type == ValueType::kTransactionId115M ; |
202 | 115M | } |
203 | | |
204 | 115M | constexpr inline bool IsInternalRecordKeyType(const ValueType value_type) { |
205 | 115M | return IsRegulaDBInternalRecordKeyType(value_type) || |
206 | 115M | IsIntentsDBInternalRecordKeyType(value_type)115M ; |
207 | 115M | } |
208 | | |
209 | 4.83G | constexpr inline bool IsPrimitiveValueType(const ValueType value_type) { |
210 | 4.83G | return (kMinPrimitiveValueType <= value_type && value_type <= kMaxPrimitiveValueType4.83G && |
211 | 4.83G | !IsCollectionType(value_type)4.77G && |
212 | 4.83G | value_type != ValueType::kTombstone4.64G ) || |
213 | 4.83G | value_type == ValueType::kTransactionApplyState421M || |
214 | 4.83G | value_type == ValueType::kExternalTransactionId421M ; |
215 | 4.83G | } |
216 | | |
217 | 1.78M | constexpr inline bool IsSpecialValueType(ValueType value_type) { |
218 | 1.78M | return value_type == ValueType::kLowest || value_type == ValueType::kHighest1.77M || |
219 | 1.78M | value_type == ValueType::kMaxByte598k || value_type == ValueType::kIntentTypeSet597k || |
220 | 1.78M | value_type == ValueType::kGreaterThanIntentType597k ; |
221 | 1.78M | } |
222 | | |
223 | 56.4M | constexpr inline bool IsPrimitiveOrSpecialValueType(ValueType value_type) { |
224 | 56.4M | return IsPrimitiveValueType(value_type) || IsSpecialValueType(value_type)1.33M ; |
225 | 56.4M | } |
226 | | |
227 | | // Decode the first byte of the given slice as a ValueType. |
228 | 1.36G | inline ValueType DecodeValueType(const rocksdb::Slice& value) { |
229 | 1.36G | return value.empty() ? ValueType::kInvalid200k : static_cast<ValueType>(value.data()[0])1.36G ; |
230 | 1.36G | } |
231 | | |
232 | | // Decode the first byte of the given slice as a ValueType and consume it. |
233 | 3.10G | inline ValueType ConsumeValueType(rocksdb::Slice* slice) { |
234 | 3.10G | return slice->empty() ? ValueType::kInvalid0 |
235 | 3.10G | : static_cast<ValueType>(slice->consume_byte()); |
236 | 3.10G | } |
237 | | |
238 | 83.4M | constexpr inline ValueType DecodeValueType(char value_type_byte) { |
239 | 83.4M | return static_cast<ValueType>(value_type_byte); |
240 | 83.4M | } |
241 | | |
242 | | // Checks if a value is a merge record, meaning it begins with the |
243 | | // kMergeFlags value type. Currently, the only merge records supported are |
244 | | // TTL records, when the flags value is 0x1. In the future, value |
245 | | // merge records may be implemented, such as a +1 merge record for INCR. |
246 | 19.2M | inline bool IsMergeRecord(const rocksdb::Slice& value) { |
247 | 19.2M | return DecodeValueType(value) == ValueType::kMergeFlags; |
248 | 19.2M | } |
249 | | |
250 | | } // namespace docdb |
251 | | } // namespace yb |
252 | | |
253 | | #endif // YB_DOCDB_VALUE_TYPE_H_ |