YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/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_