Support creating NodeFilter and CreateOp logical operators

Reviewers: mislav.bradac, buda, florijan

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D133
This commit is contained in:
Teon Banek 2017-03-16 09:45:55 +01:00
parent da0c9c03d6
commit baa644e9b7
5 changed files with 91 additions and 65 deletions

View File

@ -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
)
# -----------------------------------------------------------------------------

View File

@ -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());

View File

@ -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<LogicalOperator> 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<NodeAtom>(pattern->atoms_[0]);
return new CreateOp(node_atom);
}
static LogicalOperator *GenMatch(
Match& match,
std::shared_ptr<LogicalOperator> 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<NodeAtom>(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<LogicalOperator>(scan_all), input_symbol,
node_atom->labels_, node_atom->properties_);
}
return scan_all;
}
static Produce *GenReturn(Return& ret, std::shared_ptr<LogicalOperator> input_op)
{
if (!input_op) {
throw NotYetImplemented();
}
return new Produce(input_op, ret.named_expressions_);
}
std::unique_ptr<LogicalOperator> 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<Match*>(clause_ptr)) {
input_op = GenMatch(*match, std::shared_ptr<LogicalOperator>(input_op),
symbol_table);
} else if (auto *ret = dynamic_cast<Return*>(clause_ptr)) {
input_op = GenReturn(*ret, std::shared_ptr<LogicalOperator>(input_op));
} else if (auto *create = dynamic_cast<Create*>(clause_ptr)) {
input_op = GenCreate(*create, std::shared_ptr<LogicalOperator>(input_op));
} else {
throw NotYetImplemented();
}
}
return std::unique_ptr<LogicalOperator>(input_op);
}
}

View File

@ -1,74 +1,18 @@
#pragma once
#include <memory>
#include <stdexcept>
#include "query/frontend/ast/ast.hpp"
#include "query/frontend/logical/operator.hpp"
namespace query {
std::shared_ptr<LogicalOperator> GenCreate(
Create& match, std::shared_ptr<LogicalOperator> 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<NodeAtom>(pattern->atoms_[0]);
return std::make_shared<CreateOp>(node_atom);
}
class Query;
class SymbolTable;
std::shared_ptr<LogicalOperator> GenMatch(
Match& match, std::shared_ptr<LogicalOperator> 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<NodeAtom>(pattern->atoms_[0]);
return std::make_shared<ScanAll>(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<LogicalOperator> MakeLogicalPlan(
Query& query, const SymbolTable &symbol_table);
std::shared_ptr<LogicalOperator> GenReturn(
Return& ret, std::shared_ptr<LogicalOperator> current_op)
{
if (!current_op) {
throw std::runtime_error("Not implemented");
}
return std::make_shared<Produce>(current_op, ret.named_expressions_);
}
std::shared_ptr<LogicalOperator> MakeLogicalPlan(Query& query)
{
std::shared_ptr<LogicalOperator> current_op;
for (auto& clause : query.clauses_) {
auto* clause_ptr = clause.get();
auto* create = dynamic_cast<Create*>(clause_ptr);
auto* match = dynamic_cast<Match*>(clause_ptr);
auto* ret = dynamic_cast<Return*>(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;
}
}

View File

@ -30,6 +30,9 @@ class SymbolTable {
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_; }
private: