From baa644e9b74161de0f3edd22f2c56884e3f59ee8 Mon Sep 17 00:00:00 2001 From: Teon Banek Date: Thu, 16 Mar 2017 09:45:55 +0100 Subject: [PATCH] Support creating NodeFilter and CreateOp logical operators Reviewers: mislav.bradac, buda, florijan Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D133 --- CMakeLists.txt | 1 + src/query/entry.hpp | 2 +- src/query/frontend/logical/planner.cpp | 78 ++++++++++++++++++++ src/query/frontend/logical/planner.hpp | 70 ++---------------- src/query/frontend/semantic/symbol_table.hpp | 5 +- 5 files changed, 91 insertions(+), 65 deletions(-) create mode 100644 src/query/frontend/logical/planner.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ca6418691..62d653d48 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -353,6 +353,7 @@ set(memgraph_src_files ${src_dir}/query/frontend/ast/cypher_main_visitor.cpp ${src_dir}/query/context.cpp ${src_dir}/query/backend/cpp/typed_value.cpp + ${src_dir}/query/frontend/logical/planner.cpp ) # ----------------------------------------------------------------------------- diff --git a/src/query/entry.hpp b/src/query/entry.hpp index 347c576eb..993111fe4 100644 --- a/src/query/entry.hpp +++ b/src/query/entry.hpp @@ -59,7 +59,7 @@ class Engine { query.Accept(symbol_generator); // high level tree -> logical plan - auto logical_plan = MakeLogicalPlan(query); + auto logical_plan = MakeLogicalPlan(query, symbol_table); // generate frame based on symbol table max_position Frame frame(symbol_table.max_position()); diff --git a/src/query/frontend/logical/planner.cpp b/src/query/frontend/logical/planner.cpp new file mode 100644 index 000000000..34f115acf --- /dev/null +++ b/src/query/frontend/logical/planner.cpp @@ -0,0 +1,78 @@ +#include "query/frontend/logical/planner.hpp" + +#include "query/frontend/ast/ast.hpp" +#include "utils/exceptions/not_yet_implemented.hpp" + +namespace query { + +static LogicalOperator *GenCreate( + Create& create, std::shared_ptr input_op) +{ + if (input_op) { + throw NotYetImplemented(); + } + if (create.patterns_.size() != 1) { + throw NotYetImplemented(); + } + auto &pattern = create.patterns_[0]; + if (pattern->atoms_.size() != 1) { + throw NotYetImplemented(); + } + auto node_atom = std::dynamic_pointer_cast(pattern->atoms_[0]); + return new CreateOp(node_atom); +} + +static LogicalOperator *GenMatch( + Match& match, + std::shared_ptr input_op, + const SymbolTable &symbol_table) +{ + if (input_op) { + throw NotYetImplemented(); + } + if (match.patterns_.size() != 1) { + throw NotYetImplemented(); + } + auto &pattern = match.patterns_[0]; + if (pattern->atoms_.size() != 1) { + throw NotYetImplemented(); + } + auto node_atom = std::dynamic_pointer_cast(pattern->atoms_[0]); + auto *scan_all = new ScanAll(node_atom); + if (!node_atom->labels_.empty() || !node_atom->properties_.empty()) { + auto &input_symbol = symbol_table.at(*node_atom->identifier_); + return new NodeFilter(std::shared_ptr(scan_all), input_symbol, + node_atom->labels_, node_atom->properties_); + } + return scan_all; +} + +static Produce *GenReturn(Return& ret, std::shared_ptr input_op) +{ + if (!input_op) { + throw NotYetImplemented(); + } + return new Produce(input_op, ret.named_expressions_); +} + +std::unique_ptr MakeLogicalPlan( + Query& query, const SymbolTable &symbol_table) +{ + LogicalOperator *input_op = nullptr; + for (auto &clause : query.clauses_) { + auto *clause_ptr = clause.get(); + if (auto *match = dynamic_cast(clause_ptr)) { + input_op = GenMatch(*match, std::shared_ptr(input_op), + symbol_table); + } else if (auto *ret = dynamic_cast(clause_ptr)) { + input_op = GenReturn(*ret, std::shared_ptr(input_op)); + } else if (auto *create = dynamic_cast(clause_ptr)) { + input_op = GenCreate(*create, std::shared_ptr(input_op)); + } else { + throw NotYetImplemented(); + } + } + return std::unique_ptr(input_op); +} + +} diff --git a/src/query/frontend/logical/planner.hpp b/src/query/frontend/logical/planner.hpp index 013e37f89..d9d03cbf5 100644 --- a/src/query/frontend/logical/planner.hpp +++ b/src/query/frontend/logical/planner.hpp @@ -1,74 +1,18 @@ #pragma once #include -#include -#include "query/frontend/ast/ast.hpp" #include "query/frontend/logical/operator.hpp" namespace query { -std::shared_ptr GenCreate( - Create& match, std::shared_ptr current_op) -{ - if (current_op) { - throw std::runtime_error("Not implemented"); - } - if (match.patterns_.size() != 1) { - throw std::runtime_error("Not implemented"); - } - auto& pattern = match.patterns_[0]; - if (pattern->atoms_.size() != 1) { - throw std::runtime_error("Not implemented"); - } - auto node_atom = std::dynamic_pointer_cast(pattern->atoms_[0]); - return std::make_shared(node_atom); -} +class Query; +class SymbolTable; -std::shared_ptr GenMatch( - Match& match, std::shared_ptr current_op) -{ - if (current_op) { - throw std::runtime_error("Not implemented"); - } - if (match.patterns_.size() != 1) { - throw std::runtime_error("Not implemented"); - } - auto& pattern = match.patterns_[0]; - if (pattern->atoms_.size() != 1) { - throw std::runtime_error("Not implemented"); - } - auto node_atom = std::dynamic_pointer_cast(pattern->atoms_[0]); - return std::make_shared(node_atom); -} +// Returns the root of LogicalOperator tree. The tree is constructed by +// traversing the given AST Query node. SymbolTable is used to determine inputs +// and outputs of certain operators. +std::unique_ptr MakeLogicalPlan( + Query& query, const SymbolTable &symbol_table); -std::shared_ptr GenReturn( - Return& ret, std::shared_ptr current_op) -{ - if (!current_op) { - throw std::runtime_error("Not implemented"); - } - return std::make_shared(current_op, ret.named_expressions_); -} - -std::shared_ptr MakeLogicalPlan(Query& query) -{ - std::shared_ptr current_op; - for (auto& clause : query.clauses_) { - auto* clause_ptr = clause.get(); - auto* create = dynamic_cast(clause_ptr); - auto* match = dynamic_cast(clause_ptr); - auto* ret = dynamic_cast(clause_ptr); - if (create) { - current_op = GenCreate(*create, current_op); - } else if (match) { - current_op = GenMatch(*match, current_op); - } else if (ret) { - return GenReturn(*ret, current_op); - } else { - throw std::runtime_error("Not implemented"); - } - } - return current_op; -} } diff --git a/src/query/frontend/semantic/symbol_table.hpp b/src/query/frontend/semantic/symbol_table.hpp index 515747176..f2061dbba 100644 --- a/src/query/frontend/semantic/symbol_table.hpp +++ b/src/query/frontend/semantic/symbol_table.hpp @@ -28,7 +28,10 @@ class SymbolTable { return Symbol(name, position); } - auto& operator[](const Tree& tree) { return table_[tree.uid()]; } + auto &operator[](const Tree& tree) { return table_[tree.uid()]; } + + auto &at(const Tree& tree) { return table_.at(tree.uid()); } + const auto &at(const Tree& tree) const { return table_.at(tree.uid()); } int max_position() const { return position_; }