diff --git a/src/search/ir.h b/src/search/ir.h index af64588aa14..6f96c406bf3 100644 --- a/src/search/ir.h +++ b/src/search/ir.h @@ -48,6 +48,8 @@ struct Node { virtual NodeIterator ChildBegin() { return {}; }; virtual NodeIterator ChildEnd() { return {}; }; + virtual std::unique_ptr Clone() const = 0; + virtual ~Node() = default; template @@ -70,7 +72,9 @@ struct Node { } }; -struct FieldRef : Node { +struct Ref : Node {}; + +struct FieldRef : Ref { std::string name; explicit FieldRef(std::string name) : name(std::move(name)) {} @@ -78,9 +82,13 @@ struct FieldRef : Node { std::string_view Name() const override { return "FieldRef"; } std::string Dump() const override { return name; } std::string Content() const override { return Dump(); } + + std::unique_ptr Clone() const override { return std::make_unique(*this); } }; -struct StringLiteral : Node { +struct Literal : virtual Node {}; + +struct StringLiteral : Literal { std::string val; explicit StringLiteral(std::string val) : val(std::move(val)) {} @@ -88,9 +96,11 @@ struct StringLiteral : Node { std::string_view Name() const override { return "StringLiteral"; } std::string Dump() const override { return fmt::format("\"{}\"", util::EscapeString(val)); } std::string Content() const override { return Dump(); } + + std::unique_ptr Clone() const override { return std::make_unique(*this); } }; -struct QueryExpr : Node {}; +struct QueryExpr : virtual Node {}; struct BoolAtomExpr : QueryExpr {}; @@ -106,9 +116,14 @@ struct TagContainExpr : BoolAtomExpr { NodeIterator ChildBegin() override { return {field.get(), tag.get()}; }; NodeIterator ChildEnd() override { return {}; }; + + std::unique_ptr Clone() const override { + return std::make_unique(Node::MustAs(field->Clone()), + Node::MustAs(tag->Clone())); + } }; -struct NumericLiteral : Node { +struct NumericLiteral : Literal { double val; explicit NumericLiteral(double val) : val(val) {} @@ -116,6 +131,8 @@ struct NumericLiteral : Node { std::string_view Name() const override { return "NumericLiteral"; } std::string Dump() const override { return fmt::format("{}", val); } std::string Content() const override { return Dump(); } + + std::unique_ptr Clone() const override { return std::make_unique(*this); } }; // NOLINTNEXTLINE @@ -189,9 +206,14 @@ struct NumericCompareExpr : BoolAtomExpr { NodeIterator ChildBegin() override { return {field.get(), num.get()}; }; NodeIterator ChildEnd() override { return {}; }; + + std::unique_ptr Clone() const override { + return std::make_unique(op, Node::MustAs(field->Clone()), + Node::MustAs(num->Clone())); + } }; -struct BoolLiteral : BoolAtomExpr { +struct BoolLiteral : BoolAtomExpr, Literal { bool val; explicit BoolLiteral(bool val) : val(val) {} @@ -199,6 +221,8 @@ struct BoolLiteral : BoolAtomExpr { std::string_view Name() const override { return "BoolLiteral"; } std::string Dump() const override { return val ? "true" : "false"; } std::string Content() const override { return Dump(); } + + std::unique_ptr Clone() const override { return std::make_unique(*this); } }; struct QueryExpr; @@ -213,6 +237,10 @@ struct NotExpr : QueryExpr { NodeIterator ChildBegin() override { return NodeIterator{inner.get()}; }; NodeIterator ChildEnd() override { return {}; }; + + std::unique_ptr Clone() const override { + return std::make_unique(Node::MustAs(inner->Clone())); + } }; struct AndExpr : QueryExpr { @@ -227,6 +255,15 @@ struct AndExpr : QueryExpr { NodeIterator ChildBegin() override { return NodeIterator(inners.begin()); }; NodeIterator ChildEnd() override { return NodeIterator(inners.end()); }; + + std::unique_ptr Clone() const override { + std::vector> res; + res.reserve(inners.size()); + for (const auto &n : inners) { + res.push_back(Node::MustAs(n->Clone())); + } + return std::make_unique(std::move(res)); + } }; struct OrExpr : QueryExpr { @@ -241,6 +278,15 @@ struct OrExpr : QueryExpr { NodeIterator ChildBegin() override { return NodeIterator(inners.begin()); }; NodeIterator ChildEnd() override { return NodeIterator(inners.end()); }; + + std::unique_ptr Clone() const override { + std::vector> res; + res.reserve(inners.size()); + for (const auto &n : inners) { + res.push_back(Node::MustAs(n->Clone())); + } + return std::make_unique(std::move(res)); + } }; struct LimitClause : Node { @@ -252,6 +298,8 @@ struct LimitClause : Node { std::string_view Name() const override { return "LimitClause"; } std::string Dump() const override { return fmt::format("limit {}, {}", offset, count); } std::string Content() const override { return fmt::format("{}, {}", offset, count); } + + std::unique_ptr Clone() const override { return std::make_unique(*this); } }; struct SortByClause : Node { @@ -268,6 +316,10 @@ struct SortByClause : Node { NodeIterator ChildBegin() override { return NodeIterator(field.get()); }; NodeIterator ChildEnd() override { return {}; }; + + std::unique_ptr Clone() const override { + return std::make_unique(order, Node::MustAs(field->Clone())); + } }; struct SelectExpr : Node { @@ -283,9 +335,18 @@ struct SelectExpr : Node { NodeIterator ChildBegin() override { return NodeIterator(fields.begin()); }; NodeIterator ChildEnd() override { return NodeIterator(fields.end()); }; + + std::unique_ptr Clone() const override { + std::vector> res; + res.reserve(fields.size()); + for (const auto &f : fields) { + res.push_back(Node::MustAs(f->Clone())); + } + return std::make_unique(std::move(res)); + } }; -struct IndexRef : Node { +struct IndexRef : Ref { std::string name; explicit IndexRef(std::string name) : name(std::move(name)) {} @@ -293,6 +354,8 @@ struct IndexRef : Node { std::string_view Name() const override { return "IndexRef"; } std::string Dump() const override { return name; } std::string Content() const override { return Dump(); } + + std::unique_ptr Clone() const override { return std::make_unique(*this); } }; struct SearchStmt : Node { @@ -328,6 +391,13 @@ struct SearchStmt : Node { NodeIterator ChildBegin() override { return NodeIterator(this, ChildMap.begin()); }; NodeIterator ChildEnd() override { return NodeIterator(this, ChildMap.end()); }; + + std::unique_ptr Clone() const override { + return std::make_unique( + Node::MustAs(index->Clone()), Node::MustAs(query_expr->Clone()), + Node::MustAs(limit->Clone()), Node::MustAs(sort_by->Clone()), + Node::MustAs(select_expr->Clone())); + } }; } // namespace kqir diff --git a/src/search/ir_plan.h b/src/search/ir_plan.h index e718a33a26a..ebe2d6684fd 100644 --- a/src/search/ir_plan.h +++ b/src/search/ir_plan.h @@ -34,51 +34,77 @@ struct PlanOperator : Node {}; struct FullIndexScan : PlanOperator { IndexInfo *index; + explicit FullIndexScan(IndexInfo *index) : index(index) {} + std::string_view Name() const override { return "FullIndexScan"; }; std::string Content() const override { return index->name; }; std::string Dump() const override { return fmt::format("full-scan {}", Content()); } + + std::unique_ptr Clone() const override { return std::make_unique(*this); } }; struct FieldScan : PlanOperator { FieldInfo *field; + + explicit FieldScan(FieldInfo *field) : field(field) {} }; struct Interval { double l, r; // [l, r) + explicit Interval(double l, double r) : l(l), r(r) {} + std::string ToString() const { return fmt::format("[{}, {})", l, r); } }; struct NumericFieldScan : FieldScan { Interval range; + NumericFieldScan(FieldInfo *field, Interval range) : FieldScan(field), range(range) {} + std::string_view Name() const override { return "NumericFieldScan"; }; std::string Content() const override { return fmt::format("{}, {}", field->name, range.ToString()); }; std::string Dump() const override { return fmt::format("numeric-scan {}", Content()); } + + std::unique_ptr Clone() const override { return std::make_unique(*this); } }; struct TagFieldScan : FieldScan { std::string tag; + TagFieldScan(FieldInfo *field, std::string tag) : FieldScan(field), tag(std::move(tag)) {} + std::string_view Name() const override { return "TagFieldScan"; }; std::string Content() const override { return fmt::format("{}, {}", field->name, tag); }; std::string Dump() const override { return fmt::format("tag-scan {}", Content()); } + + std::unique_ptr Clone() const override { return std::make_unique(*this); } }; struct Filter : PlanOperator { std::unique_ptr source; std::unique_ptr filter_expr; + Filter(std::unique_ptr &&source, std::unique_ptr &&filter_expr) + : source(std::move(source)), filter_expr(std::move(filter_expr)) {} + std::string_view Name() const override { return "Filter"; }; std::string Dump() const override { return fmt::format("(filter {}, {})", source->Dump(), Content()); } NodeIterator ChildBegin() override { return {source.get(), filter_expr.get()}; } NodeIterator ChildEnd() override { return {}; } + + std::unique_ptr Clone() const override { + return std::make_unique(Node::MustAs(source->Clone()), + Node::MustAs(filter_expr->Clone())); + } }; struct Merge : PlanOperator { std::vector> ops; + explicit Merge(std::vector> &&ops) : ops(std::move(ops)) {} + std::string_view Name() const override { return "Merge"; }; std::string Dump() const override { return fmt::format("(merge {})", util::StringJoin(ops, [](const auto &v) { return v->Dump(); })); @@ -86,28 +112,54 @@ struct Merge : PlanOperator { NodeIterator ChildBegin() override { return NodeIterator(ops.begin()); } NodeIterator ChildEnd() override { return NodeIterator(ops.end()); } + + std::unique_ptr Clone() const override { + std::vector> res; + res.reserve(ops.size()); + for (const auto &op : ops) { + res.push_back(Node::MustAs(op->Clone())); + } + return std::make_unique(std::move(res)); + } }; struct Limit : PlanOperator { std::unique_ptr op; - size_t offset = 0, count = std::numeric_limits::max(); + std::unique_ptr limit; + + Limit(std::unique_ptr &&op, std::unique_ptr &&limit) + : op(std::move(op)), limit(std::move(limit)) {} std::string_view Name() const override { return "Limit"; }; - std::string Dump() const override { return fmt::format("(limit {}, {}: {})", offset, count, op->Dump()); } + std::string Dump() const override { + return fmt::format("(limit {}, {}: {})", limit->offset, limit->count, op->Dump()); + } - NodeIterator ChildBegin() override { return NodeIterator{op.get()}; } + NodeIterator ChildBegin() override { return NodeIterator{op.get(), limit.get()}; } NodeIterator ChildEnd() override { return {}; } + + std::unique_ptr Clone() const override { + return std::make_unique(Node::MustAs(op->Clone()), Node::MustAs(limit->Clone())); + } }; struct Projection : PlanOperator { std::unique_ptr source; std::unique_ptr select; + Projection(std::unique_ptr &&source, std::unique_ptr &&select) + : source(std::move(source)), select(std::move(select)) {} + std::string_view Name() const override { return "Projection"; }; std::string Dump() const override { return fmt::format("(project {}: {})", select, source); } NodeIterator ChildBegin() override { return {source.get(), select.get()}; } NodeIterator ChildEnd() override { return {}; } + + std::unique_ptr Clone() const override { + return std::make_unique(Node::MustAs(source->Clone()), + Node::MustAs(select->Clone())); + } }; } // namespace kqir