From a4a369790b36b9497b19fbf108f99e1b11eeb700 Mon Sep 17 00:00:00 2001 From: Wang Zhiyong Date: Tue, 3 Dec 2024 13:02:31 +0800 Subject: [PATCH] add ReplaceNodeScanWithIndexSeek optimization rule (#801) add ReplaceNodeScanWithIndexSeek --- src/bolt/connection.cpp | 2 +- .../ops/op_node_by_label_scan.h | 2 + .../optimization_filter_visitor_impl.h | 744 ++++++++++++------ .../optimization/pass_manager.h | 4 +- .../optimization/property_filter_detector.h | 26 +- .../optimization/rewrite_label_scan.h | 172 ++++ src/cypher/parser/cypher_base_visitor_v2.cpp | 9 + src/cypher/utils/geax_util.h | 4 +- test/cypher_plan_validate.json | 23 +- test/graph_factory.h | 6 +- .../unit_test/query/cypher/query.result | 4 +- .../vector_index/cypher/vector_index.result | 2 +- 12 files changed, 724 insertions(+), 274 deletions(-) create mode 100644 src/cypher/execution_plan/optimization/rewrite_label_scan.h diff --git a/src/bolt/connection.cpp b/src/bolt/connection.cpp index 14ee0b7b34..9d1be0961b 100644 --- a/src/bolt/connection.cpp +++ b/src/bolt/connection.cpp @@ -250,7 +250,7 @@ void BoltConnection::WriteResponseDone(const boost::system::error_code& ec) { void BoltConnection::ReadChunkSizeDone(const boost::system::error_code& ec) { if (ec) { - LOG_WARN() << FMA_FMT("ReadChunkSizeDone error: {}", ec.message()); + // LOG_WARN() << FMA_FMT("ReadChunkSizeDone error: {}", ec.message()); Close(); return; } diff --git a/src/cypher/execution_plan/ops/op_node_by_label_scan.h b/src/cypher/execution_plan/ops/op_node_by_label_scan.h index 184757eff1..6303d230af 100644 --- a/src/cypher/execution_plan/ops/op_node_by_label_scan.h +++ b/src/cypher/execution_plan/ops/op_node_by_label_scan.h @@ -138,6 +138,8 @@ class NodeByLabelScan : public OpBase { const std::string& GetLabel() { return label_; } + const SymbolTable * GetSymtab() {return sym_tab_;} + CYPHER_DEFINE_VISITABLE() CYPHER_DEFINE_CONST_VISITABLE() diff --git a/src/cypher/execution_plan/optimization/optimization_filter_visitor_impl.h b/src/cypher/execution_plan/optimization/optimization_filter_visitor_impl.h index 7226660331..7085f5f620 100644 --- a/src/cypher/execution_plan/optimization/optimization_filter_visitor_impl.h +++ b/src/cypher/execution_plan/optimization/optimization_filter_visitor_impl.h @@ -20,413 +20,639 @@ namespace cypher { -class OptimizationFilterVisitorImpl : public cypher::AstNodeVisitorImpl { +class OptimizationFilterVisitorImpl : public geax::frontend::AstNodeVisitor { public: - OptimizationFilterVisitorImpl() {} + OptimizationFilterVisitorImpl() = default; - virtual ~OptimizationFilterVisitorImpl() {} + ~OptimizationFilterVisitorImpl() override = default; - private: - std::any visit(geax::frontend::AggFunc* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->expr()); - for (auto& expr : node->distinctBy()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(expr); - } - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; - } - - std::any visit(geax::frontend::AllDifferent* node) override { - for (auto item : node->items()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(item); - } - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any reportError() override { + return error_msg_; } - std::any visit(geax::frontend::BAdd* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + private: + std::any visit(geax::frontend::GetField* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BAggFunc* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->rExpr()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(std::get<1>(node->lExpr())); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::TupleGet* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BAnd* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::Not* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BBitAnd* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::Neg* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BBitLeftShift* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::Tilde* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BBitOr* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::VSome* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BBitRightShift* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BEqual* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BBitXor* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BNotEqual* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BConcat* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BGreaterThan* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BDiv* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BNotSmallerThan* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BEqual* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BSmallerThan* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BGreaterThan* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BNotGreaterThan* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BIn* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BSafeEqual* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BIndex* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BAdd* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BLike* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BSub* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BMod* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BDiv* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } std::any visit(geax::frontend::BMul* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BNotEqual* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BMod* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BNotGreaterThan* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BSquare* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BNotSmallerThan* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BAnd* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } std::any visit(geax::frontend::BOr* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BSafeEqual* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BXor* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BSmallerThan* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BBitAnd* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BSquare* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BBitOr* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BSub* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BBitXor* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::BXor* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BBitLeftShift* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::Case* node) override { - if (node->input().has_value()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->input().value()); - } - for (auto& case_body : node->caseBodies()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(std::get<0>(case_body)); - ACCEPT_AND_CHECK_WITH_PASS_MSG(std::get<1>(case_body)); - } - if (node->elseBody().has_value()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->elseBody().value()); - } - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BBitRightShift* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::Cast* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->expr()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BConcat* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::Exists* node) override { - for (auto path_chain : node->pathChains()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(path_chain); - } - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BIndex* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::Function* node) override { - for (auto& arg : node->args()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(arg); - } - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BLike* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::GetField* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->expr()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BIn* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } std::any visit(geax::frontend::If* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->condition()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->trueBody()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->falseBody()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::IsDestinationOf* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::Function* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::IsDirected* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->expr()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::Case* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::IsLabeled* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->expr()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->labelTree()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::Cast* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::IsNormalized* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->expr()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::MatchCase* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::IsNull* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->expr()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::AggFunc* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::IsSourceOf* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BAggFunc* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::ListComprehension* node) override { - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::MultiCount* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::MatchCase* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->input()); - for (auto& case_body : node->cases()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(std::get<0>(case_body)); - ACCEPT_AND_CHECK_WITH_PASS_MSG(std::get<1>(case_body)); - } - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::Windowing* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } std::any visit(geax::frontend::MkList* node) override { - for (auto elem : node->elems()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(elem); - } - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } std::any visit(geax::frontend::MkMap* node) override { - for (auto [elem1, elem2] : node->elems()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(elem1); - ACCEPT_AND_CHECK_WITH_PASS_MSG(elem2); - } - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } std::any visit(geax::frontend::MkRecord* node) override { - for (auto [elem1, elem2] : node->elems()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(elem2); - } - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } std::any visit(geax::frontend::MkSet* node) override { - for (auto elem : node->elems()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(elem); - } - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } std::any visit(geax::frontend::MkTuple* node) override { - for (auto elem : node->elems()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(elem); - } - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::MultiCount* node) override { - for (auto& arg : node->args()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(arg); - } - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::VBool* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::Neg* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->expr()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::VInt* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::Not* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->expr()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::VDouble* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::Param* node) override { - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::VString* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::VDate* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::VDatetime* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::VDuration* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::VTime* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::VNull* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::VNone* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } std::any visit(geax::frontend::Ref* node) override { - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::GraphPattern* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::PathPattern* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::PathChain* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::Node* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::Edge* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::ElementFiller* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::WhereClause* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::OrderByField* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::PathModePrefix* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::PathSearchPrefix* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::SingleLabel* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::LabelOr* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::LabelAnd* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::LabelNot* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::PropStruct* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::YieldField* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::TableFunctionClause* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::ReadConsistency* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::AllowAnonymousTable* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::OpConcurrent* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::EdgeOnJoin* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::SetAllProperties* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::SetLabel* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::IsNull* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::IsDirected* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::IsNormalized* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::IsSourceOf* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::IsDestinationOf* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::IsLabeled* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } std::any visit(geax::frontend::Same* node) override { - for (auto item : node->items()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(item); - } - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::Tilde* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->expr()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::AllDifferent* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::TupleGet* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->expr()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::Exists* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::VBool* node) override { - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::ProcedureBody* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::VDate* node) override { - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::SchemaFromPath* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::VDatetime* node) override { - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BindingValue* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::VDouble* node) override { - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BindingGraph* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::VDuration* node) override { - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::BindingTable* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::VInt* node) override { - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::StatementWithYield* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::VNone* node) override { - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::QueryStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::VNull* node) override { - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::JoinQueryExpression* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::VSome* node) override { - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->expr()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::JoinRightPart* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::VString* node) override { - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::CompositeQueryStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::VTime* node) override { - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::AmbientLinearQueryStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } - std::any visit(geax::frontend::Windowing* node) override { - for (auto expr : node->partitionBy()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(expr); - } - for (auto [expr, b] : node->orderByClause()) { - ACCEPT_AND_CHECK_WITH_PASS_MSG(expr); - } - ACCEPT_AND_CHECK_WITH_PASS_MSG(node->expr()); - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + std::any visit(geax::frontend::SelectStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::FocusedQueryStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::FocusedResultStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::MatchStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::FilterStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::PrimitiveResultStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::CatalogModifyStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::LinearDataModifyingStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::InsertStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::ReplaceStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::SetStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::DeleteStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::RemoveStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::OtherWise* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::Union* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::Except* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::Intersect* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::UpdateProperties* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::SetSingleProperty* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } + std::any visit(geax::frontend::RemoveSingleProperty* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::SetSchemaClause* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::SetGraphClause* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::SetTimeZoneClause* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::SetParamClause* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::ResetAll* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::ResetSchema* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::ResetTimeZone* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::ResetGraph* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::ResetParam* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::ExplainActivity* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::SessionActivity* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::TransactionActivity* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::FullTransaction* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::NormalTransaction* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::StartTransaction* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::CommitTransaction* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::RollBackTransaction* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::SessionSet* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::SessionReset* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::BindingTableInnerQuery* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::BindingTableInnerExpr* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::StandaloneCallStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::CallQueryStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::CallProcedureStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::InlineProcedureCall* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::NamedProcedureCall* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::ForStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::MergeStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::Param* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::ShowProcessListStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::KillStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::ManagerStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::UnwindStatement* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + std::any visit(geax::frontend::InQueryProcedureCall* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } std::any visit(geax::frontend::DummyNode* node) override { - return geax::frontend::GEAXErrorCode::GEAX_SUCCEED; + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; } + + std::any visit(geax::frontend::ListComprehension* node) override { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + + protected: + std::string error_msg_; }; } // namespace cypher diff --git a/src/cypher/execution_plan/optimization/pass_manager.h b/src/cypher/execution_plan/optimization/pass_manager.h index 8c546b4838..b0d440b951 100644 --- a/src/cypher/execution_plan/optimization/pass_manager.h +++ b/src/cypher/execution_plan/optimization/pass_manager.h @@ -29,6 +29,7 @@ #include "execution_plan/optimization/locate_node_by_indexed_prop_v2.h" #include "execution_plan/optimization/locate_node_by_prop_range_filter.h" #include "execution_plan/optimization/parallel_traversal_v2.h" +#include "execution_plan/optimization/rewrite_label_scan.h" namespace cypher { @@ -48,7 +49,8 @@ class PassManager { all_passes_.emplace_back(new ParallelTraversal()); all_passes_.emplace_back(new ParallelTraversalV2()); all_passes_.emplace_back(new LocateNodeByVidV2()); - all_passes_.emplace_back(new LocateNodeByIndexedPropV2()); + // all_passes_.emplace_back(new LocateNodeByIndexedPropV2()); + all_passes_.emplace_back(new ReplaceNodeScanWithIndexSeek(ctx)); all_passes_.emplace_back(new LocateNodeByPropRangeFilter()); } diff --git a/src/cypher/execution_plan/optimization/property_filter_detector.h b/src/cypher/execution_plan/optimization/property_filter_detector.h index 41bc2ce7c1..eff11e3f7f 100644 --- a/src/cypher/execution_plan/optimization/property_filter_detector.h +++ b/src/cypher/execution_plan/optimization/property_filter_detector.h @@ -23,7 +23,7 @@ class PropertyFilterDetector : public cypher::OptimizationFilterVisitorImpl { public: PropertyFilterDetector() : isValidDetector(false) {} - virtual ~PropertyFilterDetector() = default; + ~PropertyFilterDetector() override = default; bool Build(geax::frontend::AstNode* astNode) { try { @@ -49,14 +49,33 @@ class PropertyFilterDetector : public cypher::OptimizationFilterVisitorImpl { std::string cur_symbol_; std::string cur_field_; std::set cur_properties_; + bool has_and = false; + bool has_or = false; + + std::any visit(geax::frontend::BAnd* node) override { + if (has_or) { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + has_and = true; + ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); + ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); + return geax::frontend::GEAXErrorCode::GEAX_OPTIMIZATION_PASS; + } std::any visit(geax::frontend::BOr* node) override { + if (has_and) { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } + has_or = true; ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); return geax::frontend::GEAXErrorCode::GEAX_OPTIMIZATION_PASS; } std::any visit(geax::frontend::GetField* node) override { + if (has_or && !cur_field_.empty() && cur_field_ != node->fieldName()) { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } isValidDetector = true; cur_field_ = node->fieldName(); ACCEPT_AND_CHECK_WITH_PASS_MSG(node->expr()); @@ -64,11 +83,15 @@ class PropertyFilterDetector : public cypher::OptimizationFilterVisitorImpl { } std::any visit(geax::frontend::Ref* node) override { + if (has_or && !cur_symbol_.empty() && cur_symbol_ != node->name()) { + return geax::frontend::GEAXErrorCode::GEAX_COMMON_NOT_SUPPORT; + } cur_symbol_ = node->name(); return geax::frontend::GEAXErrorCode::GEAX_OPTIMIZATION_PASS; } std::any visit(geax::frontend::BEqual* node) override { + cur_properties_.clear(); ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); if (!cur_properties_.empty()) { @@ -87,6 +110,7 @@ class PropertyFilterDetector : public cypher::OptimizationFilterVisitorImpl { } std::any visit(geax::frontend::BIn* node) override { + cur_properties_.clear(); ACCEPT_AND_CHECK_WITH_PASS_MSG(node->left()); ACCEPT_AND_CHECK_WITH_PASS_MSG(node->right()); if (!cur_properties_.empty()) { diff --git a/src/cypher/execution_plan/optimization/rewrite_label_scan.h b/src/cypher/execution_plan/optimization/rewrite_label_scan.h new file mode 100644 index 0000000000..5699580290 --- /dev/null +++ b/src/cypher/execution_plan/optimization/rewrite_label_scan.h @@ -0,0 +1,172 @@ +/** +* Copyright 2022 AntGroup CO., Ltd. +* +* Licensed 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. +*/ + +#pragma once + +#include "tools/lgraph_log.h" +#include "core/data_type.h" +#include "cypher/execution_plan/ops/op_filter.h" +#include "cypher/execution_plan/ops/op_node_index_seek.h" +#include "cypher/execution_plan/ops/op_node_by_label_scan.h" +#include "cypher/execution_plan/optimization/opt_pass.h" +#include "cypher/execution_plan/optimization/property_filter_detector.h" + +namespace cypher { + +typedef std::unordered_map< + std::string, std::unordered_map< + std::string, std::set>> FilterCollections; + +class ReplaceNodeScanWithIndexSeek : public OptPass { + private: + RTContext *ctx_ = nullptr; + const lgraph::SchemaInfo *si_ = nullptr; + + void Impl(OpBase *root) { + OpBase *op_filter = nullptr; + FilterCollections filters; + if (FindNodePropFilter(root, op_filter, filters)) { + Replace(op_filter, filters); + } + } + + bool FindNodePropFilter(OpBase *root, OpBase *&op_filter, FilterCollections &filters) { + auto op = root; + if (op->type == OpType::FILTER) { + auto filter = dynamic_cast(op); + if (_CheckPropFilter(filter, filters)) { + op_filter = op; + return true; + } + } + + for (auto child : op->children) { + if (FindNodePropFilter(child, op_filter, filters)) return true; + } + + return false; + } + + void Replace(OpBase *root, FilterCollections &filter_collections) { + if (root->type == OpType::NODE_BY_LABEL_SCAN) { + auto scan = dynamic_cast(root); + auto label = scan->GetLabel(); + auto node = scan->GetNode(); + auto n = node->Alias(); + if (!filter_collections.count(n)) { + return; + } + auto& filters = filter_collections.at(n); + auto schema = si_->v_schema_manager.GetSchema(label); + if (!schema) { + return; + } + auto pk = schema->GetPrimaryField(); + if (filters.count(pk)) { + std::vector values; + for (auto& val : filters.at(pk)) { + values.push_back(val); + } + auto parent = root->parent; + auto op_node_index_seek = new NodeIndexSeek(node, scan->GetSymtab(), pk, values); + op_node_index_seek->parent = parent; + parent->RemoveChild(root); + OpBase::FreeStream(root); + parent->AddChild(op_node_index_seek); + return; + } + for (auto& [k, set] : filters) { + if (k == pk) { + continue; + } + if (!schema->TryGetFieldExtractor(k)->GetVertexIndex()) { + continue; + } + std::vector values; + for (auto& val : set) { + values.push_back(val); + } + auto parent = root->parent; + auto op_node_index_seek = new NodeIndexSeek(node, scan->GetSymtab(), k, values); + op_node_index_seek->parent = parent; + parent->RemoveChild(root); + OpBase::FreeStream(root); + parent->AddChild(op_node_index_seek); + return; + } + return; + } else if (root->type == OpType::ALL_NODE_SCAN) { + auto scan = dynamic_cast(root); + auto node = scan->GetNode(); + auto n = node->Alias(); + if (!filter_collections.count(n)) { + return; + } + const auto& filters = filter_collections.at(n); + if (filters.size() != 1) { + return; + } + std::vector values; + std::string field; + for (auto& [k, v] : filters) { + field = k; + for (auto &item : v) { + values.push_back(item); + } + break; + } + auto parent = root->parent; + auto op_node_index_seek = new NodeIndexSeek(node, scan->SymTab(), field, values); + op_node_index_seek->parent = parent; + parent->RemoveChild(root); + OpBase::FreeStream(root); + parent->AddChild(op_node_index_seek); + return; + } + for (auto child : root->children) { + Replace(child, filter_collections); + } + } + + bool _CheckPropFilter(OpFilter *&op_filter, FilterCollections &filters) { + auto filter = op_filter->Filter(); + CYPHER_THROW_ASSERT(filter->Type() == lgraph::Filter::GEAX_EXPR_FILTER); + auto geax_filter = ((lgraph::GeaxExprFilter *)filter.get())->GetArithExpr(); + geax::frontend::Expr *expr = geax_filter.expr_; + PropertyFilterDetector detector; + if (!detector.Build(expr)) return false; + filters = detector.GetProperties(); + if (filters.empty()) return false; + return true; + } + + public: + explicit ReplaceNodeScanWithIndexSeek(RTContext *ctx) + : OptPass(typeid(ReplaceNodeScanWithIndexSeek).name()), ctx_(ctx) {} + bool Gate() override { return true; } + int Execute(OpBase *root) override { + if (ctx_->graph_.empty()) { + return 0; + } + ctx_->ac_db_ = std::make_unique( + ctx_->galaxy_->OpenGraph(ctx_->user_, ctx_->graph_)); + lgraph_api::GraphDB db(ctx_->ac_db_.get(), true); + auto txn = db.CreateReadTxn(); + si_ = &txn.GetTxn()->GetSchemaInfo(); + Impl(root); + txn.Abort(); + return 0; + } +}; +} // namespace cypher diff --git a/src/cypher/parser/cypher_base_visitor_v2.cpp b/src/cypher/parser/cypher_base_visitor_v2.cpp index 2fc687bb4d..b79f762d43 100644 --- a/src/cypher/parser/cypher_base_visitor_v2.cpp +++ b/src/cypher/parser/cypher_base_visitor_v2.cpp @@ -133,6 +133,15 @@ void CypherBaseVisitorV2::PropertyExtractor(geax::frontend::ElementFiller *fille } } for (auto &label : labels) { + if (isVertex) { + if (!node_property_.count(label)) { + node_property_[label] = {}; + } + } else { + if (!rel_property_.count(label)) { + rel_property_[label] = {}; + } + } for (auto field : fields) { if (isVertex) { node_property_[label].emplace(field); diff --git a/src/cypher/utils/geax_util.h b/src/cypher/utils/geax_util.h index 70933a3ad4..181389131a 100644 --- a/src/cypher/utils/geax_util.h +++ b/src/cypher/utils/geax_util.h @@ -52,9 +52,7 @@ if (!ast) NOT_SUPPORT(); \ auto res = std::any_cast(ast->accept(*this)); \ if (res != geax::frontend::GEAXErrorCode::GEAX_OPTIMIZATION_PASS) { \ - auto error_msg = fma_common::StringFormatter::Format( \ - "visit({}) failed", std::string(#ast)); \ - throw lgraph::CypherException(error_msg); \ + return res; \ } \ } while (0) #endif diff --git a/test/cypher_plan_validate.json b/test/cypher_plan_validate.json index 5869805186..0a152b83db 100644 --- a/test/cypher_plan_validate.json +++ b/test/cypher_plan_validate.json @@ -35,12 +35,12 @@ }, { "query": "MATCH (n) where n.name in [\"Rachel Kempson\",\"Dennis Quaid\",\"none\"] RETURN n", - "plan": "ReadOnly:1\nExecution Plan:\nProduce Results\n Project [n]\n Node Index Seek [n] name IN [Dennis Quaid,Rachel Kempson,none,]\n", + "plan": "ReadOnly:1\nExecution Plan:\nProduce Results\n Project [n]\n Filter [n.name In {\"Rachel Kempson\", \"Dennis Quaid\", \"none\"}]\n Node Index Seek [n] name IN [Dennis Quaid,Rachel Kempson,none,]\n", "res": 2 }, { "query": "MATCH (n) where n.name =\"Rachel Kempson\" or n.name= \"Dennis Quaid\" or n.name=\"none\" RETURN n", - "plan": "ReadOnly:1\nExecution Plan:\nProduce Results\n Project [n]\n Node Index Seek [n] name IN [Dennis Quaid,Rachel Kempson,none,]\n", + "plan": "ReadOnly:1\nExecution Plan:\nProduce Results\n Project [n]\n Filter [(((n.name=\"Rachel Kempson\") or (n.name=\"Dennis Quaid\")) or (n.name=\"none\"))]\n Node Index Seek [n] name IN [Dennis Quaid,Rachel Kempson,none,]\n", "res": 2 }, { @@ -50,7 +50,7 @@ }, { "query": "MATCH (n) where n.name = \"Rachel Kempson\" or n.name = \"Dennis Quaid\" or n.name = \"Vanessa Redgrave\" RETURN n", - "plan": "ReadOnly:1\nExecution Plan:\nProduce Results\n Project [n]\n Node Index Seek [n] name IN [Dennis Quaid,Rachel Kempson,Vanessa Redgrave,]\n", + "plan": "ReadOnly:1\nExecution Plan:\nProduce Results\n Project [n]\n Filter [(((n.name=\"Rachel Kempson\") or (n.name=\"Dennis Quaid\")) or (n.name=\"Vanessa Redgrave\"))]\n Node Index Seek [n] name IN [Dennis Quaid,Rachel Kempson,Vanessa Redgrave,]\n", "res": 3 } ], @@ -163,6 +163,23 @@ "plan": "ReadOnly:1\nExecution Plan:\nProduce Results\n Project [p]\n Expand(All) [m --> n ]\n Expand(All) [m1 <-- m ]\n Node By Label Scan [m1:City]\n", "res": 9 } + ], + "index": [ + { + "query": "match (n:Person)-[r:BORN_IN]->(m:City) where n.name in ['Vanessa Redgrave'] return m", + "plan": "ReadOnly:1\nExecution Plan:\nProduce Results\n Project [m]\n Filter [n.name In {\"Vanessa Redgrave\"}]\n Expand(All) [n --> m ]\n Node Index Seek [n] name IN [Vanessa Redgrave,]\n", + "res": 1 + }, + { + "query": "match (n:Person)-[r:BORN_IN]->(m:City) where n.name in ['Vanessa Redgrave'] and n.birthyear in [1937] return m", + "plan": "ReadOnly:1\nExecution Plan:\nProduce Results\n Project [m]\n Filter [(n.name In {\"Vanessa Redgrave\"} and n.birthyear In {1937})]\n Expand(All) [n --> m ]\n Node Index Seek [n] name IN [Vanessa Redgrave,]\n", + "res": 1 + }, + { + "query": "match (n:Person)-[r:BORN_IN]->(m:City) where n.birthyear in [1937] return m", + "plan": "ReadOnly:1\nExecution Plan:\nProduce Results\n Project [m]\n Filter [n.birthyear In {1937}]\n Expand(All) [n --> m ]\n Node Index Seek [n] birthyear IN [1937,]\n", + "res": 1 + } ] } } diff --git a/test/graph_factory.h b/test/graph_factory.h index 51431420d7..9305e147b8 100644 --- a/test/graph_factory.h +++ b/test/graph_factory.h @@ -345,9 +345,9 @@ class GraphFactory { fma_common::OutputFmaStream stream; for (auto& kv : data) { const std::string& file_name = kv.first; - const std::string& data = kv.second; + const std::string& content = kv.second; stream.Open(file_name); - stream.Write(data.data(), data.size()); + stream.Write(content.data(), content.size()); stream.Close(); UT_LOG() << file_name << " created"; } @@ -370,7 +370,7 @@ R"( "primary" : "name", "properties" : [ {"name" : "name", "type":"STRING"}, - {"name" : "birthyear", "type":"INT16", "optional":true} + {"name" : "birthyear", "type":"INT16", "optional":true, "index":true, "unique":false} ] }, { diff --git a/test/resource/unit_test/query/cypher/query.result b/test/resource/unit_test/query/cypher/query.result index baafe02d6b..ee51c1560f 100644 --- a/test/resource/unit_test/query/cypher/query.result +++ b/test/resource/unit_test/query/cypher/query.result @@ -69,9 +69,9 @@ MATCH (n:Person)-[b:BORN_IN]->(m) WHERE (b.weight + b.weight) < 38.4 OR b.weight MATCH (a)-[e]->(b) WHERE a.name='Liam Neeson' and b.title<>'' and (e.charactername='Henri Ducard' or e.relation = '') RETURN a,e,b; [{"a":{"identity":4,"label":"Person","properties":{"birthyear":1952,"name":"Liam Neeson"}},"b":{"identity":17,"label":"Film","properties":{"title":"Batman Begins"}},"e":{"dst":17,"forward":false,"identity":0,"label":"ACTED_IN","label_id":5,"properties":{"charactername":"Henri Ducard"},"src":4,"temporal_id":0}}] MATCH (a) WHERE a.name IN ['Dennis Quaid', 'Christopher Nolan'] WITH a MATCH (b) WHERE b.name IN ['London'] RETURN a, b; -[{"a":{"identity":12,"label":"Person","properties":{"birthyear":1970,"name":"Christopher Nolan"}},"b":{"identity":14,"label":"City","properties":{"name":"London"}}},{"a":{"identity":7,"label":"Person","properties":{"birthyear":1954,"name":"Dennis Quaid"}},"b":{"identity":14,"label":"City","properties":{"name":"London"}}}] +[{"a":{"identity":7,"label":"Person","properties":{"birthyear":1954,"name":"Dennis Quaid"}},"b":{"identity":14,"label":"City","properties":{"name":"London"}}},{"a":{"identity":12,"label":"Person","properties":{"birthyear":1970,"name":"Christopher Nolan"}},"b":{"identity":14,"label":"City","properties":{"name":"London"}}}] MATCH (a) WHERE a.name IN ['Dennis Quaid', 'Christopher Nolan'] WITH a MATCH (b) WHERE b.name IN ['London', 'Beijing', 'Houston'] RETURN a, b; -[{"a":{"identity":12,"label":"Person","properties":{"birthyear":1970,"name":"Christopher Nolan"}},"b":{"identity":14,"label":"City","properties":{"name":"London"}}},{"a":{"identity":12,"label":"Person","properties":{"birthyear":1970,"name":"Christopher Nolan"}},"b":{"identity":15,"label":"City","properties":{"name":"Houston"}}},{"a":{"identity":7,"label":"Person","properties":{"birthyear":1954,"name":"Dennis Quaid"}},"b":{"identity":14,"label":"City","properties":{"name":"London"}}},{"a":{"identity":7,"label":"Person","properties":{"birthyear":1954,"name":"Dennis Quaid"}},"b":{"identity":15,"label":"City","properties":{"name":"Houston"}}}] +[{"a":{"identity":7,"label":"Person","properties":{"birthyear":1954,"name":"Dennis Quaid"}},"b":{"identity":14,"label":"City","properties":{"name":"London"}}},{"a":{"identity":7,"label":"Person","properties":{"birthyear":1954,"name":"Dennis Quaid"}},"b":{"identity":15,"label":"City","properties":{"name":"Houston"}}},{"a":{"identity":12,"label":"Person","properties":{"birthyear":1970,"name":"Christopher Nolan"}},"b":{"identity":14,"label":"City","properties":{"name":"London"}}},{"a":{"identity":12,"label":"Person","properties":{"birthyear":1970,"name":"Christopher Nolan"}},"b":{"identity":15,"label":"City","properties":{"name":"Houston"}}}] MATCH (n:Person) WHERE n.name = 'Vanessa Redgrave' OR NOT n.name <> 'Dennis Quaid' RETURN n.name; [{"n.name":"Dennis Quaid"},{"n.name":"Vanessa Redgrave"}] MATCH (n:Person {name:'Vanessa Redgrave'})-[:BORN_IN|ACTED_IN]->(m) RETURN m; diff --git a/test/resource/unit_test/vector_index/cypher/vector_index.result b/test/resource/unit_test/vector_index/cypher/vector_index.result index 67ca84a63e..b8692ca9cc 100644 --- a/test/resource/unit_test/vector_index/cypher/vector_index.result +++ b/test/resource/unit_test/vector_index/cypher/vector_index.result @@ -7,7 +7,7 @@ CALL db.addVertexVectorIndex('person','embedding2', {dimension:4}); CALL db.addVertexVectorIndex('person','name', {dimension:4}); [VectorIndexException] Only FLOAT_VECTOR type supports vector index CALL db.showVertexVectorIndex(); -[{"deleted_ids_num":0,"dimension":4,"distance_type":"l2","elements_num":0,"field_name":"embedding1","hnsw.ef_construction":100,"hnsw.m":16,"index_type":"hnsw","label_name":"person","memory_usage":380},{"deleted_ids_num":0,"dimension":4,"distance_type":"l2","elements_num":0,"field_name":"embedding2","hnsw.ef_construction":100,"hnsw.m":16,"index_type":"hnsw","label_name":"person","memory_usage":380}] +[{"deleted_ids_num":0,"dimension":4,"distance_type":"l2","elements_num":0,"field_name":"embedding1","hnsw.ef_construction":100,"hnsw.m":16,"index_type":"hnsw","label_name":"person","memory_usage":224},{"deleted_ids_num":0,"dimension":4,"distance_type":"l2","elements_num":0,"field_name":"embedding2","hnsw.ef_construction":100,"hnsw.m":16,"index_type":"hnsw","label_name":"person","memory_usage":224}] CREATE (n:person {id:1, name:'name1', embedding1: [1.0,1.0,1.0,1.0], embedding2: [11.0,11.0,11.0,11.0]}); [{"":"created 1 vertices, created 0 edges."}] CREATE (n:person {id:2, name:'name2', embedding1: [2.0,2.0,2.0,2.0], embedding2: [12.0,12.0,12.0,12.0]});