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: StorageTypeTraits<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 | | // |
69 | | // The fixed-width layouts also read back. to_primitive is the inverse of to_storage for one |
70 | | // value, and storage_to_column(values, n, dst) appends the n stored values at `values`, which |
71 | | // need not be aligned, to `dst`, the column of the PrimitiveType: FileColumnIterator peels a |
72 | | // Nullable off first, as ScalarColumnWriter::append does. The page decoders read through it, |
73 | | // and the zone map turns its stored bounds back with to_primitive. |
74 | | template <FieldType FT> |
75 | | struct StorageLayout; |
76 | | |
77 | | // Where a batch conversion puts what it cannot borrow: converted fixed-width values and |
78 | | // serialised payloads in `bytes`, the Slice descriptors of the byte types in `cells`. |
79 | | struct StorageBuffers { |
80 | | PaddedPODArray<uint8_t> bytes; |
81 | | PaddedPODArray<Slice> cells; |
82 | | }; |
83 | | |
84 | | // The FieldTypes stored fixed width, for callers that only know their FieldType at run |
85 | | // time; the others are stored as bytes. |
86 | | #define DORIS_APPLY_FOR_FIXED_WIDTH_STORAGE_LAYOUT_TYPES(M) \ |
87 | 227k | M(OLAP_FIELD_TYPE_BOOL) \ |
88 | 227k | M(OLAP_FIELD_TYPE_TINYINT) \ |
89 | 60.3k | M(OLAP_FIELD_TYPE_SMALLINT) \ |
90 | 893k | M(OLAP_FIELD_TYPE_INT) \ |
91 | 893k | M(OLAP_FIELD_TYPE_BIGINT) \ |
92 | 744k | M(OLAP_FIELD_TYPE_LARGEINT) \ |
93 | 21.9k | M(OLAP_FIELD_TYPE_UNSIGNED_INT) \ |
94 | 0 | M(OLAP_FIELD_TYPE_UNSIGNED_BIGINT) \ |
95 | 12.2k | M(OLAP_FIELD_TYPE_FLOAT) \ |
96 | 27.6k | M(OLAP_FIELD_TYPE_DOUBLE) \ |
97 | 27.6k | M(OLAP_FIELD_TYPE_DECIMAL) \ |
98 | 5.35k | M(OLAP_FIELD_TYPE_DECIMAL32) \ |
99 | 20.5k | M(OLAP_FIELD_TYPE_DECIMAL64) \ |
100 | 20.5k | M(OLAP_FIELD_TYPE_DECIMAL128I) \ |
101 | 16.4k | M(OLAP_FIELD_TYPE_DECIMAL256) \ |
102 | 1.49k | M(OLAP_FIELD_TYPE_DATE) \ |
103 | 516 | M(OLAP_FIELD_TYPE_DATETIME) \ |
104 | 42.4k | M(OLAP_FIELD_TYPE_DATEV2) \ |
105 | 43.7k | M(OLAP_FIELD_TYPE_DATETIMEV2) \ |
106 | 43.7k | M(OLAP_FIELD_TYPE_TIMESTAMP_NS) \ |
107 | 7.69k | M(OLAP_FIELD_TYPE_TIMESTAMPTZ) \ |
108 | 7.69k | M(OLAP_FIELD_TYPE_IPV4) \ |
109 | 690 | M(OLAP_FIELD_TYPE_IPV6) \ |
110 | 26.4k | M(OLAP_FIELD_TYPE_UUID) |
111 | | |
112 | | namespace storage_layout_detail { |
113 | | |
114 | | // A StorageValue is the PrimitiveValue's own bytes, so a run of the column is a run of |
115 | | // stored values. |
116 | | template <FieldType FT> |
117 | | struct BitCast { |
118 | | using StorageValue = typename StorageTypeTraits<FT>::StorageType; |
119 | | using PrimitiveValue = |
120 | | typename PrimitiveTypeTraits<storage_field_type_to_primitive_type(FT)>::CppType; |
121 | | static_assert(sizeof(StorageValue) == sizeof(PrimitiveValue)); |
122 | | |
123 | 29.8M | static StorageValue to_storage(const PrimitiveValue& value) { |
124 | 29.8M | return std::bit_cast<StorageValue>(value); |
125 | 29.8M | } _ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE24EE10to_storageERKh Line | Count | Source | 123 | 26.8k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 26.8k | return std::bit_cast<StorageValue>(value); | 125 | 26.8k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE1EE10to_storageERKa Line | Count | Source | 123 | 267k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 267k | return std::bit_cast<StorageValue>(value); | 125 | 267k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE3EE10to_storageERKs Line | Count | Source | 123 | 210k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 210k | return std::bit_cast<StorageValue>(value); | 125 | 210k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE5EE10to_storageERKi Line | Count | Source | 123 | 20.1M | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 20.1M | return std::bit_cast<StorageValue>(value); | 125 | 20.1M | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE7EE10to_storageERKl Line | Count | Source | 123 | 7.63M | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 7.63M | return std::bit_cast<StorageValue>(value); | 125 | 7.63M | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE9EE10to_storageERKn Line | Count | Source | 123 | 44.3k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 44.3k | return std::bit_cast<StorageValue>(value); | 125 | 44.3k | } |
Unexecuted instantiation: _ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE6EE10to_storageERKj _ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE8EE10to_storageERKm Line | Count | Source | 123 | 1.11k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 1.11k | return std::bit_cast<StorageValue>(value); | 125 | 1.11k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE31EE10to_storageERKNS_7DecimalIiEE Line | Count | Source | 123 | 5.07k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 5.07k | return std::bit_cast<StorageValue>(value); | 125 | 5.07k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE32EE10to_storageERKNS_7DecimalIlEE Line | Count | Source | 123 | 4.40k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 4.40k | return std::bit_cast<StorageValue>(value); | 125 | 4.40k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE33EE10to_storageERKNS_12Decimal128V3E Line | Count | Source | 123 | 593k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 593k | return std::bit_cast<StorageValue>(value); | 125 | 593k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE37EE10to_storageERKNS_7DecimalIN4wide7integerILm256EiEEEE Line | Count | Source | 123 | 4.26k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 4.26k | return std::bit_cast<StorageValue>(value); | 125 | 4.26k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE28EE10to_storageERKNS_11DateV2ValueINS_15DateV2ValueTypeEEE Line | Count | Source | 123 | 278k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 278k | return std::bit_cast<StorageValue>(value); | 125 | 278k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE29EE10to_storageERKNS_11DateV2ValueINS_19DateTimeV2ValueTypeEEE Line | Count | Source | 123 | 599k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 599k | return std::bit_cast<StorageValue>(value); | 125 | 599k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE41EE10to_storageERKNS_16TimeStampNsValueE Line | Count | Source | 123 | 2.29k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 2.29k | return std::bit_cast<StorageValue>(value); | 125 | 2.29k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE40EE10to_storageERKNS_16TimestampTzValueE Line | Count | Source | 123 | 17.6k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 17.6k | return std::bit_cast<StorageValue>(value); | 125 | 17.6k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE38EE10to_storageERKj Line | Count | Source | 123 | 3.71k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 3.71k | return std::bit_cast<StorageValue>(value); | 125 | 3.71k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE39EE10to_storageERKo Line | Count | Source | 123 | 3.55k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 3.55k | return std::bit_cast<StorageValue>(value); | 125 | 3.55k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE42EE10to_storageERKo Line | Count | Source | 123 | 3.20k | static StorageValue to_storage(const PrimitiveValue& value) { | 124 | 3.20k | return std::bit_cast<StorageValue>(value); | 125 | 3.20k | } |
|
126 | 1.00M | static PrimitiveValue to_primitive(const StorageValue& value) { |
127 | 1.00M | return std::bit_cast<PrimitiveValue>(value); |
128 | 1.00M | } _ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE24EE12to_primitiveERKh Line | Count | Source | 126 | 19.6k | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 19.6k | return std::bit_cast<PrimitiveValue>(value); | 128 | 19.6k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE1EE12to_primitiveERKa Line | Count | Source | 126 | 84.0k | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 84.0k | return std::bit_cast<PrimitiveValue>(value); | 128 | 84.0k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE3EE12to_primitiveERKs Line | Count | Source | 126 | 22.1k | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 22.1k | return std::bit_cast<PrimitiveValue>(value); | 128 | 22.1k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE5EE12to_primitiveERKi Line | Count | Source | 126 | 206k | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 206k | return std::bit_cast<PrimitiveValue>(value); | 128 | 206k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE7EE12to_primitiveERKl Line | Count | Source | 126 | 443k | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 443k | return std::bit_cast<PrimitiveValue>(value); | 128 | 443k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE9EE12to_primitiveERKn Line | Count | Source | 126 | 33.4k | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 33.4k | return std::bit_cast<PrimitiveValue>(value); | 128 | 33.4k | } |
Unexecuted instantiation: _ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE6EE12to_primitiveERKj Unexecuted instantiation: _ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE8EE12to_primitiveERKm _ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE31EE12to_primitiveERKi Line | Count | Source | 126 | 6.78k | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 6.78k | return std::bit_cast<PrimitiveValue>(value); | 128 | 6.78k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE32EE12to_primitiveERKl Line | Count | Source | 126 | 31.8k | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 31.8k | return std::bit_cast<PrimitiveValue>(value); | 128 | 31.8k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE33EE12to_primitiveERKn Line | Count | Source | 126 | 19.9k | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 19.9k | return std::bit_cast<PrimitiveValue>(value); | 128 | 19.9k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE37EE12to_primitiveERKN4wide7integerILm256EiEE Line | Count | Source | 126 | 1.16k | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 1.16k | return std::bit_cast<PrimitiveValue>(value); | 128 | 1.16k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE28EE12to_primitiveERKj Line | Count | Source | 126 | 59.7k | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 59.7k | return std::bit_cast<PrimitiveValue>(value); | 128 | 59.7k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE29EE12to_primitiveERKm Line | Count | Source | 126 | 66.2k | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 66.2k | return std::bit_cast<PrimitiveValue>(value); | 128 | 66.2k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE41EE12to_primitiveERKl Line | Count | Source | 126 | 300 | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 300 | return std::bit_cast<PrimitiveValue>(value); | 128 | 300 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE40EE12to_primitiveERKm Line | Count | Source | 126 | 7.02k | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 7.02k | return std::bit_cast<PrimitiveValue>(value); | 128 | 7.02k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE38EE12to_primitiveERKj Line | Count | Source | 126 | 957 | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 957 | return std::bit_cast<PrimitiveValue>(value); | 128 | 957 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE39EE12to_primitiveERKo Line | Count | Source | 126 | 981 | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 981 | return std::bit_cast<PrimitiveValue>(value); | 128 | 981 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE42EE12to_primitiveERKo Line | Count | Source | 126 | 875 | static PrimitiveValue to_primitive(const StorageValue& value) { | 127 | 875 | return std::bit_cast<PrimitiveValue>(value); | 128 | 875 | } |
|
129 | | // Always borrows the column's bytes. |
130 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
131 | | StorageBuffers& buffers); |
132 | | // One copy: the stored values are the column's values. |
133 | | static void storage_to_column(const uint8_t* values, size_t n, IColumn& dst); |
134 | | }; |
135 | | |
136 | | // Every NaN is stored as the quiet NaN, so equal values have equal stored bytes |
137 | | // and the bloom filter / dictionary / key encodings that hash or compare bytes |
138 | | // treat all NaNs as one value. |
139 | | template <FieldType FT> |
140 | | struct FloatingPoint { |
141 | | using StorageValue = typename StorageTypeTraits<FT>::StorageType; |
142 | | using PrimitiveValue = |
143 | | typename PrimitiveTypeTraits<storage_field_type_to_primitive_type(FT)>::CppType; |
144 | | static_assert(std::is_floating_point_v<StorageValue>); |
145 | | static_assert(std::is_same_v<StorageValue, PrimitiveValue>); |
146 | | |
147 | 119k | static StorageValue canonicalize_nan(StorageValue value) { |
148 | 119k | return std::isnan(value) ? std::numeric_limits<StorageValue>::quiet_NaN() : value; |
149 | 119k | } _ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE10EE16canonicalize_nanEf Line | Count | Source | 147 | 52.9k | static StorageValue canonicalize_nan(StorageValue value) { | 148 | 52.9k | return std::isnan(value) ? std::numeric_limits<StorageValue>::quiet_NaN() : value; | 149 | 52.9k | } |
_ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE11EE16canonicalize_nanEd Line | Count | Source | 147 | 66.7k | static StorageValue canonicalize_nan(StorageValue value) { | 148 | 66.7k | return std::isnan(value) ? std::numeric_limits<StorageValue>::quiet_NaN() : value; | 149 | 66.7k | } |
|
150 | 22.5k | static StorageValue to_storage(PrimitiveValue value) { return canonicalize_nan(value); }_ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE10EE10to_storageEf Line | Count | Source | 150 | 4.43k | static StorageValue to_storage(PrimitiveValue value) { return canonicalize_nan(value); } |
_ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE11EE10to_storageEd Line | Count | Source | 150 | 18.1k | static StorageValue to_storage(PrimitiveValue value) { return canonicalize_nan(value); } |
|
151 | | // A stored value is read back as it is: only writing canonicalises. |
152 | 32.7k | static PrimitiveValue to_primitive(StorageValue value) { return value; }_ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE10EE12to_primitiveEf Line | Count | Source | 152 | 13.6k | static PrimitiveValue to_primitive(StorageValue value) { return value; } |
_ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE11EE12to_primitiveEd Line | Count | Source | 152 | 19.0k | static PrimitiveValue to_primitive(StorageValue value) { return value; } |
|
153 | | // Borrows the column's bytes when [row_pos, row_pos + n) has no NaN, otherwise |
154 | | // converts the range into buffers.bytes. NaNs outside the range do not require a |
155 | | // copy; the source column is never modified. |
156 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
157 | | StorageBuffers& buffers); |
158 | | // One copy: the stored values are the column's values. |
159 | | static void storage_to_column(const uint8_t* values, size_t n, IColumn& dst); |
160 | | }; |
161 | | |
162 | | // A string is stored as its own bytes, whatever their length: the cells are Slice |
163 | | // descriptors of the column's payloads. |
164 | | struct Bytes { |
165 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
166 | | StorageBuffers& buffers); |
167 | | }; |
168 | | |
169 | | } // namespace storage_layout_detail |
170 | | |
171 | | #define DORIS_STORAGE_LAYOUT_BIT_CAST(FT) \ |
172 | | template <> \ |
173 | | struct StorageLayout<FieldType::FT> : storage_layout_detail::BitCast<FieldType::FT> {}; |
174 | | |
175 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_BOOL) |
176 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_TINYINT) |
177 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_SMALLINT) |
178 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_INT) |
179 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_BIGINT) |
180 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_LARGEINT) |
181 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_UNSIGNED_INT) |
182 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_UNSIGNED_BIGINT) |
183 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL32) |
184 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL64) |
185 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL128I) |
186 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL256) |
187 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DATEV2) |
188 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DATETIMEV2) |
189 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_TIMESTAMP_NS) |
190 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_TIMESTAMPTZ) |
191 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_IPV4) |
192 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_IPV6) |
193 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_UUID) |
194 | | #undef DORIS_STORAGE_LAYOUT_BIT_CAST |
195 | | |
196 | | template <> |
197 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_FLOAT> |
198 | | : storage_layout_detail::FloatingPoint<FieldType::OLAP_FIELD_TYPE_FLOAT> {}; |
199 | | |
200 | | template <> |
201 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DOUBLE> |
202 | | : storage_layout_detail::FloatingPoint<FieldType::OLAP_FIELD_TYPE_DOUBLE> {}; |
203 | | |
204 | | // The batch conversions of the layouts above are instantiated once, in storage_layout.cpp. |
205 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_BOOL>; |
206 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_TINYINT>; |
207 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_SMALLINT>; |
208 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_INT>; |
209 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_BIGINT>; |
210 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_LARGEINT>; |
211 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_UNSIGNED_INT>; |
212 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_UNSIGNED_BIGINT>; |
213 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_DECIMAL32>; |
214 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_DECIMAL64>; |
215 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_DECIMAL128I>; |
216 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_DECIMAL256>; |
217 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_DATEV2>; |
218 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_DATETIMEV2>; |
219 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_TIMESTAMP_NS>; |
220 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ>; |
221 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_IPV4>; |
222 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_IPV6>; |
223 | | extern template struct storage_layout_detail::BitCast<FieldType::OLAP_FIELD_TYPE_UUID>; |
224 | | extern template struct storage_layout_detail::FloatingPoint<FieldType::OLAP_FIELD_TYPE_FLOAT>; |
225 | | extern template struct storage_layout_detail::FloatingPoint<FieldType::OLAP_FIELD_TYPE_DOUBLE>; |
226 | | |
227 | | // V1 DATE: three bytes of (year << 9) | (month << 5) | day. |
228 | | template <> |
229 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DATE> { |
230 | | using StorageValue = typename StorageTypeTraits<FieldType::OLAP_FIELD_TYPE_DATE>::StorageType; |
231 | | using PrimitiveValue = typename PrimitiveTypeTraits<TYPE_DATE>::CppType; |
232 | | static_assert(std::is_same_v<StorageValue, uint24_t>); |
233 | | |
234 | 1.60M | static StorageValue to_storage(const PrimitiveValue& value) { |
235 | 1.60M | return StorageValue(cast_set<uint32_t>(value.to_olap_date())); |
236 | 1.60M | } |
237 | | // The fields are taken as stored: a date was checked when it was written. |
238 | 3.43M | static PrimitiveValue to_primitive(const StorageValue& value) { |
239 | 3.43M | PrimitiveValue primitive; |
240 | 3.43M | primitive.set_olap_date(value); |
241 | 3.43M | return primitive; |
242 | 3.43M | } |
243 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
244 | | StorageBuffers& buffers); |
245 | | static void storage_to_column(const uint8_t* values, size_t n, IColumn& dst); |
246 | | }; |
247 | | |
248 | | // V1 DATETIME: the decimal digits YYYYMMDDhhmmss packed into one integer. |
249 | | template <> |
250 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DATETIME> { |
251 | | using StorageValue = |
252 | | typename StorageTypeTraits<FieldType::OLAP_FIELD_TYPE_DATETIME>::StorageType; |
253 | | using PrimitiveValue = typename PrimitiveTypeTraits<TYPE_DATETIME>::CppType; |
254 | | static_assert(std::is_same_v<StorageValue, int64_t>); |
255 | | |
256 | 1.48M | static StorageValue to_storage(const PrimitiveValue& value) { |
257 | 1.48M | return static_cast<StorageValue>(value.to_olap_datetime()); |
258 | 1.48M | } |
259 | 3.39M | static PrimitiveValue to_primitive(const StorageValue& value) { |
260 | 3.39M | return PrimitiveValue::create_from_olap_datetime(static_cast<uint64_t>(value)); |
261 | 3.39M | } |
262 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
263 | | StorageBuffers& buffers); |
264 | | static void storage_to_column(const uint8_t* values, size_t n, IColumn& dst); |
265 | | }; |
266 | | |
267 | | // V1 DECIMAL: the integer and the nine-digit fraction stored side by side. |
268 | | template <> |
269 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DECIMAL> { |
270 | | using StorageValue = |
271 | | typename StorageTypeTraits<FieldType::OLAP_FIELD_TYPE_DECIMAL>::StorageType; |
272 | | using PrimitiveValue = typename PrimitiveTypeTraits<TYPE_DECIMALV2>::CppType; |
273 | | static_assert(std::is_same_v<StorageValue, decimal12_t>); |
274 | | |
275 | 4.37k | static StorageValue to_storage(const PrimitiveValue& value) { |
276 | 4.37k | return {value.int_value(), value.frac_value()}; |
277 | 4.37k | } |
278 | 8.77k | static PrimitiveValue to_primitive(const StorageValue& value) { |
279 | 8.77k | return PrimitiveValue(value.integer, value.fraction); |
280 | 8.77k | } |
281 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
282 | | StorageBuffers& buffers); |
283 | | static void storage_to_column(const uint8_t* values, size_t n, IColumn& dst); |
284 | | }; |
285 | | |
286 | | template <> |
287 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_VARCHAR> : storage_layout_detail::Bytes {}; |
288 | | |
289 | | template <> |
290 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_STRING> : storage_layout_detail::Bytes {}; |
291 | | |
292 | | template <> |
293 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_JSONB> : storage_layout_detail::Bytes {}; |
294 | | |
295 | | // A VARIANT root column reaches the writer as the JSONB of its rows. |
296 | | template <> |
297 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_VARIANT> : storage_layout_detail::Bytes {}; |
298 | | |
299 | | // CHAR(N) is stored zero padded to N bytes, while a block holds it unpadded: the writers |
300 | | // pad the values they store or index with the length-taking column_to_storage. Padding |
301 | | // copies a value into an N-byte slot, so it never reads a NULL row: a NULL row can hold a |
302 | | // value longer than N, as load does not check NULL rows. The Bytes one stays for the SNII |
303 | | // index, which is fed CHAR as it reads back. |
304 | | template <> |
305 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_CHAR> : storage_layout_detail::Bytes { |
306 | | using storage_layout_detail::Bytes::column_to_storage; |
307 | | |
308 | | // Pads every non-NULL row of the range into its own `length` zeroed bytes and points its |
309 | | // cell at them; a NULL row keeps an empty cell. null_map[i] is the NULL flag of row |
310 | | // row_pos + i, and null_map is nullptr when the range holds no NULL row. |
311 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
312 | | size_t length, const uint8_t* null_map, |
313 | | StorageBuffers& buffers); |
314 | | |
315 | 4.22k | static void append_padded(StringRef value, size_t length, std::string* out) { |
316 | | DCHECK_LE(value.size, length); |
317 | 4.22k | out->reserve(out->size() + length); |
318 | 4.22k | out->append(value.data, value.size); |
319 | 4.22k | out->append(length - value.size, '\0'); |
320 | 4.22k | } |
321 | | }; |
322 | | |
323 | | // The object types are stored serialised: every value of the batch into buffers.bytes, |
324 | | // the cells pointing at them. |
325 | | template <> |
326 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_BITMAP> { |
327 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
328 | | StorageBuffers& buffers); |
329 | | }; |
330 | | |
331 | | template <> |
332 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_HLL> { |
333 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
334 | | StorageBuffers& buffers); |
335 | | }; |
336 | | |
337 | | template <> |
338 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_QUANTILE_STATE> { |
339 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
340 | | StorageBuffers& buffers); |
341 | | }; |
342 | | |
343 | | // The fixed-length objects an AGG_STATE column holds when its aggregate function serialises |
344 | | // to them, each borrowed through a Slice descriptor. String and bitmap states are stored |
345 | | // through the VARCHAR and BITMAP layouts, which the column writer is given when it is created. |
346 | | template <> |
347 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_AGG_STATE> { |
348 | | static const uint8_t* column_to_storage(const IColumn& column, size_t row_pos, size_t n, |
349 | | StorageBuffers& buffers); |
350 | | }; |
351 | | |
352 | | // The batch conversion of a FieldType known only at run time: the column_to_storage of |
353 | | // StorageLayout<type>, for the column writer and the index feeds. CHAR is not accepted: |
354 | | // whether its values are padded is the caller's choice, made through StorageLayout<CHAR>. |
355 | | const uint8_t* column_to_storage(FieldType type, const IColumn& column, size_t row_pos, size_t n, |
356 | | StorageBuffers& buffers); |
357 | | |
358 | | // The admission rule a writer applies to the rows of a column before they are stored: a |
359 | | // STRING or JSONB value must fit string_type_length_soft_limit_bytes, and a JSONB value |
360 | | // must be a well-formed JSONB document. The rows `null_map` marks NULL are not checked. |
361 | | Status admit_storage_rows(FieldType type, const IColumn& column, size_t row_pos, size_t n, |
362 | | const uint8_t* null_map); |
363 | | |
364 | | } // namespace doris |