ExecExprVisitor.cpp 8.3 KB
Newer Older
G
GuoRentong 已提交
1
#include "segcore/SegmentSmallIndex.h"
N
neza2017 已提交
2
#include <optional>
G
GuoRentong 已提交
3
#include "query/ExprImpl.h"
4
#include "boost/dynamic_bitset.hpp"
N
neza2017 已提交
5 6 7 8 9 10 11 12 13
#include "query/generated/ExecExprVisitor.h"

namespace milvus::query {
#if 1
// THIS CONTAINS EXTRA BODY FOR VISITOR
// WILL BE USED BY GENERATOR
namespace impl {
class ExecExprVisitor : ExprVisitor {
 public:
14
    using RetType = std::deque<boost::dynamic_bitset<>>;
G
GuoRentong 已提交
15
    explicit ExecExprVisitor(segcore::SegmentSmallIndex& segment) : segment_(segment) {
N
neza2017 已提交
16 17 18 19 20 21 22 23 24 25 26
    }
    RetType
    call_child(Expr& expr) {
        Assert(!ret_.has_value());
        expr.accept(*this);
        Assert(ret_.has_value());
        auto ret = std::move(ret_);
        ret_ = std::nullopt;
        return std::move(ret.value());
    }

G
GuoRentong 已提交
27 28 29 30 31 32 33 34 35
 public:
    template <typename Tp, typename Func>
    auto
    ExecRangeVisitorImpl(RangeExprImpl<Tp>& expr_scp, Func func) -> RetType;

    template <typename T>
    auto
    ExecRangeVisitorDispatcher(RangeExpr& expr_raw) -> RetType;

N
neza2017 已提交
36
 private:
G
GuoRentong 已提交
37
    segcore::SegmentSmallIndex& segment_;
N
neza2017 已提交
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
    std::optional<RetType> ret_;
};
}  // namespace impl
#endif

void
ExecExprVisitor::visit(BoolUnaryExpr& expr) {
    PanicInfo("unimplemented");
}

void
ExecExprVisitor::visit(BoolBinaryExpr& expr) {
    PanicInfo("unimplemented");
}

void
ExecExprVisitor::visit(TermExpr& expr) {
    PanicInfo("unimplemented");
}

F
FluorineDog 已提交
58
template <typename T, typename IndexFunc, typename ElementFunc>
G
GuoRentong 已提交
59
auto
F
FluorineDog 已提交
60 61
ExecExprVisitor::ExecRangeVisitorImpl(RangeExprImpl<T>& expr, IndexFunc index_func, ElementFunc element_func)
    -> RetType {
G
GuoRentong 已提交
62 63 64 65 66 67 68 69 70
    auto& records = segment_.get_insert_record();
    auto data_type = expr.data_type_;
    auto& schema = segment_.get_schema();
    auto field_offset_opt = schema.get_offset(expr.field_id_);
    Assert(field_offset_opt);
    auto field_offset = field_offset_opt.value();
    auto& field_meta = schema[field_offset];
    auto vec_ptr = records.get_scalar_entity<T>(field_offset);
    auto& vec = *vec_ptr;
F
FluorineDog 已提交
71 72 73
    auto& indexing_record = segment_.get_indexing_record();
    const segcore::ScalarIndexingEntry<T>& entry = indexing_record.get_scalar_entry<T>(field_offset);

74
    RetType results(vec.chunk_size());
F
FluorineDog 已提交
75 76 77 78 79 80 81 82 83 84
    auto indexing_barrier = indexing_record.get_finished_ack();
    for (auto chunk_id = 0; chunk_id < indexing_barrier; ++chunk_id) {
        auto& result = results[chunk_id];
        auto indexing = entry.get_indexing(chunk_id);
        auto data = index_func(indexing);
        result = ~std::move(*data);
        Assert(result.size() == segcore::DefaultElementPerChunk);
    }

    for (auto chunk_id = indexing_barrier; chunk_id < vec.chunk_size(); ++chunk_id) {
G
GuoRentong 已提交
85 86 87 88 89
        auto& result = results[chunk_id];
        result.resize(segcore::DefaultElementPerChunk);
        auto chunk = vec.get_chunk(chunk_id);
        const T* data = chunk.data();
        for (int index = 0; index < segcore::DefaultElementPerChunk; ++index) {
F
FluorineDog 已提交
90
            result[index] = element_func(data[index]);
G
GuoRentong 已提交
91
        }
F
FluorineDog 已提交
92
        Assert(result.size() == segcore::DefaultElementPerChunk);
G
GuoRentong 已提交
93 94 95 96 97 98 99 100 101 102 103 104 105
    }
    return results;
}

#pragma clang diagnostic push
#pragma ide diagnostic ignored "Simplify"
template <typename T>
auto
ExecExprVisitor::ExecRangeVisitorDispatcher(RangeExpr& expr_raw) -> RetType {
    auto& expr = static_cast<RangeExprImpl<T>&>(expr_raw);
    auto conditions = expr.conditions_;
    std::sort(conditions.begin(), conditions.end());
    using OpType = RangeExpr::OpType;
F
FluorineDog 已提交
106 107
    using Index = knowhere::scalar::StructuredIndex<T>;
    using Operator = knowhere::scalar::OperatorType;
G
GuoRentong 已提交
108 109 110 111 112 113 114
    if (conditions.size() == 1) {
        auto cond = conditions[0];
        // auto [op, val] = cond; // strange bug on capture
        auto op = std::get<0>(cond);
        auto val = std::get<1>(cond);
        switch (op) {
            case OpType::Equal: {
F
FluorineDog 已提交
115 116
                auto index_func = [val](Index* index) { return index->In(1, &val); };
                return ExecRangeVisitorImpl(expr, index_func, [val](T x) { return !(x == val); });
G
GuoRentong 已提交
117 118 119
            }

            case OpType::NotEqual: {
F
FluorineDog 已提交
120 121 122 123 124 125 126 127
                auto index_func = [val](Index* index) {
                    // Note: index->NotIn() is buggy, investigating
                    // this is a workaround
                    auto res = index->In(1, &val);
                    *res = ~std::move(*res);
                    return res;
                };
                return ExecRangeVisitorImpl(expr, index_func, [val](T x) { return !(x != val); });
G
GuoRentong 已提交
128 129 130
            }

            case OpType::GreaterEqual: {
F
FluorineDog 已提交
131 132
                auto index_func = [val](Index* index) { return index->Range(val, Operator::GE); };
                return ExecRangeVisitorImpl(expr, index_func, [val](T x) { return !(x >= val); });
G
GuoRentong 已提交
133 134 135
            }

            case OpType::GreaterThan: {
F
FluorineDog 已提交
136 137
                auto index_func = [val](Index* index) { return index->Range(val, Operator::GT); };
                return ExecRangeVisitorImpl(expr, index_func, [val](T x) { return !(x > val); });
G
GuoRentong 已提交
138 139 140
            }

            case OpType::LessEqual: {
F
FluorineDog 已提交
141 142
                auto index_func = [val](Index* index) { return index->Range(val, Operator::LE); };
                return ExecRangeVisitorImpl(expr, index_func, [val](T x) { return !(x <= val); });
G
GuoRentong 已提交
143 144 145
            }

            case OpType::LessThan: {
F
FluorineDog 已提交
146 147
                auto index_func = [val](Index* index) { return index->Range(val, Operator::LT); };
                return ExecRangeVisitorImpl(expr, index_func, [val](T x) { return !(x < val); });
G
GuoRentong 已提交
148 149 150 151 152 153 154 155 156 157 158 159 160 161
            }
            default: {
                PanicInfo("unsupported range node");
            }
        }
    } else if (conditions.size() == 2) {
        OpType op1, op2;
        T val1, val2;
        std::tie(op1, val1) = conditions[0];
        std::tie(op2, val2) = conditions[1];
        Assert(val1 <= val2);
        auto ops = std::make_tuple(op1, op2);
        if (false) {
        } else if (ops == std::make_tuple(OpType::GreaterThan, OpType::LessThan)) {
F
FluorineDog 已提交
162 163
            auto index_func = [val1, val2](Index* index) { return index->Range(val1, false, val2, false); };
            return ExecRangeVisitorImpl(expr, index_func, [val1, val2](T x) { return !(val1 < x && x < val2); });
G
GuoRentong 已提交
164
        } else if (ops == std::make_tuple(OpType::GreaterThan, OpType::LessEqual)) {
F
FluorineDog 已提交
165 166
            auto index_func = [val1, val2](Index* index) { return index->Range(val1, false, val2, true); };
            return ExecRangeVisitorImpl(expr, index_func, [val1, val2](T x) { return !(val1 < x && x <= val2); });
G
GuoRentong 已提交
167
        } else if (ops == std::make_tuple(OpType::GreaterEqual, OpType::LessThan)) {
F
FluorineDog 已提交
168 169
            auto index_func = [val1, val2](Index* index) { return index->Range(val1, true, val2, false); };
            return ExecRangeVisitorImpl(expr, index_func, [val1, val2](T x) { return !(val1 <= x && x < val2); });
G
GuoRentong 已提交
170
        } else if (ops == std::make_tuple(OpType::GreaterEqual, OpType::LessEqual)) {
F
FluorineDog 已提交
171 172
            auto index_func = [val1, val2](Index* index) { return index->Range(val1, true, val2, true); };
            return ExecRangeVisitorImpl(expr, index_func, [val1, val2](T x) { return !(val1 <= x && x <= val2); });
G
GuoRentong 已提交
173 174 175 176 177 178 179 180 181
        } else {
            PanicInfo("unsupported range node");
        }
    } else {
        PanicInfo("unsupported range node");
    }
}
#pragma clang diagnostic pop

N
neza2017 已提交
182 183
void
ExecExprVisitor::visit(RangeExpr& expr) {
G
GuoRentong 已提交
184 185 186 187 188 189 190 191
    auto& field_meta = segment_.get_schema()[expr.field_id_];
    Assert(expr.data_type_ == field_meta.get_data_type());
    RetType ret;
    switch (expr.data_type_) {
        // case DataType::BOOL: {
        //    ret = ExecRangeVisitorDispatcher<bool>(expr);
        //    break;
        //}
F
FluorineDog 已提交
192
        // case DataType::BOOL:
G
GuoRentong 已提交
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
        case DataType::INT8: {
            ret = ExecRangeVisitorDispatcher<int8_t>(expr);
            break;
        }
        case DataType::INT16: {
            ret = ExecRangeVisitorDispatcher<int16_t>(expr);
            break;
        }
        case DataType::INT32: {
            ret = ExecRangeVisitorDispatcher<int32_t>(expr);
            break;
        }
        case DataType::INT64: {
            ret = ExecRangeVisitorDispatcher<int64_t>(expr);
            break;
        }
        case DataType::FLOAT: {
            ret = ExecRangeVisitorDispatcher<float>(expr);
            break;
        }
        case DataType::DOUBLE: {
            ret = ExecRangeVisitorDispatcher<double>(expr);
            break;
        }
        default:
            PanicInfo("unsupported");
    }
    ret_ = std::move(ret);
N
neza2017 已提交
221 222 223
}

}  // namespace milvus::query