Bug fixes in cypher_main_visitor and add create clause
Reviewers: teon.banek, florijan Reviewed By: teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D143
This commit is contained in:
parent
5e6aaf231d
commit
848d022c60
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -13,6 +14,7 @@ class AstTreeStorage;
|
|||||||
|
|
||||||
class Tree : public ::utils::Visitable<TreeVisitorBase> {
|
class Tree : public ::utils::Visitable<TreeVisitorBase> {
|
||||||
friend class AstTreeStorage;
|
friend class AstTreeStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int uid() const { return uid_; }
|
int uid() const { return uid_; }
|
||||||
|
|
||||||
@ -30,6 +32,7 @@ class Expression : public Tree {
|
|||||||
|
|
||||||
class Identifier : public Expression {
|
class Identifier : public Expression {
|
||||||
friend class AstTreeStorage;
|
friend class AstTreeStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DEFVISITABLE(TreeVisitorBase);
|
DEFVISITABLE(TreeVisitorBase);
|
||||||
std::string name_;
|
std::string name_;
|
||||||
@ -40,6 +43,7 @@ class Identifier : public Expression {
|
|||||||
|
|
||||||
class PropertyLookup : public Expression {
|
class PropertyLookup : public Expression {
|
||||||
friend class AstTreeStorage;
|
friend class AstTreeStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Accept(TreeVisitorBase &visitor) override {
|
void Accept(TreeVisitorBase &visitor) override {
|
||||||
visitor.Visit(*this);
|
visitor.Visit(*this);
|
||||||
@ -57,13 +61,13 @@ class PropertyLookup : public Expression {
|
|||||||
// between the two depending on Expression result
|
// between the two depending on Expression result
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PropertyLookup(int uid, Expression* expression,
|
PropertyLookup(int uid, Expression *expression, GraphDb::Property property)
|
||||||
GraphDb::Property property)
|
|
||||||
: Expression(uid), expression_(expression), property_(property) {}
|
: Expression(uid), expression_(expression), property_(property) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class NamedExpression : public Tree {
|
class NamedExpression : public Tree {
|
||||||
friend class AstTreeStorage;
|
friend class AstTreeStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Accept(TreeVisitorBase &visitor) override {
|
void Accept(TreeVisitorBase &visitor) override {
|
||||||
visitor.Visit(*this);
|
visitor.Visit(*this);
|
||||||
@ -72,18 +76,20 @@ class NamedExpression : public Tree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string name_;
|
std::string name_;
|
||||||
Expression* expression_ = nullptr;
|
Expression *expression_ = nullptr;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NamedExpression(int uid) : Tree(uid) {}
|
NamedExpression(int uid) : Tree(uid) {}
|
||||||
NamedExpression(int uid, std::string name, Expression *expression) :
|
NamedExpression(int uid, std::string name, Expression *expression)
|
||||||
Tree(uid), name_(name), expression_(expression) {}
|
: Tree(uid), name_(name), expression_(expression) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PatternAtom : public Tree {
|
class PatternAtom : public Tree {
|
||||||
friend class AstTreeStorage;
|
friend class AstTreeStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Identifier* identifier_ = nullptr;
|
Identifier *identifier_ = nullptr;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PatternAtom(int uid) : Tree(uid) {}
|
PatternAtom(int uid) : Tree(uid) {}
|
||||||
PatternAtom(int uid, Identifier *identifier)
|
PatternAtom(int uid, Identifier *identifier)
|
||||||
@ -92,6 +98,7 @@ class PatternAtom : public Tree {
|
|||||||
|
|
||||||
class NodeAtom : public PatternAtom {
|
class NodeAtom : public PatternAtom {
|
||||||
friend class AstTreeStorage;
|
friend class AstTreeStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Accept(TreeVisitorBase &visitor) override {
|
void Accept(TreeVisitorBase &visitor) override {
|
||||||
visitor.Visit(*this);
|
visitor.Visit(*this);
|
||||||
@ -100,7 +107,8 @@ class NodeAtom : public PatternAtom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<GraphDb::Label> labels_;
|
std::vector<GraphDb::Label> labels_;
|
||||||
std::map<GraphDb::Property, Expression*> properties_;
|
// TODO: change to unordered_map
|
||||||
|
std::map<GraphDb::Property, Expression *> properties_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using PatternAtom::PatternAtom;
|
using PatternAtom::PatternAtom;
|
||||||
@ -108,6 +116,7 @@ class NodeAtom : public PatternAtom {
|
|||||||
|
|
||||||
class EdgeAtom : public PatternAtom {
|
class EdgeAtom : public PatternAtom {
|
||||||
friend class AstTreeStorage;
|
friend class AstTreeStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class Direction { LEFT, RIGHT, BOTH };
|
enum class Direction { LEFT, RIGHT, BOTH };
|
||||||
|
|
||||||
@ -119,6 +128,8 @@ class EdgeAtom : public PatternAtom {
|
|||||||
|
|
||||||
Direction direction_ = Direction::BOTH;
|
Direction direction_ = Direction::BOTH;
|
||||||
std::vector<GraphDb::EdgeType> types_;
|
std::vector<GraphDb::EdgeType> types_;
|
||||||
|
// TODO: change to unordered_map
|
||||||
|
std::map<GraphDb::Property, Expression *> properties_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using PatternAtom::PatternAtom;
|
using PatternAtom::PatternAtom;
|
||||||
@ -126,12 +137,14 @@ class EdgeAtom : public PatternAtom {
|
|||||||
|
|
||||||
class Clause : public Tree {
|
class Clause : public Tree {
|
||||||
friend class AstTreeStorage;
|
friend class AstTreeStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Clause(int uid) : Tree(uid) {}
|
Clause(int uid) : Tree(uid) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Pattern : public Tree {
|
class Pattern : public Tree {
|
||||||
friend class AstTreeStorage;
|
friend class AstTreeStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Accept(TreeVisitorBase &visitor) override {
|
void Accept(TreeVisitorBase &visitor) override {
|
||||||
visitor.Visit(*this);
|
visitor.Visit(*this);
|
||||||
@ -140,8 +153,8 @@ class Pattern : public Tree {
|
|||||||
}
|
}
|
||||||
visitor.PostVisit(*this);
|
visitor.PostVisit(*this);
|
||||||
}
|
}
|
||||||
Identifier* identifier_ = nullptr;
|
Identifier *identifier_ = nullptr;
|
||||||
std::vector<PatternAtom*> atoms_;
|
std::vector<PatternAtom *> atoms_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Pattern(int uid) : Tree(uid) {}
|
Pattern(int uid) : Tree(uid) {}
|
||||||
@ -149,6 +162,7 @@ class Pattern : public Tree {
|
|||||||
|
|
||||||
class Query : public Tree {
|
class Query : public Tree {
|
||||||
friend class AstTreeStorage;
|
friend class AstTreeStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Accept(TreeVisitorBase &visitor) override {
|
void Accept(TreeVisitorBase &visitor) override {
|
||||||
visitor.Visit(*this);
|
visitor.Visit(*this);
|
||||||
@ -157,16 +171,18 @@ class Query : public Tree {
|
|||||||
}
|
}
|
||||||
visitor.PostVisit(*this);
|
visitor.PostVisit(*this);
|
||||||
}
|
}
|
||||||
std::vector<Clause*> clauses_;
|
std::vector<Clause *> clauses_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Query(int uid) : Tree(uid) {}
|
Query(int uid) : Tree(uid) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Create : public Clause {
|
class Create : public Clause {
|
||||||
|
friend class AstTreeStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Create(int uid) : Clause(uid) {}
|
Create(int uid) : Clause(uid) {}
|
||||||
std::vector<Pattern*> patterns_;
|
std::vector<Pattern *> patterns_;
|
||||||
void Accept(TreeVisitorBase &visitor) override {
|
void Accept(TreeVisitorBase &visitor) override {
|
||||||
visitor.Visit(*this);
|
visitor.Visit(*this);
|
||||||
for (auto &pattern : patterns_) {
|
for (auto &pattern : patterns_) {
|
||||||
@ -178,8 +194,9 @@ class Create : public Clause {
|
|||||||
|
|
||||||
class Match : public Clause {
|
class Match : public Clause {
|
||||||
friend class AstTreeStorage;
|
friend class AstTreeStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<Pattern*> patterns_;
|
std::vector<Pattern *> patterns_;
|
||||||
void Accept(TreeVisitorBase &visitor) override {
|
void Accept(TreeVisitorBase &visitor) override {
|
||||||
visitor.Visit(*this);
|
visitor.Visit(*this);
|
||||||
for (auto &pattern : patterns_) {
|
for (auto &pattern : patterns_) {
|
||||||
@ -194,6 +211,7 @@ class Match : public Clause {
|
|||||||
|
|
||||||
class Return : public Clause {
|
class Return : public Clause {
|
||||||
friend class AstTreeStorage;
|
friend class AstTreeStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Accept(TreeVisitorBase &visitor) override {
|
void Accept(TreeVisitorBase &visitor) override {
|
||||||
visitor.Visit(*this);
|
visitor.Visit(*this);
|
||||||
@ -202,7 +220,7 @@ class Return : public Clause {
|
|||||||
}
|
}
|
||||||
visitor.PostVisit(*this);
|
visitor.PostVisit(*this);
|
||||||
}
|
}
|
||||||
std::vector<NamedExpression*> named_expressions_;
|
std::vector<NamedExpression *> named_expressions_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Return(int uid) : Clause(uid) {}
|
Return(int uid) : Clause(uid) {}
|
||||||
@ -215,14 +233,12 @@ class AstTreeStorage {
|
|||||||
friend class AstTreeStorage;
|
friend class AstTreeStorage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AstTreeStorage() {
|
AstTreeStorage() { storage_.emplace_back(new Query(next_uid_++)); }
|
||||||
storage_.emplace_back(new Query(next_uid_++));
|
|
||||||
}
|
|
||||||
AstTreeStorage(const AstTreeStorage &) = delete;
|
AstTreeStorage(const AstTreeStorage &) = delete;
|
||||||
AstTreeStorage &operator=(const AstTreeStorage &) = delete;
|
AstTreeStorage &operator=(const AstTreeStorage &) = delete;
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
T *Create(Args&&... args) {
|
T *Create(Args &&... args) {
|
||||||
// Never call create for a Query. Call query() instead.
|
// Never call create for a Query. Call query() instead.
|
||||||
static_assert(!std::is_same<T, Query>::value, "Call query() instead");
|
static_assert(!std::is_same<T, Query>::value, "Call query() instead");
|
||||||
// TODO: use std::forward here
|
// TODO: use std::forward here
|
||||||
@ -231,7 +247,7 @@ class AstTreeStorage {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
Query *query() { return dynamic_cast<Query*>(storage_[0].get()); }
|
Query *query() { return dynamic_cast<Query *>(storage_[0].get()); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int next_uid_ = 0;
|
int next_uid_ = 0;
|
||||||
|
@ -41,8 +41,8 @@ namespace {
|
|||||||
|
|
||||||
const std::string CypherMainVisitor::kAnonPrefix = "anon";
|
const std::string CypherMainVisitor::kAnonPrefix = "anon";
|
||||||
|
|
||||||
antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitSingleQuery(
|
||||||
CypherMainVisitor::visitSingleQuery(CypherParser::SingleQueryContext *ctx) {
|
CypherParser::SingleQueryContext *ctx) {
|
||||||
query_ = storage_.query();
|
query_ = storage_.query();
|
||||||
for (auto *child : ctx->clause()) {
|
for (auto *child : ctx->clause()) {
|
||||||
query_->clauses_.push_back(child->accept(this));
|
query_->clauses_.push_back(child->accept(this));
|
||||||
@ -68,12 +68,15 @@ antlrcpp::Any CypherMainVisitor::visitClause(CypherParser::ClauseContext *ctx) {
|
|||||||
if (ctx->cypherMatch()) {
|
if (ctx->cypherMatch()) {
|
||||||
return (Clause *)ctx->cypherMatch()->accept(this).as<Match *>();
|
return (Clause *)ctx->cypherMatch()->accept(this).as<Match *>();
|
||||||
}
|
}
|
||||||
|
if (ctx->create()) {
|
||||||
|
return (Clause *)ctx->create()->accept(this).as<Create *>();
|
||||||
|
}
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
return visitChildren(ctx);
|
return visitChildren(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitCypherMatch(
|
||||||
CypherMainVisitor::visitCypherMatch(CypherParser::CypherMatchContext *ctx) {
|
CypherParser::CypherMatchContext *ctx) {
|
||||||
auto *match = storage_.Create<Match>();
|
auto *match = storage_.Create<Match>();
|
||||||
if (ctx->OPTIONAL() || ctx->where()) {
|
if (ctx->OPTIONAL() || ctx->where()) {
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
@ -82,24 +85,31 @@ CypherMainVisitor::visitCypherMatch(CypherParser::CypherMatchContext *ctx) {
|
|||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitCreate(CypherParser::CreateContext *ctx) {
|
||||||
CypherMainVisitor::visitCypherReturn(CypherParser::CypherReturnContext *ctx) {
|
auto *create = storage_.Create<Create>();
|
||||||
|
create->patterns_ = ctx->pattern()->accept(this).as<std::vector<Pattern *>>();
|
||||||
|
return create;
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
antlrcpp::Any CypherMainVisitor::visitCypherReturn(
|
||||||
|
CypherParser::CypherReturnContext *ctx) {
|
||||||
if (ctx->DISTINCT()) {
|
if (ctx->DISTINCT()) {
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
return visitChildren(ctx);
|
return visitChildren(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitReturnBody(
|
||||||
CypherMainVisitor::visitReturnBody(CypherParser::ReturnBodyContext *ctx) {
|
CypherParser::ReturnBodyContext *ctx) {
|
||||||
if (ctx->order() || ctx->skip() || ctx->limit()) {
|
if (ctx->order() || ctx->skip() || ctx->limit()) {
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
return ctx->returnItems()->accept(this);
|
return ctx->returnItems()->accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitReturnItems(
|
||||||
CypherMainVisitor::visitReturnItems(CypherParser::ReturnItemsContext *ctx) {
|
CypherParser::ReturnItemsContext *ctx) {
|
||||||
auto *return_clause = storage_.Create<Return>();
|
auto *return_clause = storage_.Create<Return>();
|
||||||
if (ctx->getTokens(kReturnAllTokenId).size()) {
|
if (ctx->getTokens(kReturnAllTokenId).size()) {
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
@ -110,8 +120,8 @@ CypherMainVisitor::visitReturnItems(CypherParser::ReturnItemsContext *ctx) {
|
|||||||
return return_clause;
|
return return_clause;
|
||||||
}
|
}
|
||||||
|
|
||||||
antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitReturnItem(
|
||||||
CypherMainVisitor::visitReturnItem(CypherParser::ReturnItemContext *ctx) {
|
CypherParser::ReturnItemContext *ctx) {
|
||||||
auto *named_expr = storage_.Create<NamedExpression>();
|
auto *named_expr = storage_.Create<NamedExpression>();
|
||||||
if (ctx->variable()) {
|
if (ctx->variable()) {
|
||||||
named_expr->name_ =
|
named_expr->name_ =
|
||||||
@ -124,8 +134,8 @@ CypherMainVisitor::visitReturnItem(CypherParser::ReturnItemContext *ctx) {
|
|||||||
return named_expr;
|
return named_expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitNodePattern(
|
||||||
CypherMainVisitor::visitNodePattern(CypherParser::NodePatternContext *ctx) {
|
CypherParser::NodePatternContext *ctx) {
|
||||||
auto *node = storage_.Create<NodeAtom>();
|
auto *node = storage_.Create<NodeAtom>();
|
||||||
if (ctx->variable()) {
|
if (ctx->variable()) {
|
||||||
std::string variable = ctx->variable()->accept(this);
|
std::string variable = ctx->variable()->accept(this);
|
||||||
@ -139,17 +149,15 @@ CypherMainVisitor::visitNodePattern(CypherParser::NodePatternContext *ctx) {
|
|||||||
ctx->nodeLabels()->accept(this).as<std::vector<GraphDb::Label>>();
|
ctx->nodeLabels()->accept(this).as<std::vector<GraphDb::Label>>();
|
||||||
}
|
}
|
||||||
if (ctx->properties()) {
|
if (ctx->properties()) {
|
||||||
throw std::exception();
|
node->properties_ = ctx->properties()
|
||||||
// node.properties = ctx->properties()
|
->accept(this)
|
||||||
// ->accept(this)
|
.as<std::map<GraphDb::Property, Expression *>>();
|
||||||
// .as<std::unordered_map<std::string,
|
|
||||||
// std::string>>();
|
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitNodeLabels(
|
||||||
CypherMainVisitor::visitNodeLabels(CypherParser::NodeLabelsContext *ctx) {
|
CypherParser::NodeLabelsContext *ctx) {
|
||||||
std::vector<GraphDb::Label> labels;
|
std::vector<GraphDb::Label> labels;
|
||||||
for (auto *node_label : ctx->nodeLabel()) {
|
for (auto *node_label : ctx->nodeLabel()) {
|
||||||
labels.push_back(ctx_.db_accessor_.label(node_label->accept(this)));
|
labels.push_back(ctx_.db_accessor_.label(node_label->accept(this)));
|
||||||
@ -157,31 +165,35 @@ CypherMainVisitor::visitNodeLabels(CypherParser::NodeLabelsContext *ctx) {
|
|||||||
return labels;
|
return labels;
|
||||||
}
|
}
|
||||||
|
|
||||||
antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitProperties(
|
||||||
CypherMainVisitor::visitProperties(CypherParser::PropertiesContext *ctx) {
|
CypherParser::PropertiesContext *ctx) {
|
||||||
if (!ctx->mapLiteral()) {
|
if (!ctx->mapLiteral()) {
|
||||||
// If child is not mapLiteral that means child is params. At the moment
|
// If child is not mapLiteral that means child is params. At the moment
|
||||||
// memgraph doesn't support params.
|
// we don't support properties to be a param because we can generate
|
||||||
|
// better logical plan if we have an information about properties at
|
||||||
|
// compile time.
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
return ctx->mapLiteral()->accept(this);
|
return ctx->mapLiteral()->accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitMapLiteral(
|
||||||
CypherMainVisitor::visitMapLiteral(CypherParser::MapLiteralContext *ctx) {
|
CypherParser::MapLiteralContext *ctx) {
|
||||||
throw std::exception();
|
std::map<GraphDb::Property, Expression *> map;
|
||||||
(void)ctx;
|
for (int i = 0; i < (int)ctx->propertyKeyName().size(); ++i) {
|
||||||
return 0;
|
map[ctx->propertyKeyName()[i]->accept(this)] =
|
||||||
// std::unordered_map<std::string, std::string> map;
|
ctx->expression()[i]->accept(this);
|
||||||
// for (int i = 0; i < (int)ctx->propertyKeyName().size(); ++i) {
|
}
|
||||||
// map[ctx->propertyKeyName()[i]->accept(this).as<std::string>()] =
|
return map;
|
||||||
// ctx->expression()[i]->accept(this).as<std::string>();
|
|
||||||
// }
|
|
||||||
// return map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitPropertyKeyName(
|
||||||
CypherMainVisitor::visitSymbolicName(CypherParser::SymbolicNameContext *ctx) {
|
CypherParser::PropertyKeyNameContext *ctx) {
|
||||||
|
return ctx_.db_accessor_.property(visitChildren(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
antlrcpp::Any CypherMainVisitor::visitSymbolicName(
|
||||||
|
CypherParser::SymbolicNameContext *ctx) {
|
||||||
if (ctx->EscapedSymbolicName()) {
|
if (ctx->EscapedSymbolicName()) {
|
||||||
// We don't allow at this point for variable to be EscapedSymbolicName
|
// We don't allow at this point for variable to be EscapedSymbolicName
|
||||||
// because we would have t ofigure out how escaping works since same
|
// because we would have t ofigure out how escaping works since same
|
||||||
@ -192,8 +204,8 @@ CypherMainVisitor::visitSymbolicName(CypherParser::SymbolicNameContext *ctx) {
|
|||||||
return std::string(ctx->getText());
|
return std::string(ctx->getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitPattern(
|
||||||
CypherMainVisitor::visitPattern(CypherParser::PatternContext *ctx) {
|
CypherParser::PatternContext *ctx) {
|
||||||
std::vector<Pattern *> patterns;
|
std::vector<Pattern *> patterns;
|
||||||
for (auto *pattern_part : ctx->patternPart()) {
|
for (auto *pattern_part : ctx->patternPart()) {
|
||||||
patterns.push_back(pattern_part->accept(this));
|
patterns.push_back(pattern_part->accept(this));
|
||||||
@ -201,8 +213,8 @@ CypherMainVisitor::visitPattern(CypherParser::PatternContext *ctx) {
|
|||||||
return patterns;
|
return patterns;
|
||||||
}
|
}
|
||||||
|
|
||||||
antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitPatternPart(
|
||||||
CypherMainVisitor::visitPatternPart(CypherParser::PatternPartContext *ctx) {
|
CypherParser::PatternPartContext *ctx) {
|
||||||
Pattern *pattern = ctx->anonymousPatternPart()->accept(this);
|
Pattern *pattern = ctx->anonymousPatternPart()->accept(this);
|
||||||
if (ctx->variable()) {
|
if (ctx->variable()) {
|
||||||
std::string variable = ctx->variable()->accept(this);
|
std::string variable = ctx->variable()->accept(this);
|
||||||
@ -298,8 +310,8 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipTypes(
|
|||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitRangeLiteral(
|
||||||
CypherMainVisitor::visitRangeLiteral(CypherParser::RangeLiteralContext *ctx) {
|
CypherParser::RangeLiteralContext *ctx) {
|
||||||
if (ctx->integerLiteral().size() == 0U) {
|
if (ctx->integerLiteral().size() == 0U) {
|
||||||
// -[*]-
|
// -[*]-
|
||||||
return std::pair<int64_t, int64_t>(1LL, LLONG_MAX);
|
return std::pair<int64_t, int64_t>(1LL, LLONG_MAX);
|
||||||
@ -326,8 +338,8 @@ CypherMainVisitor::visitRangeLiteral(CypherParser::RangeLiteralContext *ctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitExpression(
|
||||||
CypherMainVisitor::visitExpression(CypherParser::ExpressionContext *ctx) {
|
CypherParser::ExpressionContext *ctx) {
|
||||||
return visitChildren(ctx);
|
return visitChildren(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,23 +516,22 @@ CypherMainVisitor::visitExpression(CypherParser::ExpressionContext *ctx) {
|
|||||||
// }
|
// }
|
||||||
// return visitChildren(ctx);
|
// return visitChildren(ctx);
|
||||||
//}
|
//}
|
||||||
//
|
|
||||||
// antlrcpp::Any
|
antlrcpp::Any CypherMainVisitor::visitExpression2(
|
||||||
// CypherMainVisitor::visitExpression2(CypherParser::Expression2Context *ctx) {
|
CypherParser::Expression2Context *ctx) {
|
||||||
// if (ctx->nodeLabels().size()) {
|
if (ctx->nodeLabels().size()) {
|
||||||
// // TODO: Implement this. We don't currently support label checking in
|
// TODO: Implement this. We don't currently support label checking in
|
||||||
// // expresssion.
|
// expresssion.
|
||||||
// throw SemanticException();
|
throw std::exception();
|
||||||
// }
|
}
|
||||||
// auto operand = ctx->atom()->accept(this).as<std::string>();
|
Expression *expression = ctx->atom()->accept(this);
|
||||||
// for (int i = 0; i < (int)ctx->propertyLookup().size(); ++i) {
|
for (auto *lookup : ctx->propertyLookup()) {
|
||||||
// auto lhs_id = new_id();
|
auto property_lookup =
|
||||||
// symbol_table_[lhs_id] =
|
storage_.Create<PropertyLookup>(expression, lookup->accept(this));
|
||||||
// SimpleExpression{Function::PROPERTY_GETTER, {operand}};
|
expression = property_lookup;
|
||||||
// operand = lhs_id;
|
}
|
||||||
// }
|
return expression;
|
||||||
// return operand;
|
}
|
||||||
//}
|
|
||||||
|
|
||||||
antlrcpp::Any CypherMainVisitor::visitAtom(CypherParser::AtomContext *ctx) {
|
antlrcpp::Any CypherMainVisitor::visitAtom(CypherParser::AtomContext *ctx) {
|
||||||
if (ctx->literal()) {
|
if (ctx->literal()) {
|
||||||
@ -555,7 +566,7 @@ antlrcpp::Any CypherMainVisitor::visitAtom(CypherParser::AtomContext *ctx) {
|
|||||||
} else if (ctx->variable()) {
|
} else if (ctx->variable()) {
|
||||||
std::string variable = ctx->variable()->accept(this);
|
std::string variable = ctx->variable()->accept(this);
|
||||||
users_identifiers.insert(variable);
|
users_identifiers.insert(variable);
|
||||||
return storage_.Create<Identifier>(variable);
|
return (Expression *)storage_.Create<Identifier>(variable);
|
||||||
}
|
}
|
||||||
// TODO: Implement this. We don't support comprehensions, functions,
|
// TODO: Implement this. We don't support comprehensions, functions,
|
||||||
// filtering... at the moment.
|
// filtering... at the moment.
|
||||||
|
@ -15,10 +15,10 @@ using query::Context;
|
|||||||
using antlropencypher::CypherParser;
|
using antlropencypher::CypherParser;
|
||||||
|
|
||||||
class CypherMainVisitor : public antlropencypher::CypherBaseVisitor {
|
class CypherMainVisitor : public antlropencypher::CypherBaseVisitor {
|
||||||
public:
|
public:
|
||||||
CypherMainVisitor(Context &ctx) : ctx_(ctx) {}
|
CypherMainVisitor(Context &ctx) : ctx_(ctx) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// template <typename TExpression>
|
// template <typename TExpression>
|
||||||
// antlrcpp::Any
|
// antlrcpp::Any
|
||||||
// LeftAssociativeOperatorExpression(std::vector<TExpression *> children,
|
// LeftAssociativeOperatorExpression(std::vector<TExpression *> children,
|
||||||
@ -49,90 +49,109 @@ private:
|
|||||||
// children, std::vector<Function>((int)children.size() - 1, op));
|
// children, std::vector<Function>((int)children.size() - 1, op));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
antlrcpp::Any
|
/**
|
||||||
visitSingleQuery(CypherParser::SingleQueryContext *ctx) override;
|
* @return Query*
|
||||||
|
*/
|
||||||
|
antlrcpp::Any visitSingleQuery(
|
||||||
|
CypherParser::SingleQueryContext *ctx) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Clause*
|
||||||
|
*/
|
||||||
antlrcpp::Any visitClause(CypherParser::ClauseContext *ctx) override;
|
antlrcpp::Any visitClause(CypherParser::ClauseContext *ctx) override;
|
||||||
|
|
||||||
antlrcpp::Any
|
/**
|
||||||
visitCypherMatch(CypherParser::CypherMatchContext *ctx) override;
|
* @return Match*
|
||||||
|
*/
|
||||||
|
antlrcpp::Any visitCypherMatch(
|
||||||
|
CypherParser::CypherMatchContext *ctx) override;
|
||||||
|
|
||||||
antlrcpp::Any
|
/**
|
||||||
visitCypherReturn(CypherParser::CypherReturnContext *ctx) override;
|
* @return Create*
|
||||||
|
*/
|
||||||
|
antlrcpp::Any visitCreate(CypherParser::CreateContext *ctx) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Return*
|
||||||
|
*/
|
||||||
|
antlrcpp::Any visitCypherReturn(
|
||||||
|
CypherParser::CypherReturnContext *ctx) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Return*
|
||||||
|
*/
|
||||||
antlrcpp::Any visitReturnBody(CypherParser::ReturnBodyContext *ctx) override;
|
antlrcpp::Any visitReturnBody(CypherParser::ReturnBodyContext *ctx) override;
|
||||||
|
|
||||||
antlrcpp::Any
|
/**
|
||||||
visitReturnItems(CypherParser::ReturnItemsContext *ctx) override;
|
* @return Return*
|
||||||
|
*/
|
||||||
|
antlrcpp::Any visitReturnItems(
|
||||||
|
CypherParser::ReturnItemsContext *ctx) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return NamedExpression*
|
||||||
|
*/
|
||||||
antlrcpp::Any visitReturnItem(CypherParser::ReturnItemContext *ctx) override;
|
antlrcpp::Any visitReturnItem(CypherParser::ReturnItemContext *ctx) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates Node and stores it in symbol_table_. If variable is defined it is
|
* @return NodeAtom*
|
||||||
* stored in ids_map_.
|
*/
|
||||||
*
|
antlrcpp::Any visitNodePattern(
|
||||||
* @return string - node id.
|
CypherParser::NodePatternContext *ctx) override;
|
||||||
*/
|
|
||||||
antlrcpp::Any
|
|
||||||
visitNodePattern(CypherParser::NodePatternContext *ctx) override;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return vector<string> labels.
|
* @return vector<GraphDb::Label>
|
||||||
*/
|
*/
|
||||||
antlrcpp::Any visitNodeLabels(CypherParser::NodeLabelsContext *ctx) override;
|
antlrcpp::Any visitNodeLabels(CypherParser::NodeLabelsContext *ctx) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return unordered_map<string, string> properties - property key to
|
* @return unordered_map<GraphDb::Property, Expression*>
|
||||||
* expression id.
|
*/
|
||||||
*/
|
|
||||||
antlrcpp::Any visitProperties(CypherParser::PropertiesContext *ctx) override;
|
antlrcpp::Any visitProperties(CypherParser::PropertiesContext *ctx) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return unordered_map<string, string> map - key to expression id.
|
* @return unordered_map<GraphDb::Property, Expression*>
|
||||||
*/
|
*/
|
||||||
antlrcpp::Any visitMapLiteral(CypherParser::MapLiteralContext *ctx) override;
|
antlrcpp::Any visitMapLiteral(CypherParser::MapLiteralContext *ctx) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string.
|
* @return GraphDb::Property
|
||||||
*/
|
*/
|
||||||
antlrcpp::Any
|
antlrcpp::Any visitPropertyKeyName(
|
||||||
visitSymbolicName(CypherParser::SymbolicNameContext *ctx) override;
|
CypherParser::PropertyKeyNameContext *ctx) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return vector<PatternPart> pattern.
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
antlrcpp::Any visitSymbolicName(
|
||||||
|
CypherParser::SymbolicNameContext *ctx) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return vector<Pattern*>
|
||||||
|
*/
|
||||||
antlrcpp::Any visitPattern(CypherParser::PatternContext *ctx) override;
|
antlrcpp::Any visitPattern(CypherParser::PatternContext *ctx) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores PatternPart in symbol_table_. If variable is defined it is stored
|
* @return Pattern*
|
||||||
*in
|
*/
|
||||||
* ids_map_.
|
antlrcpp::Any visitPatternPart(
|
||||||
*
|
CypherParser::PatternPartContext *ctx) override;
|
||||||
* @return string - pattern part id.
|
|
||||||
*/
|
|
||||||
antlrcpp::Any
|
|
||||||
visitPatternPart(CypherParser::PatternPartContext *ctx) override;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates PatternPart.
|
* @return Pattern*
|
||||||
*
|
*/
|
||||||
* @return PatternPart.
|
antlrcpp::Any visitPatternElement(
|
||||||
*/
|
CypherParser::PatternElementContext *ctx) override;
|
||||||
antlrcpp::Any
|
|
||||||
visitPatternElement(CypherParser::PatternElementContext *ctx) override;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return pair<string, string> - node and relationship ids.
|
* @return vector<pair<EdgeAtom*, NodeAtom*>>
|
||||||
*/
|
*/
|
||||||
antlrcpp::Any visitPatternElementChain(
|
antlrcpp::Any visitPatternElementChain(
|
||||||
CypherParser::PatternElementChainContext *ctx) override;
|
CypherParser::PatternElementChainContext *ctx) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates Relationship and stores it in symbol_table_. If variable is defined
|
*@return EdgeAtom*
|
||||||
* it is stored in symbol_table_.
|
*/
|
||||||
*
|
|
||||||
* @return string - relationship id.
|
|
||||||
*/
|
|
||||||
antlrcpp::Any visitRelationshipPattern(
|
antlrcpp::Any visitRelationshipPattern(
|
||||||
CypherParser::RelationshipPatternContext *ctx) override;
|
CypherParser::RelationshipPatternContext *ctx) override;
|
||||||
|
|
||||||
@ -142,23 +161,24 @@ private:
|
|||||||
*/
|
*/
|
||||||
antlrcpp::Any visitRelationshipDetail(
|
antlrcpp::Any visitRelationshipDetail(
|
||||||
CypherParser::RelationshipDetailContext *ctx) override;
|
CypherParser::RelationshipDetailContext *ctx) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return vector<string>.
|
* @return vector<GraphDb::EdgeType>
|
||||||
*/
|
*/
|
||||||
antlrcpp::Any
|
antlrcpp::Any visitRelationshipTypes(
|
||||||
visitRelationshipTypes(CypherParser::RelationshipTypesContext *ctx) override;
|
CypherParser::RelationshipTypesContext *ctx) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return pair<int64_t, int64_t>.
|
* @return pair<int64_t, int64_t>.
|
||||||
*/
|
*/
|
||||||
antlrcpp::Any
|
antlrcpp::Any visitRangeLiteral(
|
||||||
visitRangeLiteral(CypherParser::RangeLiteralContext *ctx) override;
|
CypherParser::RangeLiteralContext *ctx) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Top level expression.
|
* Top level expression, does nothing.
|
||||||
*
|
*
|
||||||
* @return string - expression id.
|
* @return Expression*
|
||||||
*/
|
*/
|
||||||
antlrcpp::Any visitExpression(CypherParser::ExpressionContext *ctx) override;
|
antlrcpp::Any visitExpression(CypherParser::ExpressionContext *ctx) override;
|
||||||
|
|
||||||
///**
|
///**
|
||||||
@ -248,18 +268,18 @@ private:
|
|||||||
// antlrcpp::Any
|
// antlrcpp::Any
|
||||||
// visitExpression3(CypherParser::Expression3Context *ctx) override;
|
// visitExpression3(CypherParser::Expression3Context *ctx) override;
|
||||||
|
|
||||||
///**
|
/**
|
||||||
//* Property lookup, test for node labels existence...
|
* Property lookup, test for node labels existence...
|
||||||
//*
|
*
|
||||||
//* @return string - expression id.
|
* @return Expression*
|
||||||
//*/
|
*/
|
||||||
// antlrcpp::Any
|
antlrcpp::Any visitExpression2(
|
||||||
// visitExpression2(CypherParser::Expression2Context *ctx) override;
|
CypherParser::Expression2Context *ctx) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Literals, params, list comprehension...
|
* Literals, params, list comprehension...
|
||||||
*
|
*
|
||||||
* @return string - expression id.
|
* @return Expression*
|
||||||
*/
|
*/
|
||||||
antlrcpp::Any visitAtom(CypherParser::AtomContext *ctx) override;
|
antlrcpp::Any visitAtom(CypherParser::AtomContext *ctx) override;
|
||||||
|
|
||||||
@ -285,14 +305,14 @@ private:
|
|||||||
/**
|
/**
|
||||||
* @return int64_t.
|
* @return int64_t.
|
||||||
*/
|
*/
|
||||||
antlrcpp::Any
|
antlrcpp::Any visitIntegerLiteral(
|
||||||
visitIntegerLiteral(CypherParser::IntegerLiteralContext *ctx) override;
|
CypherParser::IntegerLiteralContext *ctx) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Query *query() { return query_; }
|
Query *query() { return query_; }
|
||||||
const static std::string kAnonPrefix;
|
const static std::string kAnonPrefix;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Context &ctx_;
|
Context &ctx_;
|
||||||
// Set of identifiers from queries.
|
// Set of identifiers from queries.
|
||||||
std::unordered_set<std::string> users_identifiers;
|
std::unordered_set<std::string> users_identifiers;
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
#include "antlr4-runtime.h"
|
#include "antlr4-runtime.h"
|
||||||
#include "dbms/dbms.hpp"
|
#include "dbms/dbms.hpp"
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
#include "query/context.hpp"
|
#include "query/context.hpp"
|
||||||
#include "query/frontend/ast/cypher_main_visitor.hpp"
|
#include "query/frontend/ast/cypher_main_visitor.hpp"
|
||||||
#include "query/frontend/opencypher/parser.hpp"
|
#include "query/frontend/opencypher/parser.hpp"
|
||||||
#include "gtest/gtest.h"
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -19,11 +19,15 @@ using namespace query::frontend;
|
|||||||
using testing::UnorderedElementsAre;
|
using testing::UnorderedElementsAre;
|
||||||
|
|
||||||
class AstGenerator {
|
class AstGenerator {
|
||||||
public:
|
public:
|
||||||
AstGenerator(const std::string &query)
|
AstGenerator(const std::string &query)
|
||||||
: dbms_(), db_accessor_(dbms_.active()),
|
: dbms_(),
|
||||||
context_(Config{}, *db_accessor_), query_string_(query), parser_(query),
|
db_accessor_(dbms_.active()),
|
||||||
visitor_(context_), query_([&]() {
|
context_(Config{}, *db_accessor_),
|
||||||
|
query_string_(query),
|
||||||
|
parser_(query),
|
||||||
|
visitor_(context_),
|
||||||
|
query_([&]() {
|
||||||
visitor_.visit(parser_.tree());
|
visitor_.visit(parser_.tree());
|
||||||
return visitor_.query();
|
return visitor_.query();
|
||||||
}()) {}
|
}()) {}
|
||||||
@ -37,11 +41,11 @@ public:
|
|||||||
Query *query_;
|
Query *query_;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(CompilerStructuresTest, SyntaxException) {
|
TEST(CypherMainVisitorTest, SyntaxException) {
|
||||||
ASSERT_THROW(AstGenerator("CREATE ()-[*1...2]-()"), std::exception);
|
ASSERT_THROW(AstGenerator("CREATE ()-[*1...2]-()"), std::exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CompilerStructuresTest, NodePattern) {
|
TEST(CypherMainVisitorTest, NodePattern) {
|
||||||
AstGenerator ast_generator("MATCH (:label1:label2:label3)");
|
AstGenerator ast_generator("MATCH (:label1:label2:label3)");
|
||||||
auto *query = ast_generator.query_;
|
auto *query = ast_generator.query_;
|
||||||
ASSERT_EQ(query->clauses_.size(), 1U);
|
ASSERT_EQ(query->clauses_.size(), 1U);
|
||||||
@ -62,7 +66,7 @@ TEST(CompilerStructuresTest, NodePattern) {
|
|||||||
// TODO: add test for properties.
|
// TODO: add test for properties.
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CompilerStructuresTest, NodePatternIdentifier) {
|
TEST(CypherMainVisitorTest, NodePatternIdentifier) {
|
||||||
AstGenerator ast_generator("MATCH (var)");
|
AstGenerator ast_generator("MATCH (var)");
|
||||||
auto *query = ast_generator.query_;
|
auto *query = ast_generator.query_;
|
||||||
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
|
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
|
||||||
@ -73,7 +77,7 @@ TEST(CompilerStructuresTest, NodePatternIdentifier) {
|
|||||||
// TODO: add test for properties.
|
// TODO: add test for properties.
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CompilerStructuresTest, RelationshipPatternNoDetails) {
|
TEST(CypherMainVisitorTest, RelationshipPatternNoDetails) {
|
||||||
AstGenerator ast_generator("MATCH ()--()");
|
AstGenerator ast_generator("MATCH ()--()");
|
||||||
auto *query = ast_generator.query_;
|
auto *query = ast_generator.query_;
|
||||||
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
|
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
|
||||||
@ -92,7 +96,7 @@ TEST(CompilerStructuresTest, RelationshipPatternNoDetails) {
|
|||||||
CypherMainVisitor::kAnonPrefix + std::to_string(2));
|
CypherMainVisitor::kAnonPrefix + std::to_string(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CompilerStructuresTest, RelationshipPatternDetails) {
|
TEST(CypherMainVisitorTest, RelationshipPatternDetails) {
|
||||||
AstGenerator ast_generator("MATCH ()<-[:type1|type2]-()");
|
AstGenerator ast_generator("MATCH ()<-[:type1|type2]-()");
|
||||||
auto *query = ast_generator.query_;
|
auto *query = ast_generator.query_;
|
||||||
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
|
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
|
||||||
@ -105,7 +109,7 @@ TEST(CompilerStructuresTest, RelationshipPatternDetails) {
|
|||||||
// TODO: test properties
|
// TODO: test properties
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CompilerStructuresTest, RelationshipPatternVariable) {
|
TEST(CypherMainVisitorTest, RelationshipPatternVariable) {
|
||||||
AstGenerator ast_generator("MATCH ()-[var]->()");
|
AstGenerator ast_generator("MATCH ()-[var]->()");
|
||||||
auto *query = ast_generator.query_;
|
auto *query = ast_generator.query_;
|
||||||
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
|
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
|
||||||
@ -116,7 +120,7 @@ TEST(CompilerStructuresTest, RelationshipPatternVariable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// // Relationship with unbounded variable range.
|
// // Relationship with unbounded variable range.
|
||||||
// TEST(CompilerStructuresTest, RelationshipPatternUnbounded) {
|
// TEST(CypherMainVisitorTest, RelationshipPatternUnbounded) {
|
||||||
// ParserTables parser("CREATE ()-[*]-()");
|
// ParserTables parser("CREATE ()-[*]-()");
|
||||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||||
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
||||||
@ -126,7 +130,7 @@ TEST(CompilerStructuresTest, RelationshipPatternVariable) {
|
|||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// // Relationship with lower bounded variable range.
|
// // Relationship with lower bounded variable range.
|
||||||
// TEST(CompilerStructuresTest, RelationshipPatternLowerBounded) {
|
// TEST(CypherMainVisitorTest, RelationshipPatternLowerBounded) {
|
||||||
// ParserTables parser("CREATE ()-[*5..]-()");
|
// ParserTables parser("CREATE ()-[*5..]-()");
|
||||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||||
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
||||||
@ -136,7 +140,7 @@ TEST(CompilerStructuresTest, RelationshipPatternVariable) {
|
|||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// // Relationship with upper bounded variable range.
|
// // Relationship with upper bounded variable range.
|
||||||
// TEST(CompilerStructuresTest, RelationshipPatternUpperBounded) {
|
// TEST(CypherMainVisitorTest, RelationshipPatternUpperBounded) {
|
||||||
// ParserTables parser("CREATE ()-[*..10]-()");
|
// ParserTables parser("CREATE ()-[*..10]-()");
|
||||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||||
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
||||||
@ -145,7 +149,7 @@ TEST(CompilerStructuresTest, RelationshipPatternVariable) {
|
|||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// // Relationship with lower and upper bounded variable range.
|
// // Relationship with lower and upper bounded variable range.
|
||||||
// TEST(CompilerStructuresTest, RelationshipPatternLowerUpperBounded) {
|
// TEST(CypherMainVisitorTest, RelationshipPatternLowerUpperBounded) {
|
||||||
// ParserTables parser("CREATE ()-[*5..10]-()");
|
// ParserTables parser("CREATE ()-[*5..10]-()");
|
||||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||||
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
||||||
@ -154,7 +158,7 @@ TEST(CompilerStructuresTest, RelationshipPatternVariable) {
|
|||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// // Relationship with fixed number of edges.
|
// // Relationship with fixed number of edges.
|
||||||
// TEST(CompilerStructuresTest, RelationshipPatternFixedRange) {
|
// TEST(CypherMainVisitorTest, RelationshipPatternFixedRange) {
|
||||||
// ParserTables parser("CREATE ()-[*10]-()");
|
// ParserTables parser("CREATE ()-[*10]-()");
|
||||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||||
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
// ASSERT_EQ(parser.relationships_.size(), 1U);
|
||||||
@ -163,15 +167,14 @@ TEST(CompilerStructuresTest, RelationshipPatternVariable) {
|
|||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// // Relationship with invalid bound (larger than long long).
|
// // Relationship with invalid bound (larger than long long).
|
||||||
// TEST(CompilerStructuresTest, RelationshipPatternInvalidBound) {
|
// TEST(CypherMainVisitorTest, RelationshipPatternInvalidBound) {
|
||||||
// ASSERT_THROW(
|
// ASSERT_THROW(
|
||||||
// ParserTables parser("CREATE ()-[*100000000000000000000000000]-()"),
|
// ParserTables parser("CREATE ()-[*100000000000000000000000000]-()"),
|
||||||
// SemanticException);
|
// SemanticException);
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
//
|
|
||||||
// // PatternPart.
|
// // PatternPart.
|
||||||
// TEST(CompilerStructuresTest, PatternPart) {
|
// TEST(CypherMainVisitorTest, PatternPart) {
|
||||||
// ParserTables parser("CREATE ()--()");
|
// ParserTables parser("CREATE ()--()");
|
||||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||||
// ASSERT_EQ(parser.pattern_parts_.size(), 1U);
|
// ASSERT_EQ(parser.pattern_parts_.size(), 1U);
|
||||||
@ -182,7 +185,7 @@ TEST(CompilerStructuresTest, RelationshipPatternVariable) {
|
|||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// // PatternPart in braces.
|
// // PatternPart in braces.
|
||||||
// TEST(CompilerStructuresTest, PatternPartBraces) {
|
// TEST(CypherMainVisitorTest, PatternPartBraces) {
|
||||||
// ParserTables parser("CREATE ((()--()))");
|
// ParserTables parser("CREATE ((()--()))");
|
||||||
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
// ASSERT_EQ(parser.identifiers_map_.size(), 0U);
|
||||||
// ASSERT_EQ(parser.pattern_parts_.size(), 1U);
|
// ASSERT_EQ(parser.pattern_parts_.size(), 1U);
|
||||||
@ -193,7 +196,7 @@ TEST(CompilerStructuresTest, RelationshipPatternVariable) {
|
|||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// // PatternPart with variable.
|
// // PatternPart with variable.
|
||||||
// TEST(CompilerStructuresTest, PatternPartVariable) {
|
// TEST(CypherMainVisitorTest, PatternPartVariable) {
|
||||||
// ParserTables parser("CREATE var=()--()");
|
// ParserTables parser("CREATE var=()--()");
|
||||||
// ASSERT_EQ(parser.identifiers_map_.size(), 1U);
|
// ASSERT_EQ(parser.identifiers_map_.size(), 1U);
|
||||||
// ASSERT_EQ(parser.pattern_parts_.size(), 1U);
|
// ASSERT_EQ(parser.pattern_parts_.size(), 1U);
|
||||||
@ -209,8 +212,49 @@ TEST(CompilerStructuresTest, RelationshipPatternVariable) {
|
|||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// // Multiple nodes with same variable and properties.
|
// // Multiple nodes with same variable and properties.
|
||||||
// TEST(CompilerStructuresTest, MultipleNodesWithVariableAndProperties) {
|
// TEST(CypherMainVisitorTest, MultipleNodesWithVariableAndProperties) {
|
||||||
// ASSERT_THROW(ParserTables parser("CREATE (a {b: 5})-[]-(a {c: 5})"),
|
// ASSERT_THROW(ParserTables parser("CREATE (a {b: 5})-[]-(a {c: 5})"),
|
||||||
// SemanticException);
|
// SemanticException);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
TEST(CypherMainVisitorTest, ReturnUnanemdIdentifier) {
|
||||||
|
AstGenerator ast_generator("RETURN var");
|
||||||
|
auto *query = ast_generator.query_;
|
||||||
|
ASSERT_EQ(query->clauses_.size(), 1U);
|
||||||
|
auto *return_clause = dynamic_cast<Return *>(query->clauses_[0]);
|
||||||
|
ASSERT_TRUE(return_clause);
|
||||||
|
ASSERT_EQ(return_clause->named_expressions_.size(), 1U);
|
||||||
|
auto *named_expr = return_clause->named_expressions_[0];
|
||||||
|
ASSERT_TRUE(named_expr);
|
||||||
|
ASSERT_EQ(named_expr->name_, "var");
|
||||||
|
auto *identifier = dynamic_cast<Identifier *>(named_expr->expression_);
|
||||||
|
ASSERT_TRUE(identifier);
|
||||||
|
ASSERT_EQ(identifier->name_, "var");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CypherMainVisitorTest, ReturnNamedIdentifier) {
|
||||||
|
AstGenerator ast_generator("RETURN var AS var5");
|
||||||
|
auto *query = ast_generator.query_;
|
||||||
|
auto *return_clause = dynamic_cast<Return *>(query->clauses_[0]);
|
||||||
|
auto *named_expr = return_clause->named_expressions_[0];
|
||||||
|
ASSERT_EQ(named_expr->name_, "var5");
|
||||||
|
auto *identifier = dynamic_cast<Identifier *>(named_expr->expression_);
|
||||||
|
ASSERT_EQ(identifier->name_, "var");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CypherMainVisitorTest, Create) {
|
||||||
|
AstGenerator ast_generator("CREATE (n)");
|
||||||
|
auto *query = ast_generator.query_;
|
||||||
|
ASSERT_EQ(query->clauses_.size(), 1U);
|
||||||
|
auto *create = dynamic_cast<Create *>(query->clauses_[0]);
|
||||||
|
ASSERT_TRUE(create);
|
||||||
|
ASSERT_EQ(create->patterns_.size(), 1U);
|
||||||
|
ASSERT_TRUE(create->patterns_[0]);
|
||||||
|
ASSERT_EQ(create->patterns_[0]->atoms_.size(), 1U);
|
||||||
|
auto node = dynamic_cast<NodeAtom *>(create->patterns_[0]->atoms_[0]);
|
||||||
|
ASSERT_TRUE(node);
|
||||||
|
ASSERT_TRUE(node->identifier_);
|
||||||
|
ASSERT_EQ(node->identifier_->name_, "n");
|
||||||
|
// TODO: add test for properties.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user