Extract QueryVisitor from HierarchicalTreeVisitor
Summary: This change makes HierarchicalTreeVisitor visit only Cypher related AST nodes. QueryVisitor can be used to differentiate between various query types we have. The next step is to either rename HierarchicalTreeVisitor to something like CypherQueryVisitor, or perhaps extract Clause visiting from it. Reviewers: mtomic, llugovic Reviewed By: llugovic Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1710
This commit is contained in:
parent
bbe095d41a
commit
5df4d55ec1
@ -63,9 +63,7 @@ std::unique_ptr<LogicalPlan> DistributedInterpreter::MakeLogicalPlan(
|
||||
database::GraphDbAccessor *db_accessor) {
|
||||
auto vertex_counts = plan::MakeVertexCountCache(*db_accessor);
|
||||
|
||||
SymbolTable symbol_table;
|
||||
SymbolGenerator symbol_generator(symbol_table);
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = MakeSymbolTable(query);
|
||||
|
||||
auto planning_context = plan::MakePlanningContext(ast_storage, symbol_table,
|
||||
query, vertex_counts);
|
||||
|
@ -150,14 +150,13 @@ class AstStorage {
|
||||
};
|
||||
cpp<#
|
||||
|
||||
(lcp:define-class tree ("::utils::Visitable<HierarchicalTreeVisitor>")
|
||||
(lcp:define-class tree ()
|
||||
((uid :int32_t :scope :public))
|
||||
(:abstractp t)
|
||||
(:public
|
||||
#>cpp
|
||||
Tree() = default;
|
||||
|
||||
using ::utils::Visitable<HierarchicalTreeVisitor>::Accept;
|
||||
virtual ~Tree() {}
|
||||
|
||||
virtual Tree *Clone(AstStorage &storage) const = 0;
|
||||
cpp<#)
|
||||
@ -189,15 +188,16 @@ cpp<#
|
||||
;;; Expressions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(lcp:define-class expression (tree "::utils::Visitable<ExpressionVisitor<TypedValue>>"
|
||||
(lcp:define-class expression (tree "::utils::Visitable<HierarchicalTreeVisitor>"
|
||||
"::utils::Visitable<ExpressionVisitor<TypedValue>>"
|
||||
"::utils::Visitable<ExpressionVisitor<void>>")
|
||||
()
|
||||
(:abstractp t)
|
||||
(:public
|
||||
#>cpp
|
||||
using ::utils::Visitable<HierarchicalTreeVisitor>::Accept;
|
||||
using ::utils::Visitable<ExpressionVisitor<TypedValue>>::Accept;
|
||||
using ::utils::Visitable<ExpressionVisitor<void>>::Accept;
|
||||
using Tree::Accept;
|
||||
|
||||
Expression() = default;
|
||||
|
||||
@ -213,13 +213,15 @@ cpp<#
|
||||
cpp<#)
|
||||
(:serialize :capnp :ignore-other-base-classes t))
|
||||
|
||||
(lcp:define-class where (tree)
|
||||
(lcp:define-class where (tree "::utils::Visitable<HierarchicalTreeVisitor>")
|
||||
((expression "Expression *" :initval "nullptr" :scope :public
|
||||
:capnp-type "Tree" :capnp-init nil
|
||||
:capnp-save #'save-ast-pointer
|
||||
:capnp-load (load-ast-pointer "Expression *")))
|
||||
(:public
|
||||
#>cpp
|
||||
using ::utils::Visitable<HierarchicalTreeVisitor>::Accept;
|
||||
|
||||
Where() = default;
|
||||
|
||||
bool Accept(HierarchicalTreeVisitor &visitor) override {
|
||||
@ -242,7 +244,7 @@ cpp<#
|
||||
#>cpp
|
||||
friend class AstStorage;
|
||||
cpp<#)
|
||||
(:serialize :capnp))
|
||||
(:serialize :capnp :ignore-other-base-classes t))
|
||||
|
||||
(lcp:define-class binary-operator (expression)
|
||||
((expression1 "Expression *" :initval "nullptr" :scope :public
|
||||
@ -1119,7 +1121,8 @@ cpp<#
|
||||
cpp<#)
|
||||
(:serialize :capnp))
|
||||
|
||||
(lcp:define-class named-expression (tree "::utils::Visitable<ExpressionVisitor<TypedValue>>"
|
||||
(lcp:define-class named-expression (tree "::utils::Visitable<HierarchicalTreeVisitor>"
|
||||
"::utils::Visitable<ExpressionVisitor<TypedValue>>"
|
||||
"::utils::Visitable<ExpressionVisitor<void>>")
|
||||
((name "std::string" :scope :public)
|
||||
(expression "Expression *" :initval "nullptr" :scope :public
|
||||
@ -1132,6 +1135,7 @@ cpp<#
|
||||
#>cpp
|
||||
using ::utils::Visitable<ExpressionVisitor<TypedValue>>::Accept;
|
||||
using ::utils::Visitable<ExpressionVisitor<void>>::Accept;
|
||||
using ::utils::Visitable<HierarchicalTreeVisitor>::Accept;
|
||||
|
||||
NamedExpression() = default;
|
||||
|
||||
@ -1172,7 +1176,7 @@ cpp<#
|
||||
;;; END Expressions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(lcp:define-class pattern-atom (tree)
|
||||
(lcp:define-class pattern-atom (tree "::utils::Visitable<HierarchicalTreeVisitor>")
|
||||
((identifier "Identifier *" :initval "nullptr" :scope :public
|
||||
:capnp-type "Tree" :capnp-init nil
|
||||
:capnp-save #'save-ast-pointer
|
||||
@ -1180,6 +1184,8 @@ cpp<#
|
||||
(:abstractp t)
|
||||
(:public
|
||||
#>cpp
|
||||
using ::utils::Visitable<HierarchicalTreeVisitor>::Accept;
|
||||
|
||||
PatternAtom() = default;
|
||||
|
||||
PatternAtom *Clone(AstStorage &storage) const override = 0;
|
||||
@ -1194,7 +1200,7 @@ cpp<#
|
||||
#>cpp
|
||||
friend class AstStorage;
|
||||
cpp<#)
|
||||
(:serialize :capnp))
|
||||
(:serialize :capnp :ignore-other-base-classes t))
|
||||
|
||||
(lcp:define-class node-atom (pattern-atom)
|
||||
((labels "std::vector<storage::Label>" :scope :public
|
||||
@ -1383,7 +1389,7 @@ cpp<#
|
||||
cpp<#)
|
||||
(:serialize :capnp))
|
||||
|
||||
(lcp:define-class pattern (tree)
|
||||
(lcp:define-class pattern (tree "::utils::Visitable<HierarchicalTreeVisitor>")
|
||||
((identifier "Identifier *" :initval "nullptr" :scope :public
|
||||
:capnp-type "Tree" :capnp-init nil
|
||||
:capnp-save #'save-ast-pointer
|
||||
@ -1395,6 +1401,8 @@ cpp<#
|
||||
:capnp-load (load-ast-vector "PatternAtom *")))
|
||||
(:public
|
||||
#>cpp
|
||||
using ::utils::Visitable<HierarchicalTreeVisitor>::Accept;
|
||||
|
||||
Pattern() = default;
|
||||
|
||||
bool Accept(HierarchicalTreeVisitor &visitor) override {
|
||||
@ -1426,13 +1434,15 @@ cpp<#
|
||||
#>cpp
|
||||
friend class AstStorage;
|
||||
cpp<#)
|
||||
(:serialize :capnp))
|
||||
(:serialize :capnp :ignore-other-base-classes t))
|
||||
|
||||
(lcp:define-class clause (tree)
|
||||
(lcp:define-class clause (tree "::utils::Visitable<HierarchicalTreeVisitor>")
|
||||
()
|
||||
(:abstractp t)
|
||||
(:public
|
||||
#>cpp
|
||||
using ::utils::Visitable<HierarchicalTreeVisitor>::Accept;
|
||||
|
||||
Clause() = default;
|
||||
|
||||
Clause *Clone(AstStorage &storage) const override = 0;
|
||||
@ -1445,9 +1455,9 @@ cpp<#
|
||||
#>cpp
|
||||
friend class AstStorage;
|
||||
cpp<#)
|
||||
(:serialize :capnp))
|
||||
(:serialize :capnp :ignore-other-base-classes t))
|
||||
|
||||
(lcp:define-class single-query (tree)
|
||||
(lcp:define-class single-query (tree "::utils::Visitable<HierarchicalTreeVisitor>")
|
||||
((clauses "std::vector<Clause *>"
|
||||
:scope :public
|
||||
:capnp-type "List(Tree)"
|
||||
@ -1455,6 +1465,8 @@ cpp<#
|
||||
:capnp-load (load-ast-vector "Clause *")))
|
||||
(:public
|
||||
#>cpp
|
||||
using ::utils::Visitable<HierarchicalTreeVisitor>::Accept;
|
||||
|
||||
SingleQuery() = default;
|
||||
|
||||
bool Accept(HierarchicalTreeVisitor &visitor) override {
|
||||
@ -1482,9 +1494,9 @@ cpp<#
|
||||
#>cpp
|
||||
friend class AstStorage;
|
||||
cpp<#)
|
||||
(:serialize :capnp))
|
||||
(:serialize :capnp :ignore-other-base-classes t))
|
||||
|
||||
(lcp:define-class cypher-union (tree)
|
||||
(lcp:define-class cypher-union (tree "::utils::Visitable<HierarchicalTreeVisitor>")
|
||||
((single-query "SingleQuery *" :initval "nullptr" :scope :public
|
||||
:capnp-type "Tree" :capnp-init nil
|
||||
:capnp-save #'save-ast-pointer
|
||||
@ -1494,6 +1506,8 @@ cpp<#
|
||||
:documentation "Holds symbols that are created during symbol generation phase. These symbols are used when UNION/UNION ALL combines single query results."))
|
||||
(:public
|
||||
#>cpp
|
||||
using ::utils::Visitable<HierarchicalTreeVisitor>::Accept;
|
||||
|
||||
CypherUnion() = default;
|
||||
|
||||
bool Accept(HierarchicalTreeVisitor &visitor) override {
|
||||
@ -1525,13 +1539,15 @@ cpp<#
|
||||
#>cpp
|
||||
friend class AstStorage;
|
||||
cpp<#)
|
||||
(:serialize :capnp))
|
||||
(:serialize :capnp :ignore-other-base-classes t))
|
||||
|
||||
(lcp:define-class query (tree)
|
||||
(lcp:define-class query (tree "::utils::Visitable<QueryVisitor<void>>")
|
||||
()
|
||||
(:abstractp t)
|
||||
(:public
|
||||
#>cpp
|
||||
using ::utils::Visitable<QueryVisitor<void>>::Accept;
|
||||
|
||||
Query() = default;
|
||||
|
||||
virtual Query *Clone(AstStorage &storage) const = 0;
|
||||
@ -1544,7 +1560,7 @@ cpp<#
|
||||
#>cpp
|
||||
friend class AstStorage;
|
||||
cpp<#)
|
||||
(:serialize :capnp))
|
||||
(:serialize :capnp :ignore-other-base-classes t))
|
||||
|
||||
(lcp:define-class cypher-query (query)
|
||||
((single-query "SingleQuery *" :initval "nullptr" :scope :public
|
||||
@ -1562,17 +1578,7 @@ cpp<#
|
||||
#>cpp
|
||||
CypherQuery() = default;
|
||||
|
||||
bool Accept(HierarchicalTreeVisitor &visitor) override {
|
||||
if (visitor.PreVisit(*this)) {
|
||||
bool should_continue = single_query_->Accept(visitor);
|
||||
for (auto *cypher_union : cypher_unions_) {
|
||||
if (should_continue) {
|
||||
should_continue = cypher_union->Accept(visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
return visitor.PostVisit(*this);
|
||||
}
|
||||
DEFVISITABLE(QueryVisitor<void>);
|
||||
|
||||
CypherQuery *Clone(AstStorage &storage) const override {
|
||||
auto *cypher_query = storage.Create<CypherQuery>();
|
||||
@ -1603,12 +1609,7 @@ cpp<#
|
||||
#>cpp
|
||||
ExplainQuery() = default;
|
||||
|
||||
bool Accept(HierarchicalTreeVisitor &visitor) override {
|
||||
if (visitor.PreVisit(*this)) {
|
||||
cypher_query_->Accept(visitor);
|
||||
}
|
||||
return visitor.PostVisit(*this);
|
||||
}
|
||||
DEFVISITABLE(QueryVisitor<void>);
|
||||
|
||||
ExplainQuery *Clone(AstStorage &storage) const override {
|
||||
auto *explain_query = storage.Create<ExplainQuery>();
|
||||
@ -1640,7 +1641,7 @@ cpp<#
|
||||
#>cpp
|
||||
IndexQuery() = default;
|
||||
|
||||
DEFVISITABLE(HierarchicalTreeVisitor);
|
||||
DEFVISITABLE(QueryVisitor<void>);
|
||||
|
||||
IndexQuery *Clone(AstStorage &storage) const override {
|
||||
return storage.Create<IndexQuery>(action_, label_, properties_);
|
||||
@ -2279,12 +2280,7 @@ cpp<#
|
||||
#>cpp
|
||||
AuthQuery() = default;
|
||||
|
||||
bool Accept(HierarchicalTreeVisitor &visitor) override {
|
||||
if (visitor.PreVisit(*this)) {
|
||||
if (password_) password_->Accept(visitor);
|
||||
}
|
||||
return visitor.PostVisit(*this);
|
||||
}
|
||||
DEFVISITABLE(QueryVisitor<void>);
|
||||
|
||||
AuthQuery *Clone(AstStorage &storage) const override {
|
||||
return storage.Create<AuthQuery>(
|
||||
@ -2358,24 +2354,7 @@ cpp<#
|
||||
#>cpp
|
||||
StreamQuery() = default;
|
||||
|
||||
bool Accept(HierarchicalTreeVisitor &visitor) override {
|
||||
if (visitor.PreVisit(*this)) {
|
||||
bool cont = true;
|
||||
if (cont && stream_uri_)
|
||||
cont = stream_uri_->Accept(visitor);
|
||||
if (cont && stream_topic_)
|
||||
cont = stream_topic_->Accept(visitor);
|
||||
if (cont && transform_uri_)
|
||||
cont = transform_uri_->Accept(visitor);
|
||||
if (cont && batch_interval_in_ms_)
|
||||
cont = batch_interval_in_ms_->Accept(visitor);
|
||||
if (cont && batch_size_)
|
||||
cont = batch_size_->Accept(visitor);
|
||||
if (cont && limit_batches_)
|
||||
cont = limit_batches_->Accept(visitor);
|
||||
}
|
||||
return visitor.PostVisit(*this);
|
||||
}
|
||||
DEFVISITABLE(QueryVisitor<void>);
|
||||
|
||||
StreamQuery *Clone(AstStorage &storage) const override {
|
||||
auto *stream_uri = stream_uri_ ? stream_uri_->Clone(storage) : nullptr;
|
||||
|
@ -67,21 +67,20 @@ class IndexQuery;
|
||||
class StreamQuery;
|
||||
|
||||
using TreeCompositeVisitor = ::utils::CompositeVisitor<
|
||||
CypherQuery, ExplainQuery, SingleQuery, CypherUnion, NamedExpression,
|
||||
OrOperator, XorOperator, AndOperator, NotOperator, AdditionOperator,
|
||||
SubtractionOperator, MultiplicationOperator, DivisionOperator, ModOperator,
|
||||
NotEqualOperator, EqualOperator, LessOperator, GreaterOperator,
|
||||
LessEqualOperator, GreaterEqualOperator, InListOperator, SubscriptOperator,
|
||||
SingleQuery, CypherUnion, NamedExpression, OrOperator, XorOperator,
|
||||
AndOperator, NotOperator, AdditionOperator, SubtractionOperator,
|
||||
MultiplicationOperator, DivisionOperator, ModOperator, NotEqualOperator,
|
||||
EqualOperator, LessOperator, GreaterOperator, LessEqualOperator,
|
||||
GreaterEqualOperator, InListOperator, SubscriptOperator,
|
||||
ListSlicingOperator, IfOperator, UnaryPlusOperator, UnaryMinusOperator,
|
||||
IsNullOperator, ListLiteral, MapLiteral, PropertyLookup, LabelsTest,
|
||||
Aggregation, Function, Reduce, Coalesce, Extract, All, Single, Create,
|
||||
Match, Return, With, Pattern, NodeAtom, EdgeAtom, Delete, Where,
|
||||
SetProperty, SetProperties, SetLabels, RemoveProperty, RemoveLabels, Merge,
|
||||
Unwind, AuthQuery, StreamQuery>;
|
||||
Unwind>;
|
||||
|
||||
using TreeLeafVisitor =
|
||||
::utils::LeafVisitor<Identifier, PrimitiveLiteral, ParameterLookup,
|
||||
IndexQuery>;
|
||||
::utils::LeafVisitor<Identifier, PrimitiveLiteral, ParameterLookup>;
|
||||
|
||||
class HierarchicalTreeVisitor : public TreeCompositeVisitor,
|
||||
public TreeLeafVisitor {
|
||||
@ -106,4 +105,9 @@ class ExpressionVisitor
|
||||
Extract, All, Single, ParameterLookup, Identifier, PrimitiveLiteral> {
|
||||
};
|
||||
|
||||
template <class TResult>
|
||||
class QueryVisitor
|
||||
: public ::utils::Visitor<TResult, CypherQuery, ExplainQuery, IndexQuery,
|
||||
AuthQuery, StreamQuery> {};
|
||||
|
||||
} // namespace query
|
||||
|
@ -2,14 +2,39 @@
|
||||
|
||||
namespace query {
|
||||
|
||||
class PrivilegeExtractor : public HierarchicalTreeVisitor {
|
||||
class PrivilegeExtractor : public QueryVisitor<void>,
|
||||
public HierarchicalTreeVisitor {
|
||||
public:
|
||||
using HierarchicalTreeVisitor::PostVisit;
|
||||
using HierarchicalTreeVisitor::PreVisit;
|
||||
using HierarchicalTreeVisitor::Visit;
|
||||
using QueryVisitor<void>::Visit;
|
||||
|
||||
std::vector<AuthQuery::Privilege> privileges() { return privileges_; }
|
||||
|
||||
void Visit(IndexQuery &) override {
|
||||
AddPrivilege(AuthQuery::Privilege::INDEX);
|
||||
}
|
||||
|
||||
void Visit(AuthQuery &) override {
|
||||
AddPrivilege(AuthQuery::Privilege::AUTH);
|
||||
}
|
||||
|
||||
void Visit(StreamQuery &) override {
|
||||
AddPrivilege(AuthQuery::Privilege::STREAM);
|
||||
}
|
||||
|
||||
void Visit(ExplainQuery &query) override {
|
||||
query.cypher_query_->Accept(*this);
|
||||
}
|
||||
|
||||
void Visit(CypherQuery &query) override {
|
||||
query.single_query_->Accept(*this);
|
||||
for (auto *cypher_union : query.cypher_unions_) {
|
||||
cypher_union->Accept(*this);
|
||||
}
|
||||
}
|
||||
|
||||
bool PreVisit(Create &) override {
|
||||
AddPrivilege(AuthQuery::Privilege::CREATE);
|
||||
return false;
|
||||
@ -51,21 +76,6 @@ class PrivilegeExtractor : public HierarchicalTreeVisitor {
|
||||
bool Visit(PrimitiveLiteral &) override { return true; }
|
||||
bool Visit(ParameterLookup &) override { return true; }
|
||||
|
||||
bool Visit(IndexQuery &) override {
|
||||
AddPrivilege(AuthQuery::Privilege::INDEX);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PreVisit(AuthQuery &) override {
|
||||
AddPrivilege(AuthQuery::Privilege::AUTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PreVisit(StreamQuery &) override {
|
||||
AddPrivilege(AuthQuery::Privilege::STREAM);
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
void AddPrivilege(AuthQuery::Privilege privilege) {
|
||||
if (!utils::Contains(privileges_, privilege)) {
|
||||
|
@ -218,12 +218,6 @@ bool SymbolGenerator::PostVisit(Match &) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SymbolGenerator::Visit(IndexQuery &) { return true; }
|
||||
|
||||
bool SymbolGenerator::PreVisit(AuthQuery &) { return false; }
|
||||
|
||||
bool SymbolGenerator::PreVisit(StreamQuery &) { return false; }
|
||||
|
||||
// Expressions
|
||||
|
||||
SymbolGenerator::ReturnType SymbolGenerator::Visit(Identifier &ident) {
|
||||
@ -333,27 +327,27 @@ bool SymbolGenerator::PostVisit(IfOperator &) {
|
||||
|
||||
bool SymbolGenerator::PreVisit(All &all) {
|
||||
all.list_expression_->Accept(*this);
|
||||
VisitWithIdentifiers(*all.where_, {all.identifier_});
|
||||
VisitWithIdentifiers(all.where_->expression_, {all.identifier_});
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SymbolGenerator::PreVisit(Single &single) {
|
||||
single.list_expression_->Accept(*this);
|
||||
VisitWithIdentifiers(*single.where_, {single.identifier_});
|
||||
VisitWithIdentifiers(single.where_->expression_, {single.identifier_});
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SymbolGenerator::PreVisit(Reduce &reduce) {
|
||||
reduce.initializer_->Accept(*this);
|
||||
reduce.list_->Accept(*this);
|
||||
VisitWithIdentifiers(*reduce.expression_,
|
||||
VisitWithIdentifiers(reduce.expression_,
|
||||
{reduce.accumulator_, reduce.identifier_});
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SymbolGenerator::PreVisit(Extract &extract) {
|
||||
extract.list_->Accept(*this);
|
||||
VisitWithIdentifiers(*extract.expression_, {extract.identifier_});
|
||||
VisitWithIdentifiers(extract.expression_, {extract.identifier_});
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -435,7 +429,7 @@ bool SymbolGenerator::PreVisit(EdgeAtom &edge_atom) {
|
||||
scope_.in_edge_range = false;
|
||||
scope_.in_pattern = false;
|
||||
if (edge_atom.filter_lambda_.expression) {
|
||||
VisitWithIdentifiers(*edge_atom.filter_lambda_.expression,
|
||||
VisitWithIdentifiers(edge_atom.filter_lambda_.expression,
|
||||
{edge_atom.filter_lambda_.inner_edge,
|
||||
edge_atom.filter_lambda_.inner_node});
|
||||
} else {
|
||||
@ -449,7 +443,7 @@ bool SymbolGenerator::PreVisit(EdgeAtom &edge_atom) {
|
||||
inner_node->name_, inner_node->user_declared_, Symbol::Type::Vertex);
|
||||
}
|
||||
if (edge_atom.weight_lambda_.expression) {
|
||||
VisitWithIdentifiers(*edge_atom.weight_lambda_.expression,
|
||||
VisitWithIdentifiers(edge_atom.weight_lambda_.expression,
|
||||
{edge_atom.weight_lambda_.inner_edge,
|
||||
edge_atom.weight_lambda_.inner_node});
|
||||
}
|
||||
@ -476,7 +470,7 @@ bool SymbolGenerator::PostVisit(EdgeAtom &) {
|
||||
}
|
||||
|
||||
void SymbolGenerator::VisitWithIdentifiers(
|
||||
Tree &tree, const std::vector<Identifier *> &identifiers) {
|
||||
Expression *expr, const std::vector<Identifier *> &identifiers) {
|
||||
std::vector<std::pair<std::experimental::optional<Symbol>, Identifier *>>
|
||||
prev_symbols;
|
||||
// Collect previous symbols if they exist.
|
||||
@ -490,8 +484,8 @@ void SymbolGenerator::VisitWithIdentifiers(
|
||||
CreateSymbol(identifier->name_, identifier->user_declared_);
|
||||
prev_symbols.emplace_back(prev_symbol, identifier);
|
||||
}
|
||||
// Visit the tree with the new symbols bound.
|
||||
tree.Accept(*this);
|
||||
// Visit the expression with the new symbols bound.
|
||||
expr->Accept(*this);
|
||||
// Restore back to previous symbols.
|
||||
for (const auto &prev : prev_symbols) {
|
||||
const auto &prev_symbol = prev.first;
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
namespace query {
|
||||
|
||||
///
|
||||
/// Visits the AST and generates symbols for variables.
|
||||
///
|
||||
/// During the process of symbol generation, simple semantic checks are
|
||||
@ -46,9 +45,6 @@ class SymbolGenerator : public HierarchicalTreeVisitor {
|
||||
bool PostVisit(Unwind &) override;
|
||||
bool PreVisit(Match &) override;
|
||||
bool PostVisit(Match &) override;
|
||||
bool Visit(IndexQuery &) override;
|
||||
bool PreVisit(AuthQuery &) override;
|
||||
bool PreVisit(StreamQuery &) override;
|
||||
|
||||
// Expressions
|
||||
ReturnType Visit(Identifier &) override;
|
||||
@ -128,7 +124,7 @@ class SymbolGenerator : public HierarchicalTreeVisitor {
|
||||
|
||||
void VisitReturnBody(ReturnBody &body, Where *where = nullptr);
|
||||
|
||||
void VisitWithIdentifiers(Tree &, const std::vector<Identifier *> &);
|
||||
void VisitWithIdentifiers(Expression *, const std::vector<Identifier *> &);
|
||||
|
||||
SymbolTable &symbol_table_;
|
||||
Scope scope_;
|
||||
@ -136,4 +132,14 @@ class SymbolGenerator : public HierarchicalTreeVisitor {
|
||||
std::unordered_set<std::string> curr_return_names_;
|
||||
};
|
||||
|
||||
inline SymbolTable MakeSymbolTable(CypherQuery *query) {
|
||||
SymbolTable symbol_table;
|
||||
SymbolGenerator symbol_generator(symbol_table);
|
||||
query->single_query_->Accept(symbol_generator);
|
||||
for (auto *cypher_union : query->cypher_unions_) {
|
||||
cypher_union->Accept(symbol_generator);
|
||||
}
|
||||
return symbol_table;
|
||||
}
|
||||
|
||||
} // namespace query
|
||||
|
@ -815,9 +815,7 @@ std::unique_ptr<LogicalPlan> Interpreter::MakeLogicalPlan(
|
||||
database::GraphDbAccessor *db_accessor) {
|
||||
auto vertex_counts = plan::MakeVertexCountCache(*db_accessor);
|
||||
|
||||
SymbolTable symbol_table;
|
||||
SymbolGenerator symbol_generator(symbol_table);
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = MakeSymbolTable(query);
|
||||
|
||||
auto planning_context = plan::MakePlanningContext(ast_storage, symbol_table,
|
||||
query, vertex_counts);
|
||||
|
@ -52,9 +52,6 @@ class UsedSymbolsCollector : public HierarchicalTreeVisitor {
|
||||
|
||||
bool Visit(PrimitiveLiteral &) override { return true; }
|
||||
bool Visit(ParameterLookup &) override { return true; }
|
||||
bool Visit(query::IndexQuery &) override { return true; }
|
||||
bool PreVisit(query::AuthQuery &) override { return false; }
|
||||
bool PreVisit(query::StreamQuery &) override { return false; }
|
||||
|
||||
std::unordered_set<Symbol> symbols_;
|
||||
const SymbolTable &symbol_table_;
|
||||
|
@ -410,21 +410,6 @@ class ReturnBodyContext : public HierarchicalTreeVisitor {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Visit(query::IndexQuery &) override {
|
||||
has_aggregation_.emplace_back(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PreVisit(query::AuthQuery &) override {
|
||||
has_aggregation_.emplace_back(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PreVisit(query::StreamQuery &) override {
|
||||
has_aggregation_.emplace_back(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Creates NamedExpression with an Identifier for each user declared symbol.
|
||||
// This should be used when body.all_identifiers is true, to generate
|
||||
// expressions for Produce operator.
|
||||
|
@ -41,9 +41,7 @@ static void BM_PlanChainedMatches(benchmark::State &state) {
|
||||
query::AstStorage storage;
|
||||
int num_matches = state.range(0);
|
||||
auto *query = AddChainedMatches(num_matches, storage);
|
||||
query::SymbolTable symbol_table;
|
||||
query::SymbolGenerator symbol_generator(symbol_table);
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto ctx =
|
||||
query::plan::MakePlanningContext(storage, symbol_table, query, *dba);
|
||||
state.ResumeTiming();
|
||||
@ -121,9 +119,7 @@ static void BM_PlanAndEstimateIndexedMatching(benchmark::State &state) {
|
||||
query::AstStorage storage;
|
||||
auto *query = AddIndexedMatches(index_count, label,
|
||||
std::make_pair("prop", prop), storage);
|
||||
query::SymbolTable symbol_table;
|
||||
query::SymbolGenerator symbol_generator(symbol_table);
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
state.ResumeTiming();
|
||||
auto ctx =
|
||||
query::plan::MakePlanningContext(storage, symbol_table, query, *dba);
|
||||
@ -157,9 +153,7 @@ static void BM_PlanAndEstimateIndexedMatchingWithCachedCounts(
|
||||
query::AstStorage storage;
|
||||
auto *query = AddIndexedMatches(index_count, label,
|
||||
std::make_pair("prop", prop), storage);
|
||||
query::SymbolTable symbol_table;
|
||||
query::SymbolGenerator symbol_generator(symbol_table);
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
state.ResumeTiming();
|
||||
auto ctx = query::plan::MakePlanningContext(storage, symbol_table, query,
|
||||
vertex_counts);
|
||||
|
@ -444,13 +444,6 @@ query::Query *MakeAst(const std::string &query, query::AstStorage *storage,
|
||||
return visitor.query();
|
||||
}
|
||||
|
||||
query::SymbolTable MakeSymbolTable(query::Query *query) {
|
||||
query::SymbolTable symbol_table;
|
||||
query::SymbolGenerator symbol_generator(symbol_table);
|
||||
query->Accept(symbol_generator);
|
||||
return symbol_table;
|
||||
}
|
||||
|
||||
// Returns a list of pairs (plan, estimated cost), sorted in the ascending
|
||||
// order by cost.
|
||||
auto MakeLogicalPlans(query::CypherQuery *query, query::AstStorage &ast,
|
||||
@ -508,7 +501,7 @@ void RunInteractivePlanning(database::GraphDbAccessor *dba) {
|
||||
"Interactive planning is only avaialable for regular openCypher "
|
||||
"queries.");
|
||||
}
|
||||
auto symbol_table = MakeSymbolTable(query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
planning_timer.Start();
|
||||
auto plans = MakeLogicalPlans(query, ast, symbol_table, interactive_db);
|
||||
auto planning_time = planning_timer.Elapsed();
|
||||
|
@ -624,7 +624,7 @@ struct ExpectedDistributedPlan {
|
||||
template <class TPlanner>
|
||||
DistributedPlan MakeDistributedPlan(query::CypherQuery *query,
|
||||
query::AstStorage &storage) {
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TPlanner>(dba, storage, symbol_table, query);
|
||||
std::atomic<int64_t> next_plan_id{0};
|
||||
@ -732,7 +732,7 @@ TYPED_TEST(TestPlanner, MatchNodeReturn) {
|
||||
AstStorage storage;
|
||||
auto *as_n = NEXPR("n", IDENT("n"));
|
||||
auto *query = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"))), RETURN(as_n)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
ExpectPullRemote pull({symbol_table.at(*as_n)});
|
||||
@ -748,7 +748,7 @@ TYPED_TEST(TestPlanner, CreateNodeReturn) {
|
||||
auto ident_n = IDENT("n");
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(CREATE(PATTERN(NODE("n"))), RETURN(ident_n, AS("n"))));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto acc = ExpectAccumulate({symbol_table.at(*ident_n)});
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
@ -842,7 +842,7 @@ TYPED_TEST(TestPlanner, MatchLabeledNodes) {
|
||||
auto *as_n = NEXPR("n", IDENT("n"));
|
||||
auto *query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n", label))), RETURN(as_n)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
ExpectPullRemote pull({symbol_table.at(*as_n)});
|
||||
auto expected = ExpectDistributed(
|
||||
@ -861,7 +861,7 @@ TYPED_TEST(TestPlanner, MatchPathReturn) {
|
||||
MATCH(PATTERN(NODE("n"), EDGE("r", Direction::BOTH, {relationship}),
|
||||
NODE("m"))),
|
||||
RETURN(as_n)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
ExpectPullRemote pull({symbol_table.at(*as_n)});
|
||||
auto expected =
|
||||
@ -883,7 +883,7 @@ TYPED_TEST(TestPlanner, MatchNamedPatternReturn) {
|
||||
EDGE("r", Direction::BOTH, {relationship}),
|
||||
NODE("m"))),
|
||||
RETURN(as_p)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
ExpectPullRemote pull({symbol_table.at(*as_p)});
|
||||
auto expected = ExpectDistributed(
|
||||
@ -905,7 +905,7 @@ TYPED_TEST(TestPlanner, MatchNamedPatternWithPredicateReturn) {
|
||||
EDGE("r", Direction::BOTH, {relationship}),
|
||||
NODE("m"))),
|
||||
WHERE(EQ(LITERAL(2), IDENT("p"))), RETURN(as_p)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
ExpectPullRemote pull({symbol_table.at(*as_p)});
|
||||
auto expected =
|
||||
@ -927,7 +927,7 @@ TYPED_TEST(TestPlanner, OptionalMatchNamedPatternReturn) {
|
||||
auto pattern = NAMED_PATTERN("p", node_n, edge, node_m);
|
||||
auto as_p = AS("p");
|
||||
auto *query = QUERY(SINGLE_QUERY(OPTIONAL_MATCH(pattern), RETURN("p", as_p)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto get_symbol = [&symbol_table](const auto *ast_node) {
|
||||
return symbol_table.at(*ast_node->identifier_);
|
||||
};
|
||||
@ -955,7 +955,7 @@ TYPED_TEST(TestPlanner, MatchWhereReturn) {
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(NODE("n"))),
|
||||
WHERE(LESS(PROPERTY_LOOKUP("n", property), LITERAL(42))), RETURN(as_n)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
ExpectPullRemote pull({symbol_table.at(*as_n)});
|
||||
auto expected = ExpectDistributed(
|
||||
@ -1023,7 +1023,7 @@ TYPED_TEST(TestPlanner, MultiMatch) {
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(node_n, edge_r, node_m)),
|
||||
MATCH(PATTERN(node_j, edge_e, node_i, edge_f, node_h)), RETURN("n")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
auto get_symbol = [&symbol_table](const auto *atom_node) {
|
||||
@ -1058,7 +1058,7 @@ TYPED_TEST(TestPlanner, MultiMatchSameStart) {
|
||||
MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))), RETURN(as_n)));
|
||||
// Similar to MatchMultiPatternSameStart, we expect only Expand from second
|
||||
// MATCH clause.
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
ExpectPullRemote pull({symbol_table.at(*as_n)});
|
||||
@ -1077,7 +1077,7 @@ TYPED_TEST(TestPlanner, MatchWithReturn) {
|
||||
auto *query = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("old"))),
|
||||
WITH("old", AS("new")), RETURN(as_new)));
|
||||
// No accumulation since we only do reads.
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
ExpectPullRemote pull({symbol_table.at(*as_new)});
|
||||
@ -1097,7 +1097,7 @@ TYPED_TEST(TestPlanner, MatchWithWhereReturn) {
|
||||
MATCH(PATTERN(NODE("old"))), WITH("old", AS("new")),
|
||||
WHERE(LESS(PROPERTY_LOOKUP("new", prop), LITERAL(42))), RETURN(as_new)));
|
||||
// No accumulation since we only do reads.
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
ExpectPullRemote pull({symbol_table.at(*as_new)});
|
||||
auto expected =
|
||||
@ -1136,7 +1136,7 @@ TYPED_TEST(TestPlanner, MatchReturnSum) {
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(NODE("n"))), RETURN(sum, AS("sum"), n_prop2, AS("group"))));
|
||||
auto aggr = ExpectAggregate({sum}, {n_prop2});
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
std::atomic<int64_t> next_plan_id{0};
|
||||
auto distributed_plan =
|
||||
@ -1176,7 +1176,7 @@ TYPED_TEST(TestPlanner, MatchReturnSkipLimit) {
|
||||
auto *query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"))),
|
||||
RETURN(as_n, SKIP(LITERAL(2)), LIMIT(LITERAL(1)))));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
ExpectPullRemote pull({symbol_table.at(*as_n)});
|
||||
@ -1194,7 +1194,7 @@ TYPED_TEST(TestPlanner, CreateWithSkipReturnLimit) {
|
||||
auto query = QUERY(SINGLE_QUERY(CREATE(PATTERN(NODE("n"))),
|
||||
WITH(ident_n, AS("m"), SKIP(LITERAL(2))),
|
||||
RETURN("m", LIMIT(LITERAL(1)))));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto acc = ExpectAccumulate({symbol_table.at(*ident_n)});
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
@ -1215,7 +1215,7 @@ TYPED_TEST(TestPlanner, MatchReturnOrderBy) {
|
||||
auto *node_n = NODE("n");
|
||||
auto ret = RETURN(as_m, ORDER_BY(PROPERTY_LOOKUP("n", prop)));
|
||||
auto *query = QUERY(SINGLE_QUERY(MATCH(PATTERN(node_n)), ret));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
ExpectPullRemoteOrderBy pull_order_by(
|
||||
{symbol_table.at(*as_m), symbol_table.at(*node_n->identifier_)});
|
||||
@ -1246,7 +1246,7 @@ TYPED_TEST(TestPlanner, CreateWithOrderByWhere) {
|
||||
PATTERN(NODE("n"), EDGE("r", Direction::OUT, {r_type}), NODE("m"))),
|
||||
WITH(ident_n, AS("new"), ORDER_BY(new_prop, r_prop)),
|
||||
WHERE(LESS(m_prop, LITERAL(42)))));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Since this is a write query, we expect to accumulate to old used symbols.
|
||||
auto acc = ExpectAccumulate({
|
||||
symbol_table.at(*ident_n), // `n` in WITH
|
||||
@ -1283,7 +1283,7 @@ TYPED_TEST(TestPlanner, MatchUnwindReturn) {
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("n"))),
|
||||
UNWIND(LIST(LITERAL(1), LITERAL(2), LITERAL(3)), AS("x")),
|
||||
RETURN(as_n, as_x)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
ExpectPullRemote pull({symbol_table.at(*as_n), symbol_table.at(*as_x)});
|
||||
@ -1315,7 +1315,7 @@ TYPED_TEST(TestPlanner, MatchWhereBeforeExpand) {
|
||||
MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
|
||||
WHERE(LESS(PROPERTY_LOOKUP("n", prop), LITERAL(42))), RETURN(as_n)));
|
||||
// We expect Filter to come immediately after ScanAll, since it only uses `n`.
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
ExpectPullRemote pull({symbol_table.at(*as_n)});
|
||||
auto expected = ExpectDistributed(
|
||||
@ -1361,7 +1361,7 @@ TYPED_TEST(TestPlanner, MatchBfs) {
|
||||
auto *as_r = NEXPR("r", IDENT("r"));
|
||||
auto *query = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("n"), bfs, NODE("m"))), RETURN(as_r)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
ExpectPullRemote pull({symbol_table.at(*as_r)});
|
||||
auto expected = ExpectDistributed(
|
||||
MakeCheckers(ExpectScanAll(), ExpectDistributedExpandBfs(),
|
||||
@ -1431,7 +1431,7 @@ TYPED_TEST(TestPlanner, DistributedMatchCreateReturn) {
|
||||
auto *query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"))), CREATE(PATTERN(NODE("m"))),
|
||||
RETURN(ident_m, AS("m"))));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto acc = ExpectAccumulate({symbol_table.at(*ident_m)});
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
@ -1455,7 +1455,7 @@ TYPED_TEST(TestPlanner, DistributedCartesianCreateExpand) {
|
||||
CREATE(PATTERN(NODE("a"), EDGE("e", Direction::OUT, {relationship}),
|
||||
NODE("b"))),
|
||||
RETURN("e")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto left_cart =
|
||||
MakeCheckers(ExpectScanAll(),
|
||||
ExpectPullRemote({symbol_table.at(*node_a->identifier_)}));
|
||||
@ -1480,7 +1480,7 @@ TYPED_TEST(TestPlanner, DistributedCartesianExpand) {
|
||||
auto *node_c = NODE("c");
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(node_a), PATTERN(node_b, edge_e, node_c)), RETURN("c")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto sym_a = symbol_table.at(*node_a->identifier_);
|
||||
auto left_cart = MakeCheckers(ExpectScanAll(), ExpectPullRemote({sym_a}));
|
||||
auto sym_b = symbol_table.at(*node_b->identifier_);
|
||||
@ -1506,7 +1506,7 @@ TYPED_TEST(TestPlanner, DistributedCartesianExpandToExisting) {
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(node_a), PATTERN(node_b, EDGE("e"), NODE("a"))),
|
||||
RETURN("e")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto sym_a = symbol_table.at(*node_a->identifier_);
|
||||
auto left_cart = MakeCheckers(ExpectScanAll(), ExpectPullRemote({sym_a}));
|
||||
auto sym_b = symbol_table.at(*node_b->identifier_);
|
||||
@ -1529,7 +1529,7 @@ TYPED_TEST(TestPlanner, DistributedCartesianExpandFromExisting) {
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(node_a), PATTERN(node_b),
|
||||
PATTERN(NODE("a"), EDGE("e"), NODE("b"))),
|
||||
RETURN("e")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto sym_a = symbol_table.at(*node_a->identifier_);
|
||||
auto left_cart = MakeCheckers(ExpectScanAll(), ExpectPullRemote({sym_a}));
|
||||
auto sym_b = symbol_table.at(*node_b->identifier_);
|
||||
@ -1554,7 +1554,7 @@ TYPED_TEST(TestPlanner, DistributedCartesianFilter) {
|
||||
WHERE(AND(AND(EQ(IDENT("a"), LITERAL(42)), EQ(IDENT("b"), IDENT("a"))),
|
||||
EQ(IDENT("c"), IDENT("b")))),
|
||||
RETURN("c")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto sym_a = symbol_table.at(*node_a->identifier_);
|
||||
auto sym_b = symbol_table.at(*node_b->identifier_);
|
||||
auto sym_c = symbol_table.at(*node_c->identifier_);
|
||||
@ -1588,7 +1588,7 @@ TYPED_TEST(TestPlanner, DistributedCartesianIndexedScanByProperty) {
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(node_a), PATTERN(node_b)),
|
||||
WHERE(EQ(PROPERTY_LOOKUP("b", prop), IDENT("a"))), RETURN("b")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto sym_a = symbol_table.at(*node_a->identifier_);
|
||||
auto sym_b = symbol_table.at(*node_b->identifier_);
|
||||
auto left_cart = MakeCheckers(ExpectScanAll(), ExpectPullRemote({sym_a}));
|
||||
@ -1618,7 +1618,7 @@ TYPED_TEST(TestPlanner, DistributedCartesianIndexedScanByLowerBound) {
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(node_a), PATTERN(node_b)),
|
||||
WHERE(LESS(IDENT("a"), PROPERTY_LOOKUP("b", prop))), RETURN("b")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto sym_a = symbol_table.at(*node_a->identifier_);
|
||||
auto sym_b = symbol_table.at(*node_b->identifier_);
|
||||
auto left_cart = MakeCheckers(ExpectScanAll(), ExpectPullRemote({sym_a}));
|
||||
@ -1648,7 +1648,7 @@ TYPED_TEST(TestPlanner, DistributedCartesianIndexedScanByUpperBound) {
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(node_a), PATTERN(node_b)),
|
||||
WHERE(GREATER(IDENT("a"), PROPERTY_LOOKUP("b", prop))), RETURN("b")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto sym_a = symbol_table.at(*node_a->identifier_);
|
||||
auto sym_b = symbol_table.at(*node_b->identifier_);
|
||||
auto left_cart = MakeCheckers(ExpectScanAll(), ExpectPullRemote({sym_a}));
|
||||
@ -1792,7 +1792,7 @@ TYPED_TEST(TestPlanner, DistributedCartesianProduce) {
|
||||
auto *query = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("a"))), with_a, MATCH(PATTERN(node_b)),
|
||||
WHERE(EQ(IDENT("b"), IDENT("a"))), RETURN("b")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto sym_a = symbol_table.at(*with_a->body_.named_expressions[0]);
|
||||
auto left_cart =
|
||||
MakeCheckers(ExpectScanAll(), ExpectProduce(), ExpectPullRemote({sym_a}));
|
||||
@ -1815,7 +1815,7 @@ TYPED_TEST(TestPlanner, DistributedCartesianUnwind) {
|
||||
auto *node_b = NODE("b");
|
||||
auto *query = QUERY(SINGLE_QUERY(MATCH(PATTERN(node_a), PATTERN(node_b)),
|
||||
UNWIND(IDENT("a"), AS("x")), RETURN("x")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto sym_a = symbol_table.at(*node_a->identifier_);
|
||||
auto left_cart = MakeCheckers(ExpectScanAll(), ExpectPullRemote({sym_a}));
|
||||
auto sym_b = symbol_table.at(*node_b->identifier_);
|
||||
@ -1837,7 +1837,7 @@ TYPED_TEST(TestPlanner, DistributedCartesianMatchCreateNode) {
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(NODE("a"))), CREATE(PATTERN(node_b)), WITH("b"),
|
||||
MATCH(PATTERN(node_c)), CREATE(PATTERN(NODE("d")))));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto sym_b = symbol_table.at(*node_b->identifier_);
|
||||
auto left_cart =
|
||||
MakeCheckers(ExpectScanAll(), ExpectDistributedCreateNode(),
|
||||
@ -1861,7 +1861,7 @@ TYPED_TEST(TestPlanner, DistributedCartesianCreateNode) {
|
||||
auto *node_b = NODE("b");
|
||||
auto *query = QUERY(SINGLE_QUERY(CREATE(PATTERN(node_a)), WITH("a"),
|
||||
MATCH(PATTERN(node_b)), RETURN("b")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto sym_a = symbol_table.at(*node_a->identifier_);
|
||||
auto left_cart = MakeCheckers(ExpectDistributedCreateNode(true),
|
||||
ExpectSynchronize(true), ExpectProduce());
|
||||
@ -1886,7 +1886,7 @@ TYPED_TEST(TestPlanner, DistributedOptionalExpand) {
|
||||
auto *query = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(node_n)),
|
||||
OPTIONAL_MATCH(PATTERN(node_n, edge_e, node_m)), ret_e));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto sym_e = symbol_table.at(*ret_e->body_.named_expressions[0]);
|
||||
std::list<BaseOpChecker *> optional{new ExpectDistributedExpand()};
|
||||
auto expected = ExpectDistributed(
|
||||
@ -1908,7 +1908,7 @@ TYPED_TEST(TestPlanner, DistributedOptionalCartesian) {
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(node_a)), OPTIONAL_MATCH(PATTERN(node_b), PATTERN(node_c)),
|
||||
WHERE(GREATER(node_b->identifier_, node_a->identifier_)), RETURN("c")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto sym_a = symbol_table.at(*node_a->identifier_);
|
||||
auto sym_b = symbol_table.at(*node_b->identifier_);
|
||||
auto sym_c = symbol_table.at(*node_c->identifier_);
|
||||
@ -1941,7 +1941,7 @@ TYPED_TEST(TestPlanner, DistributedCartesianTransitiveDependency) {
|
||||
auto *edge_b = EDGE("b");
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(node_n, edge_a, node_m, edge_b, node_l)), RETURN("l")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto sym_a = symbol_table.at(*edge_a->identifier_);
|
||||
auto sym_b = symbol_table.at(*edge_b->identifier_);
|
||||
auto sym_n = symbol_table.at(*node_n->identifier_);
|
||||
@ -1979,7 +1979,7 @@ TYPED_TEST(TestPlanner, DistributedOptionalScanExpandExisting) {
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(node_a)),
|
||||
OPTIONAL_MATCH(PATTERN(node_b, EDGE("e"), NODE("a"))), RETURN("e")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto sym_a = symbol_table.at(*node_a->identifier_);
|
||||
auto sym_b = symbol_table.at(*node_b->identifier_);
|
||||
std::list<BaseOpChecker *> optional{new ExpectScanAll(),
|
||||
|
@ -66,7 +66,7 @@ auto CheckPlan(LogicalOperator &plan, const SymbolTable &symbol_table,
|
||||
template <class TPlanner, class... TChecker>
|
||||
auto CheckPlan(query::CypherQuery *query, AstStorage &storage,
|
||||
TChecker... checker) {
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TPlanner>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, checker...);
|
||||
@ -84,7 +84,7 @@ TYPED_TEST(TestPlanner, MatchNodeReturn) {
|
||||
AstStorage storage;
|
||||
auto *as_n = NEXPR("n", IDENT("n"));
|
||||
auto *query = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"))), RETURN(as_n)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAll(), ExpectProduce());
|
||||
@ -96,7 +96,7 @@ TYPED_TEST(TestPlanner, CreateNodeReturn) {
|
||||
auto ident_n = IDENT("n");
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(CREATE(PATTERN(NODE("n"))), RETURN(ident_n, AS("n"))));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto acc = ExpectAccumulate({symbol_table.at(*ident_n)});
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
@ -166,7 +166,7 @@ TYPED_TEST(TestPlanner, MatchLabeledNodes) {
|
||||
auto *as_n = NEXPR("n", IDENT("n"));
|
||||
auto *query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n", label))), RETURN(as_n)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAllByLabel(),
|
||||
ExpectProduce());
|
||||
@ -182,7 +182,7 @@ TYPED_TEST(TestPlanner, MatchPathReturn) {
|
||||
MATCH(PATTERN(NODE("n"), EDGE("r", Direction::BOTH, {relationship}),
|
||||
NODE("m"))),
|
||||
RETURN(as_n)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAll(), ExpectExpand(),
|
||||
ExpectProduce());
|
||||
@ -199,7 +199,7 @@ TYPED_TEST(TestPlanner, MatchNamedPatternReturn) {
|
||||
EDGE("r", Direction::BOTH, {relationship}),
|
||||
NODE("m"))),
|
||||
RETURN(as_p)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAll(), ExpectExpand(),
|
||||
ExpectConstructNamedPath(), ExpectProduce());
|
||||
@ -216,7 +216,7 @@ TYPED_TEST(TestPlanner, MatchNamedPatternWithPredicateReturn) {
|
||||
EDGE("r", Direction::BOTH, {relationship}),
|
||||
NODE("m"))),
|
||||
WHERE(EQ(LITERAL(2), IDENT("p"))), RETURN(as_p)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAll(), ExpectExpand(),
|
||||
ExpectConstructNamedPath(), ExpectFilter(), ExpectProduce());
|
||||
@ -231,7 +231,7 @@ TYPED_TEST(TestPlanner, OptionalMatchNamedPatternReturn) {
|
||||
auto pattern = NAMED_PATTERN("p", node_n, edge, node_m);
|
||||
auto as_p = AS("p");
|
||||
auto *query = QUERY(SINGLE_QUERY(OPTIONAL_MATCH(pattern), RETURN("p", as_p)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto get_symbol = [&symbol_table](const auto *ast_node) {
|
||||
return symbol_table.at(*ast_node->identifier_);
|
||||
};
|
||||
@ -254,7 +254,7 @@ TYPED_TEST(TestPlanner, MatchWhereReturn) {
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(NODE("n"))),
|
||||
WHERE(LESS(PROPERTY_LOOKUP("n", property), LITERAL(42))), RETURN(as_n)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAll(), ExpectFilter(),
|
||||
ExpectProduce());
|
||||
@ -350,7 +350,7 @@ TYPED_TEST(TestPlanner, MultiMatch) {
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(node_n, edge_r, node_m)),
|
||||
MATCH(PATTERN(node_j, edge_e, node_i, edge_f, node_h)), RETURN("n")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
// Multiple MATCH clauses form a Cartesian product, so the uniqueness should
|
||||
@ -369,7 +369,7 @@ TYPED_TEST(TestPlanner, MultiMatchSameStart) {
|
||||
MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))), RETURN(as_n)));
|
||||
// Similar to MatchMultiPatternSameStart, we expect only Expand from second
|
||||
// MATCH clause.
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAll(), ExpectExpand(),
|
||||
@ -383,7 +383,7 @@ TYPED_TEST(TestPlanner, MatchWithReturn) {
|
||||
auto *query = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("old"))),
|
||||
WITH("old", AS("new")), RETURN(as_new)));
|
||||
// No accumulation since we only do reads.
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAll(), ExpectProduce(),
|
||||
@ -400,7 +400,7 @@ TYPED_TEST(TestPlanner, MatchWithWhereReturn) {
|
||||
MATCH(PATTERN(NODE("old"))), WITH("old", AS("new")),
|
||||
WHERE(LESS(PROPERTY_LOOKUP("new", prop), LITERAL(42))), RETURN(as_new)));
|
||||
// No accumulation since we only do reads.
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAll(), ExpectProduce(),
|
||||
ExpectFilter(), ExpectProduce());
|
||||
@ -446,7 +446,7 @@ TYPED_TEST(TestPlanner, MatchReturnSum) {
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(NODE("n"))), RETURN(sum, AS("sum"), n_prop2, AS("group"))));
|
||||
auto aggr = ExpectAggregate({sum}, {n_prop2});
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAll(), aggr,
|
||||
ExpectProduce());
|
||||
@ -461,7 +461,7 @@ TYPED_TEST(TestPlanner, CreateWithSum) {
|
||||
auto sum = SUM(n_prop);
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(CREATE(PATTERN(NODE("n"))), WITH(sum, AS("sum"))));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto acc = ExpectAccumulate({symbol_table.at(*n_prop->expression_)});
|
||||
auto aggr = ExpectAggregate({sum}, {});
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
@ -491,7 +491,7 @@ TYPED_TEST(TestPlanner, MatchReturnSkipLimit) {
|
||||
auto *query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"))),
|
||||
RETURN(as_n, SKIP(LITERAL(2)), LIMIT(LITERAL(1)))));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAll(), ExpectProduce(),
|
||||
@ -505,7 +505,7 @@ TYPED_TEST(TestPlanner, CreateWithSkipReturnLimit) {
|
||||
auto query = QUERY(SINGLE_QUERY(CREATE(PATTERN(NODE("n"))),
|
||||
WITH(ident_n, AS("m"), SKIP(LITERAL(2))),
|
||||
RETURN("m", LIMIT(LITERAL(1)))));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto acc = ExpectAccumulate({symbol_table.at(*ident_n)});
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
@ -528,7 +528,7 @@ TYPED_TEST(TestPlanner, CreateReturnSumSkipLimit) {
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(CREATE(PATTERN(NODE("n"))),
|
||||
RETURN(sum, AS("s"), SKIP(LITERAL(2)), LIMIT(LITERAL(1)))));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto acc = ExpectAccumulate({symbol_table.at(*n_prop->expression_)});
|
||||
auto aggr = ExpectAggregate({sum}, {});
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
@ -545,7 +545,7 @@ TYPED_TEST(TestPlanner, MatchReturnOrderBy) {
|
||||
auto *node_n = NODE("n");
|
||||
auto ret = RETURN(as_m, ORDER_BY(PROPERTY_LOOKUP("n", prop)));
|
||||
auto *query = QUERY(SINGLE_QUERY(MATCH(PATTERN(node_n)), ret));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAll(), ExpectProduce(),
|
||||
ExpectOrderBy());
|
||||
@ -567,7 +567,7 @@ TYPED_TEST(TestPlanner, CreateWithOrderByWhere) {
|
||||
PATTERN(NODE("n"), EDGE("r", Direction::OUT, {r_type}), NODE("m"))),
|
||||
WITH(ident_n, AS("new"), ORDER_BY(new_prop, r_prop)),
|
||||
WHERE(LESS(m_prop, LITERAL(42)))));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Since this is a write query, we expect to accumulate to old used symbols.
|
||||
auto acc = ExpectAccumulate({
|
||||
symbol_table.at(*ident_n), // `n` in WITH
|
||||
@ -610,7 +610,7 @@ TYPED_TEST(TestPlanner, MatchMerge) {
|
||||
new ExpectSetProperty()};
|
||||
std::list<BaseOpChecker *> on_create{new ExpectCreateExpand(),
|
||||
new ExpectSetProperties()};
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// We expect Accumulate after Merge, because it is considered as a write.
|
||||
auto acc = ExpectAccumulate({symbol_table.at(*ident_n)});
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
@ -646,7 +646,7 @@ TYPED_TEST(TestPlanner, MatchUnwindReturn) {
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("n"))),
|
||||
UNWIND(LIST(LITERAL(1), LITERAL(2), LITERAL(3)), AS("x")),
|
||||
RETURN(as_n, as_x)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAll(), ExpectUnwind(),
|
||||
@ -673,7 +673,7 @@ TYPED_TEST(TestPlanner, CreateWithDistinctSumWhereReturn) {
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(CREATE(PATTERN(node_n)), WITH_DISTINCT(sum, AS("s")),
|
||||
WHERE(LESS(IDENT("s"), LITERAL(42))), RETURN("s")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto acc = ExpectAccumulate({symbol_table.at(*node_n->identifier_)});
|
||||
auto aggr = ExpectAggregate({sum}, {});
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
@ -710,7 +710,7 @@ TYPED_TEST(TestPlanner, MatchWhereBeforeExpand) {
|
||||
MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
|
||||
WHERE(LESS(PROPERTY_LOOKUP("n", prop), LITERAL(42))), RETURN(as_n)));
|
||||
// We expect Filter to come immediately after ScanAll, since it only uses `n`.
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAll(), ExpectFilter(),
|
||||
ExpectExpand(), ExpectProduce());
|
||||
@ -757,7 +757,7 @@ TYPED_TEST(TestPlanner, MatchReturnAsterisk) {
|
||||
ret->body_.all_identifiers = true;
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"), EDGE("e"), NODE("m"))), ret));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAll(), ExpectExpand(),
|
||||
ExpectProduce());
|
||||
@ -778,7 +778,7 @@ TYPED_TEST(TestPlanner, MatchReturnAsteriskSum) {
|
||||
auto ret = RETURN(sum, AS("s"));
|
||||
ret->body_.all_identifiers = true;
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"))), ret));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
auto *produce = dynamic_cast<Produce *>(&planner.plan());
|
||||
ASSERT_TRUE(produce);
|
||||
@ -949,7 +949,7 @@ TYPED_TEST(TestPlanner, AtomIndexedLabelProperty) {
|
||||
node->properties_[property] = lit_42;
|
||||
node->properties_[not_indexed] = LITERAL(0);
|
||||
auto *query = QUERY(SINGLE_QUERY(MATCH(PATTERN(node)), RETURN("n")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table,
|
||||
ExpectScanAllByLabelPropertyValue(label, property, lit_42),
|
||||
@ -973,7 +973,7 @@ TYPED_TEST(TestPlanner, AtomPropertyWhereLabelIndexing) {
|
||||
storage.Create<query::LabelsTest>(
|
||||
IDENT("n"), std::vector<storage::Label>{label}))),
|
||||
RETURN("n")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table,
|
||||
ExpectScanAllByLabelPropertyValue(label, property, lit_42),
|
||||
@ -991,7 +991,7 @@ TYPED_TEST(TestPlanner, WhereIndexedLabelProperty) {
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(NODE("n", label))),
|
||||
WHERE(EQ(PROPERTY_LOOKUP("n", property), lit_42)), RETURN("n")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table,
|
||||
ExpectScanAllByLabelPropertyValue(label, property, lit_42),
|
||||
@ -1015,7 +1015,7 @@ TYPED_TEST(TestPlanner, BestPropertyIndexed) {
|
||||
WHERE(AND(EQ(PROPERTY_LOOKUP("n", property), LITERAL(1)),
|
||||
EQ(PROPERTY_LOOKUP("n", better), lit_42))),
|
||||
RETURN("n")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table,
|
||||
ExpectScanAllByLabelPropertyValue(label, better, lit_42),
|
||||
@ -1040,7 +1040,7 @@ TYPED_TEST(TestPlanner, MultiPropertyIndexScan) {
|
||||
WHERE(AND(EQ(PROPERTY_LOOKUP("n", prop1), lit_1),
|
||||
EQ(PROPERTY_LOOKUP("m", prop2), lit_2))),
|
||||
RETURN("n", "m")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table,
|
||||
ExpectScanAllByLabelPropertyValue(label1, prop1, lit_1),
|
||||
@ -1065,7 +1065,7 @@ TYPED_TEST(TestPlanner, WhereIndexedLabelPropertyRange) {
|
||||
AstStorage storage;
|
||||
auto *query = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n", label))),
|
||||
WHERE(rel_expr), RETURN("n")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table,
|
||||
ExpectScanAllByLabelPropertyRange(label, property, lower_bound,
|
||||
@ -1109,7 +1109,7 @@ TYPED_TEST(TestPlanner, UnableToUsePropertyIndex) {
|
||||
MATCH(PATTERN(NODE("n", label))),
|
||||
WHERE(EQ(PROPERTY_LOOKUP("n", property), PROPERTY_LOOKUP("n", property))),
|
||||
RETURN("n")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
// We can only get ScanAllByLabelIndex, because we are comparing properties
|
||||
// with those on the same node.
|
||||
@ -1129,7 +1129,7 @@ TYPED_TEST(TestPlanner, SecondPropertyIndex) {
|
||||
auto *query = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("n", label)), PATTERN(NODE("m", label))),
|
||||
WHERE(EQ(m_prop, n_prop)), RETURN("n")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(
|
||||
planner.plan(), symbol_table, ExpectScanAllByLabel(),
|
||||
@ -1210,7 +1210,7 @@ TYPED_TEST(TestPlanner, MatchExpandVariableTotalWeightSymbol) {
|
||||
IDENT("total_weight"));
|
||||
auto *query = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("n"), edge, NODE("m"))), RETURN("*")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
auto *root = dynamic_cast<Produce *>(&planner.plan());
|
||||
|
||||
@ -1258,7 +1258,7 @@ TYPED_TEST(TestPlanner, MatchBfs) {
|
||||
auto *as_r = NEXPR("r", IDENT("r"));
|
||||
auto *query = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("n"), bfs, NODE("m"))), RETURN(as_r)));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectScanAll(), ExpectExpandBfs(),
|
||||
ExpectProduce());
|
||||
@ -1271,7 +1271,7 @@ TYPED_TEST(TestPlanner, MatchDoubleScanToExpandExisting) {
|
||||
AstStorage storage;
|
||||
auto *query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m", label))), RETURN("r")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
// We expect 2x ScanAll and then Expand, since we are guessing that is
|
||||
// faster (due to low label index vertex count).
|
||||
@ -1293,7 +1293,7 @@ TYPED_TEST(TestPlanner, MatchScanToExpand) {
|
||||
node_m->properties_[std::make_pair("property", property)] = LITERAL(1);
|
||||
auto *query = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), node_m)), RETURN("r")));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
// We expect 1x ScanAll and then Expand, since we are guessing that
|
||||
// is faster (due to high label index vertex count).
|
||||
@ -1326,7 +1326,7 @@ TYPED_TEST(TestPlanner, ReturnAsteriskOmitsLambdaSymbols) {
|
||||
ret->body_.all_identifiers = true;
|
||||
auto *query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"), edge, NODE("m"))), ret));
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
FakeDbAccessor dba;
|
||||
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table, query);
|
||||
auto *produce = dynamic_cast<Produce *>(&planner.plan());
|
||||
|
@ -343,13 +343,6 @@ std::list<std::unique_ptr<BaseOpChecker>> MakeCheckers(T arg, Rest &&... rest) {
|
||||
return std::move(l);
|
||||
}
|
||||
|
||||
auto MakeSymbolTable(query::Query &query) {
|
||||
SymbolTable symbol_table;
|
||||
SymbolGenerator symbol_generator(symbol_table);
|
||||
query.Accept(symbol_generator);
|
||||
return symbol_table;
|
||||
}
|
||||
|
||||
template <class TPlanner, class TDbAccessor>
|
||||
TPlanner MakePlanner(const TDbAccessor &dba, AstStorage &storage,
|
||||
SymbolTable &symbol_table, CypherQuery *query) {
|
||||
|
@ -18,8 +18,6 @@ class TestSymbolGenerator : public ::testing::Test {
|
||||
database::GraphDb db;
|
||||
std::unique_ptr<database::GraphDbAccessor> dba_ptr{db.Access()};
|
||||
database::GraphDbAccessor &dba{*dba_ptr};
|
||||
SymbolTable symbol_table;
|
||||
SymbolGenerator symbol_generator{symbol_table};
|
||||
AstStorage storage;
|
||||
};
|
||||
|
||||
@ -27,7 +25,7 @@ TEST_F(TestSymbolGenerator, MatchNodeReturn) {
|
||||
// MATCH (node_atom_1) RETURN node_atom_1
|
||||
auto query_ast = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("node_atom_1"))), RETURN("node_atom_1")));
|
||||
query_ast->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query_ast);
|
||||
// symbols for pattern, node_atom_1 and named_expr in return
|
||||
EXPECT_EQ(symbol_table.max_position(), 3);
|
||||
auto match = dynamic_cast<Match *>(query_ast->single_query_->clauses_[0]);
|
||||
@ -52,7 +50,7 @@ TEST_F(TestSymbolGenerator, MatchNamedPattern) {
|
||||
// MATCH p = (node_atom_1) RETURN node_atom_1
|
||||
auto query_ast = QUERY(SINGLE_QUERY(
|
||||
MATCH(NAMED_PATTERN("p", NODE("node_atom_1"))), RETURN("p")));
|
||||
query_ast->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query_ast);
|
||||
// symbols for p, node_atom_1 and named_expr in return
|
||||
EXPECT_EQ(symbol_table.max_position(), 3);
|
||||
auto match = dynamic_cast<Match *>(query_ast->single_query_->clauses_[0]);
|
||||
@ -69,13 +67,13 @@ TEST_F(TestSymbolGenerator, MatchUnboundMultiReturn) {
|
||||
// MATCH (node_atom_1) RETURN node_atom_1 AS n, n
|
||||
auto query_ast = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("node_atom_1"))),
|
||||
RETURN("node_atom_1", AS("n"), "n")));
|
||||
EXPECT_THROW(query_ast->Accept(symbol_generator), UnboundVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query_ast), UnboundVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchNodeUnboundReturn) {
|
||||
// AST with unbound variable in return: MATCH (n) RETURN x
|
||||
auto query_ast = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"))), RETURN("x")));
|
||||
EXPECT_THROW(query_ast->Accept(symbol_generator), UnboundVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query_ast), UnboundVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, CreatePropertyUnbound) {
|
||||
@ -83,13 +81,13 @@ TEST_F(TestSymbolGenerator, CreatePropertyUnbound) {
|
||||
auto node = NODE("anon");
|
||||
node->properties_[PROPERTY_PAIR("prop")] = IDENT("x");
|
||||
auto query_ast = QUERY(SINGLE_QUERY(CREATE(PATTERN(node))));
|
||||
EXPECT_THROW(query_ast->Accept(symbol_generator), UnboundVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query_ast), UnboundVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, CreateNodeReturn) {
|
||||
// Simple AST returning a created node: CREATE (n) RETURN n
|
||||
auto query_ast = QUERY(SINGLE_QUERY(CREATE(PATTERN(NODE("n"))), RETURN("n")));
|
||||
query_ast->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query_ast);
|
||||
// symbols for pattern, `n` and named_expr
|
||||
EXPECT_EQ(symbol_table.max_position(), 3);
|
||||
auto create = dynamic_cast<Create *>(query_ast->single_query_->clauses_[0]);
|
||||
@ -111,7 +109,7 @@ TEST_F(TestSymbolGenerator, CreateRedeclareNode) {
|
||||
// AST with redeclaring a variable when creating nodes: CREATE (n), (n)
|
||||
auto query_ast =
|
||||
QUERY(SINGLE_QUERY(CREATE(PATTERN(NODE("n")), PATTERN(NODE("n")))));
|
||||
EXPECT_THROW(query_ast->Accept(symbol_generator), RedeclareVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query_ast), RedeclareVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MultiCreateRedeclareNode) {
|
||||
@ -119,14 +117,14 @@ TEST_F(TestSymbolGenerator, MultiCreateRedeclareNode) {
|
||||
// CREATE (n) CREATE (n)
|
||||
auto query_ast = QUERY(
|
||||
SINGLE_QUERY(CREATE(PATTERN(NODE("n"))), CREATE(PATTERN(NODE("n")))));
|
||||
EXPECT_THROW(query_ast->Accept(symbol_generator), RedeclareVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query_ast), RedeclareVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchCreateRedeclareNode) {
|
||||
// AST with redeclaring a match node variable in create: MATCH (n) CREATE (n)
|
||||
auto query_ast = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("n"))), CREATE(PATTERN(NODE("n")))));
|
||||
EXPECT_THROW(query_ast->Accept(symbol_generator), RedeclareVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query_ast), RedeclareVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchCreateRedeclareEdge) {
|
||||
@ -138,7 +136,7 @@ TEST_F(TestSymbolGenerator, MatchCreateRedeclareEdge) {
|
||||
CREATE(PATTERN(NODE("n"),
|
||||
EDGE("r", EdgeAtom::Direction::OUT, {relationship}),
|
||||
NODE("l")))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), RedeclareVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), RedeclareVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchTypeMismatch) {
|
||||
@ -146,7 +144,7 @@ TEST_F(TestSymbolGenerator, MatchTypeMismatch) {
|
||||
// MATCH (n) -[r]-> (r)
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("r")))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), TypeMismatchError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), TypeMismatchError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchCreateTypeMismatch) {
|
||||
@ -156,7 +154,7 @@ TEST_F(TestSymbolGenerator, MatchCreateTypeMismatch) {
|
||||
MATCH(PATTERN(NODE("n1"), EDGE("r1"), NODE("n2"))),
|
||||
CREATE(PATTERN(NODE("r1"), EDGE("r2", EdgeAtom::Direction::OUT),
|
||||
NODE("n2")))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), TypeMismatchError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), TypeMismatchError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, CreateMultipleEdgeType) {
|
||||
@ -167,7 +165,7 @@ TEST_F(TestSymbolGenerator, CreateMultipleEdgeType) {
|
||||
auto edge = EDGE("r", EdgeAtom::Direction::OUT, {rel1});
|
||||
edge->edge_types_.emplace_back(rel2);
|
||||
auto query = QUERY(SINGLE_QUERY(CREATE(PATTERN(NODE("n"), edge, NODE("m")))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, CreateBidirectionalEdge) {
|
||||
@ -176,7 +174,7 @@ TEST_F(TestSymbolGenerator, CreateBidirectionalEdge) {
|
||||
auto rel1 = dba.EdgeType("rel1");
|
||||
auto query = QUERY(SINGLE_QUERY(CREATE(PATTERN(
|
||||
NODE("n"), EDGE("r", EdgeAtom::Direction::BOTH, {rel1}), NODE("m")))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchWhereUnbound) {
|
||||
@ -184,7 +182,7 @@ TEST_F(TestSymbolGenerator, MatchWhereUnbound) {
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"))),
|
||||
WHERE(LESS(IDENT("missing"), LITERAL(42))),
|
||||
RETURN("n")));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), UnboundVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), UnboundVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, CreateDelete) {
|
||||
@ -192,7 +190,7 @@ TEST_F(TestSymbolGenerator, CreateDelete) {
|
||||
auto node = NODE("n");
|
||||
auto ident = IDENT("n");
|
||||
auto query = QUERY(SINGLE_QUERY(CREATE(PATTERN(node)), DELETE(ident)));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// symbols for pattern and `n`
|
||||
EXPECT_EQ(symbol_table.max_position(), 2);
|
||||
auto node_symbol = symbol_table.at(*node->identifier_);
|
||||
@ -205,7 +203,7 @@ TEST_F(TestSymbolGenerator, CreateDeleteUnbound) {
|
||||
// Test CREATE (n) DELETE missing
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(CREATE(PATTERN(NODE("n"))), DELETE(IDENT("missing"))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), UnboundVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), UnboundVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchWithReturn) {
|
||||
@ -218,7 +216,7 @@ TEST_F(TestSymbolGenerator, MatchWithReturn) {
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(node)), WITH(old_ident, with_as_n),
|
||||
RETURN(n_ident, ret_as_n)));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// symbols for pattern, `old`, `n` and named_expr in return
|
||||
EXPECT_EQ(symbol_table.max_position(), 4);
|
||||
auto node_symbol = symbol_table.at(*node->identifier_);
|
||||
@ -236,7 +234,7 @@ TEST_F(TestSymbolGenerator, MatchWithReturnUnbound) {
|
||||
// Test MATCH (old) WITH old AS n RETURN old
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("old"))),
|
||||
WITH("old", AS("n")), RETURN("old")));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), UnboundVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), UnboundVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchWithWhere) {
|
||||
@ -249,7 +247,7 @@ TEST_F(TestSymbolGenerator, MatchWithWhere) {
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(node)), WITH(old_ident, with_as_n),
|
||||
WHERE(LESS(n_prop, LITERAL(42)))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// symbols for pattern, `old` and `n`
|
||||
EXPECT_EQ(symbol_table.max_position(), 3);
|
||||
auto node_symbol = symbol_table.at(*node->identifier_);
|
||||
@ -267,7 +265,7 @@ TEST_F(TestSymbolGenerator, MatchWithWhereUnbound) {
|
||||
auto query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(NODE("old"))), WITH(COUNT(IDENT("old")), AS("c")),
|
||||
WHERE(LESS(PROPERTY_LOOKUP("old", prop), LITERAL(42)))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), UnboundVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), UnboundVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, CreateMultiExpand) {
|
||||
@ -282,7 +280,7 @@ TEST_F(TestSymbolGenerator, CreateMultiExpand) {
|
||||
auto node_l = NODE("l");
|
||||
auto query = QUERY(SINGLE_QUERY(CREATE(PATTERN(node_n1, edge_r, node_m),
|
||||
PATTERN(node_n2, edge_p, node_l))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// symbols for pattern * 2, `n`, `r`, `m`, `p`, `l`
|
||||
EXPECT_EQ(symbol_table.max_position(), 7);
|
||||
auto n1 = symbol_table.at(*node_n1->identifier_);
|
||||
@ -311,7 +309,7 @@ TEST_F(TestSymbolGenerator, MatchCreateExpandLabel) {
|
||||
MATCH(PATTERN(NODE("n"))),
|
||||
CREATE(PATTERN(NODE("m"), EDGE("r", EdgeAtom::Direction::OUT, {r_type}),
|
||||
NODE("n", label)))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, CreateExpandProperty) {
|
||||
@ -321,7 +319,7 @@ TEST_F(TestSymbolGenerator, CreateExpandProperty) {
|
||||
n_prop->properties_[PROPERTY_PAIR("prop")] = LITERAL(42);
|
||||
auto query = QUERY(SINGLE_QUERY(CREATE(PATTERN(
|
||||
NODE("n"), EDGE("r", EdgeAtom::Direction::OUT, {r_type}), n_prop))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchReturnSum) {
|
||||
@ -332,7 +330,7 @@ TEST_F(TestSymbolGenerator, MatchReturnSum) {
|
||||
auto as_result = AS("result");
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(node)),
|
||||
RETURN(ADD(sum, LITERAL(42)), as_result)));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// 3 symbols for: pattern, 'n', 'sum' and 'result'.
|
||||
EXPECT_EQ(symbol_table.max_position(), 4);
|
||||
auto node_symbol = symbol_table.at(*node->identifier_);
|
||||
@ -349,7 +347,7 @@ TEST_F(TestSymbolGenerator, NestedAggregation) {
|
||||
auto query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(NODE("n"))),
|
||||
RETURN(SUM(ADD(LITERAL(42), SUM(PROPERTY_LOOKUP("n", prop)))), AS("s"))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, WrongAggregationContext) {
|
||||
@ -358,7 +356,7 @@ TEST_F(TestSymbolGenerator, WrongAggregationContext) {
|
||||
auto query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(NODE("n"))), WITH(PROPERTY_LOOKUP("n", prop), AS("prop")),
|
||||
WHERE(LESS(SUM(IDENT("prop")), LITERAL(42)))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchPropCreateNodeProp) {
|
||||
@ -370,7 +368,7 @@ TEST_F(TestSymbolGenerator, MatchPropCreateNodeProp) {
|
||||
node_m->properties_[prop] = n_prop;
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(node_n)), CREATE(PATTERN(node_m))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// symbols: pattern * 2, `node_n`, `node_m`
|
||||
EXPECT_EQ(symbol_table.max_position(), 4);
|
||||
auto n = symbol_table.at(*node_n->identifier_);
|
||||
@ -388,7 +386,7 @@ TEST_F(TestSymbolGenerator, CreateNodeEdge) {
|
||||
auto node_3 = NODE("n");
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(CREATE(PATTERN(node_1), PATTERN(node_2, edge, node_3))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// symbols: pattern * 2, `n`, `r`
|
||||
EXPECT_EQ(symbol_table.max_position(), 4);
|
||||
auto n = symbol_table.at(*node_1->identifier_);
|
||||
@ -406,7 +404,7 @@ TEST_F(TestSymbolGenerator, MatchWithCreate) {
|
||||
auto node_3 = NODE("m");
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(node_1)), WITH("n", AS("m")),
|
||||
CREATE(PATTERN(node_2, edge, node_3))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// symbols: pattern * 2, `n`, `m`, `r`
|
||||
EXPECT_EQ(symbol_table.max_position(), 5);
|
||||
auto n = symbol_table.at(*node_1->identifier_);
|
||||
@ -422,34 +420,34 @@ TEST_F(TestSymbolGenerator, SameResultsWith) {
|
||||
// Test MATCH (n) WITH n AS m, n AS m
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"))),
|
||||
WITH("n", AS("m"), "n", AS("m"))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, SameResults) {
|
||||
// Test MATCH (n) RETURN n, n
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"))), RETURN("n", "n")));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, SkipUsingIdentifier) {
|
||||
// Test MATCH (old) WITH old AS new SKIP old
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("old"))),
|
||||
WITH("old", AS("new"), SKIP(IDENT("old")))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, SkipUsingIdentifierAlias) {
|
||||
// Test MATCH (old) WITH old AS new SKIP new
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("old"))),
|
||||
WITH("old", AS("new"), SKIP(IDENT("new")))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, LimitUsingIdentifier) {
|
||||
// Test MATCH (n) RETURN n AS n LIMIT n
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("n"))), RETURN("n", LIMIT(IDENT("n")))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, OrderByAggregation) {
|
||||
@ -457,7 +455,7 @@ TEST_F(TestSymbolGenerator, OrderByAggregation) {
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("old"))),
|
||||
RETURN("old", AS("new"), ORDER_BY(COUNT(LITERAL(1))))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, OrderByUnboundVariable) {
|
||||
@ -465,7 +463,7 @@ TEST_F(TestSymbolGenerator, OrderByUnboundVariable) {
|
||||
auto query = QUERY(SINGLE_QUERY(
|
||||
MATCH(PATTERN(NODE("old"))),
|
||||
RETURN(COUNT(IDENT("old")), AS("new"), ORDER_BY(IDENT("old")))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), UnboundVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), UnboundVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, AggregationOrderBy) {
|
||||
@ -477,7 +475,7 @@ TEST_F(TestSymbolGenerator, AggregationOrderBy) {
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(node)), RETURN(COUNT(ident_old), as_new,
|
||||
ORDER_BY(ident_new))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Symbols for pattern, `old`, `count(old)` and `new`
|
||||
EXPECT_EQ(symbol_table.max_position(), 4);
|
||||
auto old = symbol_table.at(*node->identifier_);
|
||||
@ -495,7 +493,7 @@ TEST_F(TestSymbolGenerator, OrderByOldVariable) {
|
||||
auto by_old = IDENT("old");
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(node)),
|
||||
RETURN(ident_old, as_new, ORDER_BY(by_old))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Symbols for pattern, `old` and `new`
|
||||
EXPECT_EQ(symbol_table.max_position(), 3);
|
||||
auto old = symbol_table.at(*node->identifier_);
|
||||
@ -509,7 +507,7 @@ TEST_F(TestSymbolGenerator, MergeVariableError) {
|
||||
// Test MATCH (n) MERGE (n)
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"))), MERGE(PATTERN(NODE("n")))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), RedeclareVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), RedeclareVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MergeVariableErrorEdge) {
|
||||
@ -519,7 +517,7 @@ TEST_F(TestSymbolGenerator, MergeVariableErrorEdge) {
|
||||
MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
|
||||
MERGE(PATTERN(NODE("a"), EDGE("r", EdgeAtom::Direction::BOTH, {rel}),
|
||||
NODE("b")))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), RedeclareVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), RedeclareVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MergeEdgeWithoutType) {
|
||||
@ -527,7 +525,7 @@ TEST_F(TestSymbolGenerator, MergeEdgeWithoutType) {
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(MERGE(PATTERN(NODE("a"), EDGE("r"), NODE("b")))));
|
||||
// Edge must have a type, since it doesn't we raise.
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MergeOnMatchOnCreate) {
|
||||
@ -548,7 +546,7 @@ TEST_F(TestSymbolGenerator, MergeOnMatchOnCreate) {
|
||||
ON_MATCH(SET(n_prop, LITERAL(42))),
|
||||
ON_CREATE(SET(m_prop, LITERAL(42)))),
|
||||
RETURN(ident_r, as_r)));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Symbols for: pattern * 2, `n`, `r`, `m` and `AS r`.
|
||||
EXPECT_EQ(symbol_table.max_position(), 6);
|
||||
auto n = symbol_table.at(*match_n->identifier_);
|
||||
@ -570,7 +568,7 @@ TEST_F(TestSymbolGenerator, WithUnwindRedeclareReturn) {
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(WITH(LIST(LITERAL(1), LITERAL(2)), AS("list")),
|
||||
UNWIND(IDENT("list"), AS("list")), RETURN("list")));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), RedeclareVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), RedeclareVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, WithUnwindReturn) {
|
||||
@ -584,7 +582,7 @@ TEST_F(TestSymbolGenerator, WithUnwindReturn) {
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(WITH(LIST(LITERAL(1), LITERAL(2)), with_as_list), unwind,
|
||||
RETURN(ret_list, ret_as_list, ret_elem, ret_as_elem)));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Symbols for: `list`, `elem`, `AS list`, `AS elem`
|
||||
EXPECT_EQ(symbol_table.max_position(), 4);
|
||||
const auto &list = symbol_table.at(*with_as_list);
|
||||
@ -610,7 +608,7 @@ TEST_F(TestSymbolGenerator, MatchCrossReferenceVariable) {
|
||||
auto as_n = AS("n");
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(node_n), PATTERN(node_m)),
|
||||
RETURN(ident_n, as_n)));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Symbols for pattern * 2, `n`, `m` and `AS n`
|
||||
EXPECT_EQ(symbol_table.max_position(), 5);
|
||||
auto n = symbol_table.at(*node_n->identifier_);
|
||||
@ -636,7 +634,7 @@ TEST_F(TestSymbolGenerator, MatchWithAsteriskReturnAsterisk) {
|
||||
with->body_.all_identifiers = true;
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(node_n, edge, node_m)), with, ret));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Symbols for pattern, `n`, `e`, `m`, `AS n.prop`.
|
||||
EXPECT_EQ(symbol_table.max_position(), 5);
|
||||
auto n = symbol_table.at(*node_n->identifier_);
|
||||
@ -648,7 +646,7 @@ TEST_F(TestSymbolGenerator, MatchReturnAsteriskSameResult) {
|
||||
auto ret = RETURN("n");
|
||||
ret->body_.all_identifiers = true;
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"))), ret));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchReturnAsteriskNoUserVariables) {
|
||||
@ -658,7 +656,7 @@ TEST_F(TestSymbolGenerator, MatchReturnAsteriskNoUserVariables) {
|
||||
auto ident_n = storage.Create<Identifier>("anon", false);
|
||||
auto node = storage.Create<NodeAtom>(ident_n);
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(node)), ret));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchMergeExpandLabel) {
|
||||
@ -669,7 +667,7 @@ TEST_F(TestSymbolGenerator, MatchMergeExpandLabel) {
|
||||
MATCH(PATTERN(NODE("n"))),
|
||||
MERGE(PATTERN(NODE("m"), EDGE("r", EdgeAtom::Direction::OUT, {r_type}),
|
||||
NODE("n", label)))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchEdgeWithIdentifierInProperty) {
|
||||
@ -681,7 +679,7 @@ TEST_F(TestSymbolGenerator, MatchEdgeWithIdentifierInProperty) {
|
||||
auto node_n = NODE("n");
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(node_n, edge, NODE("m"))), RETURN("r")));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Symbols for pattern, `n`, `r`, `m` and implicit in RETURN `r AS r`
|
||||
EXPECT_EQ(symbol_table.max_position(), 5);
|
||||
auto n = symbol_table.at(*node_n->identifier_);
|
||||
@ -698,7 +696,7 @@ TEST_F(TestSymbolGenerator, MatchVariablePathUsingIdentifier) {
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("n"), edge, NODE("m")), PATTERN(node_l)),
|
||||
RETURN("r")));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Symbols for pattern * 2, `n`, `r`, inner_node, inner_edge, `m`, `l` and
|
||||
// implicit in RETURN `r AS r`
|
||||
EXPECT_EQ(symbol_table.max_position(), 9);
|
||||
@ -717,7 +715,7 @@ TEST_F(TestSymbolGenerator, MatchVariablePathUsingUnboundIdentifier) {
|
||||
auto node_l = NODE("l");
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(NODE("n"), edge, NODE("m"))),
|
||||
MATCH(PATTERN(node_l)), RETURN("r")));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, CreateVariablePath) {
|
||||
@ -726,7 +724,7 @@ TEST_F(TestSymbolGenerator, CreateVariablePath) {
|
||||
auto edge =
|
||||
EDGE_VARIABLE("r", EdgeAtom::Type::DEPTH_FIRST, EdgeAtom::Direction::OUT);
|
||||
auto query = QUERY(SINGLE_QUERY(CREATE(PATTERN(NODE("n"), edge, NODE("m")))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MergeVariablePath) {
|
||||
@ -735,7 +733,7 @@ TEST_F(TestSymbolGenerator, MergeVariablePath) {
|
||||
auto edge =
|
||||
EDGE_VARIABLE("r", EdgeAtom::Type::DEPTH_FIRST, EdgeAtom::Direction::OUT);
|
||||
auto query = QUERY(SINGLE_QUERY(MERGE(PATTERN(NODE("n"), edge, NODE("m")))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, RedeclareVariablePath) {
|
||||
@ -747,7 +745,7 @@ TEST_F(TestSymbolGenerator, RedeclareVariablePath) {
|
||||
EDGE_VARIABLE("n", EdgeAtom::Type::DEPTH_FIRST, EdgeAtom::Direction::OUT);
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("n"), edge, NODE("m"))), RETURN("n")));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), RedeclareVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), RedeclareVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, VariablePathSameIdentifier) {
|
||||
@ -760,7 +758,7 @@ TEST_F(TestSymbolGenerator, VariablePathSameIdentifier) {
|
||||
edge->lower_bound_ = PROPERTY_LOOKUP("r", prop);
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("n"), edge, NODE("m"))), RETURN("r")));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), UnboundVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), UnboundVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchPropertySameIdentifier) {
|
||||
@ -772,7 +770,7 @@ TEST_F(TestSymbolGenerator, MatchPropertySameIdentifier) {
|
||||
auto n_prop = PROPERTY_LOOKUP("n", prop.second);
|
||||
node_n->properties_[prop] = n_prop;
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(node_n)), RETURN("n")));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto n = symbol_table.at(*node_n->identifier_);
|
||||
EXPECT_EQ(n, symbol_table.at(*n_prop->expression_));
|
||||
}
|
||||
@ -787,7 +785,7 @@ TEST_F(TestSymbolGenerator, WithReturnAll) {
|
||||
auto *ret_x = IDENT("x");
|
||||
auto query = QUERY(SINGLE_QUERY(WITH(LITERAL(42), with_as_x),
|
||||
RETURN(all, ret_as_x, ret_x, AS("y"))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Symbols for `WITH .. AS x`, `ALL(x ...)`, `ALL(...) AS x` and `AS y`.
|
||||
EXPECT_EQ(symbol_table.max_position(), 4);
|
||||
// Check `WITH .. AS x` is the same as `[x]` and `RETURN ... x AS y`
|
||||
@ -810,7 +808,7 @@ TEST_F(TestSymbolGenerator, WithReturnSingle) {
|
||||
auto *ret_x = IDENT("x");
|
||||
auto query = QUERY(SINGLE_QUERY(WITH(LITERAL(42), with_as_x),
|
||||
RETURN(single, ret_as_x, ret_x, AS("y"))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Symbols for `WITH .. AS x`, `SINGLE(x ...)`, `SINGLE(...) AS x` and `AS y`.
|
||||
EXPECT_EQ(symbol_table.max_position(), 4);
|
||||
// Check `WITH .. AS x` is the same as `[x]` and `RETURN ... x AS y`
|
||||
@ -836,7 +834,7 @@ TEST_F(TestSymbolGenerator, WithReturnReduce) {
|
||||
auto *ret_as_y = AS("y");
|
||||
auto query = QUERY(SINGLE_QUERY(WITH(LITERAL(42), with_as_x),
|
||||
RETURN(reduce, ret_as_x, ret_x, ret_as_y)));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Symbols for `WITH .. AS x`, `REDUCE(y, x ...)`, `REDUCE(...) AS x` and `AS
|
||||
// y`.
|
||||
EXPECT_EQ(symbol_table.max_position(), 5);
|
||||
@ -864,7 +862,7 @@ TEST_F(TestSymbolGenerator, WithReturnExtract) {
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(WITH(LIST(LITERAL(1), LITERAL(2), LITERAL(3)), with_as_x),
|
||||
RETURN(extract, ret_as_x, ret_x, ret_as_y)));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Symbols for `WITH .. AS x`, `EXTRACT(x ...)`, `EXTRACT(...) AS x` and
|
||||
// `AS y`.
|
||||
EXPECT_EQ(symbol_table.max_position(), 4);
|
||||
@ -895,7 +893,7 @@ TEST_F(TestSymbolGenerator, MatchBfsReturn) {
|
||||
auto *ret_r = IDENT("r");
|
||||
auto *query = QUERY(SINGLE_QUERY(MATCH(PATTERN(node_n, bfs, NODE("m"))),
|
||||
RETURN(ret_r, AS("r"))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Symbols for pattern, `n`, `[r]`, `r|`, `n|`, `m` and `AS r`.
|
||||
EXPECT_EQ(symbol_table.max_position(), 7);
|
||||
EXPECT_EQ(symbol_table.at(*ret_r), symbol_table.at(*bfs->identifier_));
|
||||
@ -921,7 +919,7 @@ TEST_F(TestSymbolGenerator, MatchBfsUsesEdgeSymbolError) {
|
||||
bfs->upper_bound_ = LITERAL(10);
|
||||
auto *query = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("n"), bfs, NODE("m"))), RETURN("r")));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), UnboundVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), UnboundVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchBfsUsesPreviousOuterSymbol) {
|
||||
@ -935,7 +933,7 @@ TEST_F(TestSymbolGenerator, MatchBfsUsesPreviousOuterSymbol) {
|
||||
bfs->upper_bound_ = LITERAL(10);
|
||||
auto *query =
|
||||
QUERY(SINGLE_QUERY(MATCH(PATTERN(node_a, bfs, NODE("m"))), RETURN("r")));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
EXPECT_EQ(symbol_table.at(*node_a->identifier_),
|
||||
symbol_table.at(*bfs->filter_lambda_.expression));
|
||||
}
|
||||
@ -950,7 +948,7 @@ TEST_F(TestSymbolGenerator, MatchBfsUsesLaterSymbolError) {
|
||||
bfs->upper_bound_ = LITERAL(10);
|
||||
auto *query = QUERY(
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("n"), bfs, NODE("m"))), RETURN("r")));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), UnboundVariableError);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), UnboundVariableError);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchVariableLambdaSymbols) {
|
||||
@ -968,7 +966,7 @@ TEST_F(TestSymbolGenerator, MatchVariableLambdaSymbols) {
|
||||
storage.Create<NodeAtom>(storage.Create<Identifier>("anon_end", false));
|
||||
auto query = QUERY(SINGLE_QUERY(MATCH(PATTERN(node, edge, end_node)),
|
||||
RETURN(LITERAL(42), AS("res"))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Symbols for `anon_n`, `anon_r`, `anon_inner_e`, `anon_inner_n`, `anon_end`
|
||||
// `AS res` and the auto-generated path name symbol.
|
||||
EXPECT_EQ(symbol_table.max_position(), 7);
|
||||
@ -1008,7 +1006,7 @@ TEST_F(TestSymbolGenerator, MatchWShortestReturn) {
|
||||
auto *ret_r = IDENT("r");
|
||||
auto *query = QUERY(SINGLE_QUERY(MATCH(PATTERN(node_n, shortest, NODE("m"))),
|
||||
RETURN(ret_r, AS("r"))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
// Symbols for pattern, `n`, `[r]`, `total_weight`, (`r|`, `n|`)x2, `m` and
|
||||
// `AS r`.
|
||||
EXPECT_EQ(symbol_table.max_position(), 10);
|
||||
@ -1035,7 +1033,7 @@ TEST_F(TestSymbolGenerator, MatchUnionSymbols) {
|
||||
// RETURN 5 as X UNION RETURN 6 AS x
|
||||
auto query = QUERY(SINGLE_QUERY(RETURN(LITERAL(5), AS("X"))),
|
||||
UNION(SINGLE_QUERY(RETURN(LITERAL(6), AS("X")))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
EXPECT_EQ(symbol_table.max_position(), 3);
|
||||
}
|
||||
|
||||
@ -1044,7 +1042,7 @@ TEST_F(TestSymbolGenerator, MatchUnionMultipleSymbols) {
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(RETURN(LITERAL(5), AS("X"), LITERAL(6), AS("Y"))),
|
||||
UNION(SINGLE_QUERY(RETURN(LITERAL(5), AS("Y"), LITERAL(6), AS("X")))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
EXPECT_EQ(symbol_table.max_position(), 6);
|
||||
}
|
||||
|
||||
@ -1052,7 +1050,7 @@ TEST_F(TestSymbolGenerator, MatchUnionAllSymbols) {
|
||||
// RETURN 5 as X UNION ALL RETURN 6 AS x
|
||||
auto query = QUERY(SINGLE_QUERY(RETURN(LITERAL(5), AS("X"))),
|
||||
UNION_ALL(SINGLE_QUERY(RETURN(LITERAL(6), AS("X")))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
EXPECT_EQ(symbol_table.max_position(), 3);
|
||||
}
|
||||
|
||||
@ -1062,7 +1060,7 @@ TEST_F(TestSymbolGenerator, MatchUnionAllMultipleSymbols) {
|
||||
SINGLE_QUERY(RETURN(LITERAL(5), AS("X"), LITERAL(6), AS("Y"))),
|
||||
UNION_ALL(
|
||||
SINGLE_QUERY(RETURN(LITERAL(5), AS("Y"), LITERAL(6), AS("X")))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
EXPECT_EQ(symbol_table.max_position(), 6);
|
||||
}
|
||||
|
||||
@ -1073,7 +1071,7 @@ TEST_F(TestSymbolGenerator, MatchUnionReturnAllSymbols) {
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(WITH(LITERAL(1), AS("X"), LITERAL(2), AS("Y")), ret),
|
||||
UNION(SINGLE_QUERY(RETURN(LITERAL(3), AS("X"), LITERAL(4), AS("Y")))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
EXPECT_EQ(symbol_table.max_position(), 6);
|
||||
}
|
||||
|
||||
@ -1083,7 +1081,7 @@ TEST_F(TestSymbolGenerator, MatchUnionReturnSymbols) {
|
||||
SINGLE_QUERY(WITH(LITERAL(1), AS("X"), LITERAL(2), AS("Y")),
|
||||
RETURN("Y", "X")),
|
||||
UNION(SINGLE_QUERY(RETURN(LITERAL(3), AS("X"), LITERAL(4), AS("Y")))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
EXPECT_EQ(symbol_table.max_position(), 8);
|
||||
}
|
||||
|
||||
@ -1094,7 +1092,7 @@ TEST_F(TestSymbolGenerator, MatchUnionParameterNameThrowSemanticExpcetion) {
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(WITH(LITERAL(1), AS("X"), LITERAL(2), AS("Y")), ret),
|
||||
UNION(SINGLE_QUERY(RETURN(LITERAL(3), AS("Z"), LITERAL(4), AS("Y")))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchUnionParameterNumberThrowSemanticExpcetion) {
|
||||
@ -1104,7 +1102,7 @@ TEST_F(TestSymbolGenerator, MatchUnionParameterNumberThrowSemanticExpcetion) {
|
||||
auto query =
|
||||
QUERY(SINGLE_QUERY(WITH(LITERAL(1), AS("X"), LITERAL(2), AS("Y")), ret),
|
||||
UNION(SINGLE_QUERY(RETURN(LITERAL(4), AS("Y")))));
|
||||
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
|
||||
EXPECT_THROW(query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TEST_F(TestSymbolGenerator, MatchUnion) {
|
||||
@ -1115,6 +1113,6 @@ TEST_F(TestSymbolGenerator, MatchUnion) {
|
||||
QUERY(SINGLE_QUERY(WITH(LITERAL(5), AS("X"), LITERAL(3), AS("Y")), ret),
|
||||
UNION(SINGLE_QUERY(WITH(LITERAL(9), AS("Y"), LITERAL(4), AS("X")),
|
||||
RETURN("Y", "X"))));
|
||||
query->Accept(symbol_generator);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
EXPECT_EQ(symbol_table.max_position(), 8);
|
||||
}
|
||||
|
@ -32,13 +32,6 @@ std::ostream &operator<<(std::ostream &stream,
|
||||
|
||||
namespace {
|
||||
|
||||
auto MakeSymbolTable(query::Query &query) {
|
||||
query::SymbolTable symbol_table;
|
||||
query::SymbolGenerator symbol_generator(symbol_table);
|
||||
query.Accept(symbol_generator);
|
||||
return symbol_table;
|
||||
}
|
||||
|
||||
void AssertRows(const std::vector<std::vector<TypedValue>> &datum,
|
||||
std::vector<std::vector<TypedValue>> expected) {
|
||||
auto row_equal = [](const auto &row1, const auto &row2) {
|
||||
@ -67,7 +60,7 @@ void CheckPlansProduce(
|
||||
size_t expected_plan_count, query::CypherQuery *query, AstStorage &storage,
|
||||
database::GraphDbAccessor &dba,
|
||||
std::function<void(const std::vector<std::vector<TypedValue>> &)> check) {
|
||||
auto symbol_table = MakeSymbolTable(*query);
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planning_context =
|
||||
MakePlanningContext(storage, symbol_table, query, dba);
|
||||
auto query_parts = CollectQueryParts(symbol_table, storage, query);
|
||||
|
Loading…
Reference in New Issue
Block a user