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 <cstdint> |
23 | | #include <limits> |
24 | | #include <type_traits> |
25 | | |
26 | | #include "common/cast_set.h" |
27 | | #include "core/data_type/primitive_type.h" |
28 | | #include "core/data_type/storage_field_type.h" |
29 | | #include "core/decimal12.h" |
30 | | #include "core/uint24.h" |
31 | | #include "core/value/decimalv2_value.h" |
32 | | #include "core/value/vdatetime_value.h" |
33 | | #include "storage/field_type.h" |
34 | | #include "storage/types.h" |
35 | | |
36 | | namespace doris { |
37 | | |
38 | | // How a compute-layer value becomes what a segment stores for FieldType FT: its own |
39 | | // bytes, except for the V1 DATE, DATETIME and DECIMAL layouts and NaN, stored as the |
40 | | // quiet NaN. The two types are PrimitiveTypeTraits<PT>::CppType and |
41 | | // CppTypeTraits<FT>::CppType; the aliases inside are private shorthand. Declared only, |
42 | | // so a FieldType without a specialisation is a compile error, not a silent byte copy. |
43 | | template <FieldType FT> |
44 | | struct StorageLayout; |
45 | | |
46 | | namespace storage_layout_detail { |
47 | | |
48 | | // A StorageValue is the PrimitiveValue's own bytes. |
49 | | template <FieldType FT> |
50 | | struct BitCast { |
51 | | private: |
52 | | using StorageValue = typename CppTypeTraits<FT>::CppType; |
53 | | using PrimitiveValue = |
54 | | typename PrimitiveTypeTraits<storage_field_type_to_primitive_type(FT)>::CppType; |
55 | | static_assert(sizeof(StorageValue) == sizeof(PrimitiveValue)); |
56 | | |
57 | | public: |
58 | 372k | static StorageValue to_storage(const PrimitiveValue& value) { |
59 | 372k | return std::bit_cast<StorageValue>(value); |
60 | 372k | } _ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE7EE10to_storageERKl Line | Count | Source | 58 | 51 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 51 | return std::bit_cast<StorageValue>(value); | 60 | 51 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE24EE10to_storageERKh Line | Count | Source | 58 | 23 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 23 | return std::bit_cast<StorageValue>(value); | 60 | 23 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE31EE10to_storageERKNS_7DecimalIiEE Line | Count | Source | 58 | 39 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 39 | return std::bit_cast<StorageValue>(value); | 60 | 39 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE32EE10to_storageERKNS_7DecimalIlEE Line | Count | Source | 58 | 34 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 34 | return std::bit_cast<StorageValue>(value); | 60 | 34 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE33EE10to_storageERKNS_12Decimal128V3E Line | Count | Source | 58 | 29 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 29 | return std::bit_cast<StorageValue>(value); | 60 | 29 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE37EE10to_storageERKNS_7DecimalIN4wide7integerILm256EiEEEE Line | Count | Source | 58 | 29 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 29 | return std::bit_cast<StorageValue>(value); | 60 | 29 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE28EE10to_storageERKNS_11DateV2ValueINS_15DateV2ValueTypeEEE Line | Count | Source | 58 | 28 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 28 | return std::bit_cast<StorageValue>(value); | 60 | 28 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE29EE10to_storageERKNS_11DateV2ValueINS_19DateTimeV2ValueTypeEEE Line | Count | Source | 58 | 37 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 37 | return std::bit_cast<StorageValue>(value); | 60 | 37 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE40EE10to_storageERKNS_16TimestampTzValueE Line | Count | Source | 58 | 52 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 52 | return std::bit_cast<StorageValue>(value); | 60 | 52 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE1EE10to_storageERKa Line | Count | Source | 58 | 23 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 23 | return std::bit_cast<StorageValue>(value); | 60 | 23 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE3EE10to_storageERKs Line | Count | Source | 58 | 23 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 23 | return std::bit_cast<StorageValue>(value); | 60 | 23 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE5EE10to_storageERKi Line | Count | Source | 58 | 372k | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 372k | return std::bit_cast<StorageValue>(value); | 60 | 372k | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE9EE10to_storageERKn Line | Count | Source | 58 | 23 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 23 | return std::bit_cast<StorageValue>(value); | 60 | 23 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE38EE10to_storageERKj Line | Count | Source | 58 | 20 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 20 | return std::bit_cast<StorageValue>(value); | 60 | 20 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE39EE10to_storageERKo Line | Count | Source | 58 | 20 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 20 | return std::bit_cast<StorageValue>(value); | 60 | 20 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE42EE10to_storageERKo Line | Count | Source | 58 | 21 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 21 | return std::bit_cast<StorageValue>(value); | 60 | 21 | } |
_ZN5doris21storage_layout_detail7BitCastILNS_9FieldTypeE41EE10to_storageERKNS_16TimeStampNsValueE Line | Count | Source | 58 | 27 | static StorageValue to_storage(const PrimitiveValue& value) { | 59 | 27 | return std::bit_cast<StorageValue>(value); | 60 | 27 | } |
|
61 | | }; |
62 | | |
63 | | // Every NaN is stored as the quiet NaN, so equal values have equal stored bytes |
64 | | // and the bloom filter / dictionary / key encodings that hash or compare bytes |
65 | | // treat all NaNs as one value. |
66 | | template <FieldType FT> |
67 | | struct FloatingPoint { |
68 | | private: |
69 | | using StorageValue = typename CppTypeTraits<FT>::CppType; |
70 | | using PrimitiveValue = |
71 | | typename PrimitiveTypeTraits<storage_field_type_to_primitive_type(FT)>::CppType; |
72 | | static_assert(std::is_floating_point_v<StorageValue>); |
73 | | static_assert(std::is_same_v<StorageValue, PrimitiveValue>); |
74 | | |
75 | | public: |
76 | 97.1k | static StorageValue canonicalize_nan(StorageValue value) { |
77 | 97.1k | return std::isnan(value) ? std::numeric_limits<StorageValue>::quiet_NaN() : value; |
78 | 97.1k | } _ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE10EE16canonicalize_nanEf Line | Count | Source | 76 | 48.5k | static StorageValue canonicalize_nan(StorageValue value) { | 77 | 48.5k | return std::isnan(value) ? std::numeric_limits<StorageValue>::quiet_NaN() : value; | 78 | 48.5k | } |
_ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE11EE16canonicalize_nanEd Line | Count | Source | 76 | 48.5k | static StorageValue canonicalize_nan(StorageValue value) { | 77 | 48.5k | return std::isnan(value) ? std::numeric_limits<StorageValue>::quiet_NaN() : value; | 78 | 48.5k | } |
|
79 | 64 | static StorageValue to_storage(PrimitiveValue value) { return canonicalize_nan(value); }_ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE10EE10to_storageEf Line | Count | Source | 79 | 33 | static StorageValue to_storage(PrimitiveValue value) { return canonicalize_nan(value); } |
_ZN5doris21storage_layout_detail13FloatingPointILNS_9FieldTypeE11EE10to_storageEd Line | Count | Source | 79 | 31 | static StorageValue to_storage(PrimitiveValue value) { return canonicalize_nan(value); } |
|
80 | | }; |
81 | | |
82 | | } // namespace storage_layout_detail |
83 | | |
84 | | #define DORIS_STORAGE_LAYOUT_BIT_CAST(FT) \ |
85 | | template <> \ |
86 | | struct StorageLayout<FieldType::FT> : storage_layout_detail::BitCast<FieldType::FT> {}; |
87 | | |
88 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_BOOL) |
89 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_TINYINT) |
90 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_SMALLINT) |
91 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_INT) |
92 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_BIGINT) |
93 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_LARGEINT) |
94 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_UNSIGNED_INT) |
95 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_UNSIGNED_BIGINT) |
96 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL32) |
97 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL64) |
98 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL128I) |
99 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DECIMAL256) |
100 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DATEV2) |
101 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_DATETIMEV2) |
102 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_TIMESTAMP_NS) |
103 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_TIMESTAMPTZ) |
104 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_IPV4) |
105 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_IPV6) |
106 | | DORIS_STORAGE_LAYOUT_BIT_CAST(OLAP_FIELD_TYPE_UUID) |
107 | | #undef DORIS_STORAGE_LAYOUT_BIT_CAST |
108 | | |
109 | | template <> |
110 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_FLOAT> |
111 | | : storage_layout_detail::FloatingPoint<FieldType::OLAP_FIELD_TYPE_FLOAT> {}; |
112 | | |
113 | | template <> |
114 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DOUBLE> |
115 | | : storage_layout_detail::FloatingPoint<FieldType::OLAP_FIELD_TYPE_DOUBLE> {}; |
116 | | |
117 | | // V1 DATE: three bytes of (year << 9) | (month << 5) | day. |
118 | | template <> |
119 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DATE> { |
120 | | private: |
121 | | using StorageValue = typename CppTypeTraits<FieldType::OLAP_FIELD_TYPE_DATE>::CppType; |
122 | | using PrimitiveValue = typename PrimitiveTypeTraits<TYPE_DATE>::CppType; |
123 | | static_assert(std::is_same_v<StorageValue, uint24_t>); |
124 | | |
125 | | public: |
126 | 35 | static StorageValue to_storage(const PrimitiveValue& value) { |
127 | 35 | return StorageValue(cast_set<uint32_t>(value.to_olap_date())); |
128 | 35 | } |
129 | | }; |
130 | | |
131 | | // V1 DATETIME: the decimal digits YYYYMMDDhhmmss packed into one integer. |
132 | | template <> |
133 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DATETIME> { |
134 | | private: |
135 | | using StorageValue = typename CppTypeTraits<FieldType::OLAP_FIELD_TYPE_DATETIME>::CppType; |
136 | | using PrimitiveValue = typename PrimitiveTypeTraits<TYPE_DATETIME>::CppType; |
137 | | static_assert(std::is_same_v<StorageValue, int64_t>); |
138 | | |
139 | | public: |
140 | 36 | static StorageValue to_storage(const PrimitiveValue& value) { |
141 | 36 | return static_cast<StorageValue>(value.to_olap_datetime()); |
142 | 36 | } |
143 | | }; |
144 | | |
145 | | // V1 DECIMAL: the integer and the nine-digit fraction stored side by side. |
146 | | template <> |
147 | | struct StorageLayout<FieldType::OLAP_FIELD_TYPE_DECIMAL> { |
148 | | private: |
149 | | using StorageValue = typename CppTypeTraits<FieldType::OLAP_FIELD_TYPE_DECIMAL>::CppType; |
150 | | using PrimitiveValue = typename PrimitiveTypeTraits<TYPE_DECIMALV2>::CppType; |
151 | | static_assert(std::is_same_v<StorageValue, decimal12_t>); |
152 | | |
153 | | public: |
154 | 27 | static StorageValue to_storage(const PrimitiveValue& value) { |
155 | 27 | return {value.int_value(), value.frac_value()}; |
156 | 27 | } |
157 | | }; |
158 | | |
159 | | } // namespace doris |