Coverage Report

Created: 2026-08-03 17:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/doris/be/src/exprs/vtopn_pred.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/vtopn_pred.h"
19
20
#include <cstring>
21
22
#include "exprs/expr_zonemap_filter.h"
23
#include "util/simd/parquet_kernels.h"
24
25
namespace doris {
26
27
namespace {
28
29
using simd::RawComparisonOp;
30
31
80
size_t topn_raw_value_size(PrimitiveType type) {
32
80
    switch (type) {
33
0
#define RETURN_TOPN_RAW_SIZE(TYPE) \
34
65
    case TYPE:                     \
35
65
        return sizeof(typename PrimitiveTypeTraits<TYPE>::CppType)
36
2
        RETURN_TOPN_RAW_SIZE(TYPE_BOOLEAN);
37
2
        RETURN_TOPN_RAW_SIZE(TYPE_TINYINT);
38
2
        RETURN_TOPN_RAW_SIZE(TYPE_SMALLINT);
39
29
        RETURN_TOPN_RAW_SIZE(TYPE_INT);
40
2
        RETURN_TOPN_RAW_SIZE(TYPE_BIGINT);
41
2
        RETURN_TOPN_RAW_SIZE(TYPE_LARGEINT);
42
0
        RETURN_TOPN_RAW_SIZE(TYPE_FLOAT);
43
0
        RETURN_TOPN_RAW_SIZE(TYPE_DOUBLE);
44
2
        RETURN_TOPN_RAW_SIZE(TYPE_DATE);
45
2
        RETURN_TOPN_RAW_SIZE(TYPE_DATETIME);
46
2
        RETURN_TOPN_RAW_SIZE(TYPE_DATEV2);
47
2
        RETURN_TOPN_RAW_SIZE(TYPE_DATETIMEV2);
48
2
        RETURN_TOPN_RAW_SIZE(TYPE_TIMESTAMPTZ);
49
0
        RETURN_TOPN_RAW_SIZE(TYPE_TIME);
50
2
        RETURN_TOPN_RAW_SIZE(TYPE_TIMEV2);
51
2
        RETURN_TOPN_RAW_SIZE(TYPE_DECIMAL32);
52
2
        RETURN_TOPN_RAW_SIZE(TYPE_DECIMAL64);
53
2
        RETURN_TOPN_RAW_SIZE(TYPE_DECIMALV2);
54
2
        RETURN_TOPN_RAW_SIZE(TYPE_DECIMAL128I);
55
2
        RETURN_TOPN_RAW_SIZE(TYPE_DECIMAL256);
56
2
        RETURN_TOPN_RAW_SIZE(TYPE_IPV4);
57
2
        RETURN_TOPN_RAW_SIZE(TYPE_IPV6);
58
0
#undef RETURN_TOPN_RAW_SIZE
59
15
    default:
60
15
        return 0;
61
80
    }
62
80
}
63
64
22
bool topn_binary_type(PrimitiveType type) {
65
22
    return is_string_type(type) || type == TYPE_VARBINARY;
66
22
}
67
68
template <typename T, PrimitiveType PT>
69
void execute_topn_raw_comparison(const uint8_t* values, size_t num_values, const Field& bound,
70
5
                                 RawComparisonOp op, uint8_t* matches) {
71
5
    simd::raw_compare(values, num_values, bound.get<PT>(), op, matches);
72
5
}
vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_127execute_topn_raw_comparisonIiLNS_13PrimitiveTypeE5EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Line
Count
Source
70
5
                                 RawComparisonOp op, uint8_t* matches) {
71
5
    simd::raw_compare(values, num_values, bound.get<PT>(), op, matches);
72
5
}
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_127execute_topn_raw_comparisonIlLNS_13PrimitiveTypeE6EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_127execute_topn_raw_comparisonIfLNS_13PrimitiveTypeE8EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_127execute_topn_raw_comparisonIdLNS_13PrimitiveTypeE9EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
73
74
template <typename T>
75
0
bool topn_raw_scalar_matches(const T& value, const T& bound, RawComparisonOp op) {
76
0
    return op == RawComparisonOp::LE ? value <= bound : value >= bound;
77
0
}
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesIhEEbRKT_S4_NS_4simd15RawComparisonOpE
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesIaEEbRKT_S4_NS_4simd15RawComparisonOpE
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesIsEEbRKT_S4_NS_4simd15RawComparisonOpE
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesInEEbRKT_S4_NS_4simd15RawComparisonOpE
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesINS_16VecDateTimeValueEEEbRKT_S5_NS_4simd15RawComparisonOpE
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesINS_11DateV2ValueINS_15DateV2ValueTypeEEEEEbRKT_S7_NS_4simd15RawComparisonOpE
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesINS_11DateV2ValueINS_19DateTimeV2ValueTypeEEEEEbRKT_S7_NS_4simd15RawComparisonOpE
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesINS_16TimestampTzValueEEEbRKT_S5_NS_4simd15RawComparisonOpE
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesIdEEbRKT_S4_NS_4simd15RawComparisonOpE
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesINS_7DecimalIiEEEEbRKT_S6_NS_4simd15RawComparisonOpE
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesINS_7DecimalIlEEEEbRKT_S6_NS_4simd15RawComparisonOpE
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesINS_14DecimalV2ValueEEEbRKT_S5_NS_4simd15RawComparisonOpE
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesINS_12Decimal128V3EEEbRKT_S5_NS_4simd15RawComparisonOpE
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesINS_7DecimalIN4wide7integerILm256EiEEEEEEbRKT_S9_NS_4simd15RawComparisonOpE
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesIjEEbRKT_S4_NS_4simd15RawComparisonOpE
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123topn_raw_scalar_matchesIoEEbRKT_S4_NS_4simd15RawComparisonOpE
78
79
template <PrimitiveType PT>
80
void execute_topn_raw_scalar(const uint8_t* values, size_t num_values, const Field& bound,
81
0
                             RawComparisonOp op, uint8_t* matches) {
82
0
    using T = typename PrimitiveTypeTraits<PT>::CppType;
83
0
    const T& typed_bound = bound.get<PT>();
84
0
    for (size_t row = 0; row < num_values; ++row) {
85
0
        T value;
86
0
        std::memcpy(&value, values + row * sizeof(T), sizeof(T));
87
0
        matches[row] &= topn_raw_scalar_matches(value, typed_bound, op) ? 1 : 0;
88
0
    }
89
0
}
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE2EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE3EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE4EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE7EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE11EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE12EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE25EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE26EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE42EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE21EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE27EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE28EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE29EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE20EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE30EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE35EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE36EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
Unexecuted instantiation: vtopn_pred.cpp:_ZN5doris12_GLOBAL__N_123execute_topn_raw_scalarILNS_13PrimitiveTypeE37EEEvPKhmRKNS_5FieldENS_4simd15RawComparisonOpEPh
90
91
6
bool topn_string_matches(int comparison, RawComparisonOp op) {
92
6
    return op == RawComparisonOp::LE ? comparison <= 0 : comparison >= 0;
93
6
}
94
95
} // namespace
96
97
34
bool VTopNPred::can_execute_on_raw_fixed_values(const DataTypePtr& data_type, int column_id) const {
98
34
    if (_predicate == nullptr || data_type == nullptr || _children.size() != 1) {
99
0
        return false;
100
0
    }
101
34
    const auto slot = std::dynamic_pointer_cast<VSlotRef>(_children[0]);
102
34
    if (slot == nullptr || slot->column_id() != column_id || slot->data_type() == nullptr) {
103
0
        return false;
104
0
    }
105
34
    const auto raw_type = remove_nullable(data_type);
106
34
    return remove_nullable(slot->data_type())->equals(*raw_type) &&
107
34
           topn_raw_value_size(raw_type->get_primitive_type()) != 0;
108
34
}
109
110
Status VTopNPred::execute_on_raw_fixed_values(const uint8_t* values, size_t num_values,
111
                                              size_t value_width, const DataTypePtr& data_type,
112
6
                                              int column_id, uint8_t* matches) const {
113
6
    if (!can_execute_on_raw_fixed_values(data_type, column_id)) {
114
0
        return Status::NotSupported("TopN predicate cannot evaluate raw fixed-width values");
115
0
    }
116
6
    DORIS_CHECK(values != nullptr || num_values == 0);
117
6
    DORIS_CHECK(matches != nullptr || num_values == 0);
118
6
    const auto primitive_type = remove_nullable(data_type)->get_primitive_type();
119
6
    const size_t expected_width = topn_raw_value_size(primitive_type);
120
6
    if (value_width != expected_width) {
121
0
        return Status::Corruption("Raw TopN width {} does not match expected {}", value_width,
122
0
                                  expected_width);
123
0
    }
124
125
    // The bound is mutable and may arrive after reader initialization. Snapshot it once per batch
126
    // so every row observes one monotonic TopN frontier without invalidating cached capability.
127
6
    const Field bound = _predicate->get_value();
128
6
    if (bound.is_null()) {
129
1
        return Status::OK();
130
1
    }
131
5
    if (!expr_zonemap::field_types_compatible(bound.get_type(), primitive_type)) {
132
0
        return Status::InternalError("TopN bound type {} does not match raw value type {}",
133
0
                                     type_to_string(bound.get_type()),
134
0
                                     type_to_string(primitive_type));
135
0
    }
136
5
    const auto op = _predicate->is_asc() ? RawComparisonOp::LE : RawComparisonOp::GE;
137
5
    switch (primitive_type) {
138
5
    case TYPE_INT:
139
5
        execute_topn_raw_comparison<int32_t, TYPE_INT>(values, num_values, bound, op, matches);
140
5
        break;
141
0
    case TYPE_BIGINT:
142
0
        execute_topn_raw_comparison<int64_t, TYPE_BIGINT>(values, num_values, bound, op, matches);
143
0
        break;
144
0
    case TYPE_FLOAT:
145
0
        execute_topn_raw_comparison<float, TYPE_FLOAT>(values, num_values, bound, op, matches);
146
0
        break;
147
0
    case TYPE_DOUBLE:
148
0
        execute_topn_raw_comparison<double, TYPE_DOUBLE>(values, num_values, bound, op, matches);
149
0
        break;
150
0
#define EXECUTE_TOPN_RAW_SCALAR(TYPE)                                          \
151
0
    case TYPE:                                                                 \
152
0
        execute_topn_raw_scalar<TYPE>(values, num_values, bound, op, matches); \
153
0
        break
154
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_BOOLEAN);
155
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_TINYINT);
156
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_SMALLINT);
157
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_LARGEINT);
158
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DATE);
159
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DATETIME);
160
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DATEV2);
161
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DATETIMEV2);
162
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_TIMESTAMPTZ);
163
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_TIME);
164
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_TIMEV2);
165
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DECIMAL32);
166
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DECIMAL64);
167
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DECIMALV2);
168
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DECIMAL128I);
169
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DECIMAL256);
170
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_IPV4);
171
0
        EXECUTE_TOPN_RAW_SCALAR(TYPE_IPV6);
172
0
#undef EXECUTE_TOPN_RAW_SCALAR
173
0
    default:
174
0
        return Status::NotSupported("TopN raw fixed-width type {} is unsupported",
175
0
                                    type_to_string(primitive_type));
176
5
    }
177
5
    return Status::OK();
178
5
}
179
180
bool VTopNPred::can_execute_on_raw_binary_values(const DataTypePtr& data_type,
181
8
                                                 int column_id) const {
182
8
    if (_predicate == nullptr || data_type == nullptr || _children.size() != 1) {
183
0
        return false;
184
0
    }
185
8
    const auto raw_type = remove_nullable(data_type);
186
8
    const auto raw_primitive_type = raw_type->get_primitive_type();
187
8
    if (!topn_binary_type(raw_primitive_type)) {
188
1
        return false;
189
1
    }
190
7
    const auto slot = std::dynamic_pointer_cast<VSlotRef>(_children[0]);
191
7
    if (slot == nullptr || slot->column_id() != column_id || slot->data_type() == nullptr) {
192
0
        return false;
193
0
    }
194
7
    const auto slot_primitive_type = remove_nullable(slot->data_type())->get_primitive_type();
195
7
    return (is_string_type(raw_primitive_type) && is_string_type(slot_primitive_type)) ||
196
7
           (raw_primitive_type == TYPE_VARBINARY && slot_primitive_type == TYPE_VARBINARY);
197
7
}
198
199
Status VTopNPred::execute_on_raw_binary_values(const StringRef* values, size_t num_values,
200
                                               const DataTypePtr& data_type, int column_id,
201
2
                                               uint8_t* matches) const {
202
2
    if (!can_execute_on_raw_binary_values(data_type, column_id)) {
203
0
        return Status::NotSupported("TopN predicate cannot evaluate raw binary values");
204
0
    }
205
2
    DORIS_CHECK(values != nullptr || num_values == 0);
206
2
    DORIS_CHECK(matches != nullptr || num_values == 0);
207
2
    const Field bound = _predicate->get_value();
208
2
    if (bound.is_null()) {
209
0
        return Status::OK();
210
0
    }
211
2
    const auto primitive_type = remove_nullable(data_type)->get_primitive_type();
212
2
    StringRef bound_ref;
213
2
    if (is_string_type(primitive_type) && is_string_type(bound.get_type())) {
214
1
        const auto& value = bound.get<TYPE_STRING>();
215
1
        bound_ref = StringRef(value.data(), value.size());
216
1
    } else if (primitive_type == TYPE_VARBINARY && bound.get_type() == TYPE_VARBINARY) {
217
1
        bound_ref = bound.get<TYPE_VARBINARY>().to_string_ref();
218
1
    } else {
219
0
        return Status::InternalError("TopN bound type {} does not match raw binary type {}",
220
0
                                     type_to_string(bound.get_type()),
221
0
                                     type_to_string(primitive_type));
222
0
    }
223
2
    const auto op = _predicate->is_asc() ? RawComparisonOp::LE : RawComparisonOp::GE;
224
8
    for (size_t row = 0; row < num_values; ++row) {
225
6
        matches[row] &= topn_string_matches(values[row].compare(bound_ref), op) ? 1 : 0;
226
6
    }
227
2
    return Status::OK();
228
2
}
229
230
41
bool VTopNPred::can_evaluate_dictionary_filter() const {
231
41
    if (_predicate == nullptr || _predicate->nulls_first() || _children.size() != 1) {
232
1
        return false;
233
1
    }
234
40
    const auto slot = std::dynamic_pointer_cast<VSlotRef>(_children[0]);
235
40
    if (slot == nullptr || slot->data_type() == nullptr) {
236
0
        return false;
237
0
    }
238
40
    const auto primitive_type = remove_nullable(slot->data_type())->get_primitive_type();
239
40
    return topn_raw_value_size(primitive_type) != 0 || topn_binary_type(primitive_type);
240
40
}
241
242
7
ZoneMapFilterResult VTopNPred::evaluate_dictionary_filter(const DictionaryEvalContext& ctx) const {
243
7
    if (!can_evaluate_dictionary_filter()) {
244
0
        return ZoneMapFilterResult::kUnsupported;
245
0
    }
246
7
    const auto slot = std::dynamic_pointer_cast<VSlotRef>(_children[0]);
247
7
    DORIS_CHECK(slot != nullptr);
248
7
    const auto* dictionary = ctx.slot(slot->column_id());
249
7
    if (dictionary == nullptr ||
250
7
        !expr_zonemap::data_types_compatible(dictionary->data_type, slot->data_type())) {
251
0
        return ZoneMapFilterResult::kUnsupported;
252
0
    }
253
7
    const Field bound = _predicate->get_value();
254
7
    if (bound.is_null()) {
255
3
        return ZoneMapFilterResult::kMayMatch;
256
3
    }
257
4
    const auto primitive_type = remove_nullable(dictionary->data_type)->get_primitive_type();
258
4
    if (!expr_zonemap::field_types_compatible(bound.get_type(), primitive_type)) {
259
0
        return ZoneMapFilterResult::kUnsupported;
260
0
    }
261
8
    for (const Field& value : dictionary->values) {
262
8
        if (value.is_null()) {
263
0
            continue;
264
0
        }
265
8
        if (!expr_zonemap::field_types_compatible(value.get_type(), primitive_type)) {
266
0
            return ZoneMapFilterResult::kUnsupported;
267
0
        }
268
8
        if ((_predicate->is_asc() && value <= bound) || (!_predicate->is_asc() && value >= bound)) {
269
2
            return ZoneMapFilterResult::kMayMatch;
270
2
        }
271
8
    }
272
2
    return ZoneMapFilterResult::kNoMatch;
273
4
}
274
275
} // namespace doris