Compare commits

...

1 Commits

Author SHA1 Message Date
Josip Mrden
856b1dcb42 Add plan debugging options 2023-08-28 09:35:04 +02:00
4 changed files with 853 additions and 943 deletions

View File

@@ -25,6 +25,7 @@
#include "query/plan/rule_based_planner.hpp"
#include "query/plan/variable_start_planner.hpp"
#include "query/plan/vertex_count_cache.hpp"
#include "utils/logging.hpp"
namespace memgraph::query {
@@ -99,6 +100,11 @@ auto MakeLogicalPlan(TPlanningContext *context, TPlanPostProcess *post_process,
// it's ok to move it.
auto rewritten_plan = post_process->Rewrite(std::move(plan), context);
double cost = post_process->EstimatePlanCost(rewritten_plan, &vertex_counts, *context->symbol_table);
std::stringstream printed_plan;
plan::PrettyPrint(vertex_counts, &*rewritten_plan, &printed_plan);
spdlog::trace("{}", printed_plan.str());
if (!curr_plan || cost < total_cost) {
curr_plan.emplace(std::move(rewritten_plan));
total_cost = cost;

View File

@@ -19,282 +19,6 @@
namespace memgraph::query::plan {
PlanPrinter::PlanPrinter(const DbAccessor *dba, std::ostream *out) : dba_(dba), out_(out) {}
#define PRE_VISIT(TOp) \
bool PlanPrinter::PreVisit(TOp &) { \
WithPrintLn([](auto &out) { out << "* " << #TOp; }); \
return true; \
}
PRE_VISIT(CreateNode);
bool PlanPrinter::PreVisit(CreateExpand &op) {
WithPrintLn([&](auto &out) {
out << "* CreateExpand (" << op.input_symbol_.name() << ")"
<< (op.edge_info_.direction == query::EdgeAtom::Direction::IN ? "<-" : "-") << "["
<< op.edge_info_.symbol.name() << ":" << dba_->EdgeTypeToName(op.edge_info_.edge_type) << "]"
<< (op.edge_info_.direction == query::EdgeAtom::Direction::OUT ? "->" : "-") << "("
<< op.node_info_.symbol.name() << ")";
});
return true;
}
PRE_VISIT(Delete);
bool PlanPrinter::PreVisit(query::plan::ScanAll &op) {
WithPrintLn([&](auto &out) {
out << "* ScanAll"
<< " (" << op.output_symbol_.name() << ")";
});
return true;
}
bool PlanPrinter::PreVisit(query::plan::ScanAllByLabel &op) {
WithPrintLn([&](auto &out) {
out << "* ScanAllByLabel"
<< " (" << op.output_symbol_.name() << " :" << dba_->LabelToName(op.label_) << ")";
});
return true;
}
bool PlanPrinter::PreVisit(query::plan::ScanAllByLabelPropertyValue &op) {
WithPrintLn([&](auto &out) {
out << "* ScanAllByLabelPropertyValue"
<< " (" << op.output_symbol_.name() << " :" << dba_->LabelToName(op.label_) << " {"
<< dba_->PropertyToName(op.property_) << "})";
});
return true;
}
bool PlanPrinter::PreVisit(query::plan::ScanAllByLabelPropertyRange &op) {
WithPrintLn([&](auto &out) {
out << "* ScanAllByLabelPropertyRange"
<< " (" << op.output_symbol_.name() << " :" << dba_->LabelToName(op.label_) << " {"
<< dba_->PropertyToName(op.property_) << "})";
});
return true;
}
bool PlanPrinter::PreVisit(query::plan::ScanAllByLabelProperty &op) {
WithPrintLn([&](auto &out) {
out << "* ScanAllByLabelProperty"
<< " (" << op.output_symbol_.name() << " :" << dba_->LabelToName(op.label_) << " {"
<< dba_->PropertyToName(op.property_) << "})";
});
return true;
}
bool PlanPrinter::PreVisit(ScanAllById &op) {
WithPrintLn([&](auto &out) {
out << "* ScanAllById"
<< " (" << op.output_symbol_.name() << ")";
});
return true;
}
bool PlanPrinter::PreVisit(query::plan::Expand &op) {
WithPrintLn([&](auto &out) {
*out_ << "* Expand (" << op.input_symbol_.name() << ")"
<< (op.common_.direction == query::EdgeAtom::Direction::IN ? "<-" : "-") << "["
<< op.common_.edge_symbol.name();
utils::PrintIterable(*out_, op.common_.edge_types, "|", [this](auto &stream, const auto &edge_type) {
stream << ":" << dba_->EdgeTypeToName(edge_type);
});
*out_ << "]" << (op.common_.direction == query::EdgeAtom::Direction::OUT ? "->" : "-") << "("
<< op.common_.node_symbol.name() << ")";
});
return true;
}
bool PlanPrinter::PreVisit(query::plan::ExpandVariable &op) {
using Type = query::EdgeAtom::Type;
WithPrintLn([&](auto &out) {
*out_ << "* ";
switch (op.type_) {
case Type::DEPTH_FIRST:
*out_ << "ExpandVariable";
break;
case Type::BREADTH_FIRST:
*out_ << (op.common_.existing_node ? "STShortestPath" : "BFSExpand");
break;
case Type::WEIGHTED_SHORTEST_PATH:
*out_ << "WeightedShortestPath";
break;
case Type::ALL_SHORTEST_PATHS:
*out_ << "AllShortestPaths";
break;
case Type::SINGLE:
LOG_FATAL("Unexpected ExpandVariable::type_");
}
*out_ << " (" << op.input_symbol_.name() << ")"
<< (op.common_.direction == query::EdgeAtom::Direction::IN ? "<-" : "-") << "["
<< op.common_.edge_symbol.name();
utils::PrintIterable(*out_, op.common_.edge_types, "|", [this](auto &stream, const auto &edge_type) {
stream << ":" << dba_->EdgeTypeToName(edge_type);
});
*out_ << "]" << (op.common_.direction == query::EdgeAtom::Direction::OUT ? "->" : "-") << "("
<< op.common_.node_symbol.name() << ")";
});
return true;
}
bool PlanPrinter::PreVisit(query::plan::Produce &op) {
WithPrintLn([&](auto &out) {
out << "* Produce {";
utils::PrintIterable(out, op.named_expressions_, ", ", [](auto &out, const auto &nexpr) { out << nexpr->name_; });
out << "}";
});
return true;
}
PRE_VISIT(ConstructNamedPath);
PRE_VISIT(SetProperty);
PRE_VISIT(SetProperties);
PRE_VISIT(SetLabels);
PRE_VISIT(RemoveProperty);
PRE_VISIT(RemoveLabels);
PRE_VISIT(EdgeUniquenessFilter);
PRE_VISIT(Accumulate);
PRE_VISIT(EmptyResult);
PRE_VISIT(EvaluatePatternFilter);
bool PlanPrinter::PreVisit(query::plan::Aggregate &op) {
WithPrintLn([&](auto &out) {
out << "* Aggregate {";
utils::PrintIterable(out, op.aggregations_, ", ",
[](auto &out, const auto &aggr) { out << aggr.output_sym.name(); });
out << "} {";
utils::PrintIterable(out, op.remember_, ", ", [](auto &out, const auto &sym) { out << sym.name(); });
out << "}";
});
return true;
}
PRE_VISIT(Skip);
PRE_VISIT(Limit);
bool PlanPrinter::PreVisit(query::plan::OrderBy &op) {
WithPrintLn([&op](auto &out) {
out << "* OrderBy {";
utils::PrintIterable(out, op.output_symbols_, ", ", [](auto &out, const auto &sym) { out << sym.name(); });
out << "}";
});
return true;
}
bool PlanPrinter::PreVisit(query::plan::Merge &op) {
WithPrintLn([](auto &out) { out << "* Merge"; });
Branch(*op.merge_match_, "On Match");
Branch(*op.merge_create_, "On Create");
op.input_->Accept(*this);
return false;
}
bool PlanPrinter::PreVisit(query::plan::Optional &op) {
WithPrintLn([](auto &out) { out << "* Optional"; });
Branch(*op.optional_);
op.input_->Accept(*this);
return false;
}
PRE_VISIT(Unwind);
PRE_VISIT(Distinct);
bool PlanPrinter::PreVisit(query::plan::Union &op) {
WithPrintLn([&op](auto &out) {
out << "* Union {";
utils::PrintIterable(out, op.left_symbols_, ", ", [](auto &out, const auto &sym) { out << sym.name(); });
out << " : ";
utils::PrintIterable(out, op.right_symbols_, ", ", [](auto &out, const auto &sym) { out << sym.name(); });
out << "}";
});
Branch(*op.right_op_);
op.left_op_->Accept(*this);
return false;
}
bool PlanPrinter::PreVisit(query::plan::CallProcedure &op) {
WithPrintLn([&op](auto &out) {
out << "* CallProcedure<" << op.procedure_name_ << "> {";
utils::PrintIterable(out, op.result_symbols_, ", ", [](auto &out, const auto &sym) { out << sym.name(); });
out << "}";
});
return true;
}
bool PlanPrinter::PreVisit(query::plan::LoadCsv &op) {
WithPrintLn([&op](auto &out) { out << "* LoadCsv {" << op.row_var_.name() << "}"; });
return true;
}
bool PlanPrinter::Visit(query::plan::Once & /*op*/) {
WithPrintLn([](auto &out) { out << "* Once"; });
return true;
}
bool PlanPrinter::PreVisit(query::plan::Cartesian &op) {
WithPrintLn([&op](auto &out) {
out << "* Cartesian {";
utils::PrintIterable(out, op.left_symbols_, ", ", [](auto &out, const auto &sym) { out << sym.name(); });
out << " : ";
utils::PrintIterable(out, op.right_symbols_, ", ", [](auto &out, const auto &sym) { out << sym.name(); });
out << "}";
});
Branch(*op.right_op_);
op.left_op_->Accept(*this);
return false;
}
bool PlanPrinter::PreVisit(query::plan::Foreach &op) {
WithPrintLn([](auto &out) { out << "* Foreach"; });
Branch(*op.update_clauses_);
op.input_->Accept(*this);
return false;
}
bool PlanPrinter::PreVisit(query::plan::Filter &op) {
WithPrintLn([](auto &out) { out << "* Filter"; });
for (const auto &pattern_filter : op.pattern_filters_) {
Branch(*pattern_filter);
}
op.input_->Accept(*this);
return false;
}
bool PlanPrinter::PreVisit(query::plan::Apply &op) {
WithPrintLn([](auto &out) { out << "* Apply"; });
Branch(*op.subquery_);
op.input_->Accept(*this);
return false;
}
#undef PRE_VISIT
bool PlanPrinter::DefaultPreVisit() {
WithPrintLn([](auto &out) { out << "* Unknown operator!"; });
return true;
}
void PlanPrinter::Branch(query::plan::LogicalOperator &op, const std::string &branch_name) {
WithPrintLn([&](auto &out) { out << "|\\ " << branch_name; });
++depth_;
op.Accept(*this);
--depth_;
}
void PrettyPrint(const DbAccessor &dba, const LogicalOperator *plan_root, std::ostream *out) {
PlanPrinter printer(&dba, out);
// FIXME(mtomic): We should make visitors that take const arguments.
const_cast<LogicalOperator *>(plan_root)->Accept(printer);
}
nlohmann::json PlanToJson(const DbAccessor &dba, const LogicalOperator *plan_root) {
impl::PlanToJsonVisitor visitor(&dba);
// FIXME(mtomic): We should make visitors that take const arguments.
const_cast<LogicalOperator *>(plan_root)->Accept(visitor);
return visitor.output();
}
namespace impl {
///////////////////////////////////////////////////////////////////////////////
@@ -425,576 +149,6 @@ json ToJson(const Aggregate::Element &elem) {
}
////////////////////////// END HELPER FUNCTIONS ////////////////////////////////
bool PlanToJsonVisitor::Visit(Once &) {
json self;
self["name"] = "Once";
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(ScanAll &op) {
json self;
self["name"] = "ScanAll";
self["output_symbol"] = ToJson(op.output_symbol_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(ScanAllByLabel &op) {
json self;
self["name"] = "ScanAllByLabel";
self["label"] = ToJson(op.label_, *dba_);
self["output_symbol"] = ToJson(op.output_symbol_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(ScanAllByLabelPropertyRange &op) {
json self;
self["name"] = "ScanAllByLabelPropertyRange";
self["label"] = ToJson(op.label_, *dba_);
self["property"] = ToJson(op.property_, *dba_);
self["lower_bound"] = op.lower_bound_ ? ToJson(*op.lower_bound_) : json();
self["upper_bound"] = op.upper_bound_ ? ToJson(*op.upper_bound_) : json();
self["output_symbol"] = ToJson(op.output_symbol_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(ScanAllByLabelPropertyValue &op) {
json self;
self["name"] = "ScanAllByLabelPropertyValue";
self["label"] = ToJson(op.label_, *dba_);
self["property"] = ToJson(op.property_, *dba_);
self["expression"] = ToJson(op.expression_);
self["output_symbol"] = ToJson(op.output_symbol_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(ScanAllByLabelProperty &op) {
json self;
self["name"] = "ScanAllByLabelProperty";
self["label"] = ToJson(op.label_, *dba_);
self["property"] = ToJson(op.property_, *dba_);
self["output_symbol"] = ToJson(op.output_symbol_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(ScanAllById &op) {
json self;
self["name"] = "ScanAllById";
self["output_symbol"] = ToJson(op.output_symbol_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(CreateNode &op) {
json self;
self["name"] = "CreateNode";
self["node_info"] = ToJson(op.node_info_, *dba_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(CreateExpand &op) {
json self;
self["name"] = "CreateExpand";
self["input_symbol"] = ToJson(op.input_symbol_);
self["node_info"] = ToJson(op.node_info_, *dba_);
self["edge_info"] = ToJson(op.edge_info_, *dba_);
self["existing_node"] = op.existing_node_;
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Expand &op) {
json self;
self["name"] = "Expand";
self["input_symbol"] = ToJson(op.input_symbol_);
self["node_symbol"] = ToJson(op.common_.node_symbol);
self["edge_symbol"] = ToJson(op.common_.edge_symbol);
self["edge_types"] = ToJson(op.common_.edge_types, *dba_);
self["direction"] = ToString(op.common_.direction);
self["existing_node"] = op.common_.existing_node;
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(ExpandVariable &op) {
json self;
self["name"] = "ExpandVariable";
self["input_symbol"] = ToJson(op.input_symbol_);
self["node_symbol"] = ToJson(op.common_.node_symbol);
self["edge_symbol"] = ToJson(op.common_.edge_symbol);
self["edge_types"] = ToJson(op.common_.edge_types, *dba_);
self["direction"] = ToString(op.common_.direction);
self["type"] = ToString(op.type_);
self["is_reverse"] = op.is_reverse_;
self["lower_bound"] = op.lower_bound_ ? ToJson(op.lower_bound_) : json();
self["upper_bound"] = op.upper_bound_ ? ToJson(op.upper_bound_) : json();
self["existing_node"] = op.common_.existing_node;
self["filter_lambda"] = op.filter_lambda_.expression ? ToJson(op.filter_lambda_.expression) : json();
if (op.type_ == EdgeAtom::Type::WEIGHTED_SHORTEST_PATH || op.type_ == EdgeAtom::Type::ALL_SHORTEST_PATHS) {
self["weight_lambda"] = ToJson(op.weight_lambda_->expression);
self["total_weight_symbol"] = ToJson(*op.total_weight_);
}
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(ConstructNamedPath &op) {
json self;
self["name"] = "ConstructNamedPath";
self["path_symbol"] = ToJson(op.path_symbol_);
self["path_elements"] = ToJson(op.path_elements_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Filter &op) {
json self;
self["name"] = "Filter";
self["expression"] = ToJson(op.expression_);
op.input_->Accept(*this);
self["input"] = PopOutput();
for (auto pattern_idx = 0; pattern_idx < op.pattern_filters_.size(); pattern_idx++) {
auto pattern_filter_key = "pattern_filter" + std::to_string(pattern_idx + 1);
op.pattern_filters_[pattern_idx]->Accept(*this);
self[pattern_filter_key] = PopOutput();
}
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Produce &op) {
json self;
self["name"] = "Produce";
self["named_expressions"] = ToJson(op.named_expressions_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Delete &op) {
json self;
self["name"] = "Delete";
self["expressions"] = ToJson(op.expressions_);
self["detach"] = op.detach_;
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(SetProperty &op) {
json self;
self["name"] = "SetProperty";
self["property"] = ToJson(op.property_, *dba_);
self["lhs"] = ToJson(op.lhs_);
self["rhs"] = ToJson(op.rhs_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(SetProperties &op) {
json self;
self["name"] = "SetProperties";
self["input_symbol"] = ToJson(op.input_symbol_);
self["rhs"] = ToJson(op.rhs_);
switch (op.op_) {
case SetProperties::Op::UPDATE:
self["op"] = "update";
break;
case SetProperties::Op::REPLACE:
self["op"] = "replace";
break;
}
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(SetLabels &op) {
json self;
self["name"] = "SetLabels";
self["input_symbol"] = ToJson(op.input_symbol_);
self["labels"] = ToJson(op.labels_, *dba_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(RemoveProperty &op) {
json self;
self["name"] = "RemoveProperty";
self["property"] = ToJson(op.property_, *dba_);
self["lhs"] = ToJson(op.lhs_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(RemoveLabels &op) {
json self;
self["name"] = "RemoveLabels";
self["input_symbol"] = ToJson(op.input_symbol_);
self["labels"] = ToJson(op.labels_, *dba_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(EdgeUniquenessFilter &op) {
json self;
self["name"] = "EdgeUniquenessFilter";
self["expand_symbol"] = ToJson(op.expand_symbol_);
self["previous_symbols"] = ToJson(op.previous_symbols_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(EmptyResult &op) {
json self;
self["name"] = "EmptyResult";
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Accumulate &op) {
json self;
self["name"] = "Accumulate";
self["symbols"] = ToJson(op.symbols_);
self["advance_command"] = op.advance_command_;
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Aggregate &op) {
json self;
self["name"] = "Aggregate";
self["aggregations"] = ToJson(op.aggregations_);
self["group_by"] = ToJson(op.group_by_);
self["remember"] = ToJson(op.remember_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Skip &op) {
json self;
self["name"] = "Skip";
self["expression"] = ToJson(op.expression_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Limit &op) {
json self;
self["name"] = "Limit";
self["expression"] = ToJson(op.expression_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(OrderBy &op) {
json self;
self["name"] = "OrderBy";
for (auto i = 0; i < op.order_by_.size(); ++i) {
json json;
json["ordering"] = ToString(op.compare_.ordering_[i]);
json["expression"] = ToJson(op.order_by_[i]);
self["order_by"].push_back(json);
}
self["output_symbols"] = ToJson(op.output_symbols_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Merge &op) {
json self;
self["name"] = "Merge";
op.input_->Accept(*this);
self["input"] = PopOutput();
op.merge_match_->Accept(*this);
self["merge_match"] = PopOutput();
op.merge_create_->Accept(*this);
self["merge_create"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Optional &op) {
json self;
self["name"] = "Optional";
self["optional_symbols"] = ToJson(op.optional_symbols_);
op.input_->Accept(*this);
self["input"] = PopOutput();
op.optional_->Accept(*this);
self["optional"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Unwind &op) {
json self;
self["name"] = "Unwind";
self["output_symbol"] = ToJson(op.output_symbol_);
self["input_expression"] = ToJson(op.input_expression_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(query::plan::CallProcedure &op) {
json self;
self["name"] = "CallProcedure";
self["procedure_name"] = op.procedure_name_;
self["arguments"] = ToJson(op.arguments_);
self["result_fields"] = op.result_fields_;
self["result_symbols"] = ToJson(op.result_symbols_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(query::plan::LoadCsv &op) {
json self;
self["name"] = "LoadCsv";
if (op.file_) {
self["file"] = ToJson(op.file_);
}
if (op.with_header_) {
self["with_header"] = op.with_header_;
}
if (op.ignore_bad_) {
self["ignore_bad"] = op.ignore_bad_;
}
if (op.delimiter_) {
self["delimiter"] = ToJson(op.delimiter_);
}
if (op.quote_) {
self["quote"] = ToJson(op.quote_);
}
if (op.nullif_) {
self["nullif"] = ToJson(op.nullif_);
}
self["row_variable"] = ToJson(op.row_var_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Distinct &op) {
json self;
self["name"] = "Distinct";
self["value_symbols"] = ToJson(op.value_symbols_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Union &op) {
json self;
self["name"] = "Union";
self["union_symbols"] = ToJson(op.union_symbols_);
self["left_symbols"] = ToJson(op.left_symbols_);
self["right_symbols"] = ToJson(op.right_symbols_);
op.left_op_->Accept(*this);
self["left_op"] = PopOutput();
op.right_op_->Accept(*this);
self["right_op"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Cartesian &op) {
json self;
self["name"] = "Cartesian";
self["left_symbols"] = ToJson(op.left_symbols_);
self["right_symbols"] = ToJson(op.right_symbols_);
op.left_op_->Accept(*this);
self["left_op"] = PopOutput();
op.right_op_->Accept(*this);
self["right_op"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Foreach &op) {
json self;
self["name"] = "Foreach";
self["loop_variable_symbol"] = ToJson(op.loop_variable_symbol_);
self["expression"] = ToJson(op.expression_);
op.input_->Accept(*this);
self["input"] = PopOutput();
op.update_clauses_->Accept(*this);
self["update_clauses"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(EvaluatePatternFilter &op) {
json self;
self["name"] = "EvaluatePatternFilter";
self["output_symbol"] = ToJson(op.output_symbol_);
op.input_->Accept(*this);
self["input"] = PopOutput();
output_ = std::move(self);
return false;
}
bool PlanToJsonVisitor::PreVisit(Apply &op) {
json self;
self["name"] = "Apply";
op.input_->Accept(*this);
self["input"] = PopOutput();
op.subquery_->Accept(*this);
self["subquery"] = PopOutput();
output_ = std::move(self);
return false;
}
} // namespace impl
} // namespace memgraph::query::plan

File diff suppressed because it is too large Load Diff

View File

@@ -87,6 +87,12 @@ class VertexCountCache {
return db_->GetIndexStats(label, property);
}
const std::string &EdgeTypeToName(storage::EdgeTypeId type) const { return db_->EdgeTypeToName(type); }
const std::string &LabelToName(storage::LabelId label) const { return db_->LabelToName(label); }
const std::string &PropertyToName(storage::PropertyId prop) const { return db_->PropertyToName(prop); }
private:
typedef std::pair<storage::LabelId, storage::PropertyId> LabelPropertyKey;