Simplify using identifiers in RETURN/WITH test macros

Reviewers: florijan, mislav.bradac

Reviewed By: mislav.bradac

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D414
This commit is contained in:
Teon Banek 2017-05-31 14:00:30 +02:00
parent 1356fd5391
commit 2951b6bdcf
3 changed files with 114 additions and 99 deletions

View File

@ -194,44 +194,75 @@ auto GetQuery(AstTreeStorage &storage, Clause *clause, T *... clauses) {
}
// Helper functions for constructing RETURN and WITH clauses.
void FillReturnBody(ReturnBody &body, NamedExpression *named_expr) {
void FillReturnBody(AstTreeStorage &storage, ReturnBody &body,
NamedExpression *named_expr) {
body.named_expressions.emplace_back(named_expr);
}
void FillReturnBody(ReturnBody &body, Limit limit) {
void FillReturnBody(AstTreeStorage &storage, ReturnBody &body,
const std::string &name) {
auto *ident = storage.Create<query::Identifier>(name);
auto *named_expr = storage.Create<query::NamedExpression>(name, ident);
body.named_expressions.emplace_back(named_expr);
}
void FillReturnBody(AstTreeStorage &storage, ReturnBody &body, Limit limit) {
body.limit = limit.expression;
}
void FillReturnBody(ReturnBody &body, Skip skip, Limit limit = Limit{}) {
void FillReturnBody(AstTreeStorage &storage, ReturnBody &body, Skip skip,
Limit limit = Limit{}) {
body.skip = skip.expression;
body.limit = limit.expression;
}
void FillReturnBody(ReturnBody &body, OrderBy order_by, Limit limit = Limit{}) {
body.order_by = order_by.expressions;
body.limit = limit.expression;
}
void FillReturnBody(ReturnBody &body, OrderBy order_by, Skip skip,
void FillReturnBody(AstTreeStorage &storage, ReturnBody &body, OrderBy order_by,
Limit limit = Limit{}) {
body.order_by = order_by.expressions;
body.limit = limit.expression;
}
void FillReturnBody(AstTreeStorage &storage, ReturnBody &body, OrderBy order_by,
Skip skip, Limit limit = Limit{}) {
body.order_by = order_by.expressions;
body.skip = skip.expression;
body.limit = limit.expression;
}
void FillReturnBody(ReturnBody &body, Expression *expr,
void FillReturnBody(AstTreeStorage &storage, ReturnBody &body, Expression *expr,
NamedExpression *named_expr) {
// This overload supports `RETURN(expr, AS(name))` construct, since
// NamedExpression does not inherit Expression.
named_expr->expression_ = expr;
body.named_expressions.emplace_back(named_expr);
}
void FillReturnBody(AstTreeStorage &storage, ReturnBody &body,
const std::string &name, NamedExpression *named_expr) {
named_expr->expression_ = storage.Create<query::Identifier>(name);
body.named_expressions.emplace_back(named_expr);
}
template <class... T>
void FillReturnBody(ReturnBody &body, Expression *expr,
void FillReturnBody(AstTreeStorage &storage, ReturnBody &body, Expression *expr,
NamedExpression *named_expr, T... rest) {
named_expr->expression_ = expr;
body.named_expressions.emplace_back(named_expr);
FillReturnBody(body, rest...);
FillReturnBody(storage, body, rest...);
}
template <class... T>
void FillReturnBody(ReturnBody &body, NamedExpression *named_expr, T... rest) {
void FillReturnBody(AstTreeStorage &storage, ReturnBody &body,
NamedExpression *named_expr, T... rest) {
body.named_expressions.emplace_back(named_expr);
FillReturnBody(body, rest...);
FillReturnBody(storage, body, rest...);
}
template <class... T>
void FillReturnBody(AstTreeStorage &storage, ReturnBody &body,
const std::string &name, NamedExpression *named_expr,
T... rest) {
named_expr->expression_ = storage.Create<query::Identifier>(name);
body.named_expressions.emplace_back(named_expr);
FillReturnBody(storage, body, rest...);
}
template <class... T>
void FillReturnBody(AstTreeStorage &storage, ReturnBody &body,
const std::string &name, T... rest) {
auto *ident = storage.Create<query::Identifier>(name);
auto *named_expr = storage.Create<query::NamedExpression>(name, ident);
body.named_expressions.emplace_back(named_expr);
FillReturnBody(storage, body, rest...);
}
///
@ -239,18 +270,20 @@ void FillReturnBody(ReturnBody &body, NamedExpression *named_expr, T... rest) {
///
/// The supported expression combination of arguments is:
///
/// (NamedExpression | (Expression NamedExpression))+ [OrderBy] [Skip] [Limit]
/// (String | NamedExpression | (Expression NamedExpression))+
/// [OrderBy] [Skip] [Limit]
///
/// When the pair (Expression NamedExpression) is given, the Expression will be
/// moved inside the NamedExpression. This is done, so that the constructs like
/// RETURN(expr, AS("name"), ...) are supported.
/// RETURN(expr, AS("name"), ...) are supported. Taking a String is a shorthand
/// for RETURN(IDENT(string), AS(string), ....).
///
/// @sa GetWith
template <class... T>
auto GetReturn(AstTreeStorage &storage, bool distinct, T... exprs) {
auto ret = storage.Create<Return>();
ret->body_.distinct = distinct;
FillReturnBody(ret->body_, exprs...);
FillReturnBody(storage, ret->body_, exprs...);
return ret;
}
@ -264,7 +297,7 @@ template <class... T>
auto GetWith(AstTreeStorage &storage, bool distinct, T... exprs) {
auto with = storage.Create<With>();
with->body_.distinct = distinct;
FillReturnBody(with->body_, exprs...);
FillReturnBody(storage, with->body_, exprs...);
return with;
}

View File

@ -227,9 +227,9 @@ auto CheckPlan(AstTreeStorage &storage, TChecker... checker) {
}
TEST(TestLogicalPlanner, MatchNodeReturn) {
// Test MATCH (n) RETURN n AS n
// Test MATCH (n) RETURN n
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"))), RETURN(IDENT("n"), AS("n")));
QUERY(MATCH(PATTERN(NODE("n"))), RETURN("n"));
CheckPlan(storage, ExpectScanAll(), ExpectProduce());
}
@ -288,36 +288,35 @@ TEST(TestLogicalPlanner, MatchCreateExpand) {
}
TEST(TestLogicalPlanner, MatchLabeledNodes) {
// Test MATCH (n :label) RETURN n AS n
// Test MATCH (n :label) RETURN n
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto label = dba->label("label");
QUERY(MATCH(PATTERN(NODE("n", label))), RETURN(IDENT("n"), AS("n")));
QUERY(MATCH(PATTERN(NODE("n", label))), RETURN("n"));
CheckPlan(storage, ExpectScanAllByLabel(), ExpectFilter(), ExpectProduce());
}
TEST(TestLogicalPlanner, MatchPathReturn) {
// Test MATCH (n) -[r :relationship]- (m) RETURN n AS n
// Test MATCH (n) -[r :relationship]- (m) RETURN n
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto relationship = dba->edge_type("relationship");
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r", relationship), NODE("m"))),
RETURN(IDENT("n"), AS("n")));
RETURN("n"));
CheckPlan(storage, ExpectScanAll(), ExpectExpand(), ExpectFilter(),
ExpectProduce());
}
TEST(TestLogicalPlanner, MatchWhereReturn) {
// Test MATCH (n) WHERE n.property < 42 RETURN n AS n
// Test MATCH (n) WHERE n.property < 42 RETURN n
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto property = dba->property("property");
QUERY(MATCH(PATTERN(NODE("n"))),
WHERE(LESS(PROPERTY_LOOKUP("n", property), LITERAL(42))),
RETURN(IDENT("n"), AS("n")));
WHERE(LESS(PROPERTY_LOOKUP("n", property), LITERAL(42))), RETURN("n"));
CheckPlan(storage, ExpectScanAll(), ExpectFilter(), ExpectProduce());
}
@ -359,7 +358,7 @@ TEST(TestLogicalPlanner, MatchMultiPattern) {
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m")),
PATTERN(NODE("j"), EDGE("e"), NODE("i"))),
RETURN(IDENT("n"), AS("n")));
RETURN("n"));
// We expect the expansions after the first to have a uniqueness filter in a
// single MATCH clause.
CheckPlan(storage, ExpectScanAll(), ExpectExpand(), ExpectScanAll(),
@ -371,7 +370,7 @@ TEST(TestLogicalPlanner, MatchMultiPatternSameStart) {
// Test MATCH (n), (n) -[e]- (m) RETURN n
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n")), PATTERN(NODE("n"), EDGE("e"), NODE("m"))),
RETURN(IDENT("n"), AS("n")));
RETURN("n"));
// We expect the second pattern to generate only an Expand, since another
// ScanAll would be redundant.
CheckPlan(storage, ExpectScanAll(), ExpectExpand(), ExpectProduce());
@ -382,7 +381,7 @@ TEST(TestLogicalPlanner, MatchMultiPatternSameExpandStart) {
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m")),
PATTERN(NODE("m"), EDGE("e"), NODE("l"))),
RETURN(IDENT("n"), AS("n")));
RETURN("n"));
// We expect the second pattern to generate only an Expand. Another
// ScanAll would be redundant, as it would generate the nodes obtained from
// expansion. Additionally, a uniqueness filter is expected.
@ -395,7 +394,7 @@ TEST(TestLogicalPlanner, MultiMatch) {
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
MATCH(PATTERN(NODE("j"), EDGE("e"), NODE("i"), EDGE("f"), NODE("h"))),
RETURN(IDENT("n"), AS("n")));
RETURN("n"));
// Multiple MATCH clauses form a Cartesian product, so the uniqueness should
// not cross MATCH boundaries.
CheckPlan(storage, ExpectScanAll(), ExpectExpand(), ExpectScanAll(),
@ -407,8 +406,7 @@ TEST(TestLogicalPlanner, MultiMatchSameStart) {
// Test MATCH (n) MATCH (n) -[r]- (m) RETURN n
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"))),
MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
RETURN(IDENT("n"), AS("n")));
MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))), RETURN("n"));
// Similar to MatchMultiPatternSameStart, we expect only Expand from second
// MATCH clause.
CheckPlan(storage, ExpectScanAll(), ExpectExpand(), ExpectProduce());
@ -418,7 +416,7 @@ TEST(TestLogicalPlanner, MatchExistingEdge) {
// Test MATCH (n) -[r]- (m) -[r]- (j) RETURN n
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"), EDGE("r"), NODE("j"))),
RETURN(IDENT("n"), AS("n")));
RETURN("n"));
// There is no ExpandUniquenessFilter for referencing the same edge.
CheckPlan(storage, ExpectScanAll(), ExpectExpand(), ExpectExpand(),
ExpectProduce());
@ -429,7 +427,7 @@ TEST(TestLogicalPlanner, MultiMatchExistingEdgeOtherEdge) {
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
MATCH(PATTERN(NODE("m"), EDGE("r"), NODE("j"), EDGE("e"), NODE("l"))),
RETURN(IDENT("n"), AS("n")));
RETURN("n"));
// We need ExpandUniquenessFilter for edge `e` against `r` in second MATCH.
CheckPlan(storage, ExpectScanAll(), ExpectExpand(), ExpectExpand(),
ExpectExpand(), ExpectExpandUniquenessFilter<EdgeAccessor>(),
@ -437,23 +435,21 @@ TEST(TestLogicalPlanner, MultiMatchExistingEdgeOtherEdge) {
}
TEST(TestLogicalPlanner, MatchWithReturn) {
// Test MATCH (old) WITH old AS new RETURN new AS new
// Test MATCH (old) WITH old AS new RETURN new
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("old"))), WITH(IDENT("old"), AS("new")),
RETURN(IDENT("new"), AS("new")));
QUERY(MATCH(PATTERN(NODE("old"))), WITH("old", AS("new")), RETURN("new"));
// No accumulation since we only do reads.
CheckPlan(storage, ExpectScanAll(), ExpectProduce(), ExpectProduce());
}
TEST(TestLogicalPlanner, MatchWithWhereReturn) {
// Test MATCH (old) WITH old AS new WHERE new.prop < 42 RETURN new AS new
// Test MATCH (old) WITH old AS new WHERE new.prop < 42 RETURN new
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->property("prop");
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("old"))), WITH(IDENT("old"), AS("new")),
WHERE(LESS(PROPERTY_LOOKUP("new", prop), LITERAL(42))),
RETURN(IDENT("new"), AS("new")));
QUERY(MATCH(PATTERN(NODE("old"))), WITH("old", AS("new")),
WHERE(LESS(PROPERTY_LOOKUP("new", prop), LITERAL(42))), RETURN("new"));
// No accumulation since we only do reads.
CheckPlan(storage, ExpectScanAll(), ExpectProduce(), ExpectFilter(),
ExpectProduce());
@ -482,8 +478,7 @@ TEST(TestLogicalPlanner, MatchWithSumWhereReturn) {
auto sum = SUM(PROPERTY_LOOKUP("n", prop));
auto literal = LITERAL(42);
QUERY(MATCH(PATTERN(NODE("n"))), WITH(ADD(sum, literal), AS("sum")),
WHERE(LESS(IDENT("sum"), LITERAL(42))),
RETURN(IDENT("sum"), AS("result")));
WHERE(LESS(IDENT("sum"), LITERAL(42))), RETURN("sum", AS("result")));
auto aggr = ExpectAggregate({sum}, {literal});
CheckPlan(storage, ExpectScanAll(), aggr, ExpectProduce(), ExpectFilter(),
ExpectProduce());
@ -530,7 +525,7 @@ TEST(TestLogicalPlanner, MatchWithCreate) {
auto r_type = dba->edge_type("r");
AstTreeStorage storage;
QUERY(
MATCH(PATTERN(NODE("n"))), WITH(IDENT("n"), AS("a")),
MATCH(PATTERN(NODE("n"))), WITH("n", AS("a")),
CREATE(PATTERN(NODE("a"), EDGE("r", r_type, Direction::OUT), NODE("b"))));
CheckPlan(storage, ExpectScanAll(), ExpectProduce(), ExpectCreateExpand());
}
@ -539,7 +534,7 @@ TEST(TestLogicalPlanner, MatchReturnSkipLimit) {
// Test MATCH (n) RETURN n SKIP 2 LIMIT 1
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"))),
RETURN(IDENT("n"), AS("n"), SKIP(LITERAL(2)), LIMIT(LITERAL(1))));
RETURN("n", SKIP(LITERAL(2)), LIMIT(LITERAL(1))));
CheckPlan(storage, ExpectScanAll(), ExpectProduce(), ExpectSkip(),
ExpectLimit());
}
@ -550,7 +545,7 @@ TEST(TestLogicalPlanner, CreateWithSkipReturnLimit) {
auto ident_n = IDENT("n");
auto query = QUERY(CREATE(PATTERN(NODE("n"))),
WITH(ident_n, AS("m"), SKIP(LITERAL(2))),
RETURN(IDENT("m"), AS("m"), LIMIT(LITERAL(1))));
RETURN("m", LIMIT(LITERAL(1))));
auto symbol_table = MakeSymbolTable(*query);
auto acc = ExpectAccumulate({symbol_table.at(*ident_n)});
auto plan = MakeLogicalPlan<RuleBasedPlanner>(storage, symbol_table);
@ -587,7 +582,7 @@ TEST(TestLogicalPlanner, MatchReturnOrderBy) {
auto dba = dbms.active();
auto prop = dba->property("prop");
AstTreeStorage storage;
auto ret = RETURN(IDENT("n"), AS("n"), ORDER_BY(PROPERTY_LOOKUP("n", prop)));
auto ret = RETURN("n", ORDER_BY(PROPERTY_LOOKUP("n", prop)));
QUERY(MATCH(PATTERN(NODE("n"))), ret);
CheckPlan(storage, ExpectScanAll(), ExpectProduce(), ExpectOrderBy());
}
@ -670,8 +665,7 @@ TEST(TestLogicalPlanner, MatchOptionalMatchWhereReturn) {
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"))),
OPTIONAL_MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
WHERE(LESS(PROPERTY_LOOKUP("m", prop), LITERAL(42))),
RETURN(IDENT("r"), AS("r")));
WHERE(LESS(PROPERTY_LOOKUP("m", prop), LITERAL(42))), RETURN("r"));
std::list<BaseOpChecker *> optional{new ExpectScanAll(), new ExpectExpand(),
new ExpectFilter()};
CheckPlan(storage, ExpectScanAll(), ExpectOptional(optional),
@ -679,11 +673,11 @@ TEST(TestLogicalPlanner, MatchOptionalMatchWhereReturn) {
}
TEST(TestLogicalPlanner, MatchUnwindReturn) {
// Test MATCH (n) UNWIND [1,2,3] AS x RETURN n AS n, x AS x
// Test MATCH (n) UNWIND [1,2,3] AS x RETURN n, x
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"))),
UNWIND(LIST(LITERAL(1), LITERAL(2), LITERAL(3)), AS("x")),
RETURN(IDENT("n"), AS("n"), IDENT("x"), AS("x")));
RETURN("n", "x"));
CheckPlan(storage, ExpectScanAll(), ExpectUnwind(), ExpectProduce());
}
@ -704,9 +698,8 @@ TEST(TestLogicalPlanner, CreateWithDistinctSumWhereReturn) {
AstTreeStorage storage;
auto node_n = NODE("n");
auto sum = SUM(PROPERTY_LOOKUP("n", prop));
auto query =
QUERY(CREATE(PATTERN(node_n)), WITH_DISTINCT(sum, AS("s")),
WHERE(LESS(IDENT("s"), LITERAL(42))), RETURN(IDENT("s"), AS("s")));
auto query = QUERY(CREATE(PATTERN(node_n)), WITH_DISTINCT(sum, AS("s")),
WHERE(LESS(IDENT("s"), LITERAL(42))), RETURN("s"));
auto symbol_table = MakeSymbolTable(*query);
auto acc = ExpectAccumulate({symbol_table.at(*node_n->identifier_)});
auto aggr = ExpectAggregate({sum}, {});
@ -727,7 +720,7 @@ TEST(TestLogicalPlanner, MatchCrossReferenceVariable) {
auto node_m = NODE("m");
auto n_prop = PROPERTY_LOOKUP("n", prop);
node_m->properties_[prop] = n_prop;
QUERY(MATCH(PATTERN(node_n), PATTERN(node_m)), RETURN(IDENT("n"), AS("n")));
QUERY(MATCH(PATTERN(node_n), PATTERN(node_m)), RETURN("n"));
// We expect both ScanAll to come before filters (2 are joined into one),
// because they need to populate the symbol values.
CheckPlan(storage, ExpectScanAll(), ExpectScanAll(), ExpectFilter(),
@ -741,8 +734,7 @@ TEST(TestLogicalPlanner, MatchWhereBeforeExpand) {
auto prop = dba->property("prop");
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
WHERE(LESS(PROPERTY_LOOKUP("n", prop), LITERAL(42))),
RETURN(IDENT("n"), AS("n")));
WHERE(LESS(PROPERTY_LOOKUP("n", prop), LITERAL(42))), RETURN("n"));
// We expect Fitler to come immediately after ScanAll, since it only uses `n`.
CheckPlan(storage, ExpectScanAll(), ExpectFilter(), ExpectExpand(),
ExpectProduce());
@ -756,8 +748,7 @@ TEST(TestLogicalPlanner, MultiMatchWhere) {
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
MATCH(PATTERN(NODE("l"))),
WHERE(LESS(PROPERTY_LOOKUP("n", prop), LITERAL(42))),
RETURN(IDENT("n"), AS("n")));
WHERE(LESS(PROPERTY_LOOKUP("n", prop), LITERAL(42))), RETURN("n"));
// Even though WHERE is in the second MATCH clause, we expect Filter to come
// before second ScanAll, since it only uses the value from first ScanAll.
CheckPlan(storage, ExpectScanAll(), ExpectFilter(), ExpectExpand(),
@ -772,8 +763,7 @@ TEST(TestLogicalPlanner, MatchOptionalMatchWhere) {
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
OPTIONAL_MATCH(PATTERN(NODE("l"))),
WHERE(LESS(PROPERTY_LOOKUP("n", prop), LITERAL(42))),
RETURN(IDENT("n"), AS("n")));
WHERE(LESS(PROPERTY_LOOKUP("n", prop), LITERAL(42))), RETURN("n"));
// Even though WHERE is in the second MATCH clause, and it uses the value from
// first ScanAll, it must remain part of the Optional. It should come before
// optional ScanAll.
@ -852,7 +842,7 @@ TEST(TestLogicalPlanner, MultipleOptionalMatchReturn) {
// Test OPTIONAL MATCH (n) OPTIONAL MATCH (m) RETURN n
AstTreeStorage storage;
QUERY(OPTIONAL_MATCH(PATTERN(NODE("n"))), OPTIONAL_MATCH(PATTERN(NODE("m"))),
RETURN(IDENT("n"), AS("n")));
RETURN("n"));
std::list<BaseOpChecker *> optional{new ExpectScanAll()};
CheckPlan(storage, ExpectOptional(optional), ExpectOptional(optional),
ExpectProduce());

View File

@ -4,8 +4,8 @@
#include "dbms/dbms.hpp"
#include "query/frontend/ast/ast.hpp"
#include "query/frontend/semantic/symbol_table.hpp"
#include "query/frontend/semantic/symbol_generator.hpp"
#include "query/frontend/semantic/symbol_table.hpp"
#include "query_common.hpp"
@ -16,9 +16,9 @@ namespace {
TEST(TestSymbolGenerator, MatchNodeReturn) {
SymbolTable symbol_table;
AstTreeStorage storage;
// MATCH (node_atom_1) RETURN node_atom_1 AS node_atom_1
auto query_ast = QUERY(MATCH(PATTERN(NODE("node_atom_1"))),
RETURN(IDENT("node_atom_1"), AS("node_atom_1")));
// MATCH (node_atom_1) RETURN node_atom_1
auto query_ast =
QUERY(MATCH(PATTERN(NODE("node_atom_1"))), RETURN("node_atom_1"));
SymbolGenerator symbol_generator(symbol_table);
query_ast->Accept(symbol_generator);
EXPECT_EQ(symbol_table.max_position(), 2);
@ -42,10 +42,9 @@ TEST(TestSymbolGenerator, MatchUnboundMultiReturn) {
AstTreeStorage storage;
// AST using variable in return bound by naming the previous return
// expression. This is treated as an unbound variable.
// MATCH (node_atom_1) RETURN node_atom_1 AS n, n AS n
auto query_ast =
QUERY(MATCH(PATTERN(NODE("node_atom_1"))),
RETURN(IDENT("node_atom_1"), AS("n"), IDENT("n"), AS("n")));
// MATCH (node_atom_1) RETURN node_atom_1 AS n, n
auto query_ast = QUERY(MATCH(PATTERN(NODE("node_atom_1"))),
RETURN("node_atom_1", AS("n"), "n"));
SymbolGenerator symbol_generator(symbol_table);
EXPECT_THROW(query_ast->Accept(symbol_generator), UnboundVariableError);
}
@ -53,9 +52,8 @@ TEST(TestSymbolGenerator, MatchUnboundMultiReturn) {
TEST(TestSymbolGenerator, MatchNodeUnboundReturn) {
SymbolTable symbol_table;
AstTreeStorage storage;
// AST with unbound variable in return: MATCH (n) RETURN x AS x
auto query_ast =
QUERY(MATCH(PATTERN(NODE("n"))), RETURN(IDENT("x"), AS("x")));
// AST with unbound variable in return: MATCH (n) RETURN x
auto query_ast = QUERY(MATCH(PATTERN(NODE("n"))), RETURN("x"));
SymbolGenerator symbol_generator(symbol_table);
EXPECT_THROW(query_ast->Accept(symbol_generator), UnboundVariableError);
}
@ -64,11 +62,11 @@ TEST(TestSymbolGenerator, MatchSameEdge) {
SymbolTable symbol_table;
AstTreeStorage storage;
// AST with match pattern referencing an edge multiple times:
// MATCH (n) -[r]- (n) -[r]- (n) RETURN r AS r
// MATCH (n) -[r]- (n) -[r]- (n) RETURN r
// This usually throws a redeclaration error, but we support it.
auto query_ast = QUERY(
MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("n"), EDGE("r"), NODE("n"))),
RETURN(IDENT("r"), AS("r")));
RETURN("r"));
SymbolGenerator symbol_generator(symbol_table);
query_ast->Accept(symbol_generator);
EXPECT_EQ(symbol_table.max_position(), 3);
@ -120,8 +118,7 @@ TEST(TestSymbolGenerator, CreateNodeReturn) {
SymbolTable symbol_table;
AstTreeStorage storage;
// Simple AST returning a created node: CREATE (n) RETURN n
auto query_ast =
QUERY(CREATE(PATTERN(NODE("n"))), RETURN(IDENT("n"), AS("n")));
auto query_ast = QUERY(CREATE(PATTERN(NODE("n"))), RETURN("n"));
SymbolGenerator symbol_generator(symbol_table);
query_ast->Accept(symbol_generator);
EXPECT_EQ(symbol_table.max_position(), 2);
@ -238,11 +235,10 @@ TEST(TestSymbolGenerator, CreateBidirectionalEdge) {
}
TEST(TestSymbolGenerator, MatchWhereUnbound) {
// Test MATCH (n) WHERE missing < 42 RETURN n AS n
// Test MATCH (n) WHERE missing < 42 RETURN n
AstTreeStorage storage;
auto query = QUERY(MATCH(PATTERN(NODE("n"))),
WHERE(LESS(IDENT("missing"), LITERAL(42))),
RETURN(IDENT("n"), AS("n")));
WHERE(LESS(IDENT("missing"), LITERAL(42))), RETURN("n"));
SymbolTable symbol_table;
SymbolGenerator symbol_generator(symbol_table);
EXPECT_THROW(query->Accept(symbol_generator), UnboundVariableError);
@ -299,10 +295,10 @@ TEST(TestSymbolGenerator, MatchWithReturn) {
}
TEST(TestSymbolGenerator, MatchWithReturnUnbound) {
// Test MATCH (old) WITH old AS n RETURN old AS old
// Test MATCH (old) WITH old AS n RETURN old
AstTreeStorage storage;
auto query = QUERY(MATCH(PATTERN(NODE("old"))), WITH(IDENT("old"), AS("n")),
RETURN(IDENT("old"), AS("old")));
auto query =
QUERY(MATCH(PATTERN(NODE("old"))), WITH("old", AS("n")), RETURN("old"));
SymbolTable symbol_table;
SymbolGenerator symbol_generator(symbol_table);
EXPECT_THROW(query->Accept(symbol_generator), UnboundVariableError);
@ -520,7 +516,7 @@ TEST(TestSymbolGenerator, MatchWithCreate) {
auto node_2 = NODE("m");
auto edge = EDGE("r", r_type, EdgeAtom::Direction::OUT);
auto node_3 = NODE("m");
auto query = QUERY(MATCH(PATTERN(node_1)), WITH(IDENT("n"), AS("m")),
auto query = QUERY(MATCH(PATTERN(node_1)), WITH("n", AS("m")),
CREATE(PATTERN(node_2, edge, node_3)));
SymbolTable symbol_table;
SymbolGenerator symbol_generator(symbol_table);
@ -539,8 +535,8 @@ TEST(TestSymbolGenerator, SameResults) {
// Test MATCH (n) WITH n AS m, n AS m
{
AstTreeStorage storage;
auto query = QUERY(MATCH(PATTERN(NODE("n"))),
WITH(IDENT("n"), AS("m"), IDENT("n"), AS("m")));
auto query =
QUERY(MATCH(PATTERN(NODE("n"))), WITH("n", AS("m"), "n", AS("m")));
SymbolTable symbol_table;
SymbolGenerator symbol_generator(symbol_table);
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
@ -548,8 +544,7 @@ TEST(TestSymbolGenerator, SameResults) {
// Test MATCH (n) RETURN n, n
{
AstTreeStorage storage;
auto query = QUERY(MATCH(PATTERN(NODE("n"))),
RETURN(IDENT("n"), AS("n"), IDENT("n"), AS("n")));
auto query = QUERY(MATCH(PATTERN(NODE("n"))), RETURN("n", "n"));
SymbolTable symbol_table;
SymbolGenerator symbol_generator(symbol_table);
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
@ -561,7 +556,7 @@ TEST(TestSymbolGenerator, SkipUsingIdentifier) {
{
AstTreeStorage storage;
auto query = QUERY(MATCH(PATTERN(NODE("old"))),
WITH(IDENT("old"), AS("new"), SKIP(IDENT("old"))));
WITH("old", AS("new"), SKIP(IDENT("old"))));
SymbolTable symbol_table;
SymbolGenerator symbol_generator(symbol_table);
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
@ -570,7 +565,7 @@ TEST(TestSymbolGenerator, SkipUsingIdentifier) {
{
AstTreeStorage storage;
auto query = QUERY(MATCH(PATTERN(NODE("old"))),
WITH(IDENT("old"), AS("new"), SKIP(IDENT("new"))));
WITH("old", AS("new"), SKIP(IDENT("new"))));
SymbolTable symbol_table;
SymbolGenerator symbol_generator(symbol_table);
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
@ -580,8 +575,7 @@ TEST(TestSymbolGenerator, SkipUsingIdentifier) {
TEST(TestSymbolGenerator, LimitUsingIdentifier) {
// Test MATCH (n) RETURN n AS n LIMIT n
AstTreeStorage storage;
auto query = QUERY(MATCH(PATTERN(NODE("n"))),
RETURN(IDENT("n"), AS("n"), LIMIT(IDENT("n"))));
auto query = QUERY(MATCH(PATTERN(NODE("n"))), RETURN("n", LIMIT(IDENT("n"))));
SymbolTable symbol_table;
SymbolGenerator symbol_generator(symbol_table);
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
@ -590,9 +584,8 @@ TEST(TestSymbolGenerator, LimitUsingIdentifier) {
TEST(TestSymbolGenerator, OrderByAggregation) {
// Test MATCH (old) RETURN old AS new ORDER BY COUNT(1)
AstTreeStorage storage;
auto query =
QUERY(MATCH(PATTERN(NODE("old"))),
RETURN(IDENT("old"), AS("new"), ORDER_BY(COUNT(LITERAL(1)))));
auto query = QUERY(MATCH(PATTERN(NODE("old"))),
RETURN("old", AS("new"), ORDER_BY(COUNT(LITERAL(1)))));
SymbolTable symbol_table;
SymbolGenerator symbol_generator(symbol_table);
EXPECT_THROW(query->Accept(symbol_generator), SemanticException);
@ -728,8 +721,7 @@ TEST(TestSymbolGenerator, WithUnwindRedeclareReturn) {
// Test WITH [1, 2] AS list UNWIND list AS list RETURN list
AstTreeStorage storage;
auto query = QUERY(WITH(LIST(LITERAL(1), LITERAL(2)), AS("list")),
UNWIND(IDENT("list"), AS("list")),
RETURN(IDENT("list"), AS("list")));
UNWIND(IDENT("list"), AS("list")), RETURN("list"));
SymbolTable symbol_table;
SymbolGenerator symbol_generator(symbol_table);
EXPECT_THROW(query->Accept(symbol_generator), RedeclareVariableError);
@ -817,9 +809,9 @@ TEST(TestSymbolGenerator, MatchWithAsteriskReturnAsterisk) {
}
TEST(TestSymbolGenerator, MatchReturnAsteriskSameResult) {
// MATCH (n) RETURN *, n AS n
// MATCH (n) RETURN *, n
AstTreeStorage storage;
auto ret = RETURN(IDENT("n"), AS("n"));
auto ret = RETURN("n");
ret->body_.all_identifiers = true;
auto query = QUERY(MATCH(PATTERN(NODE("n"))), ret);
SymbolTable symbol_table;