Coverage Report

Created: 2026-11-04 18:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/doris/be/src/exprs/vliteral.cpp
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