| // 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. | 
 |  | 
 | #include "runtime/runtime_predicate.h" | 
 |  | 
 | #include <stdint.h> | 
 |  | 
 | #include <memory> | 
 |  | 
 | // IWYU pragma: no_include <opentelemetry/common/threadlocal.h> | 
 | #include "common/compiler_util.h" // IWYU pragma: keep | 
 | #include "olap/accept_null_predicate.h" | 
 | #include "olap/column_predicate.h" | 
 | #include "olap/predicate_creator.h" | 
 |  | 
 | namespace doris { | 
 |  | 
 | namespace vectorized { | 
 |  | 
 | std::string get_time_value(const Field& field) { | 
 |     using ValueType = typename PrimitiveTypeTraits<TYPE_TIMEV2>::CppType; | 
 |     ValueType value = field.get<ValueType>(); | 
 |     return cast_to_string<TYPE_TIMEV2, ValueType>(value, 0); | 
 | } | 
 |  | 
 | Status RuntimePredicate::init(const PrimitiveType type, const bool nulls_first) { | 
 |     std::unique_lock<std::shared_mutex> wlock(_rwlock); | 
 |  | 
 |     if (_inited) { | 
 |         return Status::OK(); | 
 |     } | 
 |  | 
 |     _nulls_first = nulls_first; | 
 |  | 
 |     _predicate_arena.reset(new Arena()); | 
 |  | 
 |     // set get value function | 
 |     switch (type) { | 
 |     case PrimitiveType::TYPE_BOOLEAN: { | 
 |         _get_value_fn = get_bool_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_TINYINT: { | 
 |         _get_value_fn = get_tinyint_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_SMALLINT: { | 
 |         _get_value_fn = get_smallint_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_INT: { | 
 |         _get_value_fn = get_int_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_BIGINT: { | 
 |         _get_value_fn = get_bigint_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_LARGEINT: { | 
 |         _get_value_fn = get_largeint_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_FLOAT: { | 
 |         _get_value_fn = get_float_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_DOUBLE: { | 
 |         _get_value_fn = get_double_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_CHAR: | 
 |     case PrimitiveType::TYPE_VARCHAR: | 
 |     case PrimitiveType::TYPE_STRING: { | 
 |         _get_value_fn = get_string_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_DATEV2: { | 
 |         _get_value_fn = get_datev2_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_DATETIMEV2: { | 
 |         _get_value_fn = get_datetimev2_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_DATE: { | 
 |         _get_value_fn = get_date_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_DATETIME: { | 
 |         _get_value_fn = get_datetime_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_TIMEV2: { | 
 |         _get_value_fn = get_time_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_DECIMAL32: { | 
 |         _get_value_fn = get_decimal32_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_DECIMAL64: { | 
 |         _get_value_fn = get_decimal64_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_DECIMALV2: { | 
 |         _get_value_fn = get_decimalv2_value; | 
 |         break; | 
 |     } | 
 |     case PrimitiveType::TYPE_DECIMAL128I: { | 
 |         _get_value_fn = get_decimal128_value; | 
 |         break; | 
 |     } | 
 |     default: | 
 |         return Status::InvalidArgument("unsupported runtime predicate type {}", type); | 
 |     } | 
 |  | 
 |     _inited = true; | 
 |     return Status::OK(); | 
 | } | 
 |  | 
 | Status RuntimePredicate::update(const Field& value, const String& col_name, bool is_reverse) { | 
 |     // skip null value | 
 |     if (value.is_null()) { | 
 |         return Status::OK(); | 
 |     } | 
 |  | 
 |     if (!_inited) { | 
 |         return Status::OK(); | 
 |     } | 
 |  | 
 |     std::unique_lock<std::shared_mutex> wlock(_rwlock); | 
 |  | 
 |     bool updated = false; | 
 |  | 
 |     if (UNLIKELY(_orderby_extrem.is_null())) { | 
 |         _orderby_extrem = value; | 
 |         updated = true; | 
 |     } else if (is_reverse) { | 
 |         if (value > _orderby_extrem) { | 
 |             _orderby_extrem = value; | 
 |             updated = true; | 
 |         } | 
 |     } else { | 
 |         if (value < _orderby_extrem) { | 
 |             _orderby_extrem = value; | 
 |             updated = true; | 
 |         } | 
 |     } | 
 |  | 
 |     if (!updated) { | 
 |         return Status::OK(); | 
 |     } | 
 |  | 
 |     // TODO defensive code | 
 |     if (!_tablet_schema || !_tablet_schema->have_column(col_name)) { | 
 |         return Status::OK(); | 
 |     } | 
 |     // update _predictate | 
 |     int32_t col_unique_id = _tablet_schema->column(col_name).unique_id(); | 
 |     const TabletColumn& column = _tablet_schema->column_by_uid(col_unique_id); | 
 |     uint32_t index = _tablet_schema->field_index(col_unique_id); | 
 |     auto val = _get_value_fn(_orderby_extrem); | 
 |     std::unique_ptr<ColumnPredicate> pred {nullptr}; | 
 |     if (is_reverse) { | 
 |         // For DESC sort, create runtime predicate col_name >= min_top_value | 
 |         // since values that < min_top_value are less than any value in current topn values | 
 |         pred.reset(create_comparison_predicate<PredicateType::GE>(column, index, val, false, | 
 |                                                                   _predicate_arena.get())); | 
 |     } else { | 
 |         // For ASC  sort, create runtime predicate col_name <= max_top_value | 
 |         // since values that > min_top_value are large than any value in current topn values | 
 |         pred.reset(create_comparison_predicate<PredicateType::LE>(column, index, val, false, | 
 |                                                                   _predicate_arena.get())); | 
 |     } | 
 |  | 
 |     // For NULLS FIRST, wrap a AcceptNullPredicate to return true for NULL | 
 |     // since ORDER BY ASC/DESC should get NULL first but pred returns NULL | 
 |     // and NULL in where predicate will be treated as FALSE | 
 |     if (_nulls_first) { | 
 |         pred = AcceptNullPredicate::create_unique(pred.release()); | 
 |     } | 
 |     _predictate.reset(pred.release()); | 
 |  | 
 |     return Status::OK(); | 
 | } | 
 |  | 
 | } // namespace vectorized | 
 | } // namespace doris |