namespace query { namespace test_common { /// /// Create PropertyLookup with given name and property. /// /// Name is used to create the Identifier which is used for property lookup. /// auto GetPropertyLookup(AstTreeStorage &storage, const std::string &name, GraphDb::Property property) { return storage.Create(storage.Create(name), property); } /// /// Create an EdgeAtom with given name, edge_type and direction. /// /// Name is used to create the Identifier which is assigned to the edge. /// auto GetEdge(AstTreeStorage &storage, const std::string &name, GraphDb::EdgeType edge_type = nullptr, EdgeAtom::Direction dir = EdgeAtom::Direction::BOTH) { auto edge = storage.Create(storage.Create(name), dir); if (edge_type) edge->edge_types_.emplace_back(edge_type); return edge; } /// /// Create an EdgeAtom with given name and direction. /// auto GetEdge(AstTreeStorage &storage, const std::string &name, EdgeAtom::Direction dir) { return GetEdge(storage, name, nullptr, dir); } /// /// Create a NodeAtom with given name and label. /// /// Name is used to create the Identifier which is assigned to the node. /// auto GetNode(AstTreeStorage &storage, const std::string &name, GraphDb::Label label = nullptr) { auto node = storage.Create(storage.Create(name)); if (label) node->labels_.emplace_back(label); return node; } /// /// Create a Pattern with given atoms. /// auto GetPattern(AstTreeStorage &storage, std::vector atoms) { auto pattern = storage.Create(); pattern->atoms_.insert(pattern->atoms_.begin(), atoms.begin(), atoms.end()); return pattern; } /// /// This function creates an AST node which can store patterns and fills them /// with given patterns. /// /// The function is most commonly used to create Match and Create clauses. /// template auto GetWithPatterns(AstTreeStorage &storage, std::vector patterns) { auto with_patterns = storage.Create(); with_patterns->patterns_.insert(with_patterns->patterns_.begin(), patterns.begin(), patterns.end()); return with_patterns; } /// /// Create a query with given clauses. /// auto GetQuery(AstTreeStorage &storage, std::vector clauses) { auto query = storage.query(); query->clauses_.insert(query->clauses_.begin(), clauses.begin(), clauses.end()); return query; } /// /// Create the return clause with given named expressions. /// auto GetReturn(AstTreeStorage &storage, std::vector named_exprs) { auto ret = storage.Create(); ret->named_expressions_.insert(ret->named_expressions_.begin(), named_exprs.begin(), named_exprs.end()); return ret; } } // namespace test_common } // namespace query /// /// All the following macros implicitly pass `storage` variable to functions. /// You /// need to have `AstTreeStorage storage;` somewhere in scope to use them. /// Refer to function documentation to see what the macro does. /// /// Example usage: /// /// // Create MATCH (n) -[r]- (m) RETURN m AS new_name /// AstTreeStorage storage; /// auto query = QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))), /// RETURN(NEXPR("new_name"), IDENT("m"))); /// #define NODE(...) query::test_common::GetNode(storage, __VA_ARGS__) #define EDGE(...) query::test_common::GetEdge(storage, __VA_ARGS__) #define PATTERN(...) query::test_common::GetPattern(storage, {__VA_ARGS__}) #define MATCH(...) \ query::test_common::GetWithPatterns(storage, {__VA_ARGS__}) #define CREATE(...) \ query::test_common::GetWithPatterns(storage, {__VA_ARGS__}) #define IDENT(name) storage.Create((name)) #define LITERAL(val) storage.Create((val)) #define PROPERTY_LOOKUP(...) query::test_common::GetPropertyLookup(storage, __VA_ARGS__) #define NEXPR(name, expr) storage.Create((name), (expr)) #define RETURN(...) query::test_common::GetReturn(storage, {__VA_ARGS__}) #define QUERY(...) query::test_common::GetQuery(storage, {__VA_ARGS__})