// Licensed to the LF AI & Data foundation 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. #pragma once #include #include #include "common/EasyAssert.h" #include "common/Types.h" #include "common/Vector.h" #include "exec/expression/Expr.h" #include "segcore/SegmentInterface.h" namespace milvus { namespace exec { namespace { template struct CmpOpHelper { using op = void; }; template <> struct CmpOpHelper { static constexpr auto op = milvus::bitset::CompareOpType::EQ; }; template <> struct CmpOpHelper { static constexpr auto op = milvus::bitset::CompareOpType::GE; }; template <> struct CmpOpHelper { static constexpr auto op = milvus::bitset::CompareOpType::GT; }; template <> struct CmpOpHelper { static constexpr auto op = milvus::bitset::CompareOpType::LE; }; template <> struct CmpOpHelper { static constexpr auto op = milvus::bitset::CompareOpType::LT; }; template <> struct CmpOpHelper { static constexpr auto op = milvus::bitset::CompareOpType::NE; }; template struct ArithOpHelper { using op = void; }; template <> struct ArithOpHelper { static constexpr auto op = milvus::bitset::ArithOpType::Add; }; template <> struct ArithOpHelper { static constexpr auto op = milvus::bitset::ArithOpType::Sub; }; template <> struct ArithOpHelper { static constexpr auto op = milvus::bitset::ArithOpType::Mul; }; template <> struct ArithOpHelper { static constexpr auto op = milvus::bitset::ArithOpType::Div; }; template <> struct ArithOpHelper { static constexpr auto op = milvus::bitset::ArithOpType::Mod; }; } // namespace template struct ArithOpElementFunc { typedef std::conditional_t && !std::is_same_v, int64_t, T> HighPrecisonType; void operator()(const T* src, size_t size, HighPrecisonType val, HighPrecisonType right_operand, TargetBitmapView res) { /* // This is the original code, kept here for the documentation purposes for (int i = 0; i < size; ++i) { if constexpr (cmp_op == proto::plan::OpType::Equal) { if constexpr (arith_op == proto::plan::ArithOpType::Add) { res[i] = (src[i] + right_operand) == val; } else if constexpr (arith_op == proto::plan::ArithOpType::Sub) { res[i] = (src[i] - right_operand) == val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mul) { res[i] = (src[i] * right_operand) == val; } else if constexpr (arith_op == proto::plan::ArithOpType::Div) { res[i] = (src[i] / right_operand) == val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mod) { res[i] = (fmod(src[i], right_operand)) == val; } else { PanicInfo( OpTypeInvalid, fmt::format( "unsupported arith type:{} for ArithOpElementFunc", arith_op)); } } else if constexpr (cmp_op == proto::plan::OpType::NotEqual) { if constexpr (arith_op == proto::plan::ArithOpType::Add) { res[i] = (src[i] + right_operand) != val; } else if constexpr (arith_op == proto::plan::ArithOpType::Sub) { res[i] = (src[i] - right_operand) != val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mul) { res[i] = (src[i] * right_operand) != val; } else if constexpr (arith_op == proto::plan::ArithOpType::Div) { res[i] = (src[i] / right_operand) != val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mod) { res[i] = (fmod(src[i], right_operand)) != val; } else { PanicInfo( OpTypeInvalid, fmt::format( "unsupported arith type:{} for ArithOpElementFunc", arith_op)); } } else if constexpr (cmp_op == proto::plan::OpType::GreaterThan) { if constexpr (arith_op == proto::plan::ArithOpType::Add) { res[i] = (src[i] + right_operand) > val; } else if constexpr (arith_op == proto::plan::ArithOpType::Sub) { res[i] = (src[i] - right_operand) > val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mul) { res[i] = (src[i] * right_operand) > val; } else if constexpr (arith_op == proto::plan::ArithOpType::Div) { res[i] = (src[i] / right_operand) > val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mod) { res[i] = (fmod(src[i], right_operand)) > val; } else { PanicInfo( OpTypeInvalid, fmt::format( "unsupported arith type:{} for ArithOpElementFunc", arith_op)); } } else if constexpr (cmp_op == proto::plan::OpType::GreaterEqual) { if constexpr (arith_op == proto::plan::ArithOpType::Add) { res[i] = (src[i] + right_operand) >= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Sub) { res[i] = (src[i] - right_operand) >= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mul) { res[i] = (src[i] * right_operand) >= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Div) { res[i] = (src[i] / right_operand) >= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mod) { res[i] = (fmod(src[i], right_operand)) >= val; } else { PanicInfo( OpTypeInvalid, fmt::format( "unsupported arith type:{} for ArithOpElementFunc", arith_op)); } } else if constexpr (cmp_op == proto::plan::OpType::LessThan) { if constexpr (arith_op == proto::plan::ArithOpType::Add) { res[i] = (src[i] + right_operand) < val; } else if constexpr (arith_op == proto::plan::ArithOpType::Sub) { res[i] = (src[i] - right_operand) < val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mul) { res[i] = (src[i] * right_operand) < val; } else if constexpr (arith_op == proto::plan::ArithOpType::Div) { res[i] = (src[i] / right_operand) < val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mod) { res[i] = (fmod(src[i], right_operand)) < val; } else { PanicInfo( OpTypeInvalid, fmt::format( "unsupported arith type:{} for ArithOpElementFunc", arith_op)); } } else if constexpr (cmp_op == proto::plan::OpType::LessEqual) { if constexpr (arith_op == proto::plan::ArithOpType::Add) { res[i] = (src[i] + right_operand) <= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Sub) { res[i] = (src[i] - right_operand) <= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mul) { res[i] = (src[i] * right_operand) <= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Div) { res[i] = (src[i] / right_operand) <= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mod) { res[i] = (fmod(src[i], right_operand)) <= val; } else { PanicInfo( OpTypeInvalid, fmt::format( "unsupported arith type:{} for ArithOpElementFunc", arith_op)); } } } */ if constexpr (!std::is_same_v::op), void>) { constexpr auto cmp_op_cvt = CmpOpHelper::op; if constexpr (!std::is_same_v::op), void>) { constexpr auto arith_op_cvt = ArithOpHelper::op; res.inplace_arith_compare( src, right_operand, val, size); } else { PanicInfo( OpTypeInvalid, fmt::format( "unsupported arith type:{} for ArithOpElementFunc", arith_op)); } } else { PanicInfo( OpTypeInvalid, fmt::format("unsupported cmp type:{} for ArithOpElementFunc", cmp_op)); } } }; template struct ArithOpIndexFunc { typedef std::conditional_t && !std::is_same_v, int64_t, T> HighPrecisonType; using Index = index::ScalarIndex; TargetBitmap operator()(Index* index, size_t size, HighPrecisonType val, HighPrecisonType right_operand) { TargetBitmap res(size); for (size_t i = 0; i < size; ++i) { auto raw = index->Reverse_Lookup(i); if (!raw.has_value()) { res[i] = false; continue; } if constexpr (cmp_op == proto::plan::OpType::Equal) { if constexpr (arith_op == proto::plan::ArithOpType::Add) { res[i] = (raw.value() + right_operand) == val; } else if constexpr (arith_op == proto::plan::ArithOpType::Sub) { res[i] = (raw.value() - right_operand) == val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mul) { res[i] = (raw.value() * right_operand) == val; } else if constexpr (arith_op == proto::plan::ArithOpType::Div) { res[i] = (raw.value() / right_operand) == val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mod) { res[i] = (fmod(raw.value(), right_operand)) == val; } else { PanicInfo( OpTypeInvalid, fmt::format( "unsupported arith type:{} for ArithOpElementFunc", arith_op)); } } else if constexpr (cmp_op == proto::plan::OpType::NotEqual) { if constexpr (arith_op == proto::plan::ArithOpType::Add) { res[i] = (raw.value() + right_operand) != val; } else if constexpr (arith_op == proto::plan::ArithOpType::Sub) { res[i] = (raw.value() - right_operand) != val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mul) { res[i] = (raw.value() * right_operand) != val; } else if constexpr (arith_op == proto::plan::ArithOpType::Div) { res[i] = (raw.value() / right_operand) != val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mod) { res[i] = (fmod(raw.value(), right_operand)) != val; } else { PanicInfo( OpTypeInvalid, fmt::format( "unsupported arith type:{} for ArithOpElementFunc", arith_op)); } } else if constexpr (cmp_op == proto::plan::OpType::GreaterThan) { if constexpr (arith_op == proto::plan::ArithOpType::Add) { res[i] = (raw.value() + right_operand) > val; } else if constexpr (arith_op == proto::plan::ArithOpType::Sub) { res[i] = (raw.value() - right_operand) > val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mul) { res[i] = (raw.value() * right_operand) > val; } else if constexpr (arith_op == proto::plan::ArithOpType::Div) { res[i] = (raw.value() / right_operand) > val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mod) { res[i] = (fmod(raw.value(), right_operand)) > val; } else { PanicInfo( OpTypeInvalid, fmt::format( "unsupported arith type:{} for ArithOpElementFunc", arith_op)); } } else if constexpr (cmp_op == proto::plan::OpType::GreaterEqual) { if constexpr (arith_op == proto::plan::ArithOpType::Add) { res[i] = (raw.value() + right_operand) >= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Sub) { res[i] = (raw.value() - right_operand) >= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mul) { res[i] = (raw.value() * right_operand) >= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Div) { res[i] = (raw.value() / right_operand) >= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mod) { res[i] = (fmod(raw.value(), right_operand)) >= val; } else { PanicInfo( OpTypeInvalid, fmt::format( "unsupported arith type:{} for ArithOpElementFunc", arith_op)); } } else if constexpr (cmp_op == proto::plan::OpType::LessThan) { if constexpr (arith_op == proto::plan::ArithOpType::Add) { res[i] = (raw.value() + right_operand) < val; } else if constexpr (arith_op == proto::plan::ArithOpType::Sub) { res[i] = (raw.value() - right_operand) < val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mul) { res[i] = (raw.value() * right_operand) < val; } else if constexpr (arith_op == proto::plan::ArithOpType::Div) { res[i] = (raw.value() / right_operand) < val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mod) { res[i] = (fmod(raw.value(), right_operand)) < val; } else { PanicInfo( OpTypeInvalid, fmt::format( "unsupported arith type:{} for ArithOpElementFunc", arith_op)); } } else if constexpr (cmp_op == proto::plan::OpType::LessEqual) { if constexpr (arith_op == proto::plan::ArithOpType::Add) { res[i] = (raw.value() + right_operand) <= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Sub) { res[i] = (raw.value() - right_operand) <= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mul) { res[i] = (raw.value() * right_operand) <= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Div) { res[i] = (raw.value() / right_operand) <= val; } else if constexpr (arith_op == proto::plan::ArithOpType::Mod) { res[i] = (fmod(raw.value(), right_operand)) <= val; } else { PanicInfo( OpTypeInvalid, fmt::format( "unsupported arith type:{} for ArithOpElementFunc", arith_op)); } } } return res; } }; class PhyBinaryArithOpEvalRangeExpr : public SegmentExpr { public: PhyBinaryArithOpEvalRangeExpr( const std::vector>& input, const std::shared_ptr& expr, const std::string& name, const segcore::SegmentInternalInterface* segment, int64_t active_count, int64_t batch_size) : SegmentExpr(std::move(input), name, segment, expr->column_.field_id_, active_count, batch_size), expr_(expr) { } void Eval(EvalCtx& context, VectorPtr& result) override; private: template VectorPtr ExecRangeVisitorImpl(); template VectorPtr ExecRangeVisitorImplForIndex(); template VectorPtr ExecRangeVisitorImplForData(); template VectorPtr ExecRangeVisitorImplForJson(); template VectorPtr ExecRangeVisitorImplForArray(); private: std::shared_ptr expr_; }; } //namespace exec } // namespace milvus