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_fwd.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 | | |
42 | | namespace doris { |
43 | | |
44 | | class IColumn; |
45 | | |
46 | | // How a compute-layer value becomes what a segment stores for FieldType FT: |
47 | | // 1. Unchanged (BitCast): BOOL, TINYINT, SMALLINT, INT, BIGINT, LARGEINT, UNSIGNED_INT, |
48 | | // UNSIGNED_BIGINT, DECIMAL32, DECIMAL64, DECIMAL128I, DECIMAL256, DATEV2, |
49 | | // DATETIMEV2, TIMESTAMP_NS, TIMESTAMPTZ, IPV4, IPV6, UUID. |
50 | | // 2. Normalised (FloatingPoint): FLOAT and DOUBLE, every NaN as the quiet NaN. |
51 | | // 3. Re-encoded (repack_from_column): the V1 DATE, DATETIME and DECIMAL layouts. |
52 | | // 4. As bytes (Bytes): VARCHAR, STRING, JSONB, VARIANT; CHAR also zero padded to its |
53 | | // length. |
54 | | // 5. Serialised: BITMAP, HLL, QUANTILE_STATE. |
55 | | // 6. AGG_STATE: a string, a bitmap or a fixed-length object, whichever its aggregate |
56 | | // function serialises to. |
57 | | // Compute-layer types: PrimitiveTypeTraits<PT>; storage-layer types: CppTypeTraits<FT>. |
58 | | // |
59 | | // Batch conversions return stored cells as bytes: fixed-width values or Slice descriptors. |
60 | | // Source bytes are borrowed when no conversion is needed; converted bytes use caller-owned |
61 | | // buffers. storage_at returns one Slice in the supplied descriptor, whose payload is borrowed |
62 | | // or held in tmp_buffer. Consumers must finish before either buffer is reused. |
63 | | // to_storage retains a typed result for single-value key and predicate conversions. |
64 | | template <FieldType FT> |
65 | | struct StorageLayout; |
66 | | |
67 | | // The FieldTypes stored fixed width, for callers that only know their FieldType at run |
68 | | // time; the others are stored as bytes. |
69 | | #define DORIS_APPLY_FOR_FIXED_WIDTH_STORAGE_LAYOUT_TYPES(M) \ |
70 | 6.60k | M(OLAP_FIELD_TYPE_BOOL) \ |
71 | 6.60k | M(OLAP_FIELD_TYPE_TINYINT) \ |
72 | 5.86k | M(OLAP_FIELD_TYPE_SMALLINT) \ |
73 | 10.2k | M(OLAP_FIELD_TYPE_INT) \ |
74 | 10.2k | M(OLAP_FIELD_TYPE_BIGINT) \ |
75 | 2.26k | M(OLAP_FIELD_TYPE_LARGEINT) \ |
76 | 1.15k | M(OLAP_FIELD_TYPE_UNSIGNED_INT) \ |
77 | 607 | M(OLAP_FIELD_TYPE_UNSIGNED_BIGINT) \ |
78 | 1.12k | M(OLAP_FIELD_TYPE_FLOAT) \ |
79 | 1.12k | M(OLAP_FIELD_TYPE_DOUBLE) \ |
80 | 1.14k | M(OLAP_FIELD_TYPE_DECIMAL) \ |
81 | 1.21k | M(OLAP_FIELD_TYPE_DECIMAL32) \ |
82 | 1.21k | M(OLAP_FIELD_TYPE_DECIMAL64) \ |
83 | 1.14k | M(OLAP_FIELD_TYPE_DECIMAL128I) \ |
84 | 1.14k | M(OLAP_FIELD_TYPE_DECIMAL256) \ |
85 | 1.59k | M(OLAP_FIELD_TYPE_DATE) \ |
86 | 1.59k | M(OLAP_FIELD_TYPE_DATETIME) \ |
87 | 1.22k | M(OLAP_FIELD_TYPE_DATEV2) \ |
88 | 1.22k | M(OLAP_FIELD_TYPE_DATETIMEV2) \ |
89 | 1.14k | M(OLAP_FIELD_TYPE_TIMESTAMP_NS) \ |
90 | 1.14k | M(OLAP_FIELD_TYPE_TIMESTAMPTZ) \ |
91 | 1.21k | M(OLAP_FIELD_TYPE_IPV4) \ |
92 | 1.21k | M(OLAP_FIELD_TYPE_IPV6) \ |
93 | 1.14k | M(OLAP_FIELD_TYPE_UUID) |
94 | | |
95 | | namespace storage_layout_detail { |
96 | | |
97 | | // A StorageValue is the PrimitiveValue's own bytes, so a run of the column is a run of |
98 | | // stored values. |
99 | | template <FieldType FT> |
100 | | struct BitCast { |
101 | | private: |
102 | | using StorageValue = typename CppTypeTraits<FT>::CppType; |
103 | | using PrimitiveValue = |
104 | | typename PrimitiveTypeTraits<storage_field_type_to_primitive_type(FT)>::CppType; |
105 | | static_assert(sizeof(StorageValue) == sizeof(PrimitiveValue)); |
106 | | |
107 | | public: |
108 | | // Every value can be borrowed without inspection or conversion. |
109 | | static constexpr bool is_direct = true; |
110 | | |
111 | 491k | static StorageValue to_storage(const PrimitiveValue& value) { |
112 | 491k | return std::bit_cast<StorageValue>(value); |
113 | 491k | } _ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE7EE10to_storageERKl Line | Count | Source | 111 | 2.69k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 2.69k | return std::bit_cast<StorageValue>(value); | 113 | 2.69k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE24EE10to_storageERKh Line | Count | Source | 111 | 8.02k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 8.02k | return std::bit_cast<StorageValue>(value); | 113 | 8.02k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE31EE10to_storageERKNS_7DecimalIiEE Line | Count | Source | 111 | 2.41k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 2.41k | return std::bit_cast<StorageValue>(value); | 113 | 2.41k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE32EE10to_storageERKNS_7DecimalIlEE Line | Count | Source | 111 | 2.34k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 2.34k | return std::bit_cast<StorageValue>(value); | 113 | 2.34k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE33EE10to_storageERKNS_12Decimal128V3E Line | Count | Source | 111 | 2.33k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 2.33k | return std::bit_cast<StorageValue>(value); | 113 | 2.33k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE37EE10to_storageERKNS_7DecimalIN4wide7integerILm256EiEEEE Line | Count | Source | 111 | 2.33k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 2.33k | return std::bit_cast<StorageValue>(value); | 113 | 2.33k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE28EE10to_storageERKNS_11DateV2ValueINS_15DateV2ValueTypeEEE Line | Count | Source | 111 | 2.41k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 2.41k | return std::bit_cast<StorageValue>(value); | 113 | 2.41k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE29EE10to_storageERKNS_11DateV2ValueINS_19DateTimeV2ValueTypeEEE Line | Count | Source | 111 | 2.35k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 2.35k | return std::bit_cast<StorageValue>(value); | 113 | 2.35k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE40EE10to_storageERKNS_16TimestampTzValueE Line | Count | Source | 111 | 2.37k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 2.37k | return std::bit_cast<StorageValue>(value); | 113 | 2.37k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE1EE10to_storageERKa Line | Count | Source | 111 | 5.68k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 5.68k | return std::bit_cast<StorageValue>(value); | 113 | 5.68k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE3EE10to_storageERKs Line | Count | Source | 111 | 3.57k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 3.57k | return std::bit_cast<StorageValue>(value); | 113 | 3.57k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE5EE10to_storageERKi Line | Count | Source | 111 | 445k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 445k | return std::bit_cast<StorageValue>(value); | 113 | 445k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE9EE10to_storageERKn Line | Count | Source | 111 | 2.34k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 2.34k | return std::bit_cast<StorageValue>(value); | 113 | 2.34k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE38EE10to_storageERKj Line | Count | Source | 111 | 2.39k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 2.39k | return std::bit_cast<StorageValue>(value); | 113 | 2.39k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE39EE10to_storageERKo Line | Count | Source | 111 | 2.33k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 2.33k | return std::bit_cast<StorageValue>(value); | 113 | 2.33k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE42EE10to_storageERKo Line | Count | Source | 111 | 1.02k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 1.02k | return std::bit_cast<StorageValue>(value); | 113 | 1.02k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE41EE10to_storageERKNS_16TimeStampNsValueE Line | Count | Source | 111 | 1.07k | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 1.07k | return std::bit_cast<StorageValue>(value); | 113 | 1.07k | } |
Unexecuted instantiation: _ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE6EE10to_storageERKj _ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE8EE10to_storageERKm Line | Count | Source | 111 | 607 | static StorageValue to_storage(const PrimitiveValue& value) { | 112 | 607 | return std::bit_cast<StorageValue>(value); | 113 | 607 | } |
|
114 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
115 | | PaddedPODArray<char>& buffer, |
116 | | const uint8_t* null_map = nullptr); |
117 | | }; |
118 | | |
119 | | // Every NaN is stored as the quiet NaN, so equal values have equal stored bytes |
120 | | // and the bloom filter / dictionary / key encodings that hash or compare bytes |
121 | | // treat all NaNs as one value. |
122 | | template <FieldType FT> |
123 | | struct FloatingPoint { |
124 | | private: |
125 | | using StorageValue = typename CppTypeTraits<FT>::CppType; |
126 | | using PrimitiveValue = |
127 | | typename PrimitiveTypeTraits<storage_field_type_to_primitive_type(FT)>::CppType; |
128 | | static_assert(std::is_floating_point_v<StorageValue>); |
129 | | static_assert(std::is_same_v<StorageValue, PrimitiveValue>); |
130 | | |
131 | | public: |
132 | | static constexpr bool is_direct = false; |
133 | | |
134 | 113k | static StorageValue canonicalize_nan(StorageValue value) { |
135 | 113k | return std::isnan(value) ? std::numeric_limits<StorageValue>::quiet_NaN() : value; |
136 | 113k | } _ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE10EE16canonicalize_nanEf Line | Count | Source | 134 | 50.9k | static StorageValue canonicalize_nan(StorageValue value) { | 135 | 50.9k | return std::isnan(value) ? std::numeric_limits<StorageValue>::quiet_NaN() : value; | 136 | 50.9k | } |
_ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE11EE16canonicalize_nanEd Line | Count | Source | 134 | 62.4k | static StorageValue canonicalize_nan(StorageValue value) { | 135 | 62.4k | return std::isnan(value) ? std::numeric_limits<StorageValue>::quiet_NaN() : value; | 136 | 62.4k | } |
|
137 | 16.2k | static StorageValue to_storage(PrimitiveValue value) { return canonicalize_nan(value); }_ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE10EE10to_storageEf Line | Count | Source | 137 | 2.38k | static StorageValue to_storage(PrimitiveValue value) { return canonicalize_nan(value); } |
_ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE11EE10to_storageEd Line | Count | Source | 137 | 13.9k | static StorageValue to_storage(PrimitiveValue value) { return canonicalize_nan(value); } |
|
138 | | // The returned bytes belong to the source column when [row_pos, row_pos + n) has |
139 | | // no NaN, otherwise to buffer until it is reused. NaNs outside the range do not |
140 | | // require a copy; the source column is never modified. |
141 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
142 | | PaddedPODArray<char>& buffer, |
143 | | const uint8_t* null_map = nullptr); |
144 | | }; |
145 | | |
146 | | // A string is stored as its own bytes, whatever their length. |
147 | | struct Bytes { |
148 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
149 | | Slice* cells, const uint8_t* null_map = nullptr); |
150 | | static const uint8_t* storage_at(const IColumn& column, size_t row, |
151 | | PaddedPODArray<char>& tmp_buffer, Slice* cell); |
152 | | }; |
153 | | |
154 | | } // namespace storage_layout_detail |
155 | | |
156 | | #define DORIS_STORAGE_LAYOUT_BIT_CAST(FT) \ |
157 | | template <> \ |
158 | | struct StorageLayout<FieldType::FT> : storage_layout_detail::BitCast<FieldType::FT> {}; \ |
159 | | extern template struct storage_layout_detail::BitCast<FieldType::FT>; |
160 | | |
161 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_BOOL) |
162 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_TINYINT) |
163 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_SMALLINT) |
164 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_INT) |
165 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_BIGINT) |
166 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_LARGEINT) |
167 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_UNSIGNED_INT) |
168 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_UNSIGNED_BIGINT) |
169 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL32) |
170 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL64) |
171 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL128I) |
172 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL256) |
173 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DATEV2) |
174 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DATETIMEV2) |
175 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_TIMESTAMP_NS) |
176 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_TIMESTAMPTZ) |
177 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_IPV4) |
178 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_IPV6) |
179 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_UUID) |
180 | | #undef DORIS_STORAGE_LAYOUT_BIT_CAST |
181 | | |
182 | | template <> |
183 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_FLOAT> |
184 | | : storage_layout_detail::FloatingPoint<FieldType::OLAP_FIELD_TYPE_FLOAT> {}; |
185 | | |
186 | | template <> |
187 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DOUBLE> |
188 | | : storage_layout_detail::FloatingPoint<FieldType::OLAP_FIELD_TYPE_DOUBLE> {}; |
189 | | |
190 | | extern template struct storage_layout_detail::FloatingPoint<FieldType::OLAP_FIELD_TYPE_FLOAT>; |
191 | | extern template struct storage_layout_detail::FloatingPoint<FieldType::OLAP_FIELD_TYPE_DOUBLE>; |
192 | | |
193 | | // V1 DATE: three bytes of (year << 9) | (month << 5) | day. |
194 | | template <> |
195 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DATE> { |
196 | | private: |
197 | | using StorageValue = typename CppTypeTraits<FieldType::OLAP_FIELD_TYPE_DATE>::CppType; |
198 | | using PrimitiveValue = typename PrimitiveTypeTraits<TYPE_DATE>::CppType; |
199 | | static_assert(std::is_same_v<StorageValue, uint24_t>); |
200 | | |
201 | | public: |
202 | | static constexpr bool is_direct = false; |
203 | | |
204 | 118k | static StorageValue to_storage(const PrimitiveValue& value) { |
205 | 118k | return StorageValue(cast_set<uint32_t>(value.to_olap_date())); |
206 | 118k | } |
207 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
208 | | PaddedPODArray<char>& buffer, |
209 | | const uint8_t* null_map = nullptr); |
210 | | }; |
211 | | |
212 | | // V1 DATETIME: the decimal digits YYYYMMDDhhmmss packed into one integer. |
213 | | template <> |
214 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DATETIME> { |
215 | | private: |
216 | | using StorageValue = typename CppTypeTraits<FieldType::OLAP_FIELD_TYPE_DATETIME>::CppType; |
217 | | using PrimitiveValue = typename PrimitiveTypeTraits<TYPE_DATETIME>::CppType; |
218 | | static_assert(std::is_same_v<StorageValue, int64_t>); |
219 | | |
220 | | public: |
221 | | static constexpr bool is_direct = false; |
222 | | |
223 | 3.04k | static StorageValue to_storage(const PrimitiveValue& value) { |
224 | 3.04k | return static_cast<StorageValue>(value.to_olap_datetime()); |
225 | 3.04k | } |
226 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
227 | | PaddedPODArray<char>& buffer, |
228 | | const uint8_t* null_map = nullptr); |
229 | | }; |
230 | | |
231 | | // V1 DECIMAL: the integer and the nine-digit fraction stored side by side. |
232 | | template <> |
233 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DECIMAL> { |
234 | | private: |
235 | | using StorageValue = typename CppTypeTraits<FieldType::OLAP_FIELD_TYPE_DECIMAL>::CppType; |
236 | | using PrimitiveValue = typename PrimitiveTypeTraits<TYPE_DECIMALV2>::CppType; |
237 | | static_assert(std::is_same_v<StorageValue, decimal12_t>); |
238 | | |
239 | | public: |
240 | | static constexpr bool is_direct = false; |
241 | | |
242 | 2.94k | static StorageValue to_storage(const PrimitiveValue& value) { |
243 | 2.94k | return {value.int_value(), value.frac_value()}; |
244 | 2.94k | } |
245 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
246 | | PaddedPODArray<char>& buffer, |
247 | | const uint8_t* null_map = nullptr); |
248 | | }; |
249 | | |
250 | | template <> |
251 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_VARCHAR> : storage_layout_detail::Bytes {}; |
252 | | |
253 | | template <> |
254 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_STRING> : storage_layout_detail::Bytes {}; |
255 | | |
256 | | template <> |
257 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_JSONB> : storage_layout_detail::Bytes {}; |
258 | | |
259 | | // A VARIANT root column reaches the writer as the JSONB of its rows. |
260 | | template <> |
261 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_VARIANT> : storage_layout_detail::Bytes {}; |
262 | | |
263 | | // CHAR(N) is stored zero padded to N bytes, while a block holds it unpadded: the column |
264 | | // writer pads the columns it stores, and storage_at reads a row of the padded column. |
265 | | template <> |
266 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_CHAR> : storage_layout_detail::Bytes { |
267 | | static bool is_padded(const IColumn& column, size_t length); |
268 | | |
269 | | // Pad selected non-NULL CHAR values into bytes and point the descriptors at them. |
270 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
271 | | size_t length, PaddedPODArray<char>& buffer, |
272 | | Slice* cells, const uint8_t* null_map = nullptr); |
273 | | |
274 | | // Writes only [row_pos, row_pos + n) to rows [0, n) of the reusable output column. |
275 | | // NULL payloads are not read; their output bytes are zero padded as well. |
276 | | static void pad_column(const IColumn& column, size_t row_pos, size_t n, size_t length, |
277 | | ColumnString& out); |
278 | | |
279 | | // Input and output have the same nullability. Copy the matching null-map range so |
280 | | // both the item writer and array index can read the compact buffer from row 0. |
281 | | static void pad_column_with_nulls(const IColumn& column, size_t row_pos, size_t n, |
282 | | size_t length, IColumn& out); |
283 | | |
284 | 1.31k | static void append_padded(StringRef value, size_t length, std::string* out) { |
285 | | DCHECK_LE(value.size, length); |
286 | 1.31k | out->reserve(out->size() + length); |
287 | 1.31k | out->append(value.data, value.size); |
288 | 1.31k | out->append(length - value.size, '\0'); |
289 | 1.31k | } |
290 | | }; |
291 | | |
292 | | // The object types are stored serialised. |
293 | | template <> |
294 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_BITMAP> { |
295 | | static const uint8_t* storage_at(const IColumn& column, size_t row, |
296 | | PaddedPODArray<char>& tmp_buffer, Slice* cell); |
297 | | }; |
298 | | |
299 | | template <> |
300 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_HLL> { |
301 | | static const uint8_t* storage_at(const IColumn& column, size_t row, |
302 | | PaddedPODArray<char>& tmp_buffer, Slice* cell); |
303 | | }; |
304 | | |
305 | | template <> |
306 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_QUANTILE_STATE> { |
307 | | static const uint8_t* storage_at(const IColumn& column, size_t row, |
308 | | PaddedPODArray<char>& tmp_buffer, Slice* cell); |
309 | | }; |
310 | | |
311 | | // An AGG_STATE column holds strings, bitmaps or fixed-length objects, whichever its |
312 | | // aggregate function serialises to, so storage_at_of picks the storage_at once per batch. |
313 | | template <> |
314 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_AGG_STATE> { |
315 | | using StorageAt = const uint8_t* (*)(const IColumn& column, size_t row, |
316 | | PaddedPODArray<char>& tmp_buffer, Slice* cell); |
317 | | static StorageAt storage_at_of(const IColumn& column); |
318 | | static bool needs_serialization(const IColumn& column); |
319 | | // Borrow serialized string/fixed-object payloads through a batch of Slice descriptors. |
320 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
321 | | PaddedPODArray<Slice>& buffer); |
322 | | |
323 | | private: |
324 | | static const uint8_t* fixed_length_object_at(const IColumn& column, size_t row, |
325 | | PaddedPODArray<char>& tmp_buffer, Slice* cell); |
326 | | }; |
327 | | |
328 | | // The admission rule a writer applies to the rows of a column before they are stored: a |
329 | | // STRING or JSONB value must fit string_type_length_soft_limit_bytes, and a JSONB value |
330 | | // must be a well-formed JSONB document. The rows `null_map` marks NULL are not checked. |
331 | | Status admit_storage_rows(FieldType type, const IColumn& column, size_t row_pos, size_t n, |
332 | | const uint8_t* null_map); |
333 | | |
334 | | } // namespace doris |