Separate auth/stream queries from rest of cypher
Summary: first step for a cleaner query front end that might be easier to open source Reviewers: teon.banek Reviewed By: teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1511
This commit is contained in:
parent
2ecb660790
commit
9a6801cb98
@ -160,15 +160,15 @@ include_directories(SYSTEM ${LIBRDKAFKA_INCLUDE_DIR})
|
||||
# openCypher parser -----------------------------------------------------------
|
||||
set(opencypher_frontend ${CMAKE_SOURCE_DIR}/src/query/frontend/opencypher)
|
||||
set(opencypher_generated ${opencypher_frontend}/generated)
|
||||
set(opencypher_lexer_grammar ${opencypher_frontend}/grammar/CypherLexer.g4)
|
||||
set(opencypher_parser_grammar ${opencypher_frontend}/grammar/CypherParser.g4)
|
||||
set(opencypher_lexer_grammar ${opencypher_frontend}/grammar/MemgraphCypherLexer.g4)
|
||||
set(opencypher_parser_grammar ${opencypher_frontend}/grammar/MemgraphCypher.g4)
|
||||
|
||||
# enumerate all files that are generated from antlr
|
||||
set(antlr_opencypher_generated_src
|
||||
${opencypher_generated}/CypherLexer.cpp
|
||||
${opencypher_generated}/CypherParser.cpp
|
||||
${opencypher_generated}/CypherParserBaseVisitor.cpp
|
||||
${opencypher_generated}/CypherParserVisitor.cpp
|
||||
${opencypher_generated}/MemgraphCypherLexer.cpp
|
||||
${opencypher_generated}/MemgraphCypher.cpp
|
||||
${opencypher_generated}/MemgraphCypherBaseVisitor.cpp
|
||||
${opencypher_generated}/MemgraphCypherVisitor.cpp
|
||||
)
|
||||
|
||||
# Provide a command to generate sources if missing. If this were a
|
||||
|
@ -24,8 +24,45 @@ namespace query::frontend {
|
||||
|
||||
const std::string CypherMainVisitor::kAnonPrefix = "anon";
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitAuthQuery(
|
||||
MemgraphCypher::AuthQueryContext *ctx) {
|
||||
query_ = storage_.query();
|
||||
query_->single_query_ = storage_.Create<SingleQuery>();
|
||||
Clause *clause = nullptr;
|
||||
if (ctx->modifyUser()) {
|
||||
clause = ctx->modifyUser()->accept(this).as<ModifyUser *>();
|
||||
} else if (ctx->dropUser()) {
|
||||
clause = ctx->dropUser()->accept(this).as<DropUser *>();
|
||||
}
|
||||
query_->single_query_->clauses_ = {clause};
|
||||
return query_;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitStreamQuery(
|
||||
MemgraphCypher::StreamQueryContext *ctx) {
|
||||
query_ = storage_.query();
|
||||
query_->single_query_ = storage_.Create<SingleQuery>();
|
||||
Clause *clause = nullptr;
|
||||
if (ctx->createStream()) {
|
||||
clause = ctx->createStream()->accept(this).as<CreateStream *>();
|
||||
} else if (ctx->dropStream()) {
|
||||
clause = ctx->dropStream()->accept(this).as<DropStream *>();
|
||||
} else if (ctx->showStreams()) {
|
||||
clause = ctx->showStreams()->accept(this).as<ShowStreams *>();
|
||||
} else if (ctx->startStopStream()) {
|
||||
clause = ctx->startStopStream()->accept(this).as<StartStopStream *>();
|
||||
} else if (ctx->startStopAllStreams()) {
|
||||
clause =
|
||||
ctx->startStopAllStreams()->accept(this).as<StartStopAllStreams *>();
|
||||
} else if (ctx->testStream()) {
|
||||
clause = ctx->testStream()->accept(this).as<TestStream *>();
|
||||
}
|
||||
query_->single_query_->clauses_ = {clause};
|
||||
return query_;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitRegularQuery(
|
||||
CypherParser::RegularQueryContext *ctx) {
|
||||
MemgraphCypher::RegularQueryContext *ctx) {
|
||||
query_ = storage_.query();
|
||||
DCHECK(ctx->singleQuery()) << "Expected single query.";
|
||||
query_->single_query_ = ctx->singleQuery()->accept(this).as<SingleQuery *>();
|
||||
@ -49,7 +86,7 @@ antlrcpp::Any CypherMainVisitor::visitRegularQuery(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitCypherUnion(
|
||||
CypherParser::CypherUnionContext *ctx) {
|
||||
MemgraphCypher::CypherUnionContext *ctx) {
|
||||
bool distinct = !ctx->ALL();
|
||||
auto *cypher_union = storage_.Create<CypherUnion>(distinct);
|
||||
DCHECK(ctx->singleQuery()) << "Expected single query.";
|
||||
@ -59,7 +96,7 @@ antlrcpp::Any CypherMainVisitor::visitCypherUnion(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitSingleQuery(
|
||||
CypherParser::SingleQueryContext *ctx) {
|
||||
MemgraphCypher::SingleQueryContext *ctx) {
|
||||
auto *single_query = storage_.Create<SingleQuery>();
|
||||
for (auto *child : ctx->clause()) {
|
||||
antlrcpp::Any got = child->accept(this);
|
||||
@ -81,8 +118,6 @@ antlrcpp::Any CypherMainVisitor::visitSingleQuery(
|
||||
bool has_return = false;
|
||||
bool has_optional_match = false;
|
||||
bool has_create_index = false;
|
||||
bool has_modify_user = false;
|
||||
bool has_stream_clause = false;
|
||||
|
||||
for (Clause *clause : single_query->clauses_) {
|
||||
if (dynamic_cast<Unwind *>(clause)) {
|
||||
@ -128,34 +163,11 @@ antlrcpp::Any CypherMainVisitor::visitSingleQuery(
|
||||
"CreateIndex must be only clause in the query.");
|
||||
}
|
||||
has_create_index = true;
|
||||
} else if (dynamic_cast<ModifyUser *>(clause)) {
|
||||
has_modify_user = true;
|
||||
if (single_query->clauses_.size() != 1U) {
|
||||
throw SemanticException("ModifyUser must be only clause in the query.");
|
||||
}
|
||||
} else if (dynamic_cast<DropUser *>(clause)) {
|
||||
has_modify_user = true;
|
||||
if (single_query->clauses_.size() != 1U) {
|
||||
throw SemanticException("DropUser must be only clause in the query.");
|
||||
}
|
||||
} else if (dynamic_cast<CreateStream *>(clause) ||
|
||||
dynamic_cast<DropStream *>(clause) ||
|
||||
dynamic_cast<ShowStreams *>(clause) ||
|
||||
dynamic_cast<StartStopStream *>(clause) ||
|
||||
dynamic_cast<StartStopAllStreams *>(clause) ||
|
||||
dynamic_cast<TestStream *>(clause)) {
|
||||
// If there is stream clause then there shouldn't be anything else.
|
||||
if (single_query->clauses_.size() != 1U) {
|
||||
throw SemanticException(
|
||||
"Stream clause must be the only clause in the query.");
|
||||
}
|
||||
has_stream_clause = true;
|
||||
} else {
|
||||
DLOG(FATAL) << "Can't happen";
|
||||
}
|
||||
}
|
||||
if (!has_update && !has_return && !has_create_index && !has_modify_user &&
|
||||
!has_stream_clause) {
|
||||
if (!has_update && !has_return && !has_create_index) {
|
||||
throw SemanticException(
|
||||
"Query should either create or update something, or return results!");
|
||||
}
|
||||
@ -174,7 +186,8 @@ antlrcpp::Any CypherMainVisitor::visitSingleQuery(
|
||||
return single_query;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitClause(CypherParser::ClauseContext *ctx) {
|
||||
antlrcpp::Any CypherMainVisitor::visitClause(
|
||||
MemgraphCypher::ClauseContext *ctx) {
|
||||
if (ctx->cypherReturn()) {
|
||||
return static_cast<Clause *>(
|
||||
ctx->cypherReturn()->accept(this).as<Return *>());
|
||||
@ -211,45 +224,13 @@ antlrcpp::Any CypherMainVisitor::visitClause(CypherParser::ClauseContext *ctx) {
|
||||
return static_cast<Clause *>(
|
||||
ctx->createIndex()->accept(this).as<CreateIndex *>());
|
||||
}
|
||||
if (ctx->modifyUser()) {
|
||||
return static_cast<Clause *>(
|
||||
ctx->modifyUser()->accept(this).as<ModifyUser *>());
|
||||
}
|
||||
if (ctx->dropUser()) {
|
||||
return static_cast<Clause *>(
|
||||
ctx->dropUser()->accept(this).as<DropUser *>());
|
||||
}
|
||||
if (ctx->createStream()) {
|
||||
return static_cast<Clause *>(
|
||||
ctx->createStream()->accept(this).as<CreateStream *>());
|
||||
}
|
||||
if (ctx->dropStream()) {
|
||||
return static_cast<Clause *>(
|
||||
ctx->dropStream()->accept(this).as<DropStream *>());
|
||||
}
|
||||
if (ctx->showStreams()) {
|
||||
return static_cast<Clause *>(
|
||||
ctx->showStreams()->accept(this).as<ShowStreams *>());
|
||||
}
|
||||
if (ctx->startStopStream()) {
|
||||
return static_cast<Clause *>(
|
||||
ctx->startStopStream()->accept(this).as<StartStopStream *>());
|
||||
}
|
||||
if (ctx->startStopAllStreams()) {
|
||||
return static_cast<Clause *>(
|
||||
ctx->startStopAllStreams()->accept(this).as<StartStopAllStreams *>());
|
||||
}
|
||||
if (ctx->testStream()) {
|
||||
return static_cast<Clause *>(
|
||||
ctx->testStream()->accept(this).as<TestStream *>());
|
||||
}
|
||||
// TODO: implement other clauses.
|
||||
throw utils::NotYetImplemented("clause '{}'", ctx->getText());
|
||||
return 0;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitCypherMatch(
|
||||
CypherParser::CypherMatchContext *ctx) {
|
||||
MemgraphCypher::CypherMatchContext *ctx) {
|
||||
auto *match = storage_.Create<Match>();
|
||||
match->optional_ = !!ctx->OPTIONAL();
|
||||
if (ctx->where()) {
|
||||
@ -259,7 +240,8 @@ antlrcpp::Any CypherMainVisitor::visitCypherMatch(
|
||||
return match;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitCreate(CypherParser::CreateContext *ctx) {
|
||||
antlrcpp::Any CypherMainVisitor::visitCreate(
|
||||
MemgraphCypher::CreateContext *ctx) {
|
||||
auto *create = storage_.Create<Create>();
|
||||
create->patterns_ = ctx->pattern()->accept(this).as<std::vector<Pattern *>>();
|
||||
return create;
|
||||
@ -269,7 +251,7 @@ antlrcpp::Any CypherMainVisitor::visitCreate(CypherParser::CreateContext *ctx) {
|
||||
* @return CreateIndex*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitCreateIndex(
|
||||
CypherParser::CreateIndexContext *ctx) {
|
||||
MemgraphCypher::CreateIndexContext *ctx) {
|
||||
std::pair<std::string, storage::Property> key =
|
||||
ctx->propertyKeyName()->accept(this);
|
||||
return storage_.Create<CreateIndex>(
|
||||
@ -280,10 +262,10 @@ antlrcpp::Any CypherMainVisitor::visitCreateIndex(
|
||||
* @return ModifyUser*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitModifyUser(
|
||||
CypherParser::ModifyUserContext *ctx) {
|
||||
std::string username(ctx->userName()->getText());
|
||||
MemgraphCypher::ModifyUserContext *ctx) {
|
||||
std::string username(ctx->userName->getText());
|
||||
Expression *password = nullptr;
|
||||
bool is_create = static_cast<bool>(ctx->createUser());
|
||||
bool is_create = static_cast<bool>(ctx->CREATE());
|
||||
for (auto option : ctx->modifyUserOption()) {
|
||||
if (option->passwordOption()) {
|
||||
if (password) {
|
||||
@ -301,7 +283,7 @@ antlrcpp::Any CypherMainVisitor::visitModifyUser(
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitPasswordOption(
|
||||
CypherParser::PasswordOptionContext *ctx) {
|
||||
MemgraphCypher::PasswordOptionContext *ctx) {
|
||||
if (!ctx->literal()->StringLiteral() && !ctx->literal()->CYPHERNULL()) {
|
||||
throw SyntaxException("password should be a string literal or NULL");
|
||||
}
|
||||
@ -312,9 +294,9 @@ antlrcpp::Any CypherMainVisitor::visitPasswordOption(
|
||||
* @return DropUser*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitDropUser(
|
||||
CypherParser::DropUserContext *ctx) {
|
||||
MemgraphCypher::DropUserContext *ctx) {
|
||||
std::vector<std::string> usernames;
|
||||
for (auto username_ptr : ctx->userName())
|
||||
for (auto username_ptr : ctx->userName)
|
||||
usernames.emplace_back(username_ptr->getText());
|
||||
return storage_.Create<DropUser>(usernames);
|
||||
}
|
||||
@ -323,7 +305,7 @@ antlrcpp::Any CypherMainVisitor::visitDropUser(
|
||||
* @return CreateStream*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitCreateStream(
|
||||
CypherParser::CreateStreamContext *ctx) {
|
||||
MemgraphCypher::CreateStreamContext *ctx) {
|
||||
std::string stream_name(ctx->streamName()->getText());
|
||||
if (!ctx->streamUri->StringLiteral()) {
|
||||
throw SyntaxException("Stream URI should be a string literal!");
|
||||
@ -359,7 +341,7 @@ antlrcpp::Any CypherMainVisitor::visitCreateStream(
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitBatchIntervalOption(
|
||||
CypherParser::BatchIntervalOptionContext *ctx) {
|
||||
MemgraphCypher::BatchIntervalOptionContext *ctx) {
|
||||
if (!ctx->literal()->numberLiteral() ||
|
||||
!ctx->literal()->numberLiteral()->integerLiteral()) {
|
||||
throw SyntaxException("Batch interval should be an integer literal!");
|
||||
@ -371,7 +353,7 @@ antlrcpp::Any CypherMainVisitor::visitBatchIntervalOption(
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitBatchSizeOption(
|
||||
CypherParser::BatchSizeOptionContext *ctx) {
|
||||
MemgraphCypher::BatchSizeOptionContext *ctx) {
|
||||
if (!ctx->literal()->numberLiteral() ||
|
||||
!ctx->literal()->numberLiteral()->integerLiteral()) {
|
||||
throw SyntaxException("Batch size should be an integer literal!");
|
||||
@ -383,7 +365,7 @@ antlrcpp::Any CypherMainVisitor::visitBatchSizeOption(
|
||||
* @return DropStream*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitDropStream(
|
||||
CypherParser::DropStreamContext *ctx) {
|
||||
MemgraphCypher::DropStreamContext *ctx) {
|
||||
return storage_.Create<DropStream>(std::string(ctx->streamName()->getText()));
|
||||
}
|
||||
|
||||
@ -391,7 +373,7 @@ antlrcpp::Any CypherMainVisitor::visitDropStream(
|
||||
* @return ShowStreams*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitShowStreams(
|
||||
CypherParser::ShowStreamsContext *ctx) {
|
||||
MemgraphCypher::ShowStreamsContext *ctx) {
|
||||
return storage_.Create<ShowStreams>();
|
||||
}
|
||||
|
||||
@ -399,7 +381,7 @@ antlrcpp::Any CypherMainVisitor::visitShowStreams(
|
||||
* @return StartStopStream*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitStartStopStream(
|
||||
CypherParser::StartStopStreamContext *ctx) {
|
||||
MemgraphCypher::StartStopStreamContext *ctx) {
|
||||
std::string stream_name(std::string(ctx->streamName()->getText()));
|
||||
bool is_start = static_cast<bool>(ctx->START());
|
||||
Expression *limit_batches = nullptr;
|
||||
@ -418,7 +400,7 @@ antlrcpp::Any CypherMainVisitor::visitStartStopStream(
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitLimitBatchesOption(
|
||||
CypherParser::LimitBatchesOptionContext *ctx) {
|
||||
MemgraphCypher::LimitBatchesOptionContext *ctx) {
|
||||
if (!ctx->literal()->numberLiteral() ||
|
||||
!ctx->literal()->numberLiteral()->integerLiteral()) {
|
||||
throw SyntaxException("Batch limit should be an integer literal!");
|
||||
@ -430,13 +412,13 @@ antlrcpp::Any CypherMainVisitor::visitLimitBatchesOption(
|
||||
* @return StartStopAllStreams*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitStartStopAllStreams(
|
||||
CypherParser::StartStopAllStreamsContext *ctx) {
|
||||
MemgraphCypher::StartStopAllStreamsContext *ctx) {
|
||||
bool is_start = static_cast<bool>(ctx->START());
|
||||
return storage_.Create<StartStopAllStreams>(is_start);
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitCypherReturn(
|
||||
CypherParser::CypherReturnContext *ctx) {
|
||||
MemgraphCypher::CypherReturnContext *ctx) {
|
||||
auto *return_clause = storage_.Create<Return>();
|
||||
return_clause->body_ = ctx->returnBody()->accept(this);
|
||||
if (ctx->DISTINCT()) {
|
||||
@ -449,7 +431,7 @@ antlrcpp::Any CypherMainVisitor::visitCypherReturn(
|
||||
* @return TestStream*
|
||||
*/
|
||||
antlrcpp::Any CypherMainVisitor::visitTestStream(
|
||||
CypherParser::TestStreamContext *ctx) {
|
||||
MemgraphCypher::TestStreamContext *ctx) {
|
||||
std::string stream_name(std::string(ctx->streamName()->getText()));
|
||||
Expression *limit_batches = nullptr;
|
||||
|
||||
@ -461,7 +443,7 @@ antlrcpp::Any CypherMainVisitor::visitTestStream(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitReturnBody(
|
||||
CypherParser::ReturnBodyContext *ctx) {
|
||||
MemgraphCypher::ReturnBodyContext *ctx) {
|
||||
ReturnBody body;
|
||||
if (ctx->order()) {
|
||||
body.order_by = ctx->order()
|
||||
@ -482,17 +464,17 @@ antlrcpp::Any CypherMainVisitor::visitReturnBody(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitReturnItems(
|
||||
CypherParser::ReturnItemsContext *ctx) {
|
||||
MemgraphCypher::ReturnItemsContext *ctx) {
|
||||
std::vector<NamedExpression *> named_expressions;
|
||||
for (auto *item : ctx->returnItem()) {
|
||||
named_expressions.push_back(item->accept(this));
|
||||
}
|
||||
return std::pair<bool, std::vector<NamedExpression *>>(
|
||||
ctx->getTokens(CypherParser::ASTERISK).size(), named_expressions);
|
||||
ctx->getTokens(MemgraphCypher::ASTERISK).size(), named_expressions);
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitReturnItem(
|
||||
CypherParser::ReturnItemContext *ctx) {
|
||||
MemgraphCypher::ReturnItemContext *ctx) {
|
||||
auto *named_expr = storage_.Create<NamedExpression>();
|
||||
named_expr->expression_ = ctx->expression()->accept(this);
|
||||
if (ctx->variable()) {
|
||||
@ -509,7 +491,7 @@ antlrcpp::Any CypherMainVisitor::visitReturnItem(
|
||||
return named_expr;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitOrder(CypherParser::OrderContext *ctx) {
|
||||
antlrcpp::Any CypherMainVisitor::visitOrder(MemgraphCypher::OrderContext *ctx) {
|
||||
std::vector<std::pair<Ordering, Expression *>> order_by;
|
||||
for (auto *sort_item : ctx->sortItem()) {
|
||||
order_by.push_back(sort_item->accept(this));
|
||||
@ -518,14 +500,14 @@ antlrcpp::Any CypherMainVisitor::visitOrder(CypherParser::OrderContext *ctx) {
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitSortItem(
|
||||
CypherParser::SortItemContext *ctx) {
|
||||
MemgraphCypher::SortItemContext *ctx) {
|
||||
return std::pair<Ordering, Expression *>(
|
||||
ctx->DESC() || ctx->DESCENDING() ? Ordering::DESC : Ordering::ASC,
|
||||
ctx->expression()->accept(this));
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitNodePattern(
|
||||
CypherParser::NodePatternContext *ctx) {
|
||||
MemgraphCypher::NodePatternContext *ctx) {
|
||||
auto *node = storage_.Create<NodeAtom>();
|
||||
if (ctx->variable()) {
|
||||
std::string variable = ctx->variable()->accept(this);
|
||||
@ -549,7 +531,7 @@ antlrcpp::Any CypherMainVisitor::visitNodePattern(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitNodeLabels(
|
||||
CypherParser::NodeLabelsContext *ctx) {
|
||||
MemgraphCypher::NodeLabelsContext *ctx) {
|
||||
std::vector<storage::Label> labels;
|
||||
for (auto *node_label : ctx->nodeLabel()) {
|
||||
labels.push_back(ctx_.db_accessor_.Label(node_label->accept(this)));
|
||||
@ -558,7 +540,7 @@ antlrcpp::Any CypherMainVisitor::visitNodeLabels(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitProperties(
|
||||
CypherParser::PropertiesContext *ctx) {
|
||||
MemgraphCypher::PropertiesContext *ctx) {
|
||||
if (!ctx->mapLiteral()) {
|
||||
// If child is not mapLiteral that means child is params. At the moment
|
||||
// we don't support properties to be a param because we can generate
|
||||
@ -571,7 +553,7 @@ antlrcpp::Any CypherMainVisitor::visitProperties(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitMapLiteral(
|
||||
CypherParser::MapLiteralContext *ctx) {
|
||||
MemgraphCypher::MapLiteralContext *ctx) {
|
||||
std::unordered_map<std::pair<std::string, storage::Property>, Expression *>
|
||||
map;
|
||||
for (int i = 0; i < static_cast<int>(ctx->propertyKeyName().size()); ++i) {
|
||||
@ -586,7 +568,7 @@ antlrcpp::Any CypherMainVisitor::visitMapLiteral(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitListLiteral(
|
||||
CypherParser::ListLiteralContext *ctx) {
|
||||
MemgraphCypher::ListLiteralContext *ctx) {
|
||||
std::vector<Expression *> expressions;
|
||||
for (auto expr_ctx_ptr : ctx->expression())
|
||||
expressions.push_back(expr_ctx_ptr->accept(this));
|
||||
@ -594,13 +576,13 @@ antlrcpp::Any CypherMainVisitor::visitListLiteral(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitPropertyKeyName(
|
||||
CypherParser::PropertyKeyNameContext *ctx) {
|
||||
MemgraphCypher::PropertyKeyNameContext *ctx) {
|
||||
const std::string key_name = visitChildren(ctx);
|
||||
return std::make_pair(key_name, ctx_.db_accessor_.Property(key_name));
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitSymbolicName(
|
||||
CypherParser::SymbolicNameContext *ctx) {
|
||||
MemgraphCypher::SymbolicNameContext *ctx) {
|
||||
if (ctx->EscapedSymbolicName()) {
|
||||
auto quoted_name = ctx->getText();
|
||||
DCHECK(quoted_name.size() >= 2U && quoted_name[0] == '`' &&
|
||||
@ -635,7 +617,7 @@ antlrcpp::Any CypherMainVisitor::visitSymbolicName(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitPattern(
|
||||
CypherParser::PatternContext *ctx) {
|
||||
MemgraphCypher::PatternContext *ctx) {
|
||||
std::vector<Pattern *> patterns;
|
||||
for (auto *pattern_part : ctx->patternPart()) {
|
||||
patterns.push_back(pattern_part->accept(this));
|
||||
@ -644,7 +626,7 @@ antlrcpp::Any CypherMainVisitor::visitPattern(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitPatternPart(
|
||||
CypherParser::PatternPartContext *ctx) {
|
||||
MemgraphCypher::PatternPartContext *ctx) {
|
||||
Pattern *pattern = ctx->anonymousPatternPart()->accept(this);
|
||||
if (ctx->variable()) {
|
||||
std::string variable = ctx->variable()->accept(this);
|
||||
@ -657,7 +639,7 @@ antlrcpp::Any CypherMainVisitor::visitPatternPart(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitPatternElement(
|
||||
CypherParser::PatternElementContext *ctx) {
|
||||
MemgraphCypher::PatternElementContext *ctx) {
|
||||
if (ctx->patternElement()) {
|
||||
return ctx->patternElement()->accept(this);
|
||||
}
|
||||
@ -673,14 +655,14 @@ antlrcpp::Any CypherMainVisitor::visitPatternElement(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitPatternElementChain(
|
||||
CypherParser::PatternElementChainContext *ctx) {
|
||||
MemgraphCypher::PatternElementChainContext *ctx) {
|
||||
return std::pair<PatternAtom *, PatternAtom *>(
|
||||
ctx->relationshipPattern()->accept(this).as<EdgeAtom *>(),
|
||||
ctx->nodePattern()->accept(this).as<NodeAtom *>());
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(
|
||||
CypherParser::RelationshipPatternContext *ctx) {
|
||||
MemgraphCypher::RelationshipPatternContext *ctx) {
|
||||
auto *edge = storage_.Create<EdgeAtom>();
|
||||
|
||||
auto relationshipDetail = ctx->relationshipDetail();
|
||||
@ -808,19 +790,19 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitRelationshipDetail(
|
||||
CypherParser::RelationshipDetailContext *) {
|
||||
MemgraphCypher::RelationshipDetailContext *) {
|
||||
DLOG(FATAL) << "Should never be called. See documentation in hpp.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitRelationshipLambda(
|
||||
CypherParser::RelationshipLambdaContext *) {
|
||||
MemgraphCypher::RelationshipLambdaContext *) {
|
||||
DLOG(FATAL) << "Should never be called. See documentation in hpp.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitRelationshipTypes(
|
||||
CypherParser::RelationshipTypesContext *ctx) {
|
||||
MemgraphCypher::RelationshipTypesContext *ctx) {
|
||||
std::vector<storage::EdgeType> types;
|
||||
for (auto *edge_type : ctx->relTypeName()) {
|
||||
types.push_back(ctx_.db_accessor_.EdgeType(edge_type->accept(this)));
|
||||
@ -829,14 +811,14 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipTypes(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitVariableExpansion(
|
||||
CypherParser::VariableExpansionContext *ctx) {
|
||||
MemgraphCypher::VariableExpansionContext *ctx) {
|
||||
DCHECK(ctx->expression().size() <= 2U)
|
||||
<< "Expected 0, 1 or 2 bounds in range literal.";
|
||||
|
||||
EdgeAtom::Type edge_type = EdgeAtom::Type::DEPTH_FIRST;
|
||||
if (!ctx->getTokens(CypherParser::BFS).empty())
|
||||
if (!ctx->getTokens(MemgraphCypher::BFS).empty())
|
||||
edge_type = EdgeAtom::Type::BREADTH_FIRST;
|
||||
else if (!ctx->getTokens(CypherParser::WSHORTEST).empty())
|
||||
else if (!ctx->getTokens(MemgraphCypher::WSHORTEST).empty())
|
||||
edge_type = EdgeAtom::Type::WEIGHTED_SHORTEST_PATH;
|
||||
Expression *lower = nullptr;
|
||||
Expression *upper = nullptr;
|
||||
@ -844,7 +826,7 @@ antlrcpp::Any CypherMainVisitor::visitVariableExpansion(
|
||||
if (ctx->expression().size() == 0U) {
|
||||
// Case -[*]-
|
||||
} else if (ctx->expression().size() == 1U) {
|
||||
auto dots_tokens = ctx->getTokens(CypherParser::DOTS);
|
||||
auto dots_tokens = ctx->getTokens(MemgraphCypher::DOTS);
|
||||
Expression *bound = ctx->expression()[0]->accept(this);
|
||||
if (!dots_tokens.size()) {
|
||||
// Case -[*bound]-
|
||||
@ -870,43 +852,43 @@ antlrcpp::Any CypherMainVisitor::visitVariableExpansion(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitExpression(
|
||||
CypherParser::ExpressionContext *ctx) {
|
||||
MemgraphCypher::ExpressionContext *ctx) {
|
||||
return static_cast<Expression *>(ctx->expression12()->accept(this));
|
||||
}
|
||||
|
||||
// OR.
|
||||
antlrcpp::Any CypherMainVisitor::visitExpression12(
|
||||
CypherParser::Expression12Context *ctx) {
|
||||
MemgraphCypher::Expression12Context *ctx) {
|
||||
return LeftAssociativeOperatorExpression(ctx->expression11(), ctx->children,
|
||||
{CypherParser::OR});
|
||||
{MemgraphCypher::OR});
|
||||
}
|
||||
|
||||
// XOR.
|
||||
antlrcpp::Any CypherMainVisitor::visitExpression11(
|
||||
CypherParser::Expression11Context *ctx) {
|
||||
MemgraphCypher::Expression11Context *ctx) {
|
||||
return LeftAssociativeOperatorExpression(ctx->expression10(), ctx->children,
|
||||
{CypherParser::XOR});
|
||||
{MemgraphCypher::XOR});
|
||||
}
|
||||
|
||||
// AND.
|
||||
antlrcpp::Any CypherMainVisitor::visitExpression10(
|
||||
CypherParser::Expression10Context *ctx) {
|
||||
MemgraphCypher::Expression10Context *ctx) {
|
||||
return LeftAssociativeOperatorExpression(ctx->expression9(), ctx->children,
|
||||
{CypherParser::AND});
|
||||
{MemgraphCypher::AND});
|
||||
}
|
||||
|
||||
// NOT.
|
||||
antlrcpp::Any CypherMainVisitor::visitExpression9(
|
||||
CypherParser::Expression9Context *ctx) {
|
||||
MemgraphCypher::Expression9Context *ctx) {
|
||||
return PrefixUnaryOperator(ctx->expression8(), ctx->children,
|
||||
{CypherParser::NOT});
|
||||
{MemgraphCypher::NOT});
|
||||
}
|
||||
|
||||
// Comparisons.
|
||||
// Expresion 1 < 2 < 3 is converted to 1 < 2 && 2 < 3 and then binary operator
|
||||
// ast node is constructed for each operator.
|
||||
antlrcpp::Any CypherMainVisitor::visitExpression8(
|
||||
CypherParser::Expression8Context *ctx) {
|
||||
MemgraphCypher::Expression8Context *ctx) {
|
||||
if (!ctx->partialComparisonExpression().size()) {
|
||||
// There is no comparison operators. We generate expression7.
|
||||
return ctx->expression7()->accept(this);
|
||||
@ -962,30 +944,31 @@ antlrcpp::Any CypherMainVisitor::visitExpression8(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitPartialComparisonExpression(
|
||||
CypherParser::PartialComparisonExpressionContext *) {
|
||||
MemgraphCypher::PartialComparisonExpressionContext *) {
|
||||
DLOG(FATAL) << "Should never be called. See documentation in hpp.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Addition and subtraction.
|
||||
antlrcpp::Any CypherMainVisitor::visitExpression7(
|
||||
CypherParser::Expression7Context *ctx) {
|
||||
MemgraphCypher::Expression7Context *ctx) {
|
||||
return LeftAssociativeOperatorExpression(
|
||||
ctx->expression6(), ctx->children,
|
||||
{CypherParser::PLUS, CypherParser::MINUS});
|
||||
{MemgraphCypher::PLUS, MemgraphCypher::MINUS});
|
||||
}
|
||||
|
||||
// Multiplication, division, modding.
|
||||
antlrcpp::Any CypherMainVisitor::visitExpression6(
|
||||
CypherParser::Expression6Context *ctx) {
|
||||
MemgraphCypher::Expression6Context *ctx) {
|
||||
return LeftAssociativeOperatorExpression(
|
||||
ctx->expression5(), ctx->children,
|
||||
{CypherParser::ASTERISK, CypherParser::SLASH, CypherParser::PERCENT});
|
||||
{MemgraphCypher::ASTERISK, MemgraphCypher::SLASH,
|
||||
MemgraphCypher::PERCENT});
|
||||
}
|
||||
|
||||
// Power.
|
||||
antlrcpp::Any CypherMainVisitor::visitExpression5(
|
||||
CypherParser::Expression5Context *ctx) {
|
||||
MemgraphCypher::Expression5Context *ctx) {
|
||||
if (ctx->expression4().size() > 1U) {
|
||||
// TODO: implement power operator. In neo4j power is left associative and
|
||||
// int^int -> float.
|
||||
@ -996,14 +979,14 @@ antlrcpp::Any CypherMainVisitor::visitExpression5(
|
||||
|
||||
// Unary minus and plus.
|
||||
antlrcpp::Any CypherMainVisitor::visitExpression4(
|
||||
CypherParser::Expression4Context *ctx) {
|
||||
MemgraphCypher::Expression4Context *ctx) {
|
||||
return PrefixUnaryOperator(ctx->expression3a(), ctx->children,
|
||||
{CypherParser::PLUS, CypherParser::MINUS});
|
||||
{MemgraphCypher::PLUS, MemgraphCypher::MINUS});
|
||||
}
|
||||
|
||||
// IS NULL, IS NOT NULL, STARTS WITH, ..
|
||||
antlrcpp::Any CypherMainVisitor::visitExpression3a(
|
||||
CypherParser::Expression3aContext *ctx) {
|
||||
MemgraphCypher::Expression3aContext *ctx) {
|
||||
Expression *expression = ctx->expression3b()->accept(this);
|
||||
|
||||
for (auto *op : ctx->stringAndNullOperators()) {
|
||||
@ -1036,16 +1019,16 @@ antlrcpp::Any CypherMainVisitor::visitExpression3a(
|
||||
return expression;
|
||||
}
|
||||
antlrcpp::Any CypherMainVisitor::visitStringAndNullOperators(
|
||||
CypherParser::StringAndNullOperatorsContext *) {
|
||||
MemgraphCypher::StringAndNullOperatorsContext *) {
|
||||
DLOG(FATAL) << "Should never be called. See documentation in hpp.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitExpression3b(
|
||||
CypherParser::Expression3bContext *ctx) {
|
||||
MemgraphCypher::Expression3bContext *ctx) {
|
||||
Expression *expression = ctx->expression2a()->accept(this);
|
||||
for (auto *list_op : ctx->listIndexingOrSlicing()) {
|
||||
if (list_op->getTokens(CypherParser::DOTS).size() == 0U) {
|
||||
if (list_op->getTokens(MemgraphCypher::DOTS).size() == 0U) {
|
||||
// If there is no '..' then we need to create list indexing operator.
|
||||
expression = storage_.Create<SubscriptOperator>(
|
||||
expression, list_op->expression()[0]->accept(this));
|
||||
@ -1069,13 +1052,13 @@ antlrcpp::Any CypherMainVisitor::visitExpression3b(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitListIndexingOrSlicing(
|
||||
CypherParser::ListIndexingOrSlicingContext *) {
|
||||
MemgraphCypher::ListIndexingOrSlicingContext *) {
|
||||
DLOG(FATAL) << "Should never be called. See documentation in hpp.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitExpression2a(
|
||||
CypherParser::Expression2aContext *ctx) {
|
||||
MemgraphCypher::Expression2aContext *ctx) {
|
||||
Expression *expression = ctx->expression2b()->accept(this);
|
||||
if (ctx->nodeLabels()) {
|
||||
auto labels =
|
||||
@ -1086,7 +1069,7 @@ antlrcpp::Any CypherMainVisitor::visitExpression2a(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitExpression2b(
|
||||
CypherParser::Expression2bContext *ctx) {
|
||||
MemgraphCypher::Expression2bContext *ctx) {
|
||||
Expression *expression = ctx->atom()->accept(this);
|
||||
for (auto *lookup : ctx->propertyLookup()) {
|
||||
std::pair<std::string, storage::Property> key = lookup->accept(this);
|
||||
@ -1097,7 +1080,7 @@ antlrcpp::Any CypherMainVisitor::visitExpression2b(
|
||||
return expression;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitAtom(CypherParser::AtomContext *ctx) {
|
||||
antlrcpp::Any CypherMainVisitor::visitAtom(MemgraphCypher::AtomContext *ctx) {
|
||||
if (ctx->literal()) {
|
||||
return ctx->literal()->accept(this);
|
||||
} else if (ctx->parameter()) {
|
||||
@ -1175,12 +1158,12 @@ antlrcpp::Any CypherMainVisitor::visitAtom(CypherParser::AtomContext *ctx) {
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitParameter(
|
||||
CypherParser::ParameterContext *ctx) {
|
||||
MemgraphCypher::ParameterContext *ctx) {
|
||||
return storage_.Create<ParameterLookup>(ctx->getStart()->getTokenIndex());
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitLiteral(
|
||||
CypherParser::LiteralContext *ctx) {
|
||||
MemgraphCypher::LiteralContext *ctx) {
|
||||
if (ctx->CYPHERNULL() || ctx->StringLiteral() || ctx->booleanLiteral() ||
|
||||
ctx->numberLiteral()) {
|
||||
int token_position = ctx->getStart()->getTokenIndex();
|
||||
@ -1221,12 +1204,12 @@ antlrcpp::Any CypherMainVisitor::visitLiteral(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitParenthesizedExpression(
|
||||
CypherParser::ParenthesizedExpressionContext *ctx) {
|
||||
MemgraphCypher::ParenthesizedExpressionContext *ctx) {
|
||||
return static_cast<Expression *>(ctx->expression()->accept(this));
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitNumberLiteral(
|
||||
CypherParser::NumberLiteralContext *ctx) {
|
||||
MemgraphCypher::NumberLiteralContext *ctx) {
|
||||
if (ctx->integerLiteral()) {
|
||||
return TypedValue(ctx->integerLiteral()->accept(this).as<int64_t>());
|
||||
} else if (ctx->doubleLiteral()) {
|
||||
@ -1240,7 +1223,7 @@ antlrcpp::Any CypherMainVisitor::visitNumberLiteral(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitFunctionInvocation(
|
||||
CypherParser::FunctionInvocationContext *ctx) {
|
||||
MemgraphCypher::FunctionInvocationContext *ctx) {
|
||||
if (ctx->DISTINCT()) {
|
||||
throw utils::NotYetImplemented("DISTINCT function call");
|
||||
}
|
||||
@ -1289,17 +1272,17 @@ antlrcpp::Any CypherMainVisitor::visitFunctionInvocation(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitFunctionName(
|
||||
CypherParser::FunctionNameContext *ctx) {
|
||||
MemgraphCypher::FunctionNameContext *ctx) {
|
||||
return utils::ToUpperCase(ctx->getText());
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitDoubleLiteral(
|
||||
CypherParser::DoubleLiteralContext *ctx) {
|
||||
MemgraphCypher::DoubleLiteralContext *ctx) {
|
||||
return ParseDoubleLiteral(ctx->getText());
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitIntegerLiteral(
|
||||
CypherParser::IntegerLiteralContext *ctx) {
|
||||
MemgraphCypher::IntegerLiteralContext *ctx) {
|
||||
return ParseIntegerLiteral(ctx->getText());
|
||||
}
|
||||
|
||||
@ -1309,11 +1292,11 @@ antlrcpp::Any CypherMainVisitor::visitStringLiteral(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitBooleanLiteral(
|
||||
CypherParser::BooleanLiteralContext *ctx) {
|
||||
if (ctx->getTokens(CypherParser::TRUE).size()) {
|
||||
MemgraphCypher::BooleanLiteralContext *ctx) {
|
||||
if (ctx->getTokens(MemgraphCypher::TRUE).size()) {
|
||||
return true;
|
||||
}
|
||||
if (ctx->getTokens(CypherParser::FALSE).size()) {
|
||||
if (ctx->getTokens(MemgraphCypher::FALSE).size()) {
|
||||
return false;
|
||||
}
|
||||
DLOG(FATAL) << "Shouldn't happend";
|
||||
@ -1321,7 +1304,7 @@ antlrcpp::Any CypherMainVisitor::visitBooleanLiteral(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitCypherDelete(
|
||||
CypherParser::CypherDeleteContext *ctx) {
|
||||
MemgraphCypher::CypherDeleteContext *ctx) {
|
||||
auto *del = storage_.Create<Delete>();
|
||||
if (ctx->DETACH()) {
|
||||
del->detach_ = true;
|
||||
@ -1332,13 +1315,13 @@ antlrcpp::Any CypherMainVisitor::visitCypherDelete(
|
||||
return del;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitWhere(CypherParser::WhereContext *ctx) {
|
||||
antlrcpp::Any CypherMainVisitor::visitWhere(MemgraphCypher::WhereContext *ctx) {
|
||||
auto *where = storage_.Create<Where>();
|
||||
where->expression_ = ctx->expression()->accept(this);
|
||||
return where;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitSet(CypherParser::SetContext *ctx) {
|
||||
antlrcpp::Any CypherMainVisitor::visitSet(MemgraphCypher::SetContext *ctx) {
|
||||
std::vector<Clause *> set_items;
|
||||
for (auto *set_item : ctx->setItem()) {
|
||||
set_items.push_back(set_item->accept(this));
|
||||
@ -1347,7 +1330,7 @@ antlrcpp::Any CypherMainVisitor::visitSet(CypherParser::SetContext *ctx) {
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitSetItem(
|
||||
CypherParser::SetItemContext *ctx) {
|
||||
MemgraphCypher::SetItemContext *ctx) {
|
||||
// SetProperty
|
||||
if (ctx->propertyExpression()) {
|
||||
auto *set_property = storage_.Create<SetProperty>();
|
||||
@ -1357,13 +1340,13 @@ antlrcpp::Any CypherMainVisitor::visitSetItem(
|
||||
}
|
||||
|
||||
// SetProperties either assignment or update
|
||||
if (ctx->getTokens(CypherParser::EQ).size() ||
|
||||
ctx->getTokens(CypherParser::PLUS_EQ).size()) {
|
||||
if (ctx->getTokens(MemgraphCypher::EQ).size() ||
|
||||
ctx->getTokens(MemgraphCypher::PLUS_EQ).size()) {
|
||||
auto *set_properties = storage_.Create<SetProperties>();
|
||||
set_properties->identifier_ = storage_.Create<Identifier>(
|
||||
ctx->variable()->accept(this).as<std::string>());
|
||||
set_properties->expression_ = ctx->expression()->accept(this);
|
||||
if (ctx->getTokens(CypherParser::PLUS_EQ).size()) {
|
||||
if (ctx->getTokens(MemgraphCypher::PLUS_EQ).size()) {
|
||||
set_properties->update_ = true;
|
||||
}
|
||||
return static_cast<Clause *>(set_properties);
|
||||
@ -1378,7 +1361,8 @@ antlrcpp::Any CypherMainVisitor::visitSetItem(
|
||||
return static_cast<Clause *>(set_labels);
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitRemove(CypherParser::RemoveContext *ctx) {
|
||||
antlrcpp::Any CypherMainVisitor::visitRemove(
|
||||
MemgraphCypher::RemoveContext *ctx) {
|
||||
std::vector<Clause *> remove_items;
|
||||
for (auto *remove_item : ctx->removeItem()) {
|
||||
remove_items.push_back(remove_item->accept(this));
|
||||
@ -1387,7 +1371,7 @@ antlrcpp::Any CypherMainVisitor::visitRemove(CypherParser::RemoveContext *ctx) {
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitRemoveItem(
|
||||
CypherParser::RemoveItemContext *ctx) {
|
||||
MemgraphCypher::RemoveItemContext *ctx) {
|
||||
// RemoveProperty
|
||||
if (ctx->propertyExpression()) {
|
||||
auto *remove_property = storage_.Create<RemoveProperty>();
|
||||
@ -1405,7 +1389,7 @@ antlrcpp::Any CypherMainVisitor::visitRemoveItem(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitPropertyExpression(
|
||||
CypherParser::PropertyExpressionContext *ctx) {
|
||||
MemgraphCypher::PropertyExpressionContext *ctx) {
|
||||
Expression *expression = ctx->atom()->accept(this);
|
||||
for (auto *lookup : ctx->propertyLookup()) {
|
||||
std::pair<std::string, storage::Property> key = lookup->accept(this);
|
||||
@ -1418,7 +1402,7 @@ antlrcpp::Any CypherMainVisitor::visitPropertyExpression(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitCaseExpression(
|
||||
CypherParser::CaseExpressionContext *ctx) {
|
||||
MemgraphCypher::CaseExpressionContext *ctx) {
|
||||
Expression *test_expression =
|
||||
ctx->test ? ctx->test->accept(this).as<Expression *>() : nullptr;
|
||||
auto alternatives = ctx->caseAlternatives();
|
||||
@ -1442,12 +1426,12 @@ antlrcpp::Any CypherMainVisitor::visitCaseExpression(
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitCaseAlternatives(
|
||||
CypherParser::CaseAlternativesContext *) {
|
||||
MemgraphCypher::CaseAlternativesContext *) {
|
||||
DLOG(FATAL) << "Should never be called. See documentation in hpp.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitWith(CypherParser::WithContext *ctx) {
|
||||
antlrcpp::Any CypherMainVisitor::visitWith(MemgraphCypher::WithContext *ctx) {
|
||||
auto *with = storage_.Create<With>();
|
||||
in_with_ = true;
|
||||
with->body_ = ctx->returnBody()->accept(this);
|
||||
@ -1461,7 +1445,7 @@ antlrcpp::Any CypherMainVisitor::visitWith(CypherParser::WithContext *ctx) {
|
||||
return with;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitMerge(CypherParser::MergeContext *ctx) {
|
||||
antlrcpp::Any CypherMainVisitor::visitMerge(MemgraphCypher::MergeContext *ctx) {
|
||||
auto *merge = storage_.Create<Merge>();
|
||||
merge->pattern_ = ctx->patternPart()->accept(this);
|
||||
for (auto &merge_action : ctx->mergeAction()) {
|
||||
@ -1476,7 +1460,8 @@ antlrcpp::Any CypherMainVisitor::visitMerge(CypherParser::MergeContext *ctx) {
|
||||
return merge;
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitUnwind(CypherParser::UnwindContext *ctx) {
|
||||
antlrcpp::Any CypherMainVisitor::visitUnwind(
|
||||
MemgraphCypher::UnwindContext *ctx) {
|
||||
auto *named_expr = storage_.Create<NamedExpression>();
|
||||
named_expr->expression_ = ctx->expression()->accept(this);
|
||||
named_expr->name_ =
|
||||
@ -1485,7 +1470,7 @@ antlrcpp::Any CypherMainVisitor::visitUnwind(CypherParser::UnwindContext *ctx) {
|
||||
}
|
||||
|
||||
antlrcpp::Any CypherMainVisitor::visitFilterExpression(
|
||||
CypherParser::FilterExpressionContext *) {
|
||||
MemgraphCypher::FilterExpressionContext *) {
|
||||
LOG(FATAL) << "Should never be called. See documentation in hpp.";
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,16 +9,16 @@
|
||||
|
||||
#include "query/context.hpp"
|
||||
#include "query/frontend/ast/ast.hpp"
|
||||
#include "query/frontend/opencypher/generated/CypherParserBaseVisitor.h"
|
||||
#include "query/frontend/opencypher/generated/MemgraphCypherBaseVisitor.h"
|
||||
#include "utils/exceptions.hpp"
|
||||
|
||||
namespace query {
|
||||
namespace frontend {
|
||||
|
||||
using antlropencypher::CypherParser;
|
||||
using antlropencypher::MemgraphCypher;
|
||||
using query::Context;
|
||||
|
||||
class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor {
|
||||
public:
|
||||
explicit CypherMainVisitor(Context &ctx) : ctx_(ctx) {}
|
||||
|
||||
@ -26,34 +26,34 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
Expression *CreateBinaryOperatorByToken(size_t token, Expression *e1,
|
||||
Expression *e2) {
|
||||
switch (token) {
|
||||
case CypherParser::OR:
|
||||
case MemgraphCypher::OR:
|
||||
return storage_.Create<OrOperator>(e1, e2);
|
||||
case CypherParser::XOR:
|
||||
case MemgraphCypher::XOR:
|
||||
return storage_.Create<XorOperator>(e1, e2);
|
||||
case CypherParser::AND:
|
||||
case MemgraphCypher::AND:
|
||||
return storage_.Create<AndOperator>(e1, e2);
|
||||
case CypherParser::PLUS:
|
||||
case MemgraphCypher::PLUS:
|
||||
return storage_.Create<AdditionOperator>(e1, e2);
|
||||
case CypherParser::MINUS:
|
||||
case MemgraphCypher::MINUS:
|
||||
return storage_.Create<SubtractionOperator>(e1, e2);
|
||||
case CypherParser::ASTERISK:
|
||||
case MemgraphCypher::ASTERISK:
|
||||
return storage_.Create<MultiplicationOperator>(e1, e2);
|
||||
case CypherParser::SLASH:
|
||||
case MemgraphCypher::SLASH:
|
||||
return storage_.Create<DivisionOperator>(e1, e2);
|
||||
case CypherParser::PERCENT:
|
||||
case MemgraphCypher::PERCENT:
|
||||
return storage_.Create<ModOperator>(e1, e2);
|
||||
case CypherParser::EQ:
|
||||
case MemgraphCypher::EQ:
|
||||
return storage_.Create<EqualOperator>(e1, e2);
|
||||
case CypherParser::NEQ1:
|
||||
case CypherParser::NEQ2:
|
||||
case MemgraphCypher::NEQ1:
|
||||
case MemgraphCypher::NEQ2:
|
||||
return storage_.Create<NotEqualOperator>(e1, e2);
|
||||
case CypherParser::LT:
|
||||
case MemgraphCypher::LT:
|
||||
return storage_.Create<LessOperator>(e1, e2);
|
||||
case CypherParser::GT:
|
||||
case MemgraphCypher::GT:
|
||||
return storage_.Create<GreaterOperator>(e1, e2);
|
||||
case CypherParser::LTE:
|
||||
case MemgraphCypher::LTE:
|
||||
return storage_.Create<LessEqualOperator>(e1, e2);
|
||||
case CypherParser::GTE:
|
||||
case MemgraphCypher::GTE:
|
||||
return storage_.Create<GreaterEqualOperator>(e1, e2);
|
||||
default:
|
||||
throw utils::NotYetImplemented("binary operator");
|
||||
@ -62,11 +62,11 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
|
||||
Expression *CreateUnaryOperatorByToken(size_t token, Expression *e) {
|
||||
switch (token) {
|
||||
case CypherParser::NOT:
|
||||
case MemgraphCypher::NOT:
|
||||
return storage_.Create<NotOperator>(e);
|
||||
case CypherParser::PLUS:
|
||||
case MemgraphCypher::PLUS:
|
||||
return storage_.Create<UnaryPlusOperator>(e);
|
||||
case CypherParser::MINUS:
|
||||
case MemgraphCypher::MINUS:
|
||||
return storage_.Create<UnaryMinusOperator>(e);
|
||||
default:
|
||||
throw utils::NotYetImplemented("unary operator");
|
||||
@ -132,112 +132,127 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
return expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Query*
|
||||
*/
|
||||
antlrcpp::Any visitAuthQuery(MemgraphCypher::AuthQueryContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Query*
|
||||
*/
|
||||
antlrcpp::Any visitStreamQuery(
|
||||
MemgraphCypher::StreamQueryContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Query*
|
||||
*/
|
||||
antlrcpp::Any visitRegularQuery(
|
||||
CypherParser::RegularQueryContext *ctx) override;
|
||||
MemgraphCypher::RegularQueryContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return CypherUnion*
|
||||
*/
|
||||
antlrcpp::Any visitCypherUnion(
|
||||
CypherParser::CypherUnionContext *ctx) override;
|
||||
MemgraphCypher::CypherUnionContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return SingleQuery*
|
||||
*/
|
||||
antlrcpp::Any visitSingleQuery(
|
||||
CypherParser::SingleQueryContext *ctx) override;
|
||||
MemgraphCypher::SingleQueryContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Clause* or vector<Clause*>!!!
|
||||
*/
|
||||
antlrcpp::Any visitClause(CypherParser::ClauseContext *ctx) override;
|
||||
antlrcpp::Any visitClause(MemgraphCypher::ClauseContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Match*
|
||||
*/
|
||||
antlrcpp::Any visitCypherMatch(
|
||||
CypherParser::CypherMatchContext *ctx) override;
|
||||
MemgraphCypher::CypherMatchContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Create*
|
||||
*/
|
||||
antlrcpp::Any visitCreate(CypherParser::CreateContext *ctx) override;
|
||||
antlrcpp::Any visitCreate(MemgraphCypher::CreateContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return CreateIndex*
|
||||
*/
|
||||
antlrcpp::Any visitCreateIndex(
|
||||
CypherParser::CreateIndexContext *ctx) override;
|
||||
MemgraphCypher::CreateIndexContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return ModifyUser*
|
||||
*/
|
||||
antlrcpp::Any visitModifyUser(CypherParser::ModifyUserContext *ctx) override;
|
||||
antlrcpp::Any visitModifyUser(
|
||||
MemgraphCypher::ModifyUserContext *ctx) override;
|
||||
|
||||
antlrcpp::Any visitPasswordOption(
|
||||
CypherParser::PasswordOptionContext *ctx) override;
|
||||
MemgraphCypher::PasswordOptionContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return DropUser*
|
||||
*/
|
||||
antlrcpp::Any visitDropUser(CypherParser::DropUserContext *ctx) override;
|
||||
antlrcpp::Any visitDropUser(MemgraphCypher::DropUserContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return CreateStream*
|
||||
*/
|
||||
antlrcpp::Any visitCreateStream(
|
||||
CypherParser::CreateStreamContext *ctx) override;
|
||||
MemgraphCypher::CreateStreamContext *ctx) override;
|
||||
|
||||
antlrcpp::Any visitBatchIntervalOption(
|
||||
CypherParser::BatchIntervalOptionContext *ctx) override;
|
||||
MemgraphCypher::BatchIntervalOptionContext *ctx) override;
|
||||
|
||||
antlrcpp::Any visitBatchSizeOption(
|
||||
CypherParser::BatchSizeOptionContext *ctx) override;
|
||||
MemgraphCypher::BatchSizeOptionContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return DropStream*
|
||||
*/
|
||||
antlrcpp::Any visitDropStream(CypherParser::DropStreamContext *ctx) override;
|
||||
antlrcpp::Any visitDropStream(
|
||||
MemgraphCypher::DropStreamContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return ShowStreams*
|
||||
*/
|
||||
antlrcpp::Any visitShowStreams(
|
||||
CypherParser::ShowStreamsContext *ctx) override;
|
||||
MemgraphCypher::ShowStreamsContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return StartStopStream*
|
||||
*/
|
||||
antlrcpp::Any visitStartStopStream(
|
||||
CypherParser::StartStopStreamContext *ctx) override;
|
||||
MemgraphCypher::StartStopStreamContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return StartStopAllStreams*
|
||||
*/
|
||||
antlrcpp::Any visitStartStopAllStreams(
|
||||
CypherParser::StartStopAllStreamsContext *ctx) override;
|
||||
MemgraphCypher::StartStopAllStreamsContext *ctx) override;
|
||||
|
||||
antlrcpp::Any visitLimitBatchesOption(
|
||||
CypherParser::LimitBatchesOptionContext *ctx) override;
|
||||
MemgraphCypher::LimitBatchesOptionContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return TestStream*
|
||||
*/
|
||||
antlrcpp::Any visitTestStream(CypherParser::TestStreamContext *ctx) override;
|
||||
antlrcpp::Any visitTestStream(
|
||||
MemgraphCypher::TestStreamContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Return*
|
||||
*/
|
||||
antlrcpp::Any visitCypherReturn(
|
||||
CypherParser::CypherReturnContext *ctx) override;
|
||||
MemgraphCypher::CypherReturnContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Return*
|
||||
*/
|
||||
antlrcpp::Any visitReturnBody(CypherParser::ReturnBodyContext *ctx) override;
|
||||
antlrcpp::Any visitReturnBody(
|
||||
MemgraphCypher::ReturnBodyContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return pair<bool, vector<NamedExpression*>> first member is true if
|
||||
@ -245,123 +260,128 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* expressions.
|
||||
*/
|
||||
antlrcpp::Any visitReturnItems(
|
||||
CypherParser::ReturnItemsContext *ctx) override;
|
||||
MemgraphCypher::ReturnItemsContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return vector<NamedExpression*>
|
||||
*/
|
||||
antlrcpp::Any visitReturnItem(CypherParser::ReturnItemContext *ctx) override;
|
||||
antlrcpp::Any visitReturnItem(
|
||||
MemgraphCypher::ReturnItemContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return vector<pair<Ordering, Expression*>>
|
||||
*/
|
||||
antlrcpp::Any visitOrder(CypherParser::OrderContext *ctx) override;
|
||||
antlrcpp::Any visitOrder(MemgraphCypher::OrderContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return pair<Ordering, Expression*>
|
||||
*/
|
||||
antlrcpp::Any visitSortItem(CypherParser::SortItemContext *ctx) override;
|
||||
antlrcpp::Any visitSortItem(MemgraphCypher::SortItemContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return NodeAtom*
|
||||
*/
|
||||
antlrcpp::Any visitNodePattern(
|
||||
CypherParser::NodePatternContext *ctx) override;
|
||||
MemgraphCypher::NodePatternContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return vector<storage::Label>
|
||||
*/
|
||||
antlrcpp::Any visitNodeLabels(CypherParser::NodeLabelsContext *ctx) override;
|
||||
antlrcpp::Any visitNodeLabels(
|
||||
MemgraphCypher::NodeLabelsContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return unordered_map<storage::Property, Expression*>
|
||||
*/
|
||||
antlrcpp::Any visitProperties(CypherParser::PropertiesContext *ctx) override;
|
||||
antlrcpp::Any visitProperties(
|
||||
MemgraphCypher::PropertiesContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return map<std::string, Expression*>
|
||||
*/
|
||||
antlrcpp::Any visitMapLiteral(CypherParser::MapLiteralContext *ctx) override;
|
||||
antlrcpp::Any visitMapLiteral(
|
||||
MemgraphCypher::MapLiteralContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return vector<Expression*>
|
||||
*/
|
||||
antlrcpp::Any visitListLiteral(
|
||||
CypherParser::ListLiteralContext *ctx) override;
|
||||
MemgraphCypher::ListLiteralContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return storage::Property
|
||||
*/
|
||||
antlrcpp::Any visitPropertyKeyName(
|
||||
CypherParser::PropertyKeyNameContext *ctx) override;
|
||||
MemgraphCypher::PropertyKeyNameContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
antlrcpp::Any visitSymbolicName(
|
||||
CypherParser::SymbolicNameContext *ctx) override;
|
||||
MemgraphCypher::SymbolicNameContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return vector<Pattern*>
|
||||
*/
|
||||
antlrcpp::Any visitPattern(CypherParser::PatternContext *ctx) override;
|
||||
antlrcpp::Any visitPattern(MemgraphCypher::PatternContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Pattern*
|
||||
*/
|
||||
antlrcpp::Any visitPatternPart(
|
||||
CypherParser::PatternPartContext *ctx) override;
|
||||
MemgraphCypher::PatternPartContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Pattern*
|
||||
*/
|
||||
antlrcpp::Any visitPatternElement(
|
||||
CypherParser::PatternElementContext *ctx) override;
|
||||
MemgraphCypher::PatternElementContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return vector<pair<EdgeAtom*, NodeAtom*>>
|
||||
*/
|
||||
antlrcpp::Any visitPatternElementChain(
|
||||
CypherParser::PatternElementChainContext *ctx) override;
|
||||
MemgraphCypher::PatternElementChainContext *ctx) override;
|
||||
|
||||
/**
|
||||
*@return EdgeAtom*
|
||||
*/
|
||||
antlrcpp::Any visitRelationshipPattern(
|
||||
CypherParser::RelationshipPatternContext *ctx) override;
|
||||
MemgraphCypher::RelationshipPatternContext *ctx) override;
|
||||
|
||||
/**
|
||||
* This should never be called. Everything is done directly in
|
||||
* visitRelationshipPattern.
|
||||
*/
|
||||
antlrcpp::Any visitRelationshipDetail(
|
||||
CypherParser::RelationshipDetailContext *ctx) override;
|
||||
MemgraphCypher::RelationshipDetailContext *ctx) override;
|
||||
|
||||
/**
|
||||
* This should never be called. Everything is done directly in
|
||||
* visitRelationshipPattern.
|
||||
*/
|
||||
antlrcpp::Any visitRelationshipLambda(
|
||||
CypherParser::RelationshipLambdaContext *ctx) override;
|
||||
MemgraphCypher::RelationshipLambdaContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return vector<storage::EdgeType>
|
||||
*/
|
||||
antlrcpp::Any visitRelationshipTypes(
|
||||
CypherParser::RelationshipTypesContext *ctx) override;
|
||||
MemgraphCypher::RelationshipTypesContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return std::tuple<EdgeAtom::Type, int64_t, int64_t>.
|
||||
*/
|
||||
antlrcpp::Any visitVariableExpansion(
|
||||
CypherParser::VariableExpansionContext *ctx) override;
|
||||
MemgraphCypher::VariableExpansionContext *ctx) override;
|
||||
|
||||
/**
|
||||
* Top level expression, does nothing.
|
||||
*
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitExpression(CypherParser::ExpressionContext *ctx) override;
|
||||
antlrcpp::Any visitExpression(
|
||||
MemgraphCypher::ExpressionContext *ctx) override;
|
||||
|
||||
/**
|
||||
* OR.
|
||||
@ -369,7 +389,7 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitExpression12(
|
||||
CypherParser::Expression12Context *ctx) override;
|
||||
MemgraphCypher::Expression12Context *ctx) override;
|
||||
|
||||
/**
|
||||
* XOR.
|
||||
@ -377,7 +397,7 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitExpression11(
|
||||
CypherParser::Expression11Context *ctx) override;
|
||||
MemgraphCypher::Expression11Context *ctx) override;
|
||||
|
||||
/**
|
||||
* AND.
|
||||
@ -385,7 +405,7 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitExpression10(
|
||||
CypherParser::Expression10Context *ctx) override;
|
||||
MemgraphCypher::Expression10Context *ctx) override;
|
||||
|
||||
/**
|
||||
* NOT.
|
||||
@ -393,7 +413,7 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitExpression9(
|
||||
CypherParser::Expression9Context *ctx) override;
|
||||
MemgraphCypher::Expression9Context *ctx) override;
|
||||
|
||||
/**
|
||||
* Comparisons.
|
||||
@ -401,14 +421,14 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitExpression8(
|
||||
CypherParser::Expression8Context *ctx) override;
|
||||
MemgraphCypher::Expression8Context *ctx) override;
|
||||
|
||||
/**
|
||||
* Never call this. Everything related to generating code for comparison
|
||||
* operators should be done in visitExpression8.
|
||||
*/
|
||||
antlrcpp::Any visitPartialComparisonExpression(
|
||||
CypherParser::PartialComparisonExpressionContext *ctx) override;
|
||||
MemgraphCypher::PartialComparisonExpressionContext *ctx) override;
|
||||
|
||||
/**
|
||||
* Addition and subtraction.
|
||||
@ -416,7 +436,7 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitExpression7(
|
||||
CypherParser::Expression7Context *ctx) override;
|
||||
MemgraphCypher::Expression7Context *ctx) override;
|
||||
|
||||
/**
|
||||
* Multiplication, division, modding.
|
||||
@ -424,7 +444,7 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitExpression6(
|
||||
CypherParser::Expression6Context *ctx) override;
|
||||
MemgraphCypher::Expression6Context *ctx) override;
|
||||
|
||||
/**
|
||||
* Power.
|
||||
@ -432,7 +452,7 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitExpression5(
|
||||
CypherParser::Expression5Context *ctx) override;
|
||||
MemgraphCypher::Expression5Context *ctx) override;
|
||||
|
||||
/**
|
||||
* Unary minus and plus.
|
||||
@ -440,7 +460,7 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitExpression4(
|
||||
CypherParser::Expression4Context *ctx) override;
|
||||
MemgraphCypher::Expression4Context *ctx) override;
|
||||
|
||||
/**
|
||||
* IS NULL, IS NOT NULL, STARTS WITH, END WITH, =~, ...
|
||||
@ -448,7 +468,7 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitExpression3a(
|
||||
CypherParser::Expression3aContext *ctx) override;
|
||||
MemgraphCypher::Expression3aContext *ctx) override;
|
||||
|
||||
/**
|
||||
* Does nothing, everything is done in visitExpression3a.
|
||||
@ -456,7 +476,7 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitStringAndNullOperators(
|
||||
CypherParser::StringAndNullOperatorsContext *ctx) override;
|
||||
MemgraphCypher::StringAndNullOperatorsContext *ctx) override;
|
||||
|
||||
/**
|
||||
* List indexing and slicing.
|
||||
@ -464,13 +484,13 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitExpression3b(
|
||||
CypherParser::Expression3bContext *ctx) override;
|
||||
MemgraphCypher::Expression3bContext *ctx) override;
|
||||
|
||||
/**
|
||||
* Does nothing, everything is done in visitExpression3b.
|
||||
*/
|
||||
antlrcpp::Any visitListIndexingOrSlicing(
|
||||
CypherParser::ListIndexingOrSlicingContext *ctx) override;
|
||||
MemgraphCypher::ListIndexingOrSlicingContext *ctx) override;
|
||||
|
||||
/**
|
||||
* Node labels test.
|
||||
@ -478,7 +498,7 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitExpression2a(
|
||||
CypherParser::Expression2aContext *ctx) override;
|
||||
MemgraphCypher::Expression2aContext *ctx) override;
|
||||
|
||||
/**
|
||||
* Property lookup.
|
||||
@ -486,42 +506,42 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitExpression2b(
|
||||
CypherParser::Expression2bContext *ctx) override;
|
||||
MemgraphCypher::Expression2bContext *ctx) override;
|
||||
|
||||
/**
|
||||
* Literals, params, list comprehension...
|
||||
*
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitAtom(CypherParser::AtomContext *ctx) override;
|
||||
antlrcpp::Any visitAtom(MemgraphCypher::AtomContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return ParameterLookup*
|
||||
*/
|
||||
antlrcpp::Any visitParameter(CypherParser::ParameterContext *ctx) override;
|
||||
antlrcpp::Any visitParameter(MemgraphCypher::ParameterContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitParenthesizedExpression(
|
||||
CypherParser::ParenthesizedExpressionContext *ctx) override;
|
||||
MemgraphCypher::ParenthesizedExpressionContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitFunctionInvocation(
|
||||
CypherParser::FunctionInvocationContext *ctx) override;
|
||||
MemgraphCypher::FunctionInvocationContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return string - uppercased
|
||||
*/
|
||||
antlrcpp::Any visitFunctionName(
|
||||
CypherParser::FunctionNameContext *ctx) override;
|
||||
MemgraphCypher::FunctionNameContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Expression*
|
||||
*/
|
||||
antlrcpp::Any visitLiteral(CypherParser::LiteralContext *ctx) override;
|
||||
antlrcpp::Any visitLiteral(MemgraphCypher::LiteralContext *ctx) override;
|
||||
|
||||
/**
|
||||
* Convert escaped string from a query to unescaped utf8 string.
|
||||
@ -534,97 +554,98 @@ class CypherMainVisitor : public antlropencypher::CypherParserBaseVisitor {
|
||||
* @return bool
|
||||
*/
|
||||
antlrcpp::Any visitBooleanLiteral(
|
||||
CypherParser::BooleanLiteralContext *ctx) override;
|
||||
MemgraphCypher::BooleanLiteralContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return TypedValue with either double or int
|
||||
*/
|
||||
antlrcpp::Any visitNumberLiteral(
|
||||
CypherParser::NumberLiteralContext *ctx) override;
|
||||
MemgraphCypher::NumberLiteralContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return int64_t
|
||||
*/
|
||||
antlrcpp::Any visitIntegerLiteral(
|
||||
CypherParser::IntegerLiteralContext *ctx) override;
|
||||
MemgraphCypher::IntegerLiteralContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return double
|
||||
*/
|
||||
antlrcpp::Any visitDoubleLiteral(
|
||||
CypherParser::DoubleLiteralContext *ctx) override;
|
||||
MemgraphCypher::DoubleLiteralContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Delete*
|
||||
*/
|
||||
antlrcpp::Any visitCypherDelete(
|
||||
CypherParser::CypherDeleteContext *ctx) override;
|
||||
MemgraphCypher::CypherDeleteContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Where*
|
||||
*/
|
||||
antlrcpp::Any visitWhere(CypherParser::WhereContext *ctx) override;
|
||||
antlrcpp::Any visitWhere(MemgraphCypher::WhereContext *ctx) override;
|
||||
|
||||
/**
|
||||
* return vector<Clause*>
|
||||
*/
|
||||
antlrcpp::Any visitSet(CypherParser::SetContext *ctx) override;
|
||||
antlrcpp::Any visitSet(MemgraphCypher::SetContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Clause*
|
||||
*/
|
||||
antlrcpp::Any visitSetItem(CypherParser::SetItemContext *ctx) override;
|
||||
antlrcpp::Any visitSetItem(MemgraphCypher::SetItemContext *ctx) override;
|
||||
|
||||
/**
|
||||
* return vector<Clause*>
|
||||
*/
|
||||
antlrcpp::Any visitRemove(CypherParser::RemoveContext *ctx) override;
|
||||
antlrcpp::Any visitRemove(MemgraphCypher::RemoveContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Clause*
|
||||
*/
|
||||
antlrcpp::Any visitRemoveItem(CypherParser::RemoveItemContext *ctx) override;
|
||||
antlrcpp::Any visitRemoveItem(
|
||||
MemgraphCypher::RemoveItemContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return PropertyLookup*
|
||||
*/
|
||||
antlrcpp::Any visitPropertyExpression(
|
||||
CypherParser::PropertyExpressionContext *ctx) override;
|
||||
MemgraphCypher::PropertyExpressionContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return IfOperator*
|
||||
*/
|
||||
antlrcpp::Any visitCaseExpression(
|
||||
CypherParser::CaseExpressionContext *ctx) override;
|
||||
MemgraphCypher::CaseExpressionContext *ctx) override;
|
||||
|
||||
/**
|
||||
* Never call this. Ast generation for this production is done in
|
||||
* @c visitCaseExpression.
|
||||
*/
|
||||
antlrcpp::Any visitCaseAlternatives(
|
||||
CypherParser::CaseAlternativesContext *ctx) override;
|
||||
MemgraphCypher::CaseAlternativesContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return With*
|
||||
*/
|
||||
antlrcpp::Any visitWith(CypherParser::WithContext *ctx) override;
|
||||
antlrcpp::Any visitWith(MemgraphCypher::WithContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Merge*
|
||||
*/
|
||||
antlrcpp::Any visitMerge(CypherParser::MergeContext *ctx) override;
|
||||
antlrcpp::Any visitMerge(MemgraphCypher::MergeContext *ctx) override;
|
||||
|
||||
/**
|
||||
* @return Unwind*
|
||||
*/
|
||||
antlrcpp::Any visitUnwind(CypherParser::UnwindContext *ctx) override;
|
||||
antlrcpp::Any visitUnwind(MemgraphCypher::UnwindContext *ctx) override;
|
||||
|
||||
/**
|
||||
* Never call this. Ast generation for these expressions should be done by
|
||||
* explicitly visiting the members of @c FilterExpressionContext.
|
||||
*/
|
||||
antlrcpp::Any visitFilterExpression(
|
||||
CypherParser::FilterExpressionContext *) override;
|
||||
MemgraphCypher::FilterExpressionContext *) override;
|
||||
|
||||
public:
|
||||
Query *query() { return query_; }
|
||||
|
@ -1,13 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2016 "Neo Technology,"
|
||||
* Network Engine for Objects in Lund AB [http://neotechnology.com]
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -15,17 +15,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* When changing this grammar make sure to update constants in
|
||||
* src/query/frontend/stripped_lexer_constants.hpp (kKeywords, kSpecialTokens
|
||||
* and bitsets) if needed.
|
||||
*/
|
||||
|
||||
parser grammar CypherParser ;
|
||||
parser grammar Cypher;
|
||||
|
||||
options { tokenVocab=CypherLexer; }
|
||||
|
||||
cypher : statement ;
|
||||
cypher : statement ';'? EOF ;
|
||||
|
||||
statement : query ;
|
||||
|
||||
@ -49,14 +43,6 @@ clause : cypherMatch
|
||||
| with
|
||||
| cypherReturn
|
||||
| createIndex
|
||||
| modifyUser
|
||||
| dropUser
|
||||
| createStream
|
||||
| dropStream
|
||||
| showStreams
|
||||
| startStopStream
|
||||
| startStopAllStreams
|
||||
| testStream
|
||||
;
|
||||
|
||||
cypherMatch : OPTIONAL? MATCH pattern where? ;
|
||||
@ -249,9 +235,7 @@ idInColl : variable IN expression ;
|
||||
|
||||
functionInvocation : functionName '(' ( DISTINCT )? ( expression ( ',' expression )* )? ')' ;
|
||||
|
||||
functionName : UnescapedSymbolicName
|
||||
| EscapedSymbolicName
|
||||
| COUNT ;
|
||||
functionName : symbolicName ;
|
||||
|
||||
listComprehension : '[' filterExpression ( '|' expression )? ']' ;
|
||||
|
||||
@ -281,112 +265,67 @@ integerLiteral : DecimalLiteral
|
||||
| OctalLiteral
|
||||
| HexadecimalLiteral
|
||||
;
|
||||
|
||||
|
||||
createIndex : CREATE INDEX ON ':' labelName '(' propertyKeyName ')' ;
|
||||
|
||||
userName : UnescapedSymbolicName ;
|
||||
|
||||
createUser : CREATE USER ;
|
||||
|
||||
alterUser : ALTER USER ;
|
||||
|
||||
modifyUser : ( createUser | alterUser ) userName ( WITH ( modifyUserOption )+ )? ;
|
||||
|
||||
modifyUserOption : passwordOption ;
|
||||
|
||||
passwordOption : PASSWORD literal;
|
||||
|
||||
dropUser : DROP USER userName ( ',' userName )* ;
|
||||
|
||||
streamName : UnescapedSymbolicName ;
|
||||
|
||||
createStream : CREATE STREAM streamName AS LOAD DATA KAFKA
|
||||
streamUri=literal WITH TOPIC streamTopic=literal WITH TRANSFORM
|
||||
transformUri=literal ( batchIntervalOption )? (batchSizeOption )? ;
|
||||
|
||||
batchIntervalOption : BATCH_INTERVAL literal ;
|
||||
|
||||
batchSizeOption : BATCH_SIZE literal ;
|
||||
|
||||
dropStream : DROP STREAM streamName ;
|
||||
|
||||
showStreams : SHOW STREAMS ;
|
||||
|
||||
startStopStream : ( START | STOP ) STREAM streamName ( limitBatchesOption )? ;
|
||||
|
||||
limitBatchesOption : LIMIT limitBatches=literal BATCHES ;
|
||||
|
||||
startStopAllStreams : ( START | STOP ) ALL STREAMS ;
|
||||
|
||||
testStream : K_TEST STREAM streamName ( limitBatchesOption )? ;
|
||||
|
||||
doubleLiteral : FloatingLiteral ;
|
||||
|
||||
cypherKeyword : ALL
|
||||
| AND
|
||||
| ANY
|
||||
| AS
|
||||
| ASC
|
||||
| ASCENDING
|
||||
| BFS
|
||||
| BY
|
||||
| CASE
|
||||
| CONTAINS
|
||||
| COUNT
|
||||
| CREATE
|
||||
| CYPHERNULL
|
||||
| DELETE
|
||||
| DESC
|
||||
| DESCENDING
|
||||
| DETACH
|
||||
| DISTINCT
|
||||
| ELSE
|
||||
| END
|
||||
| ENDS
|
||||
| EXTRACT
|
||||
| FALSE
|
||||
| FILTER
|
||||
| IN
|
||||
| INDEX
|
||||
| IS
|
||||
| LIMIT
|
||||
| L_SKIP
|
||||
| MATCH
|
||||
| MERGE
|
||||
| NONE
|
||||
| NOT
|
||||
| ON
|
||||
| OPTIONAL
|
||||
| OR
|
||||
| ORDER
|
||||
| REDUCE
|
||||
| REMOVE
|
||||
| RETURN
|
||||
| SET
|
||||
| SHOW
|
||||
| SINGLE
|
||||
| STARTS
|
||||
| THEN
|
||||
| TRUE
|
||||
| UNION
|
||||
| UNWIND
|
||||
| WHEN
|
||||
| WHERE
|
||||
| WITH
|
||||
| WSHORTEST
|
||||
| XOR
|
||||
;
|
||||
|
||||
symbolicName : UnescapedSymbolicName
|
||||
| EscapedSymbolicName
|
||||
| UNION
|
||||
| ALL
|
||||
| REDUCE
|
||||
| OPTIONAL
|
||||
| MATCH
|
||||
| UNWIND
|
||||
| AS
|
||||
| MERGE
|
||||
| ON
|
||||
| CREATE
|
||||
| SET
|
||||
| DETACH
|
||||
| DELETE
|
||||
| REMOVE
|
||||
| WITH
|
||||
| DISTINCT
|
||||
| RETURN
|
||||
| ORDER
|
||||
| BY
|
||||
| L_SKIP
|
||||
| LIMIT
|
||||
| ASCENDING
|
||||
| ASC
|
||||
| DESCENDING
|
||||
| DESC
|
||||
| WHERE
|
||||
| OR
|
||||
| XOR
|
||||
| AND
|
||||
| NOT
|
||||
| IN
|
||||
| STARTS
|
||||
| ENDS
|
||||
| CONTAINS
|
||||
| IS
|
||||
| CYPHERNULL
|
||||
| CASE
|
||||
| WHEN
|
||||
| THEN
|
||||
| ELSE
|
||||
| END
|
||||
| COUNT
|
||||
| FILTER
|
||||
| EXTRACT
|
||||
| ANY
|
||||
| NONE
|
||||
| SINGLE
|
||||
| TRUE
|
||||
| FALSE
|
||||
| USER
|
||||
| PASSWORD
|
||||
| ALTER
|
||||
| DROP
|
||||
| STREAM
|
||||
| STREAMS
|
||||
| LOAD
|
||||
| DATA
|
||||
| KAFKA
|
||||
| TRANSFORM
|
||||
| BATCH_SIZE
|
||||
| BATCH_INTERVAL
|
||||
| SHOW
|
||||
| START
|
||||
| STOP
|
||||
| cypherKeyword
|
||||
;
|
||||
|
@ -1,3 +1,9 @@
|
||||
/*
|
||||
* When changing this grammar make sure to update constants in
|
||||
* src/query/frontend/stripped_lexer_constants.hpp (kKeywords, kSpecialTokens
|
||||
* and bitsets) if needed.
|
||||
*/
|
||||
|
||||
lexer grammar CypherLexer ;
|
||||
|
||||
import UnicodeCategories ;
|
||||
@ -22,36 +28,37 @@ fragment Comment : '/*' .*? '*/'
|
||||
;
|
||||
|
||||
/* Special symbols. */
|
||||
LPAREN : '(' ;
|
||||
RPAREN : ')' ;
|
||||
LBRACK : '[' ;
|
||||
RBRACK : ']' ;
|
||||
LBRACE : '{' ;
|
||||
RBRACE : '}' ;
|
||||
LPAREN : '(' ;
|
||||
RPAREN : ')' ;
|
||||
LBRACK : '[' ;
|
||||
RBRACK : ']' ;
|
||||
LBRACE : '{' ;
|
||||
RBRACE : '}' ;
|
||||
|
||||
COMMA : ',' ;
|
||||
DOT : '.' ;
|
||||
DOTS : '..' ;
|
||||
COLON : ':' ;
|
||||
DOLLAR : '$' ;
|
||||
PIPE : '|' ;
|
||||
COMMA : ',' ;
|
||||
DOT : '.' ;
|
||||
DOTS : '..' ;
|
||||
COLON : ':' ;
|
||||
SEMICOLON : ';' ;
|
||||
DOLLAR : '$' ;
|
||||
PIPE : '|' ;
|
||||
|
||||
EQ : '=' ;
|
||||
LT : '<' ;
|
||||
GT : '>' ;
|
||||
LTE : '<=' ;
|
||||
GTE : '>=' ;
|
||||
NEQ1 : '<>' ;
|
||||
NEQ2 : '!=' ;
|
||||
SIM : '=~' ;
|
||||
EQ : '=' ;
|
||||
LT : '<' ;
|
||||
GT : '>' ;
|
||||
LTE : '<=' ;
|
||||
GTE : '>=' ;
|
||||
NEQ1 : '<>' ;
|
||||
NEQ2 : '!=' ;
|
||||
SIM : '=~' ;
|
||||
|
||||
PLUS : '+' ;
|
||||
MINUS : '-' ;
|
||||
ASTERISK : '*' ;
|
||||
SLASH : '/' ;
|
||||
PERCENT : '%' ;
|
||||
CARET : '^' ;
|
||||
PLUS_EQ : '+=' ;
|
||||
PLUS : '+' ;
|
||||
MINUS : '-' ;
|
||||
ASTERISK : '*' ;
|
||||
SLASH : '/' ;
|
||||
PERCENT : '%' ;
|
||||
CARET : '^' ;
|
||||
PLUS_EQ : '+=' ;
|
||||
|
||||
/* Some random unicode characters that can be used to draw arrows. */
|
||||
LeftArrowHeadPart : '⟨' | '〈' | '﹤' | '<' ;
|
||||
@ -62,15 +69,11 @@ DashPart : '' | '‐' | '‑' | '‒' | '–' | '—' | '―'
|
||||
|
||||
/* Cypher reserved words. */
|
||||
ALL : A L L ;
|
||||
ALTER : A L T E R ;
|
||||
AND : A N D ;
|
||||
ANY : A N Y ;
|
||||
AS : A S ;
|
||||
ASC : A S C ;
|
||||
ASCENDING : A S C E N D I N G ;
|
||||
BATCHES : B A T C H E S ;
|
||||
BATCH_INTERVAL : B A T C H '_' I N T E R V A L ;
|
||||
BATCH_SIZE : B A T C H '_' S I Z E ;
|
||||
BFS : B F S ;
|
||||
BY : B Y ;
|
||||
CASE : C A S E ;
|
||||
@ -78,13 +81,11 @@ CONTAINS : C O N T A I N S ;
|
||||
COUNT : C O U N T ;
|
||||
CREATE : C R E A T E ;
|
||||
CYPHERNULL : N U L L ;
|
||||
DATA : D A T A ;
|
||||
DELETE : D E L E T E ;
|
||||
DESC : D E S C ;
|
||||
DESCENDING : D E S C E N D I N G ;
|
||||
DETACH : D E T A C H ;
|
||||
DISTINCT : D I S T I N C T ;
|
||||
DROP : D R O P ;
|
||||
ELSE : E L S E ;
|
||||
END : E N D ;
|
||||
ENDS : E N D S ;
|
||||
@ -94,10 +95,7 @@ FILTER : F I L T E R ;
|
||||
IN : I N ;
|
||||
INDEX : I N D E X ;
|
||||
IS : I S ;
|
||||
KAFKA : K A F K A ;
|
||||
K_TEST : T E S T ;
|
||||
LIMIT : L I M I T ;
|
||||
LOAD : L O A D ;
|
||||
L_SKIP : S K I P ;
|
||||
MATCH : M A T C H ;
|
||||
MERGE : M E R G E ;
|
||||
@ -107,25 +105,17 @@ ON : O N ;
|
||||
OPTIONAL : O P T I O N A L ;
|
||||
OR : O R ;
|
||||
ORDER : O R D E R ;
|
||||
PASSWORD : P A S S W O R D ;
|
||||
REDUCE : R E D U C E ;
|
||||
REMOVE : R E M O V E ;
|
||||
RETURN : R E T U R N ;
|
||||
SET : S E T ;
|
||||
SHOW : S H O W ;
|
||||
SINGLE : S I N G L E ;
|
||||
START : S T A R T ;
|
||||
STARTS : S T A R T S ;
|
||||
STOP : S T O P ;
|
||||
STREAM : S T R E A M ;
|
||||
STREAMS : S T R E A M S ;
|
||||
THEN : T H E N ;
|
||||
TOPIC : T O P I C ;
|
||||
TRANSFORM : T R A N S F O R M ;
|
||||
TRUE : T R U E ;
|
||||
UNION : U N I O N ;
|
||||
UNWIND : U N W I N D ;
|
||||
USER : U S E R ;
|
||||
WHEN : W H E N ;
|
||||
WHERE : W H E R E ;
|
||||
WITH : W I T H ;
|
||||
|
82
src/query/frontend/opencypher/grammar/MemgraphCypher.g4
Normal file
82
src/query/frontend/opencypher/grammar/MemgraphCypher.g4
Normal file
@ -0,0 +1,82 @@
|
||||
/* Memgraph specific part of Cypher grammar. */
|
||||
|
||||
parser grammar MemgraphCypher ;
|
||||
|
||||
options { tokenVocab=MemgraphCypherLexer; }
|
||||
|
||||
import Cypher ;
|
||||
|
||||
memgraphCypherKeyword : cypherKeyword
|
||||
| ALTER
|
||||
| BATCH
|
||||
| BATCHES
|
||||
| DATA
|
||||
| DROP
|
||||
| INTERVAL
|
||||
| K_TEST
|
||||
| KAFKA
|
||||
| LOAD
|
||||
| PASSWORD
|
||||
| SIZE
|
||||
| START
|
||||
| STOP
|
||||
| STREAM
|
||||
| STREAMS
|
||||
| TOPIC
|
||||
| TRANSFORM
|
||||
| USER
|
||||
;
|
||||
|
||||
symbolicName : UnescapedSymbolicName
|
||||
| EscapedSymbolicName
|
||||
| memgraphCypherKeyword
|
||||
;
|
||||
|
||||
query : regularQuery
|
||||
| authQuery
|
||||
| streamQuery
|
||||
;
|
||||
|
||||
authQuery : modifyUser
|
||||
| dropUser
|
||||
;
|
||||
|
||||
modifyUser : ( CREATE | ALTER ) USER userName=UnescapedSymbolicName
|
||||
( WITH ( modifyUserOption )+ )? ;
|
||||
|
||||
modifyUserOption : passwordOption ;
|
||||
|
||||
passwordOption : PASSWORD literal;
|
||||
|
||||
dropUser : DROP USER userName+=UnescapedSymbolicName
|
||||
( ',' userName+=UnescapedSymbolicName )* ;
|
||||
|
||||
streamQuery : createStream
|
||||
| dropStream
|
||||
| showStreams
|
||||
| startStopStream
|
||||
| startStopAllStreams
|
||||
| testStream
|
||||
;
|
||||
|
||||
streamName : UnescapedSymbolicName ;
|
||||
|
||||
createStream : CREATE STREAM streamName AS LOAD DATA KAFKA
|
||||
streamUri=literal WITH TOPIC streamTopic=literal WITH TRANSFORM
|
||||
transformUri=literal ( batchIntervalOption )? ( batchSizeOption )? ;
|
||||
|
||||
batchIntervalOption : BATCH INTERVAL literal ;
|
||||
|
||||
batchSizeOption : BATCH SIZE literal ;
|
||||
|
||||
dropStream : DROP STREAM streamName ;
|
||||
|
||||
showStreams : SHOW STREAMS ;
|
||||
|
||||
startStopStream : ( START | STOP ) STREAM streamName ( limitBatchesOption )? ;
|
||||
|
||||
limitBatchesOption : LIMIT limitBatches=literal BATCHES ;
|
||||
|
||||
startStopAllStreams : ( START | STOP ) ALL STREAMS ;
|
||||
|
||||
testStream : K_TEST STREAM streamName ( limitBatchesOption )? ;
|
30
src/query/frontend/opencypher/grammar/MemgraphCypherLexer.g4
Normal file
30
src/query/frontend/opencypher/grammar/MemgraphCypherLexer.g4
Normal file
@ -0,0 +1,30 @@
|
||||
/* Memgraph specific Cypher reserved words. */
|
||||
|
||||
/*
|
||||
* When changing this grammar make sure to update constants in
|
||||
* src/query/frontend/stripped_lexer_constants.hpp (kKeywords, kSpecialTokens
|
||||
* and bitsets) if needed.
|
||||
*/
|
||||
|
||||
lexer grammar MemgraphCypherLexer ;
|
||||
|
||||
import CypherLexer ;
|
||||
|
||||
ALTER : A L T E R ;
|
||||
BATCH : B A T C H ;
|
||||
BATCHES : B A T C H E S ;
|
||||
DATA : D A T A ;
|
||||
DROP : D R O P ;
|
||||
INTERVAL : I N T E R V A L ;
|
||||
K_TEST : T E S T ;
|
||||
KAFKA : K A F K A ;
|
||||
LOAD : L O A D ;
|
||||
PASSWORD : P A S S W O R D ;
|
||||
SIZE : S I Z E ;
|
||||
START : S T A R T ;
|
||||
STOP : S T O P ;
|
||||
STREAM : S T R E A M ;
|
||||
STREAMS : S T R E A M S ;
|
||||
TOPIC : T O P I C ;
|
||||
TRANSFORM : T R A N S F O R M ;
|
||||
USER : U S E R ;
|
@ -4,8 +4,8 @@
|
||||
|
||||
#include "antlr4-runtime.h"
|
||||
#include "query/exceptions.hpp"
|
||||
#include "query/frontend/opencypher/generated/CypherLexer.h"
|
||||
#include "query/frontend/opencypher/generated/CypherParser.h"
|
||||
#include "query/frontend/opencypher/generated/MemgraphCypher.h"
|
||||
#include "query/frontend/opencypher/generated/MemgraphCypherLexer.h"
|
||||
|
||||
namespace query {
|
||||
namespace frontend {
|
||||
@ -51,11 +51,11 @@ class Parser {
|
||||
FirstMessageErrorListener error_listener_;
|
||||
std::string query_;
|
||||
antlr4::ANTLRInputStream input_{query_.c_str()};
|
||||
antlropencypher::CypherLexer lexer_{&input_};
|
||||
antlropencypher::MemgraphCypherLexer lexer_{&input_};
|
||||
antlr4::CommonTokenStream tokens_{&lexer_};
|
||||
|
||||
// generate ast
|
||||
antlropencypher::CypherParser parser_{&tokens_};
|
||||
antlropencypher::MemgraphCypher parser_{&tokens_};
|
||||
antlr4::tree::ParseTree *tree_ = nullptr;
|
||||
};
|
||||
} // namespace opencypher
|
||||
|
@ -10,9 +10,9 @@
|
||||
|
||||
#include "query/common.hpp"
|
||||
#include "query/exceptions.hpp"
|
||||
#include "query/frontend/opencypher/generated/CypherLexer.h"
|
||||
#include "query/frontend/opencypher/generated/CypherParser.h"
|
||||
#include "query/frontend/opencypher/generated/CypherParserBaseVisitor.h"
|
||||
#include "query/frontend/opencypher/generated/MemgraphCypher.h"
|
||||
#include "query/frontend/opencypher/generated/MemgraphCypherBaseVisitor.h"
|
||||
#include "query/frontend/opencypher/generated/MemgraphCypherLexer.h"
|
||||
#include "query/frontend/stripped_lexer_constants.hpp"
|
||||
#include "utils/hashing/fnv.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "antlr4-runtime.h"
|
||||
#include "query/frontend/opencypher/generated/CypherLexer.h"
|
||||
#include "query/frontend/opencypher/generated/CypherParser.h"
|
||||
#include "query/frontend/opencypher/generated/MemgraphCypher.h"
|
||||
#include "query/frontend/opencypher/generated/MemgraphCypherLexer.h"
|
||||
|
||||
using namespace antlropencypher;
|
||||
using namespace antlr4;
|
||||
@ -11,7 +11,7 @@ int main(int, const char **a) {
|
||||
const char *query = a[1];
|
||||
|
||||
ANTLRInputStream input(query);
|
||||
CypherLexer lexer(&input);
|
||||
MemgraphCypherLexer lexer(&input);
|
||||
CommonTokenStream tokens(&lexer);
|
||||
|
||||
const auto &vocabulary = lexer.getVocabulary();
|
||||
@ -22,7 +22,7 @@ int main(int, const char **a) {
|
||||
<< "; STRING: " << token->toString() << std::endl;
|
||||
}
|
||||
|
||||
CypherParser parser(&tokens);
|
||||
MemgraphCypher parser(&tokens);
|
||||
tree::ParseTree *tree = parser.cypher();
|
||||
|
||||
std::cout << tree->toStringTree(&parser) << std::endl << std::endl;
|
||||
|
@ -5,8 +5,8 @@
|
||||
#include <string>
|
||||
|
||||
#include "antlr4-runtime.h"
|
||||
#include "query/frontend/opencypher/generated/CypherLexer.h"
|
||||
#include "query/frontend/opencypher/generated/CypherParser.h"
|
||||
#include "query/frontend/opencypher/generated/MemgraphCypher.h"
|
||||
#include "query/frontend/opencypher/generated/MemgraphCypherLexer.h"
|
||||
|
||||
using namespace antlropencypher;
|
||||
using namespace antlr4;
|
||||
@ -22,10 +22,10 @@ std::string ReadAllInput() {
|
||||
return results;
|
||||
}
|
||||
|
||||
int main(int, const char**) {
|
||||
int main(int, const char **) {
|
||||
std::string input_string = ReadAllInput();
|
||||
ANTLRInputStream input(input_string);
|
||||
CypherLexer lexer(&input);
|
||||
MemgraphCypherLexer lexer(&input);
|
||||
CommonTokenStream tokens(&lexer);
|
||||
|
||||
tokens.fill();
|
||||
@ -33,8 +33,8 @@ int main(int, const char**) {
|
||||
std::cout << token->toString() << std::endl;
|
||||
}
|
||||
|
||||
CypherParser parser(&tokens);
|
||||
tree::ParseTree* tree = parser.cypher();
|
||||
MemgraphCypher parser(&tokens);
|
||||
tree::ParseTree *tree = parser.cypher();
|
||||
|
||||
// Print tree indented. This is a hacky implementation and not very correct.
|
||||
std::string indent;
|
||||
|
@ -240,18 +240,20 @@ TYPED_TEST(CypherMainVisitorTest, EscapedLabel) {
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, KeywordLabel) {
|
||||
TypeParam ast_generator("RETURN n:DEletE");
|
||||
auto *query = ast_generator.query_;
|
||||
ASSERT_TRUE(query->single_query_);
|
||||
auto *single_query = query->single_query_;
|
||||
ASSERT_EQ(single_query->clauses_.size(), 1U);
|
||||
auto *return_clause = dynamic_cast<Return *>(single_query->clauses_[0]);
|
||||
auto *labels_test = dynamic_cast<LabelsTest *>(
|
||||
return_clause->body_.named_expressions[0]->expression_);
|
||||
auto identifier = dynamic_cast<Identifier *>(labels_test->expression_);
|
||||
ASSERT_EQ(identifier->name_, "n");
|
||||
ASSERT_THAT(labels_test->labels_,
|
||||
ElementsAre(ast_generator.db_accessor_->Label("DEletE")));
|
||||
for (const auto &label : {"DeLete", "UsER"}) {
|
||||
TypeParam ast_generator(fmt::format("RETURN n:{}", label));
|
||||
auto *query = ast_generator.query_;
|
||||
ASSERT_TRUE(query->single_query_);
|
||||
auto *single_query = query->single_query_;
|
||||
ASSERT_EQ(single_query->clauses_.size(), 1U);
|
||||
auto *return_clause = dynamic_cast<Return *>(single_query->clauses_[0]);
|
||||
auto *labels_test = dynamic_cast<LabelsTest *>(
|
||||
return_clause->body_.named_expressions[0]->expression_);
|
||||
auto identifier = dynamic_cast<Identifier *>(labels_test->expression_);
|
||||
ASSERT_EQ(identifier->name_, "n");
|
||||
ASSERT_THAT(labels_test->labels_,
|
||||
ElementsAre(ast_generator.db_accessor_->Label(label)));
|
||||
}
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, HexLetterLabel) {
|
||||
@ -779,21 +781,6 @@ TYPED_TEST(CypherMainVisitorTest, UndefinedFunction) {
|
||||
SemanticException);
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, FunctionSpecialCase) {
|
||||
// For some reason parsing of function calls with single letter name in a-f
|
||||
// range would fail, so here's a test for that (also see D1464).
|
||||
TypeParam ast_generator("RETURN e()");
|
||||
auto *query = ast_generator.query_;
|
||||
ASSERT_TRUE(query->single_query_);
|
||||
auto *single_query = query->single_query_;
|
||||
auto *return_clause = dynamic_cast<Return *>(single_query->clauses_[0]);
|
||||
ASSERT_EQ(return_clause->body_.named_expressions.size(), 1);
|
||||
auto *function = dynamic_cast<Function *>(
|
||||
return_clause->body_.named_expressions[0]->expression_);
|
||||
ASSERT_TRUE(function);
|
||||
ASSERT_TRUE(function->function());
|
||||
}
|
||||
|
||||
TYPED_TEST(CypherMainVisitorTest, Function) {
|
||||
TypeParam ast_generator("RETURN abs(n, 2)");
|
||||
auto *query = ast_generator.query_;
|
||||
@ -2023,40 +2010,40 @@ TYPED_TEST(CypherMainVisitorTest, CreateStream) {
|
||||
check_create_stream(
|
||||
"CreaTE StreaM strim AS LOad daTA KAFKA 'localhost' "
|
||||
"WitH TopIC 'tropika' "
|
||||
"WITH TRAnsFORM 'localhost/test.py' bAtCH_inTErvAL 168",
|
||||
"WITH TRAnsFORM 'localhost/test.py' bAtCH inTErvAL 168",
|
||||
"strim", "localhost", "tropika", "localhost/test.py", 168,
|
||||
std::experimental::nullopt);
|
||||
|
||||
check_create_stream(
|
||||
"CreaTE StreaM strim AS LOad daTA KAFKA 'localhost' "
|
||||
"WITH TopIC 'tropika' "
|
||||
"WITH TRAnsFORM 'localhost/test.py' bAtCH_SizE 17",
|
||||
"WITH TRAnsFORM 'localhost/test.py' bAtCH SizE 17",
|
||||
"strim", "localhost", "tropika", "localhost/test.py",
|
||||
std::experimental::nullopt, 17);
|
||||
|
||||
check_create_stream(
|
||||
"CreaTE StreaM strim AS LOad daTA KAFKA 'localhost' "
|
||||
"WitH TOPic 'tropika' "
|
||||
"WITH TRAnsFORM 'localhost/test.py' bAtCH_inTErvAL 168 Batch_SIze 17",
|
||||
"WITH TRAnsFORM 'localhost/test.py' bAtCH inTErvAL 168 Batch SIze 17",
|
||||
"strim", "localhost", "tropika", "localhost/test.py", 168, 17);
|
||||
|
||||
EXPECT_THROW(check_create_stream(
|
||||
"CREATE STREAM strim AS LOAD DATA KAFKA 'localhost' "
|
||||
"WITH TRANSFORM 'localhost/test.py' BATCH_INTERVAL 'jedan' ",
|
||||
"WITH TRANSFORM 'localhost/test.py' BATCH INTERVAL 'jedan' ",
|
||||
"strim", "localhost", "tropika", "localhost/test.py", 168,
|
||||
std::experimental::nullopt),
|
||||
SyntaxException);
|
||||
EXPECT_THROW(check_create_stream(
|
||||
"CREATE STREAM strim AS LOAD DATA KAFKA 'localhost' "
|
||||
"WITH TOPIC 'tropika' "
|
||||
"WITH TRANSFORM 'localhost/test.py' BATCH_SIZE 'jedan' ",
|
||||
"WITH TRANSFORM 'localhost/test.py' BATCH SIZE 'jedan' ",
|
||||
"strim", "localhost", "tropika", "localhost/test.py",
|
||||
std::experimental::nullopt, 17),
|
||||
SyntaxException);
|
||||
EXPECT_THROW(check_create_stream(
|
||||
"CREATE STREAM 123 AS LOAD DATA KAFKA 'localhost' "
|
||||
"WITH TOPIC 'tropika' "
|
||||
"WITH TRANSFORM 'localhost/test.py' BATCH_INTERVAL 168 ",
|
||||
"WITH TRANSFORM 'localhost/test.py' BATCH INTERVAL 168 ",
|
||||
"strim", "localhost", "tropika", "localhost/test.py", 168,
|
||||
std::experimental::nullopt),
|
||||
SyntaxException);
|
||||
@ -2070,14 +2057,14 @@ TYPED_TEST(CypherMainVisitorTest, CreateStream) {
|
||||
EXPECT_THROW(check_create_stream(
|
||||
"CREATE STREAM strim AS LOAD DATA KAFKA 'localhost' "
|
||||
"WITH TOPIC 2"
|
||||
"WITH TRANSFORM localhost/test.py BATCH_INTERVAL 168 ",
|
||||
"WITH TRANSFORM localhost/test.py BATCH INTERVAL 168 ",
|
||||
"strim", "localhost", "tropika", "localhost/test.py", 168,
|
||||
std::experimental::nullopt),
|
||||
SyntaxException);
|
||||
EXPECT_THROW(check_create_stream(
|
||||
"CREATE STREAM strim AS LOAD DATA KAFKA 'localhost' "
|
||||
"WITH TOPIC 'tropika'"
|
||||
"WITH TRANSFORM localhost/test.py BATCH_INTERVAL 168 ",
|
||||
"WITH TRANSFORM localhost/test.py BATCH INTERVAL 168 ",
|
||||
"strim", "localhost", "tropika", "localhost/test.py", 168,
|
||||
std::experimental::nullopt),
|
||||
SyntaxException);
|
||||
|
Loading…
Reference in New Issue
Block a user