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 | | #include "exprs/vliteral.h" |
19 | | |
20 | | #include <fmt/format.h> |
21 | | #include <gen_cpp/Exprs_types.h> |
22 | | #include <gen_cpp/Types_types.h> |
23 | | #include <glog/logging.h> |
24 | | #include <sys/types.h> |
25 | | |
26 | | #include <algorithm> |
27 | | #include <ostream> |
28 | | |
29 | | #include "core/block/block.h" |
30 | | #include "core/column/column.h" |
31 | | #include "core/column/column_array.h" |
32 | | #include "core/column/column_complex.h" |
33 | | #include "core/column/column_const.h" |
34 | | #include "core/column/column_fixed_length_object.h" |
35 | | #include "core/column/column_map.h" |
36 | | #include "core/column/column_nullable.h" |
37 | | #include "core/column/column_struct.h" |
38 | | #include "core/column/column_varbinary.h" |
39 | | #include "core/data_type/data_type_decimal.h" |
40 | | #include "core/field.h" |
41 | | #include "core/types.h" |
42 | | #include "exprs/aggregate/aggregate_function.h" |
43 | | |
44 | | namespace doris { |
45 | | #include "common/compile_check_begin.h" |
46 | | |
47 | | namespace { |
48 | | |
49 | 369 | bool supports_literal_digest(const IColumn& column) { |
50 | | // These concrete columns inherit IColumn's throwing xxHash implementation. |
51 | | // Inspect the column rather than the SQL type: AGG_STATE can use either a |
52 | | // hashable string column or an unsupported fixed-length object column. |
53 | 369 | if (is_column<ColumnBitmap>(column) || is_column<ColumnHLL>(column) || |
54 | 369 | is_column<ColumnQuantileState>(column) || is_column<ColumnVarbinary>(column) || |
55 | 369 | is_column<ColumnFixedLengthObject>(column)) { |
56 | 18 | return false; |
57 | 18 | } |
58 | | |
59 | | // The branch's mutable subcolumn traversal moves array offsets and updates variant state. |
60 | | // Inspect wrappers and containers through const accessors instead. |
61 | 351 | if (const auto* constant = check_and_get_column<ColumnConst>(column)) { |
62 | 147 | return supports_literal_digest(constant->get_data_column()); |
63 | 147 | } |
64 | 204 | if (const auto* nullable = check_and_get_column<ColumnNullable>(column)) { |
65 | 52 | return supports_literal_digest(nullable->get_nested_column()); |
66 | 52 | } |
67 | 152 | if (const auto* array = check_and_get_column<ColumnArray>(column)) { |
68 | 11 | return supports_literal_digest(array->get_data()); |
69 | 11 | } |
70 | 141 | if (const auto* map = check_and_get_column<ColumnMap>(column)) { |
71 | 4 | return supports_literal_digest(map->get_keys()) && |
72 | 4 | supports_literal_digest(map->get_values()); |
73 | 4 | } |
74 | 137 | if (const auto* structure = check_and_get_column<ColumnStruct>(column)) { |
75 | 4 | return std::ranges::all_of(structure->get_columns(), [](const auto& child) { |
76 | 4 | return supports_literal_digest(*child); |
77 | 4 | }); |
78 | 2 | } |
79 | 135 | return true; |
80 | 137 | } |
81 | | |
82 | | } // namespace |
83 | | |
84 | | class VExprContext; |
85 | | |
86 | 704 | Status VLiteral::prepare(RuntimeState* state, const RowDescriptor& desc, VExprContext* context) { |
87 | 704 | RETURN_IF_ERROR_OR_PREPARED(VExpr::prepare(state, desc, context)); |
88 | 647 | return Status::OK(); |
89 | 647 | } |
90 | | |
91 | | Status VLiteral::execute_column_impl(VExprContext* context, const Block* block, |
92 | | const Selector* selector, size_t count, |
93 | 871 | ColumnPtr& result_column) const { |
94 | 871 | DCHECK(selector == nullptr || selector->size() == count); |
95 | 871 | result_column = _column_ptr->clone_resized(count); |
96 | 871 | DCHECK_EQ(result_column->size(), count); |
97 | 871 | return Status::OK(); |
98 | 871 | } |
99 | | |
100 | 125 | std::string VLiteral::value(const DataTypeSerDe::FormatOptions& options) const { |
101 | 125 | DCHECK(_column_ptr->size() == 1); |
102 | 125 | return _data_type->to_string(*_column_ptr, 0, options); |
103 | 125 | } |
104 | | |
105 | | #ifdef BE_TEST |
106 | 43 | std::string VLiteral::value() const { |
107 | 43 | auto format_options = DataTypeSerDe::get_default_format_options(); |
108 | 43 | auto timezone = cctz::utc_time_zone(); |
109 | 43 | format_options.timezone = &timezone; |
110 | 43 | return value(format_options); |
111 | 43 | } |
112 | | #endif |
113 | | |
114 | 15 | std::string VLiteral::debug_string() const { |
115 | 15 | auto format_options = DataTypeSerDe::get_default_format_options(); |
116 | 15 | auto timezone = cctz::utc_time_zone(); |
117 | 15 | format_options.timezone = &timezone; |
118 | | |
119 | 15 | std::stringstream out; |
120 | 15 | out << "VLiteral (name = " << _expr_name; |
121 | 15 | out << ", type = " << _data_type->get_name(); |
122 | 15 | out << ", value = (" << value(format_options); |
123 | 15 | out << "))"; |
124 | 15 | return out.str(); |
125 | 15 | } |
126 | | |
127 | 0 | bool VLiteral::equals(const VExpr& other) { |
128 | 0 | const auto* other_ptr = dynamic_cast<const VLiteral*>(&other); |
129 | 0 | if (!other_ptr) { |
130 | 0 | return false; |
131 | 0 | } |
132 | 0 | if (this->_expr_name != other_ptr->_expr_name) { |
133 | 0 | return false; |
134 | 0 | } |
135 | 0 | if (this->_column_ptr->structure_equals(*other_ptr->_column_ptr)) { |
136 | 0 | if (this->_column_ptr->size() != other_ptr->_column_ptr->size()) { |
137 | 0 | return false; |
138 | 0 | } |
139 | 0 | for (size_t i = 0; i < this->_column_ptr->size(); i++) { |
140 | 0 | if (this->_column_ptr->compare_at(i, i, *other_ptr->_column_ptr, -1) != 0) { |
141 | 0 | return false; |
142 | 0 | } |
143 | 0 | } |
144 | 0 | } |
145 | 0 | return true; |
146 | 0 | } |
147 | | |
148 | 147 | uint64_t VLiteral::get_digest(uint64_t seed) const { |
149 | | // Wrappers and containers delegate hashing to their nested columns. A zero |
150 | | // digest disables the condition cache without changing the column hash contract. |
151 | 147 | if (!supports_literal_digest(*_column_ptr)) { |
152 | 18 | return 0; |
153 | 18 | } |
154 | 129 | _column_ptr->update_xxHash_with_value(0, 1, seed, nullptr); |
155 | 129 | return seed; |
156 | 147 | } |
157 | | |
158 | | #include "common/compile_check_end.h" |
159 | | } // namespace doris |