// 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 "exprs/in_predicate.h" #include #include "exprs/anyval_util.h" #include "exprs/anyval_util.h" #include "codegen/llvm_codegen.h" #include "runtime/raw_value.h" #include "runtime/string_value.hpp" #include "runtime/runtime_state.h" namespace doris { InPredicate::InPredicate(const TExprNode& node) : Predicate(node), _is_not_in(node.in_predicate.is_not_in), _is_prepare(false), _null_in_set(false), _hybird_set() { } InPredicate::~InPredicate() { } Status InPredicate::prepare(RuntimeState* state, const TypeDescriptor& type) { if (_is_prepare) { return Status::OK; } _hybird_set.reset(HybirdSetBase::create_set(type.type)); if (NULL == _hybird_set.get()) { return Status("Unknown column type."); } _is_prepare = true; return Status::OK; } Status InPredicate::open( RuntimeState* state, ExprContext* context, FunctionContext::FunctionStateScope scope) { Expr::open(state, context, scope); for (int i = 1; i < _children.size(); ++i) { if (_children[0]->type().is_string_type()) { if (!_children[i]->type().is_string_type()) { return Status("InPredicate type not same"); } } else { if (_children[i]->type().type != _children[0]->type().type) { return Status("InPredicate type not same"); } } void* value = context->get_value(_children[i], NULL); if (value == NULL) { _null_in_set = true; continue; } _hybird_set->insert(value); } return Status::OK; } Status InPredicate::prepare( RuntimeState* state, const RowDescriptor& row_desc, ExprContext* context) { for (int i = 0; i < _children.size(); ++i) { RETURN_IF_ERROR(_children[i]->prepare(state, row_desc, context)); } if (_is_prepare) { return Status::OK; } if (_children.size() < 1) { return Status("no Function operator in."); } _hybird_set.reset(HybirdSetBase::create_set(_children[0]->type().type)); if (NULL == _hybird_set.get()) { return Status("Unknown column type."); } _is_prepare = true; return Status::OK; } void InPredicate::insert(void* value) { if (NULL == value) { _null_in_set = true; } else { _hybird_set->insert(value); } } std::string InPredicate::debug_string() const { std::stringstream out; out << "InPredicate(" << get_child(0)->debug_string() << " " << _is_not_in << ",["; int num_children = get_num_children(); for (int i = 1; i < num_children; ++i) { out << (i == 1 ? "" : " ") << get_child(i)->debug_string(); } out << "])"; return out.str(); } // this in predicate profile for case "a IN (1, 2, 3)" // not for "a IN (b, 2, 3)" // a, b is a column or a expr that contain slot BooleanVal InPredicate::get_boolean_val(ExprContext* ctx, TupleRow* row) { void* lhs_slot = ctx->get_value(_children[0], row); if (lhs_slot == NULL) { return BooleanVal::null(); } if (_null_in_set) { return BooleanVal::null(); } // if find in const set, return true if (_hybird_set->find(lhs_slot)) { return BooleanVal(!_is_not_in); } return BooleanVal(_is_not_in); } }