be/src/storage/storage_layout.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #pragma once |
19 | | |
20 | | #include <bit> |
21 | | #include <cmath> |
22 | | #include <cstddef> |
23 | | #include <cstdint> |
24 | | #include <limits> |
25 | | #include <string> |
26 | | #include <type_traits> |
27 | | |
28 | | #include "common/cast_set.h" |
29 | | #include "common/logging.h" |
30 | | #include "common/status.h" |
31 | | #include "core/data_type/primitive_type.h" |
32 | | #include "core/data_type/storage_field_type.h" |
33 | | #include "core/decimal12.h" |
34 | | #include "core/pod_array.h" |
35 | | #include "core/string_ref.h" |
36 | | #include "core/uint24.h" |
37 | | #include "core/value/decimalv2_value.h" |
38 | | #include "core/value/vdatetime_value.h" |
39 | | #include "storage/field_type.h" |
40 | | #include "storage/types.h" |
41 | | #include "util/slice.h" |
42 | | |
43 | | namespace doris { |
44 | | |
45 | | class IColumn; |
46 | | |
47 | | // How a compute-layer value becomes what a segment stores for FieldType FT: |
48 | | // 1. Unchanged (BitCast): BOOL, TINYINT, SMALLINT, INT, BIGINT, LARGEINT, UNSIGNED_INT, |
49 | | // UNSIGNED_BIGINT, DECIMAL32, DECIMAL64, DECIMAL128I, DECIMAL256, DATEV2, |
50 | | // DATETIMEV2, TIMESTAMP_NS, TIMESTAMPTZ, IPV4, IPV6, UUID. |
51 | | // 2. Normalised (FloatingPoint): FLOAT and DOUBLE, every NaN as the quiet NaN. |
52 | | // 3. Re-encoded (repack_from_column): the V1 DATE, DATETIME and DECIMAL layouts. |
53 | | // 4. As bytes (Bytes): VARCHAR, STRING, JSONB, VARIANT; CHAR also zero padded to its |
54 | | // length. |
55 | | // 5. Serialised: BITMAP, HLL, QUANTILE_STATE. |
56 | | // 6. AGG_STATE: a string, a bitmap or a fixed-length object, whichever its aggregate |
57 | | // function serialises to; the column holding the states tells which. |
58 | | // Compute-layer types: PrimitiveTypeTraits<PT>; storage-layer types: CppTypeTraits<FT>. |
59 | | // |
60 | | // Every layout converts a batch the same way: column_to_storage(column, row_pos, n, buffers) |
61 | | // returns the stored cells of rows [row_pos, row_pos + n) back to back, n fixed-width values |
62 | | // or n Slice descriptors. It returns the column's own bytes when they are stored unchanged |
63 | | // and otherwise fills the StorageBuffers it is given, which the caller keeps until it has |
64 | | // consumed the cells. Every row of the range is converted, NULL rows included: whatever a |
65 | | // NULL row holds converts without harm, and no caller uses a NULL row's cell. CHAR padding is |
66 | | // the one exception: it needs a range without NULL rows, see StorageLayout<CHAR>. to_storage |
67 | | // retains a typed result for single-value key and predicate conversions. |
68 | | template <FieldType FT> |
69 | | struct StorageLayout; |
70 | | |
71 | | // Where a batch conversion puts what it cannot borrow: converted fixed-width values and |
72 | | // serialised payloads in `bytes`, the Slice descriptors of the byte types in `cells`. |
73 | | struct StorageBuffers { |
74 | | PaddedPODArray<uint8_t> bytes; |
75 | | PaddedPODArray<Slice> cells; |
76 | | }; |
77 | | |
78 | | // The FieldTypes stored fixed width, for callers that only know their FieldType at run |
79 | | // time; the others are stored as bytes. |
80 | | #define DORIS_APPLY_FOR_FIXED_WIDTH_STORAGE_LAYOUT_TYPES(M) \ |
81 | 168k | M(OLAP_FIELD_TYPE_BOOL) \ |
82 | 168k | M(OLAP_FIELD_TYPE_TINYINT) \ |
83 | 60.9k | M(OLAP_FIELD_TYPE_SMALLINT) \ |
84 | 891k | M(OLAP_FIELD_TYPE_INT) \ |
85 | 891k | M(OLAP_FIELD_TYPE_BIGINT) \ |
86 | 598k | M(OLAP_FIELD_TYPE_LARGEINT) \ |
87 | 22.1k | M(OLAP_FIELD_TYPE_UNSIGNED_INT) \ |
88 | 0 | M(OLAP_FIELD_TYPE_UNSIGNED_BIGINT) \ |
89 | 12.3k | M(OLAP_FIELD_TYPE_FLOAT) \ |
90 | 25.9k | M(OLAP_FIELD_TYPE_DOUBLE) \ |
91 | 25.9k | M(OLAP_FIELD_TYPE_DECIMAL) \ |
92 | 5.38k | M(OLAP_FIELD_TYPE_DECIMAL32) \ |
93 | 18.9k | M(OLAP_FIELD_TYPE_DECIMAL64) \ |
94 | 18.9k | M(OLAP_FIELD_TYPE_DECIMAL128I) \ |
95 | 16.5k | M(OLAP_FIELD_TYPE_DECIMAL256) \ |
96 | 1.49k | M(OLAP_FIELD_TYPE_DATE) \ |
97 | 835 | M(OLAP_FIELD_TYPE_DATETIME) \ |
98 | 43.0k | M(OLAP_FIELD_TYPE_DATEV2) \ |
99 | 44.1k | M(OLAP_FIELD_TYPE_DATETIMEV2) \ |
100 | 44.1k | M(OLAP_FIELD_TYPE_TIMESTAMP_NS) \ |
101 | 7.75k | M(OLAP_FIELD_TYPE_TIMESTAMPTZ) \ |
102 | 7.75k | M(OLAP_FIELD_TYPE_IPV4) \ |
103 | 736 | M(OLAP_FIELD_TYPE_IPV6) \ |
104 | 26.3k | M(OLAP_FIELD_TYPE_UUID) |
105 | | |
106 | | namespace storage_layout_detail { |
107 | | |
108 | | // A StorageValue is the PrimitiveValue's own bytes, so a run of the column is a run of |
109 | | // stored values. |
110 | | template <FieldType FT> |
111 | | struct BitCast { |
112 | | private: |
113 | | using StorageValue = typename CppTypeTraits<FT>::CppType; |
114 | | using PrimitiveValue = |
115 | | typename PrimitiveTypeTraits<storage_field_type_to_primitive_type(FT)>::CppType; |
116 | | static_assert(sizeof(StorageValue) == sizeof(PrimitiveValue)); |
117 | | |
118 | | public: |
119 | 28.3M | static StorageValue to_storage(const PrimitiveValue& value) { |
120 | 28.3M | return std::bit_cast<StorageValue>(value); |
121 | 28.3M | } _ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE24EE10to_storageERKh Line | Count | Source | 119 | 21.7k | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 21.7k | return std::bit_cast<StorageValue>(value); | 121 | 21.7k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE1EE10to_storageERKa Line | Count | Source | 119 | 263k | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 263k | return std::bit_cast<StorageValue>(value); | 121 | 263k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE3EE10to_storageERKs Line | Count | Source | 119 | 212k | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 212k | return std::bit_cast<StorageValue>(value); | 121 | 212k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE5EE10to_storageERKi Line | Count | Source | 119 | 18.6M | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 18.6M | return std::bit_cast<StorageValue>(value); | 121 | 18.6M | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE7EE10to_storageERKl Line | Count | Source | 119 | 7.60M | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 7.60M | return std::bit_cast<StorageValue>(value); | 121 | 7.60M | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE9EE10to_storageERKn Line | Count | Source | 119 | 43.6k | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 43.6k | return std::bit_cast<StorageValue>(value); | 121 | 43.6k | } |
Unexecuted instantiation: _ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE6EE10to_storageERKj _ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE8EE10to_storageERKm Line | Count | Source | 119 | 607 | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 607 | return std::bit_cast<StorageValue>(value); | 121 | 607 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE31EE10to_storageERKNS_7DecimalIiEE Line | Count | Source | 119 | 4.21k | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 4.21k | return std::bit_cast<StorageValue>(value); | 121 | 4.21k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE32EE10to_storageERKNS_7DecimalIlEE Line | Count | Source | 119 | 3.58k | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 3.58k | return std::bit_cast<StorageValue>(value); | 121 | 3.58k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE33EE10to_storageERKNS_12Decimal128V3E Line | Count | Source | 119 | 586k | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 586k | return std::bit_cast<StorageValue>(value); | 121 | 586k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE37EE10to_storageERKNS_7DecimalIN4wide7integerILm256EiEEEE Line | Count | Source | 119 | 3.47k | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 3.47k | return std::bit_cast<StorageValue>(value); | 121 | 3.47k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE28EE10to_storageERKNS_11DateV2ValueINS_15DateV2ValueTypeEEE Line | Count | Source | 119 | 297k | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 297k | return std::bit_cast<StorageValue>(value); | 121 | 297k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE29EE10to_storageERKNS_11DateV2ValueINS_19DateTimeV2ValueTypeEEE Line | Count | Source | 119 | 601k | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 601k | return std::bit_cast<StorageValue>(value); | 121 | 601k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE41EE10to_storageERKNS_16TimeStampNsValueE Line | Count | Source | 119 | 1.54k | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 1.54k | return std::bit_cast<StorageValue>(value); | 121 | 1.54k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE40EE10to_storageERKNS_16TimestampTzValueE Line | Count | Source | 119 | 16.8k | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 16.8k | return std::bit_cast<StorageValue>(value); | 121 | 16.8k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE38EE10to_storageERKj Line | Count | Source | 119 | 2.82k | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 2.82k | return std::bit_cast<StorageValue>(value); | 121 | 2.82k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE39EE10to_storageERKo Line | Count | Source | 119 | 2.72k | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 2.72k | return std::bit_cast<StorageValue>(value); | 121 | 2.72k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE42EE10to_storageERKo Line | Count | Source | 119 | 6.50k | static StorageValue to_storage(const PrimitiveValue& value) { | 120 | 6.50k | return std::bit_cast<StorageValue>(value); | 121 | 6.50k | } |
|
122 | | // Always borrows the column's bytes. |
123 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
124 | | StorageBuffers& buffers); |
125 | | }; |
126 | | |
127 | | // Every NaN is stored as the quiet NaN, so equal values have equal stored bytes |
128 | | // and the bloom filter / dictionary / key encodings that hash or compare bytes |
129 | | // treat all NaNs as one value. |
130 | | template <FieldType FT> |
131 | | struct FloatingPoint { |
132 | | private: |
133 | | using StorageValue = typename CppTypeTraits<FT>::CppType; |
134 | | using PrimitiveValue = |
135 | | typename PrimitiveTypeTraits<storage_field_type_to_primitive_type(FT)>::CppType; |
136 | | static_assert(std::is_floating_point_v<StorageValue>); |
137 | | static_assert(std::is_same_v<StorageValue, PrimitiveValue>); |
138 | | |
139 | | public: |
140 | 117k | static StorageValue canonicalize_nan(StorageValue value) { |
141 | 117k | return std::isnan(value) ? std::numeric_limits<StorageValue>::quiet_NaN() : value; |
142 | 117k | } _ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE10EE16canonicalize_nanEf Line | Count | Source | 140 | 52.0k | static StorageValue canonicalize_nan(StorageValue value) { | 141 | 52.0k | return std::isnan(value) ? std::numeric_limits<StorageValue>::quiet_NaN() : value; | 142 | 52.0k | } |
_ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE11EE16canonicalize_nanEd Line | Count | Source | 140 | 65.8k | static StorageValue canonicalize_nan(StorageValue value) { | 141 | 65.8k | return std::isnan(value) ? std::numeric_limits<StorageValue>::quiet_NaN() : value; | 142 | 65.8k | } |
|
143 | 20.8k | static StorageValue to_storage(PrimitiveValue value) { return canonicalize_nan(value); }_ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE10EE10to_storageEf Line | Count | Source | 143 | 3.55k | static StorageValue to_storage(PrimitiveValue value) { return canonicalize_nan(value); } |
_ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE11EE10to_storageEd Line | Count | Source | 143 | 17.3k | static StorageValue to_storage(PrimitiveValue value) { return canonicalize_nan(value); } |
|
144 | | // Borrows the column's bytes when [row_pos, row_pos + n) has no NaN, otherwise |
145 | | // converts the range into buffers.bytes. NaNs outside the range do not require a |
146 | | // copy; the source column is never modified. |
147 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
148 | | StorageBuffers& buffers); |
149 | | }; |
150 | | |
151 | | // A string is stored as its own bytes, whatever their length: the cells are Slice |
152 | | // descriptors of the column's payloads. |
153 | | struct Bytes { |
154 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
155 | | StorageBuffers& buffers); |
156 | | }; |
157 | | |
158 | | } // namespace storage_layout_detail |
159 | | |
160 | | #define DORIS_STORAGE_LAYOUT_BIT_CAST(FT) \ |
161 | | template <> \ |
162 | | struct StorageLayout<FieldType::FT> : storage_layout_detail::BitCast<FieldType::FT> {}; |
163 | | |
164 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_BOOL) |
165 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_TINYINT) |
166 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_SMALLINT) |
167 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_INT) |
168 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_BIGINT) |
169 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_LARGEINT) |
170 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_UNSIGNED_INT) |
171 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_UNSIGNED_BIGINT) |
172 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL32) |
173 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL64) |
174 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL128I) |
175 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL256) |
176 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DATEV2) |
177 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DATETIMEV2) |
178 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_TIMESTAMP_NS) |
179 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_TIMESTAMPTZ) |
180 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_IPV4) |
181 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_IPV6) |
182 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_UUID) |
183 | | #undef DORIS_STORAGE_LAYOUT_BIT_CAST |
184 | | |
185 | | template <> |
186 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_FLOAT> |
187 | | : storage_layout_detail::FloatingPoint<FieldType::OLAP_FIELD_TYPE_FLOAT> {}; |
188 | | |
189 | | template <> |
190 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DOUBLE> |
191 | | : storage_layout_detail::FloatingPoint<FieldType::OLAP_FIELD_TYPE_DOUBLE> {}; |
192 | | |
193 | | // The batch conversions of the layouts above are instantiated once, in storage_layout.cpp. |
194 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_BOOL>; |
195 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_TINYINT>; |
196 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_SMALLINT>; |
197 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_INT>; |
198 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_BIGINT>; |
199 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_LARGEINT>; |
200 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_UNSIGNED_INT>; |
201 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_UNSIGNED_BIGINT>; |
202 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_DECIMAL32>; |
203 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_DECIMAL64>; |
204 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_DECIMAL128I>; |
205 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_DECIMAL256>; |
206 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_DATEV2>; |
207 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_DATETIMEV2>; |
208 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS>; |
209 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ>; |
210 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_IPV4>; |
211 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_IPV6>; |
212 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_UUID>; |
213 | | extern template struct storage_layout_detail::FloatingPoint<FieldType::OLAP_FIELD_TYPE_FLOAT>; |
214 | | extern template struct storage_layout_detail::FloatingPoint<FieldType::OLAP_FIELD_TYPE_DOUBLE>; |
215 | | |
216 | | // V1 DATE: three bytes of (year << 9) | (month << 5) | day. |
217 | | template <> |
218 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DATE> { |
219 | | private: |
220 | | using StorageValue = typename CppTypeTraits<FieldType::OLAP_FIELD_TYPE_DATE>::CppType; |
221 | | using PrimitiveValue = typename PrimitiveTypeTraits<TYPE_DATE>::CppType; |
222 | | static_assert(std::is_same_v<StorageValue, uint24_t>); |
223 | | |
224 | | public: |
225 | 1.54M | static StorageValue to_storage(const PrimitiveValue& value) { |
226 | 1.54M | return StorageValue(cast_set<uint32_t>(value.to_olap_date())); |
227 | 1.54M | } |
228 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
229 | | StorageBuffers& buffers); |
230 | | }; |
231 | | |
232 | | // V1 DATETIME: the decimal digits YYYYMMDDhhmmss packed into one integer. |
233 | | template <> |
234 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DATETIME> { |
235 | | private: |
236 | | using StorageValue = typename CppTypeTraits<FieldType::OLAP_FIELD_TYPE_DATETIME>::CppType; |
237 | | using PrimitiveValue = typename PrimitiveTypeTraits<TYPE_DATETIME>::CppType; |
238 | | static_assert(std::is_same_v<StorageValue, int64_t>); |
239 | | |
240 | | public: |
241 | 1.42M | static StorageValue to_storage(const PrimitiveValue& value) { |
242 | 1.42M | return static_cast<StorageValue>(value.to_olap_datetime()); |
243 | 1.42M | } |
244 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
245 | | StorageBuffers& buffers); |
246 | | }; |
247 | | |
248 | | // V1 DECIMAL: the integer and the nine-digit fraction stored side by side. |
249 | | template <> |
250 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DECIMAL> { |
251 | | private: |
252 | | using StorageValue = typename CppTypeTraits<FieldType::OLAP_FIELD_TYPE_DECIMAL>::CppType; |
253 | | using PrimitiveValue = typename PrimitiveTypeTraits<TYPE_DECIMALV2>::CppType; |
254 | | static_assert(std::is_same_v<StorageValue, decimal12_t>); |
255 | | |
256 | | public: |
257 | 3.53k | static StorageValue to_storage(const PrimitiveValue& value) { |
258 | 3.53k | return {value.int_value(), value.frac_value()}; |
259 | 3.53k | } |
260 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
261 | | StorageBuffers& buffers); |
262 | | }; |
263 | | |
264 | | template <> |
265 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_VARCHAR> : storage_layout_detail::Bytes {}; |
266 | | |
267 | | template <> |
268 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_STRING> : storage_layout_detail::Bytes {}; |
269 | | |
270 | | template <> |
271 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_JSONB> : storage_layout_detail::Bytes {}; |
272 | | |
273 | | // A VARIANT root column reaches the writer as the JSONB of its rows. |
274 | | template <> |
275 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_VARIANT> : storage_layout_detail::Bytes {}; |
276 | | |
277 | | // CHAR(N) is stored zero padded to N bytes, while a block holds it unpadded: the writers |
278 | | // pad the values they store or index with the length-taking column_to_storage. Padding |
279 | | // copies a value into an N-byte slot, so it never reads a NULL row: a NULL row can hold a |
280 | | // value longer than N, as load does not check NULL rows. The Bytes one stays for the SNII |
281 | | // index, which is fed CHAR as it reads back. |
282 | | template <> |
283 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_CHAR> : storage_layout_detail::Bytes { |
284 | | using storage_layout_detail::Bytes::column_to_storage; |
285 | | |
286 | | // Pads every non-NULL row of the range into its own `length` zeroed bytes and points its |
287 | | // cell at them; a NULL row keeps an empty cell. null_map[i] is the NULL flag of row |
288 | | // row_pos + i, and null_map is nullptr when the range holds no NULL row. |
289 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
290 | | size_t length, const uint8_t* null_map, |
291 | | StorageBuffers& buffers); |
292 | | |
293 | 4.23k | static void append_padded(StringRef value, size_t length, std::string* out) { |
294 | | DCHECK_LE(value.size, length); |
295 | 4.23k | out->reserve(out->size() + length); |
296 | 4.23k | out->append(value.data, value.size); |
297 | 4.23k | out->append(length - value.size, '\0'); |
298 | 4.23k | } |
299 | | }; |
300 | | |
301 | | // The object types are stored serialised: every value of the batch into buffers.bytes, |
302 | | // the cells pointing at them. |
303 | | template <> |
304 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_BITMAP> { |
305 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
306 | | StorageBuffers& buffers); |
307 | | }; |
308 | | |
309 | | template <> |
310 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_HLL> { |
311 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
312 | | StorageBuffers& buffers); |
313 | | }; |
314 | | |
315 | | template <> |
316 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_QUANTILE_STATE> { |
317 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
318 | | StorageBuffers& buffers); |
319 | | }; |
320 | | |
321 | | // The fixed-length objects an AGG_STATE column holds when its aggregate function serialises |
322 | | // to them, each borrowed through a Slice descriptor. String and bitmap states are stored |
323 | | // through the VARCHAR and BITMAP layouts, which the column writer is given when it is created. |
324 | | template <> |
325 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_AGG_STATE> { |
326 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
327 | | StorageBuffers& buffers); |
328 | | }; |
329 | | |
330 | | // The batch conversion of a FieldType known only at run time: the column_to_storage of |
331 | | // StorageLayout<type>, for the column writer and the index feeds. CHAR is not accepted: |
332 | | // whether its values are padded is the caller's choice, made through StorageLayout<CHAR>. |
333 | | const uint8_t* column_to_storage(FieldType type, const IColumn& column, size_t row_pos, size_t n, |
334 | | StorageBuffers& buffers); |
335 | | |
336 | | // The admission rule a writer applies to the rows of a column before they are stored: a |
337 | | // STRING or JSONB value must fit string_type_length_soft_limit_bytes, and a JSONB value |
338 | | // must be a well-formed JSONB document. The rows `null_map` marks NULL are not checked. |
339 | | Status admit_storage_rows(FieldType type, const IColumn& column, size_t row_pos, size_t n, |
340 | | const uint8_t* null_map); |
341 | | |
342 | | } // namespace doris |