Coverage Report

Created: 2026-10-28 04:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
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