forked from apache/doris
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdictionary.h
More file actions
211 lines (178 loc) · 9.4 KB
/
Copy pathdictionary.h
File metadata and controls
211 lines (178 loc) · 9.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#pragma once
#include <memory>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>
#include "core/assert_cast.h"
#include "core/column/column.h"
#include "core/column/column_string.h"
#include "core/data_type/data_type.h"
#include "core/data_type/data_type_date_or_datetime_v2.h"
#include "core/data_type/data_type_date_time.h"
#include "core/data_type/data_type_ipv4.h"
#include "core/data_type/data_type_ipv6.h"
#include "core/data_type/data_type_number.h"
#include "core/data_type/data_type_string.h"
#include "core/types.h"
#include "exprs/function/cast_type_to_either.h"
namespace doris {
class MemTrackerLimiter;
}
class DictionaryFactory;
namespace doris {
/*
* Dictionary implementation in Doris that provides key-value mapping functionality
* Currently only supports in-memory dictionary storage
*/
const static std::string DICT_DATA_ERROR_TAG = "[INVALID_DICT_MARK]";
struct DictionaryAttribute {
const std::string name; // value name
const DataTypePtr type; // value type
};
// Abstract base class IDictionary that only stores values. Keys are maintained by specific derived classes
// IDictionary serves as the foundation for dictionary implementations where:
// - Only values are stored at the base level
// - Key management is delegated to derived classes
// - Provides interface for dictionary operations
class IDictionary {
public:
IDictionary(std::string name, std::vector<DictionaryAttribute> values);
virtual ~IDictionary();
std::string dict_name() const { return _dict_name; }
// Returns the result column, throws an exception if there is an issue
// attribute_type , key_type must be no nullable type
virtual ColumnPtr get_column(const std::string& attribute_name,
const DataTypePtr& attribute_type, const ColumnPtr& key_column,
const DataTypePtr& key_type) const = 0;
// Returns multiple result columns, throws an exception if there is an issue
// The default implementation calls get_column. If a more performant implementation is needed, this method can be overridden
virtual ColumnPtrs get_columns(const std::vector<std::string>& attribute_names,
const DataTypes& attribute_types, const ColumnPtr& key_column,
const DataTypePtr& key_type) const {
ColumnPtrs columns;
for (size_t i = 0; i < attribute_names.size(); ++i) {
columns.push_back(
get_column(attribute_names[i], attribute_types[i], key_column, key_type));
}
return columns;
}
// Compared to get_column and get_columns, supports multiple key columns and multiple value columns
// The default implementation only supports one key column, such as IPAddressDictionary, HashMapDictionary
// If support for multiple key columns is needed, this method can be overridden
virtual ColumnPtrs get_tuple_columns(const std::vector<std::string>& attribute_names,
const DataTypes& attribute_types,
const ColumnPtrs& key_columns,
const DataTypes& key_types) const {
if (key_types.size() != 1) {
throw doris::Exception(ErrorCode::INTERNAL_ERROR,
"Dictionary {} does not support multiple key columns",
dict_name());
}
return get_columns(attribute_names, attribute_types, key_columns[0], key_types[0]);
}
bool has_attribute(const std::string& name) const;
// will return a non-nullable type
DataTypePtr get_attribute_type(const std::string& name) const;
size_t attribute_index(const std::string& name) const;
bool attribute_is_nullable(size_t idx) const;
std::variant<std::false_type, std::true_type> attribute_nullable_variant(size_t idx) const;
template <typename F>
static bool cast_type(const IDataType* type, F&& f) {
// The data types supported by cast_type must be consistent with the AttributeData below.
return cast_type_to_either<DataTypeUInt8, DataTypeInt8, DataTypeInt16, DataTypeInt32,
DataTypeInt64, DataTypeInt128, DataTypeFloat32, DataTypeFloat64,
DataTypeIPv4, DataTypeIPv6, DataTypeString, DataTypeDateV2,
DataTypeDateTimeV2, DataTypeDecimal32, DataTypeDecimal64,
DataTypeDecimal128, DataTypeDecimal256>(type,
std::forward<F>(f));
}
virtual size_t allocated_bytes() const;
protected:
friend class DictionaryFactory;
// Only used to distinguish from DataTypeString, used for ColumnWithType
struct DictDataTypeString64 {
using ColumnType = ColumnString;
};
template <typename Type>
struct ColumnWithType {
// OutputColumnType is used as the result column type
ColumnPtr null_map;
// RealColumnType is the real type of the column, as there may be ColumnString64, but the result column will not be ColumnString64
using OutputColumnType = Type::ColumnType;
using RealColumnType = std::conditional_t<std::is_same_v<DictDataTypeString64, Type>,
ColumnString64, OutputColumnType>;
RealColumnType::Ptr column;
const RealColumnType* get() const { return column.get(); }
const ColumnUInt8* get_null_map() const {
if (!null_map) {
return nullptr;
}
return assert_cast<const ColumnUInt8*, TypeCheckOnRelease::DISABLE>(null_map.get());
}
};
// res_real_column : result column (get_column result)
// res_null : if value is null, will set res_null to true
// value_column : corresponding value column, non-nullable
// value_null_column : corresponding value null map, if the original value is non-nullable, it will be nullptr
// value_idx : index in the value column
template <bool value_is_nullable, typename ResultColumnType>
ALWAYS_INLINE static void set_value_data(ResultColumnType* res_real_column, UInt8& res_null,
const auto* value_column,
const ColumnUInt8* value_null_column,
const size_t& value_idx) {
if constexpr (value_is_nullable) {
// if the value is null, set the result column to null
if (value_null_column->get_element(value_idx)) {
res_null = true;
res_real_column->insert_default();
return;
}
}
if constexpr (std::is_same_v<ResultColumnType, ColumnString>) {
// If it is a string column, use get_data_at to avoid copying
StringRef str_ref = value_column->get_data_at(value_idx);
res_real_column->insert_data(str_ref.data, str_ref.size);
} else {
res_real_column->insert_value(value_column->get_element(value_idx));
}
}
/// TODO: Add support for more data types ,such as Array, Map, etc.
using ValueData =
std::variant<ColumnWithType<DataTypeUInt8>, ColumnWithType<DataTypeInt8>,
ColumnWithType<DataTypeInt16>, ColumnWithType<DataTypeInt32>,
ColumnWithType<DataTypeInt64>, ColumnWithType<DataTypeInt128>,
ColumnWithType<DataTypeFloat32>, ColumnWithType<DataTypeFloat64>,
ColumnWithType<DataTypeIPv4>, ColumnWithType<DataTypeIPv6>,
ColumnWithType<DataTypeString>, ColumnWithType<DictDataTypeString64>,
ColumnWithType<DataTypeDateV2>, ColumnWithType<DataTypeDateTimeV2>,
ColumnWithType<DataTypeDecimal32>, ColumnWithType<DataTypeDecimal64>,
ColumnWithType<DataTypeDecimal128>, ColumnWithType<DataTypeDecimal256>>;
void load_values(const std::vector<ColumnPtr>& values_column);
// _value_data is used to store the data of value columns.
std::vector<ValueData> _values_data;
std::string _dict_name;
std::vector<DictionaryAttribute> _attributes;
// A mapping from attribute names to their corresponding indices.
std::unordered_map<std::string, size_t> _name_to_attributes_index;
// mem_tracker comes from DictionaryFactory. If _mem_tracker is nullptr, it means it is in UT.
std::shared_ptr<MemTrackerLimiter> _mem_tracker;
};
using DictionaryPtr = std::shared_ptr<IDictionary>;
} // namespace doris