diff --git a/.github/workflows/diff.yaml b/.github/workflows/diff.yaml index c82bd9278..bf6a39147 100644 --- a/.github/workflows/diff.yaml +++ b/.github/workflows/diff.yaml @@ -70,6 +70,11 @@ jobs: # branches and tags. (default: 1) fetch-depth: 0 + # This is also needed if we want do to comparison against other branches + # See https://github.community/t/checkout-code-fails-when-it-runs-lerna-run-test-since-master/17920 + - name: Fetch all history for all tags and branches + run: git fetch + - name: Build combined ASAN, UBSAN and coverage binaries run: | # Activate toolchain. @@ -110,12 +115,22 @@ jobs: name: "Code coverage" path: tools/github/generated/code_coverage.tar.gz + - name: Set base branch + if: ${{ github.event_name == 'pull_request' }} + run: | + echo "BASE_BRANCH=origin/${{ github.base_ref }}" >> $GITHUB_ENV + + - name: Set base branch # if we manually dispatch or push to master + if: ${{ github.event_name != 'pull_request' }} + run: | + echo "BASE_BRANCH=origin/master" >> $GITHUB_ENV + - name: Run clang-tidy run: | source /opt/toolchain-v4/activate # Restrict clang-tidy results only to the modified parts - git diff -U0 master... -- src | ./tools/github/clang-tidy/clang-tidy-diff.py -p 1 -j $THREADS -path build | tee ./build/clang_tidy_output.txt + git diff -U0 ${{ env.BASE_BRANCH }}... -- src | ./tools/github/clang-tidy/clang-tidy-diff.py -p 1 -j $THREADS -path build | tee ./build/clang_tidy_output.txt # Fail if any warning is reported ! cat ./build/clang_tidy_output.txt | ./tools/github/clang-tidy/grep_error_lines.sh > /dev/null diff --git a/libs/.gitignore b/libs/.gitignore index 0bec9e7d4..f4ebfc3a0 100644 --- a/libs/.gitignore +++ b/libs/.gitignore @@ -5,3 +5,4 @@ !CMakeLists.txt !__main.cpp !pulsar.patch +!antlr4.10.1.patch diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index 10f30dfe6..618c0ce5c 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -106,6 +106,7 @@ import_external_library(antlr4 STATIC -DWITH_LIBCXX=OFF # because of debian bug -DCMAKE_SKIP_INSTALL_ALL_DEPENDENCY=true -DCMAKE_CXX_STANDARD=20 + -DANTLR_BUILD_CPP_TESTS=OFF BUILD_COMMAND $(MAKE) antlr4_static INSTALL_COMMAND $(MAKE) install) diff --git a/libs/antlr4.10.1.patch b/libs/antlr4.10.1.patch new file mode 100644 index 000000000..b5206f491 --- /dev/null +++ b/libs/antlr4.10.1.patch @@ -0,0 +1,13 @@ +diff --git a/runtime/Cpp/runtime/CMakeLists.txt b/runtime/Cpp/runtime/CMakeLists.txt +index baf46cac9..2e7756de8 100644 +--- a/runtime/Cpp/runtime/CMakeLists.txt ++++ b/runtime/Cpp/runtime/CMakeLists.txt +@@ -134,7 +134,7 @@ set_target_properties(antlr4_static + ARCHIVE_OUTPUT_DIRECTORY ${LIB_OUTPUT_DIR} + COMPILE_FLAGS "${disabled_compile_warnings} ${extra_static_compile_flags}") + +-install(TARGETS antlr4_shared ++install(TARGETS antlr4_shared OPTIONAL + EXPORT antlr4-targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/libs/antlr4.patch b/libs/antlr4.patch deleted file mode 100644 index 694dd2e39..000000000 --- a/libs/antlr4.patch +++ /dev/null @@ -1,43 +0,0 @@ -diff --git a/runtime/Cpp/runtime/CMakeLists.txt b/runtime/Cpp/runtime/CMakeLists.txt -index a8503bb..11362cf 100644 ---- a/runtime/Cpp/runtime/CMakeLists.txt -+++ b/runtime/Cpp/runtime/CMakeLists.txt -@@ -5,8 +5,8 @@ set(THIRDPARTY_DIR ${CMAKE_BINARY_DIR}/runtime/thirdparty) - set(UTFCPP_DIR ${THIRDPARTY_DIR}/utfcpp) - ExternalProject_Add( - utfcpp -- GIT_REPOSITORY "git://github.com/nemtrif/utfcpp" -- GIT_TAG "v3.1.1" -+ GIT_REPOSITORY "https://github.com/nemtrif/utfcpp" -+ GIT_TAG "v3.2.1" - SOURCE_DIR ${UTFCPP_DIR} - UPDATE_DISCONNECTED 1 - CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${UTFCPP_DIR}/install -Dgtest_force_shared_crt=ON -@@ -118,7 +118,7 @@ set_target_properties(antlr4_static - ARCHIVE_OUTPUT_DIRECTORY ${LIB_OUTPUT_DIR} - COMPILE_FLAGS "${disabled_compile_warnings} ${extra_static_compile_flags}") - --install(TARGETS antlr4_shared -+install(TARGETS antlr4_shared OPTIONAL - DESTINATION lib - EXPORT antlr4-targets) - install(TARGETS antlr4_static -diff --git a/runtime/Cpp/runtime/src/support/Any.h b/runtime/Cpp/runtime/src/support/Any.h -index 468db98..65a473b 100644 ---- a/runtime/Cpp/runtime/src/support/Any.h -+++ b/runtime/Cpp/runtime/src/support/Any.h -@@ -122,12 +122,12 @@ private: - } - - private: -- template::value, int>::type = 0> -+ template::value, int>::type = 0> - Base* clone() const { - return new Derived(value); - } - -- template::value, int>::type = 0> -+ template::value, int>::type = 0> - Base* clone() const { - return nullptr; - } diff --git a/libs/setup.sh b/libs/setup.sh index 6a73f65d1..d902aadb1 100755 --- a/libs/setup.sh +++ b/libs/setup.sh @@ -105,7 +105,7 @@ repo_clone_try_double () { # Download from primary_urls might fail because the cache is not installed. declare -A primary_urls=( ["antlr4-code"]="http://$local_cache_host/git/antlr4.git" - ["antlr4-generator"]="http://$local_cache_host/file/antlr-4.9.2-complete.jar" + ["antlr4-generator"]="http://$local_cache_host/file/antlr-4.10.1-complete.jar" ["cppitertools"]="http://$local_cache_host/git/cppitertools.git" ["rapidcheck"]="http://$local_cache_host/git/rapidcheck.git" ["gbenchmark"]="http://$local_cache_host/git/benchmark.git" @@ -130,7 +130,7 @@ declare -A primary_urls=( # should fail. declare -A secondary_urls=( ["antlr4-code"]="https://github.com/antlr/antlr4.git" - ["antlr4-generator"]="http://www.antlr.org/download/antlr-4.9.2-complete.jar" + ["antlr4-generator"]="https://www.antlr.org/download/antlr-4.10.1-complete.jar" ["cppitertools"]="https://github.com/ryanhaining/cppitertools.git" ["rapidcheck"]="https://github.com/emil-e/rapidcheck.git" ["gbenchmark"]="https://github.com/google/benchmark.git" @@ -152,10 +152,10 @@ declare -A secondary_urls=( # antlr file_get_try_double "${primary_urls[antlr4-generator]}" "${secondary_urls[antlr4-generator]}" -antlr4_tag="4.9.2" # v4.9.2 +antlr4_tag="4.10.1" # v4.10.1 repo_clone_try_double "${primary_urls[antlr4-code]}" "${secondary_urls[antlr4-code]}" "antlr4" "$antlr4_tag" true pushd antlr4 -git apply ../antlr4.patch +git apply ../antlr4.10.1.patch popd # cppitertools v2.0 2019-12-23 @@ -199,7 +199,7 @@ git apply ../rocksdb.patch popd # mgclient -mgclient_tag="96e95c6845463cbe88948392be58d26da0d5ffd3" # (2022-02-08) +mgclient_tag="v1.4.0" # (2022-06-14) repo_clone_try_double "${primary_urls[mgclient]}" "${secondary_urls[mgclient]}" "mgclient" "$mgclient_tag" sed -i 's/\${CMAKE_INSTALL_LIBDIR}/lib/' mgclient/src/CMakeLists.txt diff --git a/src/memgraph.cpp b/src/memgraph.cpp index 9bd3f3f92..d4fc3bad1 100644 --- a/src/memgraph.cpp +++ b/src/memgraph.cpp @@ -1252,9 +1252,8 @@ int main(int argc, char **argv) { // the triggers auto storage_accessor = interpreter_context.db->Access(); auto dba = memgraph::query::DbAccessor{&storage_accessor}; - interpreter_context.trigger_store.RestoreTriggers(&interpreter_context.ast_cache, &dba, - &interpreter_context.antlr_lock, interpreter_context.config.query, - interpreter_context.auth_checker); + interpreter_context.trigger_store.RestoreTriggers( + &interpreter_context.ast_cache, &dba, interpreter_context.config.query, interpreter_context.auth_checker); } // As the Stream transformations are using modules, they have to be restored after the query modules are loaded. diff --git a/src/query/CMakeLists.txt b/src/query/CMakeLists.txt index 0302df4da..0303f2fa5 100644 --- a/src/query/CMakeLists.txt +++ b/src/query/CMakeLists.txt @@ -82,7 +82,7 @@ add_custom_command( OUTPUT ${antlr_opencypher_generated_src} ${antlr_opencypher_generated_include} COMMAND ${CMAKE_COMMAND} -E make_directory ${opencypher_generated} COMMAND - java -jar ${CMAKE_SOURCE_DIR}/libs/antlr-4.9.2-complete.jar + java -jar ${CMAKE_SOURCE_DIR}/libs/antlr-4.10.1-complete.jar -Dlanguage=Cpp -visitor -package antlropencypher -o ${opencypher_generated} ${opencypher_lexer_grammar} ${opencypher_parser_grammar} diff --git a/src/query/cypher_query_interpreter.cpp b/src/query/cypher_query_interpreter.cpp index 96aa75d03..05d7e417e 100644 --- a/src/query/cypher_query_interpreter.cpp +++ b/src/query/cypher_query_interpreter.cpp @@ -21,8 +21,7 @@ namespace memgraph::query { CachedPlan::CachedPlan(std::unique_ptr plan) : plan_(std::move(plan)) {} ParsedQuery ParseQuery(const std::string &query_string, const std::map ¶ms, - utils::SkipList *cache, utils::SpinLock *antlr_lock, - const InterpreterConfig::Query &query_config) { + utils::SkipList *cache, const InterpreterConfig::Query &query_config) { // Strip the query for caching purposes. The process of stripping a query // "normalizes" it by replacing any literals with new parameters. This // results in just the *structure* of the query being taken into account for @@ -63,20 +62,16 @@ ParsedQuery ParseQuery(const std::string &query_string, const std::map guard(*antlr_lock); + try { + parser = std::make_unique(stripped_query.query()); + } catch (const SyntaxException &e) { + // There is a syntax exception in the stripped query. Re-run the parser + // on the original query to get an appropriate error messsage. + parser = std::make_unique(query_string); - try { - parser = std::make_unique(stripped_query.query()); - } catch (const SyntaxException &e) { - // There is a syntax exception in the stripped query. Re-run the parser - // on the original query to get an appropriate error messsage. - parser = std::make_unique(query_string); - - // If an exception was not thrown here, the stripper messed something - // up. - LOG_FATAL("The stripped query can't be parsed, but the original can."); - } + // If an exception was not thrown here, the stripper messed something + // up. + LOG_FATAL("The stripped query can't be parsed, but the original can."); } // Convert the ANTLR4 parse tree into an AST. diff --git a/src/query/cypher_query_interpreter.hpp b/src/query/cypher_query_interpreter.hpp index 2318cae3f..14b4a3792 100644 --- a/src/query/cypher_query_interpreter.hpp +++ b/src/query/cypher_query_interpreter.hpp @@ -111,8 +111,7 @@ struct ParsedQuery { }; ParsedQuery ParseQuery(const std::string &query_string, const std::map ¶ms, - utils::SkipList *cache, utils::SpinLock *antlr_lock, - const InterpreterConfig::Query &query_config); + utils::SkipList *cache, const InterpreterConfig::Query &query_config); class SingleNodeLogicalPlan final : public LogicalPlan { public: diff --git a/src/query/frontend/ast/cypher_main_visitor.cpp b/src/query/frontend/ast/cypher_main_visitor.cpp index a12643298..e97bdc05e 100644 --- a/src/query/frontend/ast/cypher_main_visitor.cpp +++ b/src/query/frontend/ast/cypher_main_visitor.cpp @@ -52,7 +52,7 @@ std::optional> VisitMemoryLimit return std::nullopt; } - auto memory_limit = memory_limit_ctx->literal()->accept(visitor); + auto *memory_limit = std::any_cast(memory_limit_ctx->literal()->accept(visitor)); size_t memory_scale = 1024U; if (memory_limit_ctx->MB()) { memory_scale = 1024U * 1024U; @@ -77,7 +77,7 @@ std::string JoinSymbolicNames(antlr4::tree::ParseTreeVisitor *visitor, const std::vector symbolicNames, const std::string &separator = ".") { return JoinTokens( - symbolicNames, [&](auto *token) { return token->accept(visitor).template as(); }, separator); + symbolicNames, [&](auto *token) { return std::any_cast(token->accept(visitor)); }, separator); } std::string JoinSymbolicNamesWithDotsAndMinus(antlr4::tree::ParseTreeVisitor &visitor, @@ -90,7 +90,7 @@ std::string JoinSymbolicNamesWithDotsAndMinus(antlr4::tree::ParseTreeVisitor &vi antlrcpp::Any CypherMainVisitor::visitExplainQuery(MemgraphCypher::ExplainQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 2, "ExplainQuery should have exactly two children!"); - auto *cypher_query = ctx->children[1]->accept(this).as(); + auto *cypher_query = std::any_cast(ctx->children[1]->accept(this)); auto *explain_query = storage_->Create(); explain_query->cypher_query_ = cypher_query; query_ = explain_query; @@ -99,7 +99,7 @@ antlrcpp::Any CypherMainVisitor::visitExplainQuery(MemgraphCypher::ExplainQueryC antlrcpp::Any CypherMainVisitor::visitProfileQuery(MemgraphCypher::ProfileQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 2, "ProfileQuery should have exactly two children!"); - auto *cypher_query = ctx->children[1]->accept(this).as(); + auto *cypher_query = std::any_cast(ctx->children[1]->accept(this)); auto *profile_query = storage_->Create(); profile_query->cypher_query_ = cypher_query; query_ = profile_query; @@ -132,7 +132,7 @@ antlrcpp::Any CypherMainVisitor::visitConstraintQuery(MemgraphCypher::Constraint } else if (ctx->DROP()) { constraint_query->action_type_ = ConstraintQuery::ActionType::DROP; } - constraint_query->constraint_ = ctx->constraint()->accept(this).as(); + constraint_query->constraint_ = std::any_cast(ctx->constraint()->accept(this)); query_ = constraint_query; return query_; } @@ -147,16 +147,16 @@ antlrcpp::Any CypherMainVisitor::visitConstraint(MemgraphCypher::ConstraintConte } else if (ctx->NODE() && ctx->KEY()) { constraint.type = Constraint::Type::NODE_KEY; } - constraint.label = AddLabel(ctx->labelName()->accept(this)); - std::string node_name = ctx->nodeName->symbolicName()->accept(this); + constraint.label = AddLabel(std::any_cast(ctx->labelName()->accept(this))); + auto node_name = std::any_cast(ctx->nodeName->symbolicName()->accept(this)); for (const auto &var_ctx : ctx->constraintPropertyList()->variable()) { - std::string var_name = var_ctx->symbolicName()->accept(this); + auto var_name = std::any_cast(var_ctx->symbolicName()->accept(this)); if (var_name != node_name) { throw SemanticException("All constraint variable should reference node '{}'", node_name); } } for (const auto &prop_lookup : ctx->constraintPropertyList()->propertyLookup()) { - constraint.properties.push_back(prop_lookup->propertyKeyName()->accept(this)); + constraint.properties.push_back(std::any_cast(prop_lookup->propertyKeyName()->accept(this))); } return constraint; @@ -165,7 +165,7 @@ antlrcpp::Any CypherMainVisitor::visitConstraint(MemgraphCypher::ConstraintConte antlrcpp::Any CypherMainVisitor::visitCypherQuery(MemgraphCypher::CypherQueryContext *ctx) { auto *cypher_query = storage_->Create(); MG_ASSERT(ctx->singleQuery(), "Expected single query."); - cypher_query->single_query_ = ctx->singleQuery()->accept(this).as(); + cypher_query->single_query_ = std::any_cast(ctx->singleQuery()->accept(this)); // Check that union and union all dont mix bool has_union = false; @@ -179,7 +179,7 @@ antlrcpp::Any CypherMainVisitor::visitCypherQuery(MemgraphCypher::CypherQueryCon if (has_union && has_union_all) { throw SemanticException("Invalid combination of UNION and UNION ALL."); } - cypher_query->cypher_unions_.push_back(child->accept(this).as()); + cypher_query->cypher_unions_.push_back(std::any_cast(child->accept(this))); } if (auto *memory_limit_ctx = ctx->queryMemoryLimit()) { @@ -196,7 +196,7 @@ antlrcpp::Any CypherMainVisitor::visitCypherQuery(MemgraphCypher::CypherQueryCon antlrcpp::Any CypherMainVisitor::visitIndexQuery(MemgraphCypher::IndexQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 1, "IndexQuery should have exactly one child!"); - auto *index_query = ctx->children[0]->accept(this).as(); + auto *index_query = std::any_cast(ctx->children[0]->accept(this)); query_ = index_query; return index_query; } @@ -204,9 +204,9 @@ antlrcpp::Any CypherMainVisitor::visitIndexQuery(MemgraphCypher::IndexQueryConte antlrcpp::Any CypherMainVisitor::visitCreateIndex(MemgraphCypher::CreateIndexContext *ctx) { auto *index_query = storage_->Create(); index_query->action_ = IndexQuery::Action::CREATE; - index_query->label_ = AddLabel(ctx->labelName()->accept(this)); + index_query->label_ = AddLabel(std::any_cast(ctx->labelName()->accept(this))); if (ctx->propertyKeyName()) { - PropertyIx name_key = ctx->propertyKeyName()->accept(this); + auto name_key = std::any_cast(ctx->propertyKeyName()->accept(this)); index_query->properties_ = {name_key}; } return index_query; @@ -216,16 +216,16 @@ antlrcpp::Any CypherMainVisitor::visitDropIndex(MemgraphCypher::DropIndexContext auto *index_query = storage_->Create(); index_query->action_ = IndexQuery::Action::DROP; if (ctx->propertyKeyName()) { - PropertyIx key = ctx->propertyKeyName()->accept(this); + auto key = std::any_cast(ctx->propertyKeyName()->accept(this)); index_query->properties_ = {key}; } - index_query->label_ = AddLabel(ctx->labelName()->accept(this)); + index_query->label_ = AddLabel(std::any_cast(ctx->labelName()->accept(this))); return index_query; } antlrcpp::Any CypherMainVisitor::visitAuthQuery(MemgraphCypher::AuthQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 1, "AuthQuery should have exactly one child!"); - auto *auth_query = ctx->children[0]->accept(this).as(); + auto *auth_query = std::any_cast(ctx->children[0]->accept(this)); query_ = auth_query; return auth_query; } @@ -238,7 +238,7 @@ antlrcpp::Any CypherMainVisitor::visitDumpQuery(MemgraphCypher::DumpQueryContext antlrcpp::Any CypherMainVisitor::visitReplicationQuery(MemgraphCypher::ReplicationQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 1, "ReplicationQuery should have exactly one child!"); - auto *replication_query = ctx->children[0]->accept(this).as(); + auto *replication_query = std::any_cast(ctx->children[0]->accept(this)); query_ = replication_query; return replication_query; } @@ -255,7 +255,7 @@ antlrcpp::Any CypherMainVisitor::visitSetReplicationRole(MemgraphCypher::SetRepl replication_query->role_ = ReplicationQuery::ReplicationRole::REPLICA; if (ctx->WITH() && ctx->PORT()) { if (ctx->port->numberLiteral() && ctx->port->numberLiteral()->integerLiteral()) { - replication_query->port_ = ctx->port->accept(this); + replication_query->port_ = std::any_cast(ctx->port->accept(this)); } else { throw SyntaxException("Port must be an integer literal!"); } @@ -272,7 +272,7 @@ antlrcpp::Any CypherMainVisitor::visitShowReplicationRole(MemgraphCypher::ShowRe antlrcpp::Any CypherMainVisitor::visitRegisterReplica(MemgraphCypher::RegisterReplicaContext *ctx) { auto *replication_query = storage_->Create(); replication_query->action_ = ReplicationQuery::Action::REGISTER_REPLICA; - replication_query->replica_name_ = ctx->replicaName()->symbolicName()->accept(this).as(); + replication_query->replica_name_ = std::any_cast(ctx->replicaName()->symbolicName()->accept(this)); if (ctx->SYNC()) { replication_query->sync_mode_ = memgraph::query::ReplicationQuery::SyncMode::SYNC; } else if (ctx->ASYNC()) { @@ -282,7 +282,7 @@ antlrcpp::Any CypherMainVisitor::visitRegisterReplica(MemgraphCypher::RegisterRe if (!ctx->socketAddress()->literal()->StringLiteral()) { throw SemanticException("Socket address should be a string literal!"); } else { - replication_query->socket_address_ = ctx->socketAddress()->accept(this); + replication_query->socket_address_ = std::any_cast(ctx->socketAddress()->accept(this)); } return replication_query; @@ -291,7 +291,7 @@ antlrcpp::Any CypherMainVisitor::visitRegisterReplica(MemgraphCypher::RegisterRe antlrcpp::Any CypherMainVisitor::visitDropReplica(MemgraphCypher::DropReplicaContext *ctx) { auto *replication_query = storage_->Create(); replication_query->action_ = ReplicationQuery::Action::DROP_REPLICA; - replication_query->replica_name_ = ctx->replicaName()->symbolicName()->accept(this).as(); + replication_query->replica_name_ = std::any_cast(ctx->replicaName()->symbolicName()->accept(this)); return replication_query; } @@ -321,7 +321,7 @@ antlrcpp::Any CypherMainVisitor::visitLoadCsv(MemgraphCypher::LoadCsvContext *ct auto *load_csv = storage_->Create(); // handle file name if (ctx->csvFile()->literal()->StringLiteral()) { - load_csv->file_ = ctx->csvFile()->accept(this); + load_csv->file_ = std::any_cast(ctx->csvFile()->accept(this)); } else { throw SemanticException("CSV file path should be a string literal"); } @@ -338,7 +338,7 @@ antlrcpp::Any CypherMainVisitor::visitLoadCsv(MemgraphCypher::LoadCsvContext *ct // handle delimiter if (ctx->DELIMITER()) { if (ctx->delimiter()->literal()->StringLiteral()) { - load_csv->delimiter_ = ctx->delimiter()->accept(this); + load_csv->delimiter_ = std::any_cast(ctx->delimiter()->accept(this)); } else { throw SemanticException("Delimiter should be a string literal"); } @@ -347,14 +347,15 @@ antlrcpp::Any CypherMainVisitor::visitLoadCsv(MemgraphCypher::LoadCsvContext *ct // handle quote if (ctx->QUOTE()) { if (ctx->quote()->literal()->StringLiteral()) { - load_csv->quote_ = ctx->quote()->accept(this); + load_csv->quote_ = std::any_cast(ctx->quote()->accept(this)); } else { throw SemanticException("Quote should be a string literal"); } } // handle row variable - load_csv->row_var_ = storage_->Create(ctx->rowVar()->variable()->accept(this).as()); + load_csv->row_var_ = + storage_->Create(std::any_cast(ctx->rowVar()->variable()->accept(this))); return load_csv; } @@ -367,7 +368,7 @@ antlrcpp::Any CypherMainVisitor::visitFreeMemoryQuery(MemgraphCypher::FreeMemory antlrcpp::Any CypherMainVisitor::visitTriggerQuery(MemgraphCypher::TriggerQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 1, "TriggerQuery should have exactly one child!"); - auto *trigger_query = ctx->children[0]->accept(this).as(); + auto *trigger_query = std::any_cast(ctx->children[0]->accept(this)); query_ = trigger_query; return trigger_query; } @@ -375,7 +376,7 @@ antlrcpp::Any CypherMainVisitor::visitTriggerQuery(MemgraphCypher::TriggerQueryC antlrcpp::Any CypherMainVisitor::visitCreateTrigger(MemgraphCypher::CreateTriggerContext *ctx) { auto *trigger_query = storage_->Create(); trigger_query->action_ = TriggerQuery::Action::CREATE_TRIGGER; - trigger_query->trigger_name_ = ctx->triggerName()->symbolicName()->accept(this).as(); + trigger_query->trigger_name_ = std::any_cast(ctx->triggerName()->symbolicName()->accept(this)); auto *statement = ctx->triggerStatement(); antlr4::misc::Interval interval{statement->start->getStartIndex(), statement->stop->getStopIndex()}; @@ -427,7 +428,7 @@ antlrcpp::Any CypherMainVisitor::visitCreateTrigger(MemgraphCypher::CreateTrigge antlrcpp::Any CypherMainVisitor::visitDropTrigger(MemgraphCypher::DropTriggerContext *ctx) { auto *trigger_query = storage_->Create(); trigger_query->action_ = TriggerQuery::Action::DROP_TRIGGER; - trigger_query->trigger_name_ = ctx->triggerName()->symbolicName()->accept(this).as(); + trigger_query->trigger_name_ = std::any_cast(ctx->triggerName()->symbolicName()->accept(this)); return trigger_query; } @@ -471,14 +472,14 @@ antlrcpp::Any CypherMainVisitor::visitCreateSnapshotQuery(MemgraphCypher::Create antlrcpp::Any CypherMainVisitor::visitStreamQuery(MemgraphCypher::StreamQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 1, "StreamQuery should have exactly one child!"); - auto *stream_query = ctx->children[0]->accept(this).as(); + auto *stream_query = std::any_cast(ctx->children[0]->accept(this)); query_ = stream_query; return stream_query; } antlrcpp::Any CypherMainVisitor::visitCreateStream(MemgraphCypher::CreateStreamContext *ctx) { MG_ASSERT(ctx->children.size() == 1, "CreateStreamQuery should have exactly one child!"); - auto *stream_query = ctx->children[0]->accept(this).as(); + auto *stream_query = std::any_cast(ctx->children[0]->accept(this)); query_ = stream_query; return stream_query; } @@ -570,7 +571,8 @@ void MapCommonStreamConfigs(auto &memory, StreamQuery &stream_query) { antlrcpp::Any CypherMainVisitor::visitConfigKeyValuePair(MemgraphCypher::ConfigKeyValuePairContext *ctx) { MG_ASSERT(ctx->literal().size() == 2); - return std::pair{ctx->literal(0)->accept(this).as(), ctx->literal(1)->accept(this).as()}; + return std::pair{std::any_cast(ctx->literal(0)->accept(this)), + std::any_cast(ctx->literal(1)->accept(this))}; } antlrcpp::Any CypherMainVisitor::visitConfigMap(MemgraphCypher::ConfigMapContext *ctx) { @@ -578,7 +580,7 @@ antlrcpp::Any CypherMainVisitor::visitConfigMap(MemgraphCypher::ConfigMapContext for (auto *key_value_pair : ctx->configKeyValuePair()) { // If the queries are cached, then only the stripped query is parsed, so the actual keys cannot be determined // here. That means duplicates cannot be checked. - map.insert(key_value_pair->accept(this).as>()); + map.insert(std::any_cast>(key_value_pair->accept(this))); } return map; } @@ -587,7 +589,7 @@ antlrcpp::Any CypherMainVisitor::visitKafkaCreateStream(MemgraphCypher::KafkaCre auto *stream_query = storage_->Create(); stream_query->action_ = StreamQuery::Action::CREATE_STREAM; stream_query->type_ = StreamQuery::Type::KAFKA; - stream_query->stream_name_ = ctx->streamName()->symbolicName()->accept(this).as(); + stream_query->stream_name_ = std::any_cast(ctx->streamName()->symbolicName()->accept(this)); for (auto *create_config_ctx : ctx->kafkaCreateStreamConfig()) { create_config_ctx->accept(this); @@ -623,7 +625,7 @@ void GetTopicNames(auto &destination, MemgraphCypher::TopicNamesContext *topic_n if (!topic_names_ctx->literal()->StringLiteral()) { throw SemanticException("Topic names should be defined as a string literal or as symbolic names"); } - destination = topic_names_ctx->accept(&visitor).as(); + destination = std::any_cast(topic_names_ctx->accept(&visitor)); } } } // namespace @@ -650,7 +652,8 @@ antlrcpp::Any CypherMainVisitor::visitKafkaCreateStreamConfig(MemgraphCypher::Ka if (ctx->CONFIGS()) { ThrowIfExists(memory_, KafkaConfigKey::CONFIGS); static constexpr auto configs_key = static_cast(KafkaConfigKey::CONFIGS); - memory_.emplace(configs_key, ctx->configsMap->accept(this).as>()); + memory_.emplace(configs_key, + std::any_cast>(ctx->configsMap->accept(this))); return {}; } @@ -658,7 +661,7 @@ antlrcpp::Any CypherMainVisitor::visitKafkaCreateStreamConfig(MemgraphCypher::Ka ThrowIfExists(memory_, KafkaConfigKey::CREDENTIALS); static constexpr auto credentials_key = static_cast(KafkaConfigKey::CREDENTIALS); memory_.emplace(credentials_key, - ctx->credentialsMap->accept(this).as>()); + std::any_cast>(ctx->credentialsMap->accept(this))); return {}; } @@ -669,7 +672,7 @@ antlrcpp::Any CypherMainVisitor::visitKafkaCreateStreamConfig(MemgraphCypher::Ka } const auto bootstrap_servers_key = static_cast(KafkaConfigKey::BOOTSTRAP_SERVERS); - memory_[bootstrap_servers_key] = ctx->bootstrapServers->accept(this).as(); + memory_[bootstrap_servers_key] = std::any_cast(ctx->bootstrapServers->accept(this)); return {}; } @@ -690,7 +693,7 @@ antlrcpp::Any CypherMainVisitor::visitPulsarCreateStream(MemgraphCypher::PulsarC auto *stream_query = storage_->Create(); stream_query->action_ = StreamQuery::Action::CREATE_STREAM; stream_query->type_ = StreamQuery::Type::PULSAR; - stream_query->stream_name_ = ctx->streamName()->symbolicName()->accept(this).as(); + stream_query->stream_name_ = std::any_cast(ctx->streamName()->symbolicName()->accept(this)); for (auto *create_config_ctx : ctx->pulsarCreateStreamConfig()) { create_config_ctx->accept(this); @@ -722,7 +725,7 @@ antlrcpp::Any CypherMainVisitor::visitPulsarCreateStreamConfig(MemgraphCypher::P throw SemanticException("Service URL must be a string!"); } const auto service_url_key = static_cast(PulsarConfigKey::SERVICE_URL); - memory_[service_url_key] = ctx->serviceUrl->accept(this).as(); + memory_[service_url_key] = std::any_cast(ctx->serviceUrl->accept(this)); return {}; } @@ -740,7 +743,7 @@ antlrcpp::Any CypherMainVisitor::visitCommonCreateStreamConfig(MemgraphCypher::C throw SemanticException("Batch interval must be an integer literal!"); } const auto batch_interval_key = static_cast(CommonStreamConfigKey::BATCH_INTERVAL); - memory_[batch_interval_key] = ctx->batchInterval->accept(this).as(); + memory_[batch_interval_key] = std::any_cast(ctx->batchInterval->accept(this)); return {}; } @@ -750,14 +753,14 @@ antlrcpp::Any CypherMainVisitor::visitCommonCreateStreamConfig(MemgraphCypher::C throw SemanticException("Batch size must be an integer literal!"); } const auto batch_size_key = static_cast(CommonStreamConfigKey::BATCH_SIZE); - memory_[batch_size_key] = ctx->batchSize->accept(this).as(); + memory_[batch_size_key] = std::any_cast(ctx->batchSize->accept(this)); return {}; } antlrcpp::Any CypherMainVisitor::visitDropStream(MemgraphCypher::DropStreamContext *ctx) { auto *stream_query = storage_->Create(); stream_query->action_ = StreamQuery::Action::DROP_STREAM; - stream_query->stream_name_ = ctx->streamName()->symbolicName()->accept(this).as(); + stream_query->stream_name_ = std::any_cast(ctx->streamName()->symbolicName()->accept(this)); return stream_query; } @@ -769,7 +772,7 @@ antlrcpp::Any CypherMainVisitor::visitStartStream(MemgraphCypher::StartStreamCon if (!ctx->batchLimit->numberLiteral() || !ctx->batchLimit->numberLiteral()->integerLiteral()) { throw SemanticException("Batch limit should be an integer literal!"); } - stream_query->batch_limit_ = ctx->batchLimit->accept(this); + stream_query->batch_limit_ = std::any_cast(ctx->batchLimit->accept(this)); } if (ctx->TIMEOUT()) { if (!ctx->timeout->numberLiteral() || !ctx->timeout->numberLiteral()->integerLiteral()) { @@ -778,10 +781,10 @@ antlrcpp::Any CypherMainVisitor::visitStartStream(MemgraphCypher::StartStreamCon if (!ctx->BATCH_LIMIT()) { throw SemanticException("Parameter TIMEOUT can only be defined if BATCH_LIMIT is defined"); } - stream_query->timeout_ = ctx->timeout->accept(this); + stream_query->timeout_ = std::any_cast(ctx->timeout->accept(this)); } - stream_query->stream_name_ = ctx->streamName()->symbolicName()->accept(this).as(); + stream_query->stream_name_ = std::any_cast(ctx->streamName()->symbolicName()->accept(this)); return stream_query; } @@ -794,7 +797,7 @@ antlrcpp::Any CypherMainVisitor::visitStartAllStreams(MemgraphCypher::StartAllSt antlrcpp::Any CypherMainVisitor::visitStopStream(MemgraphCypher::StopStreamContext *ctx) { auto *stream_query = storage_->Create(); stream_query->action_ = StreamQuery::Action::STOP_STREAM; - stream_query->stream_name_ = ctx->streamName()->symbolicName()->accept(this).as(); + stream_query->stream_name_ = std::any_cast(ctx->streamName()->symbolicName()->accept(this)); return stream_query; } @@ -813,26 +816,26 @@ antlrcpp::Any CypherMainVisitor::visitShowStreams(MemgraphCypher::ShowStreamsCon antlrcpp::Any CypherMainVisitor::visitCheckStream(MemgraphCypher::CheckStreamContext *ctx) { auto *stream_query = storage_->Create(); stream_query->action_ = StreamQuery::Action::CHECK_STREAM; - stream_query->stream_name_ = ctx->streamName()->symbolicName()->accept(this).as(); + stream_query->stream_name_ = std::any_cast(ctx->streamName()->symbolicName()->accept(this)); if (ctx->BATCH_LIMIT()) { if (!ctx->batchLimit->numberLiteral() || !ctx->batchLimit->numberLiteral()->integerLiteral()) { throw SemanticException("Batch limit should be an integer literal!"); } - stream_query->batch_limit_ = ctx->batchLimit->accept(this); + stream_query->batch_limit_ = std::any_cast(ctx->batchLimit->accept(this)); } if (ctx->TIMEOUT()) { if (!ctx->timeout->numberLiteral() || !ctx->timeout->numberLiteral()->integerLiteral()) { throw SemanticException("Timeout should be an integer literal!"); } - stream_query->timeout_ = ctx->timeout->accept(this); + stream_query->timeout_ = std::any_cast(ctx->timeout->accept(this)); } return stream_query; } antlrcpp::Any CypherMainVisitor::visitSettingQuery(MemgraphCypher::SettingQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 1, "SettingQuery should have exactly one child!"); - auto *setting_query = ctx->children[0]->accept(this).as(); + auto *setting_query = std::any_cast(ctx->children[0]->accept(this)); query_ = setting_query; return setting_query; } @@ -849,10 +852,10 @@ antlrcpp::Any CypherMainVisitor::visitSetSetting(MemgraphCypher::SetSettingConte throw SemanticException("Setting value should be a string literal"); } - setting_query->setting_name_ = ctx->settingName()->accept(this); + setting_query->setting_name_ = std::any_cast(ctx->settingName()->accept(this)); MG_ASSERT(setting_query->setting_name_); - setting_query->setting_value_ = ctx->settingValue()->accept(this); + setting_query->setting_value_ = std::any_cast(ctx->settingValue()->accept(this)); MG_ASSERT(setting_query->setting_value_); return setting_query; } @@ -865,7 +868,7 @@ antlrcpp::Any CypherMainVisitor::visitShowSetting(MemgraphCypher::ShowSettingCon throw SemanticException("Setting name should be a string literal"); } - setting_query->setting_name_ = ctx->settingName()->accept(this); + setting_query->setting_name_ = std::any_cast(ctx->settingName()->accept(this)); MG_ASSERT(setting_query->setting_name_); return setting_query; @@ -887,7 +890,7 @@ antlrcpp::Any CypherMainVisitor::visitCypherUnion(MemgraphCypher::CypherUnionCon bool distinct = !ctx->ALL(); auto *cypher_union = storage_->Create(distinct); DMG_ASSERT(ctx->singleQuery(), "Expected single query."); - cypher_union->single_query_ = ctx->singleQuery()->accept(this).as(); + cypher_union->single_query_ = std::any_cast(ctx->singleQuery()->accept(this)); return cypher_union; } @@ -895,10 +898,10 @@ antlrcpp::Any CypherMainVisitor::visitSingleQuery(MemgraphCypher::SingleQueryCon auto *single_query = storage_->Create(); for (auto *child : ctx->clause()) { antlrcpp::Any got = child->accept(this); - if (got.is()) { - single_query->clauses_.push_back(got.as()); + if (got.type() == typeid(Clause *)) { + single_query->clauses_.push_back(std::any_cast(got)); } else { - auto child_clauses = got.as>(); + auto child_clauses = std::any_cast>(got); single_query->clauses_.insert(single_query->clauses_.end(), child_clauses.begin(), child_clauses.end()); } } @@ -1010,42 +1013,42 @@ antlrcpp::Any CypherMainVisitor::visitSingleQuery(MemgraphCypher::SingleQueryCon antlrcpp::Any CypherMainVisitor::visitClause(MemgraphCypher::ClauseContext *ctx) { if (ctx->cypherReturn()) { - return static_cast(ctx->cypherReturn()->accept(this).as()); + return static_cast(std::any_cast(ctx->cypherReturn()->accept(this))); } if (ctx->cypherMatch()) { - return static_cast(ctx->cypherMatch()->accept(this).as()); + return static_cast(std::any_cast(ctx->cypherMatch()->accept(this))); } if (ctx->create()) { - return static_cast(ctx->create()->accept(this).as()); + return static_cast(std::any_cast(ctx->create()->accept(this))); } if (ctx->cypherDelete()) { - return static_cast(ctx->cypherDelete()->accept(this).as()); + return static_cast(std::any_cast(ctx->cypherDelete()->accept(this))); } if (ctx->set()) { // Different return type!!! - return ctx->set()->accept(this).as>(); + return std::any_cast>(ctx->set()->accept(this)); } if (ctx->remove()) { // Different return type!!! - return ctx->remove()->accept(this).as>(); + return std::any_cast>(ctx->remove()->accept(this)); } if (ctx->with()) { - return static_cast(ctx->with()->accept(this).as()); + return static_cast(std::any_cast(ctx->with()->accept(this))); } if (ctx->merge()) { - return static_cast(ctx->merge()->accept(this).as()); + return static_cast(std::any_cast(ctx->merge()->accept(this))); } if (ctx->unwind()) { - return static_cast(ctx->unwind()->accept(this).as()); + return static_cast(std::any_cast(ctx->unwind()->accept(this))); } if (ctx->callProcedure()) { - return static_cast(ctx->callProcedure()->accept(this).as()); + return static_cast(std::any_cast(ctx->callProcedure()->accept(this))); } if (ctx->loadCsv()) { - return static_cast(ctx->loadCsv()->accept(this).as()); + return static_cast(std::any_cast(ctx->loadCsv()->accept(this))); } if (ctx->foreach ()) { - return static_cast(ctx->foreach ()->accept(this).as()); + return static_cast(std::any_cast(ctx->foreach ()->accept(this))); } // TODO: implement other clauses. throw utils::NotYetImplemented("clause '{}'", ctx->getText()); @@ -1056,15 +1059,15 @@ antlrcpp::Any CypherMainVisitor::visitCypherMatch(MemgraphCypher::CypherMatchCon auto *match = storage_->Create(); match->optional_ = !!ctx->OPTIONAL(); if (ctx->where()) { - match->where_ = ctx->where()->accept(this); + match->where_ = std::any_cast(ctx->where()->accept(this)); } - match->patterns_ = ctx->pattern()->accept(this).as>(); + match->patterns_ = std::any_cast>(ctx->pattern()->accept(this)); return match; } antlrcpp::Any CypherMainVisitor::visitCreate(MemgraphCypher::CreateContext *ctx) { auto *create = storage_->Create(); - create->patterns_ = ctx->pattern()->accept(this).as>(); + create->patterns_ = std::any_cast>(ctx->pattern()->accept(this)); return create; } @@ -1082,7 +1085,7 @@ antlrcpp::Any CypherMainVisitor::visitCallProcedure(MemgraphCypher::CallProcedur call_proc->procedure_name_ = JoinSymbolicNames(this, ctx->procedureName()->symbolicName()); call_proc->arguments_.reserve(ctx->expression().size()); for (auto *expr : ctx->expression()) { - call_proc->arguments_.push_back(expr->accept(this)); + call_proc->arguments_.push_back(std::any_cast(expr->accept(this))); } if (auto *memory_limit_ctx = ctx->procedureMemoryLimit()) { @@ -1122,12 +1125,12 @@ antlrcpp::Any CypherMainVisitor::visitCallProcedure(MemgraphCypher::CallProcedur call_proc->result_identifiers_.reserve(yield_ctx->procedureResult().size()); for (auto *result : yield_ctx->procedureResult()) { MG_ASSERT(result->variable().size() == 1 || result->variable().size() == 2); - call_proc->result_fields_.push_back(result->variable()[0]->accept(this).as()); + call_proc->result_fields_.push_back(std::any_cast(result->variable()[0]->accept(this))); std::string result_alias; if (result->variable().size() == 2) { - result_alias = result->variable()[1]->accept(this).as(); + result_alias = std::any_cast(result->variable()[1]->accept(this)); } else { - result_alias = result->variable()[0]->accept(this).as(); + result_alias = std::any_cast(result->variable()[0]->accept(this)); } call_proc->result_identifiers_.push_back(storage_->Create(result_alias)); } @@ -1163,7 +1166,7 @@ antlrcpp::Any CypherMainVisitor::visitCallProcedure(MemgraphCypher::CallProcedur * @return std::string */ antlrcpp::Any CypherMainVisitor::visitUserOrRoleName(MemgraphCypher::UserOrRoleNameContext *ctx) { - return ctx->symbolicName()->accept(this).as(); + return std::any_cast(ctx->symbolicName()->accept(this)); } /** @@ -1172,7 +1175,7 @@ antlrcpp::Any CypherMainVisitor::visitUserOrRoleName(MemgraphCypher::UserOrRoleN antlrcpp::Any CypherMainVisitor::visitCreateRole(MemgraphCypher::CreateRoleContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::CREATE_ROLE; - auth->role_ = ctx->role->accept(this).as(); + auth->role_ = std::any_cast(ctx->role->accept(this)); return auth; } @@ -1182,7 +1185,7 @@ antlrcpp::Any CypherMainVisitor::visitCreateRole(MemgraphCypher::CreateRoleConte antlrcpp::Any CypherMainVisitor::visitDropRole(MemgraphCypher::DropRoleContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::DROP_ROLE; - auth->role_ = ctx->role->accept(this).as(); + auth->role_ = std::any_cast(ctx->role->accept(this)); return auth; } @@ -1201,12 +1204,12 @@ antlrcpp::Any CypherMainVisitor::visitShowRoles(MemgraphCypher::ShowRolesContext antlrcpp::Any CypherMainVisitor::visitCreateUser(MemgraphCypher::CreateUserContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::CREATE_USER; - auth->user_ = ctx->user->accept(this).as(); + auth->user_ = std::any_cast(ctx->user->accept(this)); if (ctx->password) { if (!ctx->password->StringLiteral() && !ctx->literal()->CYPHERNULL()) { throw SyntaxException("Password should be a string literal or null."); } - auth->password_ = ctx->password->accept(this); + auth->password_ = std::any_cast(ctx->password->accept(this)); } return auth; } @@ -1217,11 +1220,11 @@ antlrcpp::Any CypherMainVisitor::visitCreateUser(MemgraphCypher::CreateUserConte antlrcpp::Any CypherMainVisitor::visitSetPassword(MemgraphCypher::SetPasswordContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::SET_PASSWORD; - auth->user_ = ctx->user->accept(this).as(); + auth->user_ = std::any_cast(ctx->user->accept(this)); if (!ctx->password->StringLiteral() && !ctx->literal()->CYPHERNULL()) { throw SyntaxException("Password should be a string literal or null."); } - auth->password_ = ctx->password->accept(this); + auth->password_ = std::any_cast(ctx->password->accept(this)); return auth; } @@ -1231,7 +1234,7 @@ antlrcpp::Any CypherMainVisitor::visitSetPassword(MemgraphCypher::SetPasswordCon antlrcpp::Any CypherMainVisitor::visitDropUser(MemgraphCypher::DropUserContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::DROP_USER; - auth->user_ = ctx->user->accept(this).as(); + auth->user_ = std::any_cast(ctx->user->accept(this)); return auth; } @@ -1250,8 +1253,8 @@ antlrcpp::Any CypherMainVisitor::visitShowUsers(MemgraphCypher::ShowUsersContext antlrcpp::Any CypherMainVisitor::visitSetRole(MemgraphCypher::SetRoleContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::SET_ROLE; - auth->user_ = ctx->user->accept(this).as(); - auth->role_ = ctx->role->accept(this).as(); + auth->user_ = std::any_cast(ctx->user->accept(this)); + auth->role_ = std::any_cast(ctx->role->accept(this)); return auth; } @@ -1261,7 +1264,7 @@ antlrcpp::Any CypherMainVisitor::visitSetRole(MemgraphCypher::SetRoleContext *ct antlrcpp::Any CypherMainVisitor::visitClearRole(MemgraphCypher::ClearRoleContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::CLEAR_ROLE; - auth->user_ = ctx->user->accept(this).as(); + auth->user_ = std::any_cast(ctx->user->accept(this)); return auth; } @@ -1271,10 +1274,10 @@ antlrcpp::Any CypherMainVisitor::visitClearRole(MemgraphCypher::ClearRoleContext antlrcpp::Any CypherMainVisitor::visitGrantPrivilege(MemgraphCypher::GrantPrivilegeContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::GRANT_PRIVILEGE; - auth->user_or_role_ = ctx->userOrRole->accept(this).as(); + auth->user_or_role_ = std::any_cast(ctx->userOrRole->accept(this)); if (ctx->privilegeList()) { for (auto *privilege : ctx->privilegeList()->privilege()) { - auth->privileges_.push_back(privilege->accept(this)); + auth->privileges_.push_back(std::any_cast(privilege->accept(this))); } } else { /* grant all privileges */ @@ -1289,10 +1292,10 @@ antlrcpp::Any CypherMainVisitor::visitGrantPrivilege(MemgraphCypher::GrantPrivil antlrcpp::Any CypherMainVisitor::visitDenyPrivilege(MemgraphCypher::DenyPrivilegeContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::DENY_PRIVILEGE; - auth->user_or_role_ = ctx->userOrRole->accept(this).as(); + auth->user_or_role_ = std::any_cast(ctx->userOrRole->accept(this)); if (ctx->privilegeList()) { for (auto *privilege : ctx->privilegeList()->privilege()) { - auth->privileges_.push_back(privilege->accept(this)); + auth->privileges_.push_back(std::any_cast(privilege->accept(this))); } } else { /* deny all privileges */ @@ -1307,10 +1310,10 @@ antlrcpp::Any CypherMainVisitor::visitDenyPrivilege(MemgraphCypher::DenyPrivileg antlrcpp::Any CypherMainVisitor::visitRevokePrivilege(MemgraphCypher::RevokePrivilegeContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::REVOKE_PRIVILEGE; - auth->user_or_role_ = ctx->userOrRole->accept(this).as(); + auth->user_or_role_ = std::any_cast(ctx->userOrRole->accept(this)); if (ctx->privilegeList()) { for (auto *privilege : ctx->privilegeList()->privilege()) { - auth->privileges_.push_back(privilege->accept(this)); + auth->privileges_.push_back(std::any_cast(privilege->accept(this))); } } else { /* revoke all privileges */ @@ -1353,7 +1356,7 @@ antlrcpp::Any CypherMainVisitor::visitPrivilege(MemgraphCypher::PrivilegeContext antlrcpp::Any CypherMainVisitor::visitShowPrivileges(MemgraphCypher::ShowPrivilegesContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::SHOW_PRIVILEGES; - auth->user_or_role_ = ctx->userOrRole->accept(this).as(); + auth->user_or_role_ = std::any_cast(ctx->userOrRole->accept(this)); return auth; } @@ -1363,7 +1366,7 @@ antlrcpp::Any CypherMainVisitor::visitShowPrivileges(MemgraphCypher::ShowPrivile antlrcpp::Any CypherMainVisitor::visitShowRoleForUser(MemgraphCypher::ShowRoleForUserContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::SHOW_ROLE_FOR_USER; - auth->user_ = ctx->user->accept(this).as(); + auth->user_ = std::any_cast(ctx->user->accept(this)); return auth; } @@ -1373,13 +1376,13 @@ antlrcpp::Any CypherMainVisitor::visitShowRoleForUser(MemgraphCypher::ShowRoleFo antlrcpp::Any CypherMainVisitor::visitShowUsersForRole(MemgraphCypher::ShowUsersForRoleContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::SHOW_USERS_FOR_ROLE; - auth->role_ = ctx->role->accept(this).as(); + auth->role_ = std::any_cast(ctx->role->accept(this)); return auth; } antlrcpp::Any CypherMainVisitor::visitCypherReturn(MemgraphCypher::CypherReturnContext *ctx) { auto *return_clause = storage_->Create(); - return_clause->body_ = ctx->returnBody()->accept(this); + return_clause->body_ = std::any_cast(ctx->returnBody()->accept(this)); if (ctx->DISTINCT()) { return_clause->body_.distinct = true; } @@ -1389,23 +1392,23 @@ antlrcpp::Any CypherMainVisitor::visitCypherReturn(MemgraphCypher::CypherReturnC antlrcpp::Any CypherMainVisitor::visitReturnBody(MemgraphCypher::ReturnBodyContext *ctx) { ReturnBody body; if (ctx->order()) { - body.order_by = ctx->order()->accept(this).as>(); + body.order_by = std::any_cast>(ctx->order()->accept(this)); } if (ctx->skip()) { - body.skip = static_cast(ctx->skip()->accept(this)); + body.skip = static_cast(std::any_cast(ctx->skip()->accept(this))); } if (ctx->limit()) { - body.limit = static_cast(ctx->limit()->accept(this)); + body.limit = static_cast(std::any_cast(ctx->limit()->accept(this))); } std::tie(body.all_identifiers, body.named_expressions) = - ctx->returnItems()->accept(this).as>>(); + std::any_cast>>(ctx->returnItems()->accept(this)); return body; } antlrcpp::Any CypherMainVisitor::visitReturnItems(MemgraphCypher::ReturnItemsContext *ctx) { std::vector named_expressions; for (auto *item : ctx->returnItem()) { - named_expressions.push_back(item->accept(this)); + named_expressions.push_back(std::any_cast(item->accept(this))); } return std::pair>(ctx->getTokens(MemgraphCypher::ASTERISK).size(), named_expressions); @@ -1413,10 +1416,10 @@ antlrcpp::Any CypherMainVisitor::visitReturnItems(MemgraphCypher::ReturnItemsCon antlrcpp::Any CypherMainVisitor::visitReturnItem(MemgraphCypher::ReturnItemContext *ctx) { auto *named_expr = storage_->Create(); - named_expr->expression_ = ctx->expression()->accept(this); + named_expr->expression_ = std::any_cast(ctx->expression()->accept(this)); MG_ASSERT(named_expr->expression_); if (ctx->variable()) { - named_expr->name_ = std::string(ctx->variable()->accept(this).as()); + named_expr->name_ = std::string(std::any_cast(ctx->variable()->accept(this))); users_identifiers.insert(named_expr->name_); } else { if (in_with_ && !utils::IsSubtype(*named_expr->expression_, Identifier::kType)) { @@ -1431,33 +1434,34 @@ antlrcpp::Any CypherMainVisitor::visitReturnItem(MemgraphCypher::ReturnItemConte antlrcpp::Any CypherMainVisitor::visitOrder(MemgraphCypher::OrderContext *ctx) { std::vector order_by; for (auto *sort_item : ctx->sortItem()) { - order_by.push_back(sort_item->accept(this)); + order_by.push_back(std::any_cast(sort_item->accept(this))); } return order_by; } antlrcpp::Any CypherMainVisitor::visitSortItem(MemgraphCypher::SortItemContext *ctx) { - return SortItem{ctx->DESC() || ctx->DESCENDING() ? Ordering::DESC : Ordering::ASC, ctx->expression()->accept(this)}; + return SortItem{ctx->DESC() || ctx->DESCENDING() ? Ordering::DESC : Ordering::ASC, + std::any_cast(ctx->expression()->accept(this))}; } antlrcpp::Any CypherMainVisitor::visitNodePattern(MemgraphCypher::NodePatternContext *ctx) { auto *node = storage_->Create(); if (ctx->variable()) { - std::string variable = ctx->variable()->accept(this); + auto variable = std::any_cast(ctx->variable()->accept(this)); node->identifier_ = storage_->Create(variable); users_identifiers.insert(variable); } else { anonymous_identifiers.push_back(&node->identifier_); } if (ctx->nodeLabels()) { - node->labels_ = ctx->nodeLabels()->accept(this).as>(); + node->labels_ = std::any_cast>(ctx->nodeLabels()->accept(this)); } if (ctx->properties()) { // This can return either properties or parameters if (ctx->properties()->mapLiteral()) { - node->properties_ = ctx->properties()->accept(this).as>(); + node->properties_ = std::any_cast>(ctx->properties()->accept(this)); } else { - node->properties_ = ctx->properties()->accept(this).as(); + node->properties_ = std::any_cast(ctx->properties()->accept(this)); } } return node; @@ -1466,7 +1470,7 @@ antlrcpp::Any CypherMainVisitor::visitNodePattern(MemgraphCypher::NodePatternCon antlrcpp::Any CypherMainVisitor::visitNodeLabels(MemgraphCypher::NodeLabelsContext *ctx) { std::vector labels; for (auto *node_label : ctx->nodeLabel()) { - labels.push_back(AddLabel(node_label->accept(this))); + labels.push_back(AddLabel(std::any_cast(node_label->accept(this)))); } return labels; } @@ -1483,8 +1487,8 @@ antlrcpp::Any CypherMainVisitor::visitProperties(MemgraphCypher::PropertiesConte antlrcpp::Any CypherMainVisitor::visitMapLiteral(MemgraphCypher::MapLiteralContext *ctx) { std::unordered_map map; for (int i = 0; i < static_cast(ctx->propertyKeyName().size()); ++i) { - PropertyIx key = ctx->propertyKeyName()[i]->accept(this); - Expression *value = ctx->expression()[i]->accept(this); + auto key = std::any_cast(ctx->propertyKeyName()[i]->accept(this)); + auto *value = std::any_cast(ctx->expression()[i]->accept(this)); if (!map.insert({key, value}).second) { throw SemanticException("Same key can't appear twice in a map literal."); } @@ -1494,12 +1498,14 @@ antlrcpp::Any CypherMainVisitor::visitMapLiteral(MemgraphCypher::MapLiteralConte antlrcpp::Any CypherMainVisitor::visitListLiteral(MemgraphCypher::ListLiteralContext *ctx) { std::vector expressions; - for (auto expr_ctx_ptr : ctx->expression()) expressions.push_back(expr_ctx_ptr->accept(this)); + for (auto *expr_ctx : ctx->expression()) { + expressions.push_back(std::any_cast(expr_ctx->accept(this))); + } return expressions; } antlrcpp::Any CypherMainVisitor::visitPropertyKeyName(MemgraphCypher::PropertyKeyNameContext *ctx) { - return AddProperty(visitChildren(ctx)); + return AddProperty(std::any_cast(visitChildren(ctx))); } antlrcpp::Any CypherMainVisitor::visitSymbolicName(MemgraphCypher::SymbolicNameContext *ctx) { @@ -1537,15 +1543,15 @@ antlrcpp::Any CypherMainVisitor::visitSymbolicName(MemgraphCypher::SymbolicNameC antlrcpp::Any CypherMainVisitor::visitPattern(MemgraphCypher::PatternContext *ctx) { std::vector patterns; for (auto *pattern_part : ctx->patternPart()) { - patterns.push_back(pattern_part->accept(this)); + patterns.push_back(std::any_cast(pattern_part->accept(this))); } return patterns; } antlrcpp::Any CypherMainVisitor::visitPatternPart(MemgraphCypher::PatternPartContext *ctx) { - Pattern *pattern = ctx->anonymousPatternPart()->accept(this); + auto *pattern = std::any_cast(ctx->anonymousPatternPart()->accept(this)); if (ctx->variable()) { - std::string variable = ctx->variable()->accept(this); + auto variable = std::any_cast(ctx->variable()->accept(this)); pattern->identifier_ = storage_->Create(variable); users_identifiers.insert(variable); } else { @@ -1558,10 +1564,10 @@ antlrcpp::Any CypherMainVisitor::visitPatternElement(MemgraphCypher::PatternElem if (ctx->patternElement()) { return ctx->patternElement()->accept(this); } - auto pattern = storage_->Create(); - pattern->atoms_.push_back(ctx->nodePattern()->accept(this).as()); + auto *pattern = storage_->Create(); + pattern->atoms_.push_back(std::any_cast(ctx->nodePattern()->accept(this))); for (auto *pattern_element_chain : ctx->patternElementChain()) { - std::pair element = pattern_element_chain->accept(this); + auto element = std::any_cast>(pattern_element_chain->accept(this)); pattern->atoms_.push_back(element.first); pattern->atoms_.push_back(element.second); } @@ -1569,8 +1575,8 @@ antlrcpp::Any CypherMainVisitor::visitPatternElement(MemgraphCypher::PatternElem } antlrcpp::Any CypherMainVisitor::visitPatternElementChain(MemgraphCypher::PatternElementChainContext *ctx) { - return std::pair(ctx->relationshipPattern()->accept(this).as(), - ctx->nodePattern()->accept(this).as()); + return std::pair(std::any_cast(ctx->relationshipPattern()->accept(this)), + std::any_cast(ctx->nodePattern()->accept(this))); } antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(MemgraphCypher::RelationshipPatternContext *ctx) { @@ -1581,7 +1587,7 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(MemgraphCypher::Relati edge->type_ = EdgeAtom::Type::SINGLE; if (variableExpansion) std::tie(edge->type_, edge->lower_bound_, edge->upper_bound_) = - variableExpansion->accept(this).as>(); + std::any_cast>(variableExpansion->accept(this)); if (ctx->leftArrowHead() && !ctx->rightArrowHead()) { edge->direction_ = EdgeAtom::Direction::IN; @@ -1599,7 +1605,7 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(MemgraphCypher::Relati } if (relationshipDetail->name) { - std::string variable = relationshipDetail->name->accept(this); + auto variable = std::any_cast(relationshipDetail->name->accept(this)); edge->identifier_ = storage_->Create(variable); users_identifiers.insert(variable); } else { @@ -1607,7 +1613,8 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(MemgraphCypher::Relati } if (relationshipDetail->relationshipTypes()) { - edge->edge_types_ = ctx->relationshipDetail()->relationshipTypes()->accept(this).as>(); + edge->edge_types_ = + std::any_cast>(ctx->relationshipDetail()->relationshipTypes()->accept(this)); } auto relationshipLambdas = relationshipDetail->relationshipLambda(); @@ -1618,16 +1625,16 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(MemgraphCypher::Relati "path expansion."); auto visit_lambda = [this](auto *lambda) { EdgeAtom::Lambda edge_lambda; - std::string traversed_edge_variable = lambda->traversed_edge->accept(this); + auto traversed_edge_variable = std::any_cast(lambda->traversed_edge->accept(this)); edge_lambda.inner_edge = storage_->Create(traversed_edge_variable); - std::string traversed_node_variable = lambda->traversed_node->accept(this); + auto traversed_node_variable = std::any_cast(lambda->traversed_node->accept(this)); edge_lambda.inner_node = storage_->Create(traversed_node_variable); - edge_lambda.expression = lambda->expression()->accept(this); + edge_lambda.expression = std::any_cast(lambda->expression()->accept(this)); return edge_lambda; }; auto visit_total_weight = [&]() { if (relationshipDetail->total_weight) { - std::string total_weight_name = relationshipDetail->total_weight->accept(this); + auto total_weight_name = std::any_cast(relationshipDetail->total_weight->accept(this)); edge->total_weight_ = storage_->Create(total_weight_name); } else { anonymous_identifiers.push_back(&edge->total_weight_); @@ -1677,11 +1684,11 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(MemgraphCypher::Relati break; case 1: { if (properties[0]->mapLiteral()) { - edge->properties_ = properties[0]->accept(this).as>(); + edge->properties_ = std::any_cast>(properties[0]->accept(this)); break; } MG_ASSERT(properties[0]->parameter()); - edge->properties_ = properties[0]->accept(this).as(); + edge->properties_ = std::any_cast(properties[0]->accept(this)); break; } default: @@ -1704,7 +1711,7 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipLambda(MemgraphCypher::Relatio antlrcpp::Any CypherMainVisitor::visitRelationshipTypes(MemgraphCypher::RelationshipTypesContext *ctx) { std::vector types; for (auto *edge_type : ctx->relTypeName()) { - types.push_back(AddEdgeType(edge_type->accept(this))); + types.push_back(AddEdgeType(std::any_cast(edge_type->accept(this)))); } return types; } @@ -1724,7 +1731,7 @@ antlrcpp::Any CypherMainVisitor::visitVariableExpansion(MemgraphCypher::Variable // Case -[*]- } else if (ctx->expression().size() == 1U) { auto dots_tokens = ctx->getTokens(MemgraphCypher::DOTS); - Expression *bound = ctx->expression()[0]->accept(this); + auto *bound = std::any_cast(ctx->expression()[0]->accept(this)); if (!dots_tokens.size()) { // Case -[*bound]- if (edge_type != EdgeAtom::Type::WEIGHTED_SHORTEST_PATH) lower = bound; @@ -1738,8 +1745,8 @@ antlrcpp::Any CypherMainVisitor::visitVariableExpansion(MemgraphCypher::Variable } } else { // Case -[*lbound..rbound]- - lower = ctx->expression()[0]->accept(this); - upper = ctx->expression()[1]->accept(this); + lower = std::any_cast(ctx->expression()[0]->accept(this)); + upper = std::any_cast(ctx->expression()[1]->accept(this)); } if (lower && edge_type == EdgeAtom::Type::WEIGHTED_SHORTEST_PATH) throw SemanticException("Lower bound is not allowed in weighted shortest path expansion."); @@ -1748,7 +1755,7 @@ antlrcpp::Any CypherMainVisitor::visitVariableExpansion(MemgraphCypher::Variable } antlrcpp::Any CypherMainVisitor::visitExpression(MemgraphCypher::ExpressionContext *ctx) { - return static_cast(ctx->expression12()->accept(this)); + return std::any_cast(ctx->expression12()->accept(this)); } // OR. @@ -1794,11 +1801,11 @@ antlrcpp::Any CypherMainVisitor::visitExpression8(MemgraphCypher::Expression8Con // 4 <= 5 < 7 > 6 -> false // All of those comparisons evaluate to true in memgraph. std::vector children; - children.push_back(ctx->expression7()->accept(this)); + children.push_back(std::any_cast(ctx->expression7()->accept(this))); std::vector operators; auto partial_comparison_expressions = ctx->partialComparisonExpression(); for (auto *child : partial_comparison_expressions) { - children.push_back(child->expression7()->accept(this)); + children.push_back(std::any_cast(child->expression7()->accept(this))); } // First production is comparison operator. for (auto *child : partial_comparison_expressions) { @@ -1860,7 +1867,7 @@ antlrcpp::Any CypherMainVisitor::visitExpression4(MemgraphCypher::Expression4Con // IS NULL, IS NOT NULL, STARTS WITH, .. antlrcpp::Any CypherMainVisitor::visitExpression3a(MemgraphCypher::Expression3aContext *ctx) { - Expression *expression = ctx->expression3b()->accept(this); + auto *expression = std::any_cast(ctx->expression3b()->accept(this)); for (auto *op : ctx->stringAndNullOperators()) { if (op->IS() && op->NOT() && op->CYPHERNULL()) { @@ -1869,12 +1876,12 @@ antlrcpp::Any CypherMainVisitor::visitExpression3a(MemgraphCypher::Expression3aC } else if (op->IS() && op->CYPHERNULL()) { expression = static_cast(storage_->Create(expression)); } else if (op->IN()) { - expression = - static_cast(storage_->Create(expression, op->expression3b()->accept(this))); + expression = static_cast( + storage_->Create(expression, std::any_cast(op->expression3b()->accept(this)))); } else if (utils::StartsWith(op->getText(), "=~")) { auto *regex_match = storage_->Create(); regex_match->string_expr_ = expression; - regex_match->regex_ = op->expression3b()->accept(this); + regex_match->regex_ = std::any_cast(op->expression3b()->accept(this)); expression = regex_match; } else { std::string function_name; @@ -1887,7 +1894,7 @@ antlrcpp::Any CypherMainVisitor::visitExpression3a(MemgraphCypher::Expression3aC } else { throw utils::NotYetImplemented("function '{}'", op->getText()); } - auto expression2 = op->expression3b()->accept(this); + auto *expression2 = std::any_cast(op->expression3b()->accept(this)); std::vector args = {expression, expression2}; expression = static_cast(storage_->Create(function_name, args)); } @@ -1900,18 +1907,19 @@ antlrcpp::Any CypherMainVisitor::visitStringAndNullOperators(MemgraphCypher::Str } antlrcpp::Any CypherMainVisitor::visitExpression3b(MemgraphCypher::Expression3bContext *ctx) { - Expression *expression = ctx->expression2a()->accept(this); + auto *expression = std::any_cast(ctx->expression2a()->accept(this)); for (auto *list_op : ctx->listIndexingOrSlicing()) { if (list_op->getTokens(MemgraphCypher::DOTS).size() == 0U) { // If there is no '..' then we need to create list indexing operator. - expression = storage_->Create(expression, list_op->expression()[0]->accept(this)); + expression = storage_->Create( + expression, std::any_cast(list_op->expression()[0]->accept(this))); } else if (!list_op->lower_bound && !list_op->upper_bound) { throw SemanticException("List slicing operator requires at least one bound."); } else { Expression *lower_bound_ast = - list_op->lower_bound ? static_cast(list_op->lower_bound->accept(this)) : nullptr; + list_op->lower_bound ? std::any_cast(list_op->lower_bound->accept(this)) : nullptr; Expression *upper_bound_ast = - list_op->upper_bound ? static_cast(list_op->upper_bound->accept(this)) : nullptr; + list_op->upper_bound ? std::any_cast(list_op->upper_bound->accept(this)) : nullptr; expression = storage_->Create(expression, lower_bound_ast, upper_bound_ast); } } @@ -1924,18 +1932,18 @@ antlrcpp::Any CypherMainVisitor::visitListIndexingOrSlicing(MemgraphCypher::List } antlrcpp::Any CypherMainVisitor::visitExpression2a(MemgraphCypher::Expression2aContext *ctx) { - Expression *expression = ctx->expression2b()->accept(this); + auto *expression = std::any_cast(ctx->expression2b()->accept(this)); if (ctx->nodeLabels()) { - auto labels = ctx->nodeLabels()->accept(this).as>(); + auto labels = std::any_cast>(ctx->nodeLabels()->accept(this)); expression = storage_->Create(expression, labels); } return expression; } antlrcpp::Any CypherMainVisitor::visitExpression2b(MemgraphCypher::Expression2bContext *ctx) { - Expression *expression = ctx->atom()->accept(this); + auto *expression = std::any_cast(ctx->atom()->accept(this)); for (auto *lookup : ctx->propertyLookup()) { - PropertyIx key = lookup->accept(this); + auto key = std::any_cast(lookup->accept(this)); auto property_lookup = storage_->Create(expression, key); expression = property_lookup; } @@ -1946,19 +1954,19 @@ antlrcpp::Any CypherMainVisitor::visitAtom(MemgraphCypher::AtomContext *ctx) { if (ctx->literal()) { return ctx->literal()->accept(this); } else if (ctx->parameter()) { - return static_cast(ctx->parameter()->accept(this).as()); + return static_cast(std::any_cast(ctx->parameter()->accept(this))); } else if (ctx->parenthesizedExpression()) { - return static_cast(ctx->parenthesizedExpression()->accept(this)); + return static_cast(std::any_cast(ctx->parenthesizedExpression()->accept(this))); } else if (ctx->variable()) { - std::string variable = ctx->variable()->accept(this); + auto variable = std::any_cast(ctx->variable()->accept(this)); users_identifiers.insert(variable); return static_cast(storage_->Create(variable)); } else if (ctx->functionInvocation()) { - return static_cast(ctx->functionInvocation()->accept(this)); + return std::any_cast(ctx->functionInvocation()->accept(this)); } else if (ctx->COALESCE()) { std::vector exprs; for (auto *expr_context : ctx->expression()) { - exprs.emplace_back(expr_context->accept(this).as()); + exprs.emplace_back(std::any_cast(expr_context->accept(this))); } return static_cast(storage_->Create(std::move(exprs))); } else if (ctx->COUNT()) { @@ -1967,57 +1975,57 @@ antlrcpp::Any CypherMainVisitor::visitAtom(MemgraphCypher::AtomContext *ctx) { // functionInvocation and atom producions in opencypher grammar. return static_cast(storage_->Create(nullptr, nullptr, Aggregation::Op::COUNT)); } else if (ctx->ALL()) { - auto *ident = - storage_->Create(ctx->filterExpression()->idInColl()->variable()->accept(this).as()); - Expression *list_expr = ctx->filterExpression()->idInColl()->expression()->accept(this); + auto *ident = storage_->Create( + std::any_cast(ctx->filterExpression()->idInColl()->variable()->accept(this))); + auto *list_expr = std::any_cast(ctx->filterExpression()->idInColl()->expression()->accept(this)); if (!ctx->filterExpression()->where()) { throw SyntaxException("ALL(...) requires a WHERE predicate."); } - Where *where = ctx->filterExpression()->where()->accept(this); + auto *where = std::any_cast(ctx->filterExpression()->where()->accept(this)); return static_cast(storage_->Create(ident, list_expr, where)); } else if (ctx->SINGLE()) { - auto *ident = - storage_->Create(ctx->filterExpression()->idInColl()->variable()->accept(this).as()); - Expression *list_expr = ctx->filterExpression()->idInColl()->expression()->accept(this); + auto *ident = storage_->Create( + std::any_cast(ctx->filterExpression()->idInColl()->variable()->accept(this))); + auto *list_expr = std::any_cast(ctx->filterExpression()->idInColl()->expression()->accept(this)); if (!ctx->filterExpression()->where()) { throw SyntaxException("SINGLE(...) requires a WHERE predicate."); } - Where *where = ctx->filterExpression()->where()->accept(this); + auto *where = std::any_cast(ctx->filterExpression()->where()->accept(this)); return static_cast(storage_->Create(ident, list_expr, where)); } else if (ctx->ANY()) { - auto *ident = - storage_->Create(ctx->filterExpression()->idInColl()->variable()->accept(this).as()); - Expression *list_expr = ctx->filterExpression()->idInColl()->expression()->accept(this); + auto *ident = storage_->Create( + std::any_cast(ctx->filterExpression()->idInColl()->variable()->accept(this))); + auto *list_expr = std::any_cast(ctx->filterExpression()->idInColl()->expression()->accept(this)); if (!ctx->filterExpression()->where()) { throw SyntaxException("ANY(...) requires a WHERE predicate."); } - Where *where = ctx->filterExpression()->where()->accept(this); + auto *where = std::any_cast(ctx->filterExpression()->where()->accept(this)); return static_cast(storage_->Create(ident, list_expr, where)); } else if (ctx->NONE()) { - auto *ident = - storage_->Create(ctx->filterExpression()->idInColl()->variable()->accept(this).as()); - Expression *list_expr = ctx->filterExpression()->idInColl()->expression()->accept(this); + auto *ident = storage_->Create( + std::any_cast(ctx->filterExpression()->idInColl()->variable()->accept(this))); + auto *list_expr = std::any_cast(ctx->filterExpression()->idInColl()->expression()->accept(this)); if (!ctx->filterExpression()->where()) { throw SyntaxException("NONE(...) requires a WHERE predicate."); } - Where *where = ctx->filterExpression()->where()->accept(this); + auto *where = std::any_cast(ctx->filterExpression()->where()->accept(this)); return static_cast(storage_->Create(ident, list_expr, where)); } else if (ctx->REDUCE()) { auto *accumulator = - storage_->Create(ctx->reduceExpression()->accumulator->accept(this).as()); - Expression *initializer = ctx->reduceExpression()->initial->accept(this); - auto *ident = - storage_->Create(ctx->reduceExpression()->idInColl()->variable()->accept(this).as()); - Expression *list = ctx->reduceExpression()->idInColl()->expression()->accept(this); - Expression *expr = ctx->reduceExpression()->expression().back()->accept(this); + storage_->Create(std::any_cast(ctx->reduceExpression()->accumulator->accept(this))); + auto *initializer = std::any_cast(ctx->reduceExpression()->initial->accept(this)); + auto *ident = storage_->Create( + std::any_cast(ctx->reduceExpression()->idInColl()->variable()->accept(this))); + auto *list = std::any_cast(ctx->reduceExpression()->idInColl()->expression()->accept(this)); + auto *expr = std::any_cast(ctx->reduceExpression()->expression().back()->accept(this)); return static_cast(storage_->Create(accumulator, initializer, ident, list, expr)); } else if (ctx->caseExpression()) { - return static_cast(ctx->caseExpression()->accept(this)); + return std::any_cast(ctx->caseExpression()->accept(this)); } else if (ctx->extractExpression()) { - auto *ident = - storage_->Create(ctx->extractExpression()->idInColl()->variable()->accept(this).as()); - Expression *list = ctx->extractExpression()->idInColl()->expression()->accept(this); - Expression *expr = ctx->extractExpression()->expression()->accept(this); + auto *ident = storage_->Create( + std::any_cast(ctx->extractExpression()->idInColl()->variable()->accept(this))); + auto *list = std::any_cast(ctx->extractExpression()->idInColl()->expression()->accept(this)); + auto *expr = std::any_cast(ctx->extractExpression()->expression()->accept(this)); return static_cast(storage_->Create(ident, list, expr)); } // TODO: Implement this. We don't support comprehensions, filtering... at @@ -2043,34 +2051,35 @@ antlrcpp::Any CypherMainVisitor::visitLiteral(MemgraphCypher::LiteralContext *ct return static_cast(storage_->Create(token_position)); } else if (ctx->StringLiteral()) { return static_cast(storage_->Create( - visitStringLiteral(ctx->StringLiteral()->getText()).as(), token_position)); + std::any_cast(visitStringLiteral(std::any_cast(ctx->StringLiteral()->getText()))), + token_position)); } else if (ctx->booleanLiteral()) { return static_cast( - storage_->Create(ctx->booleanLiteral()->accept(this).as(), token_position)); + storage_->Create(std::any_cast(ctx->booleanLiteral()->accept(this)), token_position)); } else if (ctx->numberLiteral()) { - return static_cast( - storage_->Create(ctx->numberLiteral()->accept(this).as(), token_position)); + return static_cast(storage_->Create( + std::any_cast(ctx->numberLiteral()->accept(this)), token_position)); } LOG_FATAL("Expected to handle all cases above"); } else if (ctx->listLiteral()) { return static_cast( - storage_->Create(ctx->listLiteral()->accept(this).as>())); + storage_->Create(std::any_cast>(ctx->listLiteral()->accept(this)))); } else { return static_cast(storage_->Create( - ctx->mapLiteral()->accept(this).as>())); + std::any_cast>(ctx->mapLiteral()->accept(this)))); } return visitChildren(ctx); } antlrcpp::Any CypherMainVisitor::visitParenthesizedExpression(MemgraphCypher::ParenthesizedExpressionContext *ctx) { - return static_cast(ctx->expression()->accept(this)); + return std::any_cast(ctx->expression()->accept(this)); } antlrcpp::Any CypherMainVisitor::visitNumberLiteral(MemgraphCypher::NumberLiteralContext *ctx) { if (ctx->integerLiteral()) { - return TypedValue(ctx->integerLiteral()->accept(this).as()); + return TypedValue(std::any_cast(ctx->integerLiteral()->accept(this))); } else if (ctx->doubleLiteral()) { - return TypedValue(ctx->doubleLiteral()->accept(this).as()); + return TypedValue(std::any_cast(ctx->doubleLiteral()->accept(this))); } else { // This should never happen, except grammar changes and we don't notice // change in this production. @@ -2083,10 +2092,10 @@ antlrcpp::Any CypherMainVisitor::visitFunctionInvocation(MemgraphCypher::Functio if (ctx->DISTINCT()) { throw utils::NotYetImplemented("DISTINCT function call"); } - std::string function_name = ctx->functionName()->accept(this); + auto function_name = std::any_cast(ctx->functionName()->accept(this)); std::vector expressions; for (auto *expression : ctx->expression()) { - expressions.push_back(expression->accept(this)); + expressions.push_back(std::any_cast(expression->accept(this))); } if (expressions.size() == 1U) { if (function_name == Aggregation::kCount) { @@ -2168,21 +2177,21 @@ antlrcpp::Any CypherMainVisitor::visitCypherDelete(MemgraphCypher::CypherDeleteC del->detach_ = true; } for (auto *expression : ctx->expression()) { - del->expressions_.push_back(expression->accept(this)); + del->expressions_.push_back(std::any_cast(expression->accept(this))); } return del; } antlrcpp::Any CypherMainVisitor::visitWhere(MemgraphCypher::WhereContext *ctx) { auto *where = storage_->Create(); - where->expression_ = ctx->expression()->accept(this); + where->expression_ = std::any_cast(ctx->expression()->accept(this)); return where; } antlrcpp::Any CypherMainVisitor::visitSet(MemgraphCypher::SetContext *ctx) { std::vector set_items; for (auto *set_item : ctx->setItem()) { - set_items.push_back(set_item->accept(this)); + set_items.push_back(std::any_cast(set_item->accept(this))); } return set_items; } @@ -2191,16 +2200,17 @@ antlrcpp::Any CypherMainVisitor::visitSetItem(MemgraphCypher::SetItemContext *ct // SetProperty if (ctx->propertyExpression()) { auto *set_property = storage_->Create(); - set_property->property_lookup_ = ctx->propertyExpression()->accept(this); - set_property->expression_ = ctx->expression()->accept(this); + set_property->property_lookup_ = std::any_cast(ctx->propertyExpression()->accept(this)); + set_property->expression_ = std::any_cast(ctx->expression()->accept(this)); return static_cast(set_property); } // SetProperties either assignment or update if (ctx->getTokens(MemgraphCypher::EQ).size() || ctx->getTokens(MemgraphCypher::PLUS_EQ).size()) { auto *set_properties = storage_->Create(); - set_properties->identifier_ = storage_->Create(ctx->variable()->accept(this).as()); - set_properties->expression_ = ctx->expression()->accept(this); + set_properties->identifier_ = + storage_->Create(std::any_cast(ctx->variable()->accept(this))); + set_properties->expression_ = std::any_cast(ctx->expression()->accept(this)); if (ctx->getTokens(MemgraphCypher::PLUS_EQ).size()) { set_properties->update_ = true; } @@ -2209,15 +2219,15 @@ antlrcpp::Any CypherMainVisitor::visitSetItem(MemgraphCypher::SetItemContext *ct // SetLabels auto *set_labels = storage_->Create(); - set_labels->identifier_ = storage_->Create(ctx->variable()->accept(this).as()); - set_labels->labels_ = ctx->nodeLabels()->accept(this).as>(); + set_labels->identifier_ = storage_->Create(std::any_cast(ctx->variable()->accept(this))); + set_labels->labels_ = std::any_cast>(ctx->nodeLabels()->accept(this)); return static_cast(set_labels); } antlrcpp::Any CypherMainVisitor::visitRemove(MemgraphCypher::RemoveContext *ctx) { std::vector remove_items; for (auto *remove_item : ctx->removeItem()) { - remove_items.push_back(remove_item->accept(this)); + remove_items.push_back(std::any_cast(remove_item->accept(this))); } return remove_items; } @@ -2226,21 +2236,21 @@ antlrcpp::Any CypherMainVisitor::visitRemoveItem(MemgraphCypher::RemoveItemConte // RemoveProperty if (ctx->propertyExpression()) { auto *remove_property = storage_->Create(); - remove_property->property_lookup_ = ctx->propertyExpression()->accept(this); + remove_property->property_lookup_ = std::any_cast(ctx->propertyExpression()->accept(this)); return static_cast(remove_property); } // RemoveLabels auto *remove_labels = storage_->Create(); - remove_labels->identifier_ = storage_->Create(ctx->variable()->accept(this).as()); - remove_labels->labels_ = ctx->nodeLabels()->accept(this).as>(); + remove_labels->identifier_ = storage_->Create(std::any_cast(ctx->variable()->accept(this))); + remove_labels->labels_ = std::any_cast>(ctx->nodeLabels()->accept(this)); return static_cast(remove_labels); } antlrcpp::Any CypherMainVisitor::visitPropertyExpression(MemgraphCypher::PropertyExpressionContext *ctx) { - Expression *expression = ctx->atom()->accept(this); + auto *expression = std::any_cast(ctx->atom()->accept(this)); for (auto *lookup : ctx->propertyLookup()) { - PropertyIx key = lookup->accept(this); + auto key = std::any_cast(lookup->accept(this)); auto property_lookup = storage_->Create(expression, key); expression = property_lookup; } @@ -2249,17 +2259,18 @@ antlrcpp::Any CypherMainVisitor::visitPropertyExpression(MemgraphCypher::Propert } antlrcpp::Any CypherMainVisitor::visitCaseExpression(MemgraphCypher::CaseExpressionContext *ctx) { - Expression *test_expression = ctx->test ? ctx->test->accept(this).as() : nullptr; + Expression *test_expression = ctx->test ? std::any_cast(ctx->test->accept(this)) : nullptr; auto alternatives = ctx->caseAlternatives(); // Reverse alternatives so that tree of IfOperators can be built bottom-up. std::reverse(alternatives.begin(), alternatives.end()); - Expression *else_expression = ctx->else_expression ? ctx->else_expression->accept(this).as() + Expression *else_expression = ctx->else_expression ? std::any_cast(ctx->else_expression->accept(this)) : storage_->Create(TypedValue()); for (auto *alternative : alternatives) { Expression *condition = - test_expression ? storage_->Create(test_expression, alternative->when_expression->accept(this)) - : alternative->when_expression->accept(this).as(); - Expression *then_expression = alternative->then_expression->accept(this); + test_expression ? storage_->Create( + test_expression, std::any_cast(alternative->when_expression->accept(this))) + : std::any_cast(alternative->when_expression->accept(this)); + auto *then_expression = std::any_cast(alternative->then_expression->accept(this)); else_expression = storage_->Create(condition, then_expression, else_expression); } return else_expression; @@ -2273,22 +2284,22 @@ antlrcpp::Any CypherMainVisitor::visitCaseAlternatives(MemgraphCypher::CaseAlter antlrcpp::Any CypherMainVisitor::visitWith(MemgraphCypher::WithContext *ctx) { auto *with = storage_->Create(); in_with_ = true; - with->body_ = ctx->returnBody()->accept(this); + with->body_ = std::any_cast(ctx->returnBody()->accept(this)); in_with_ = false; if (ctx->DISTINCT()) { with->body_.distinct = true; } if (ctx->where()) { - with->where_ = ctx->where()->accept(this); + with->where_ = std::any_cast(ctx->where()->accept(this)); } return with; } antlrcpp::Any CypherMainVisitor::visitMerge(MemgraphCypher::MergeContext *ctx) { auto *merge = storage_->Create(); - merge->pattern_ = ctx->patternPart()->accept(this); + merge->pattern_ = std::any_cast(ctx->patternPart()->accept(this)); for (auto &merge_action : ctx->mergeAction()) { - auto set = merge_action->set()->accept(this).as>(); + auto set = std::any_cast>(merge_action->set()->accept(this)); if (merge_action->MATCH()) { merge->on_match_.insert(merge->on_match_.end(), set.begin(), set.end()); } else { @@ -2301,8 +2312,8 @@ antlrcpp::Any CypherMainVisitor::visitMerge(MemgraphCypher::MergeContext *ctx) { antlrcpp::Any CypherMainVisitor::visitUnwind(MemgraphCypher::UnwindContext *ctx) { auto *named_expr = storage_->Create(); - named_expr->expression_ = ctx->expression()->accept(this); - named_expr->name_ = std::string(ctx->variable()->accept(this).as()); + named_expr->expression_ = std::any_cast(ctx->expression()->accept(this)); + named_expr->name_ = std::any_cast(ctx->variable()->accept(this)); return storage_->Create(named_expr); } @@ -2315,27 +2326,27 @@ antlrcpp::Any CypherMainVisitor::visitForeach(MemgraphCypher::ForeachContext *ct auto *for_each = storage_->Create(); auto *named_expr = storage_->Create(); - named_expr->expression_ = ctx->expression()->accept(this); - named_expr->name_ = std::string(ctx->variable()->accept(this).as()); + named_expr->expression_ = std::any_cast(ctx->expression()->accept(this)); + named_expr->name_ = std::any_cast(ctx->variable()->accept(this)); for_each->named_expression_ = named_expr; for (auto *update_clause_ctx : ctx->updateClause()) { if (auto *set = update_clause_ctx->set(); set) { - auto set_items = visitSet(set).as>(); + auto set_items = std::any_cast>(visitSet(set)); std::copy(set_items.begin(), set_items.end(), std::back_inserter(for_each->clauses_)); } else if (auto *remove = update_clause_ctx->remove(); remove) { - auto remove_items = visitRemove(remove).as>(); + auto remove_items = std::any_cast>(visitRemove(remove)); std::copy(remove_items.begin(), remove_items.end(), std::back_inserter(for_each->clauses_)); } else if (auto *merge = update_clause_ctx->merge(); merge) { - for_each->clauses_.push_back(visitMerge(merge).as()); + for_each->clauses_.push_back(std::any_cast(visitMerge(merge))); } else if (auto *create = update_clause_ctx->create(); create) { - for_each->clauses_.push_back(visitCreate(create).as()); + for_each->clauses_.push_back(std::any_cast(visitCreate(create))); } else if (auto *cypher_delete = update_clause_ctx->cypherDelete(); cypher_delete) { - for_each->clauses_.push_back(visitCypherDelete(cypher_delete).as()); + for_each->clauses_.push_back(std::any_cast(visitCypherDelete(cypher_delete))); } else { auto *nested_for_each = update_clause_ctx->foreach (); MG_ASSERT(nested_for_each != nullptr, "Unexpected clause in FOREACH"); - for_each->clauses_.push_back(visitForeach(nested_for_each).as()); + for_each->clauses_.push_back(std::any_cast(visitForeach(nested_for_each))); } } diff --git a/src/query/frontend/ast/cypher_main_visitor.hpp b/src/query/frontend/ast/cypher_main_visitor.hpp index 2a6b8ff5e..d3a12072e 100644 --- a/src/query/frontend/ast/cypher_main_visitor.hpp +++ b/src/query/frontend/ast/cypher_main_visitor.hpp @@ -115,7 +115,7 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor { auto operators = ExtractOperators(all_children, allowed_operators); for (auto *expression : _expressions) { - expressions.push_back(expression->accept(this)); + expressions.push_back(std::any_cast(expression->accept(this))); } Expression *first_operand = expressions[0]; @@ -131,7 +131,7 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor { DMG_ASSERT(_expression, "can't happen"); auto operators = ExtractOperators(all_children, allowed_operators); - Expression *expression = _expression->accept(this); + Expression *expression = std::any_cast(_expression->accept(this)); for (int i = (int)operators.size() - 1; i >= 0; --i) { expression = CreateUnaryOperatorByToken(operators[i], expression); } diff --git a/src/query/interpreter.cpp b/src/query/interpreter.cpp index bc1a6a725..2925b1c14 100644 --- a/src/query/interpreter.cpp +++ b/src/query/interpreter.cpp @@ -1181,7 +1181,7 @@ PreparedQuery PrepareExplainQuery(ParsedQuery parsed_query, std::mapast_cache, &interpreter_context->antlr_lock, interpreter_context->config.query); + &interpreter_context->ast_cache, interpreter_context->config.query); auto *cypher_query = utils::Downcast(parsed_inner_query.query); MG_ASSERT(cypher_query, "Cypher grammar should not allow other queries in EXPLAIN"); @@ -1248,7 +1248,7 @@ PreparedQuery PrepareProfileQuery(ParsedQuery parsed_query, bool in_explicit_tra // full query string) when given just the inner query to execute. ParsedQuery parsed_inner_query = ParseQuery(parsed_query.query_string.substr(kProfileQueryStart.size()), parsed_query.user_parameters, - &interpreter_context->ast_cache, &interpreter_context->antlr_lock, interpreter_context->config.query); + &interpreter_context->ast_cache, interpreter_context->config.query); auto *cypher_query = utils::Downcast(parsed_inner_query.query); MG_ASSERT(cypher_query, "Cypher grammar should not allow other queries in PROFILE"); @@ -1566,8 +1566,7 @@ Callback CreateTrigger(TriggerQuery *trigger_query, interpreter_context->trigger_store.AddTrigger( std::move(trigger_name), trigger_statement, user_parameters, ToTriggerEventType(event_type), before_commit ? TriggerPhase::BEFORE_COMMIT : TriggerPhase::AFTER_COMMIT, &interpreter_context->ast_cache, - dba, &interpreter_context->antlr_lock, interpreter_context->config.query, std::move(owner), - interpreter_context->auth_checker); + dba, interpreter_context->config.query, std::move(owner), interpreter_context->auth_checker); return {}; }}; } @@ -2123,8 +2122,8 @@ Interpreter::PrepareResult Interpreter::Prepare(const std::string &query_string, query_execution->summary["cost_estimate"] = 0.0; utils::Timer parsing_timer; - ParsedQuery parsed_query = ParseQuery(query_string, params, &interpreter_context_->ast_cache, - &interpreter_context_->antlr_lock, interpreter_context_->config.query); + ParsedQuery parsed_query = + ParseQuery(query_string, params, &interpreter_context_->ast_cache, interpreter_context_->config.query); query_execution->summary["parsing_time"] = parsing_timer.Elapsed().count(); // Some queries require an active transaction in order to be prepared. diff --git a/src/query/interpreter.hpp b/src/query/interpreter.hpp index 5373588d9..0f9e8b901 100644 --- a/src/query/interpreter.hpp +++ b/src/query/interpreter.hpp @@ -173,13 +173,6 @@ struct InterpreterContext { storage::Storage *db; - // ANTLR has singleton instance that is shared between threads. It is - // protected by locks inside of ANTLR. Unfortunately, they are not protected - // in a very good way. Once we have ANTLR version without race conditions we - // can remove this lock. This will probably never happen since ANTLR - // developers introduce more bugs in each version. Fortunately, we have - // cache so this lock probably won't impact performance much... - utils::SpinLock antlr_lock; std::optional tsc_frequency{utils::GetTSCFrequency()}; std::atomic is_shutting_down{false}; diff --git a/src/query/plan/operator.cpp b/src/query/plan/operator.cpp index 74463ead0..a4ae9da66 100644 --- a/src/query/plan/operator.cpp +++ b/src/query/plan/operator.cpp @@ -2600,13 +2600,13 @@ namespace { * when there are */ TypedValue DefaultAggregationOpValue(const Aggregate::Element &element, utils::MemoryResource *memory) { switch (element.op) { - case Aggregation::Op::COUNT: - return TypedValue(0, memory); - case Aggregation::Op::SUM: case Aggregation::Op::MIN: case Aggregation::Op::MAX: case Aggregation::Op::AVG: return TypedValue(memory); + case Aggregation::Op::COUNT: + case Aggregation::Op::SUM: + return TypedValue(0, memory); case Aggregation::Op::COLLECT_LIST: return TypedValue(TypedValue::TVector(memory)); case Aggregation::Op::COLLECT_MAP: @@ -2628,9 +2628,7 @@ class AggregateCursor : public Cursor { pulled_all_input_ = true; aggregation_it_ = aggregation_.begin(); - // in case there is no input and no group_bys we need to return true - // just this once - if (aggregation_.empty() && self_.group_by_.empty()) { + if (aggregation_.empty()) { auto *pull_memory = context.evaluation_context.memory; // place default aggregation values on the frame for (const auto &elem : self_.aggregations_) diff --git a/src/query/trigger.cpp b/src/query/trigger.cpp index 9ff3262a7..ee8e84e3f 100644 --- a/src/query/trigger.cpp +++ b/src/query/trigger.cpp @@ -153,10 +153,10 @@ std::vector> GetPredefinedIdentifier Trigger::Trigger(std::string name, const std::string &query, const std::map &user_parameters, const TriggerEventType event_type, utils::SkipList *query_cache, - DbAccessor *db_accessor, utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config, + DbAccessor *db_accessor, const InterpreterConfig::Query &query_config, std::optional owner, const query::AuthChecker *auth_checker) : name_{std::move(name)}, - parsed_statements_{ParseQuery(query, user_parameters, query_cache, antlr_lock, query_config)}, + parsed_statements_{ParseQuery(query, user_parameters, query_cache, query_config)}, event_type_{event_type}, owner_{std::move(owner)} { // We check immediately if the query is valid by trying to create a plan. @@ -257,7 +257,7 @@ inline constexpr uint64_t kVersion{2}; TriggerStore::TriggerStore(std::filesystem::path directory) : storage_{std::move(directory)} {} void TriggerStore::RestoreTriggers(utils::SkipList *query_cache, DbAccessor *db_accessor, - utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config, + const InterpreterConfig::Query &query_config, const query::AuthChecker *auth_checker) { MG_ASSERT(before_commit_triggers_.size() == 0 && after_commit_triggers_.size() == 0, "Cannot restore trigger when some triggers already exist!"); @@ -317,8 +317,8 @@ void TriggerStore::RestoreTriggers(utils::SkipList *query_cache std::optional trigger; try { - trigger.emplace(trigger_name, statement, user_parameters, event_type, query_cache, db_accessor, antlr_lock, - query_config, std::move(owner), auth_checker); + trigger.emplace(trigger_name, statement, user_parameters, event_type, query_cache, db_accessor, query_config, + std::move(owner), auth_checker); } catch (const utils::BasicException &e) { spdlog::warn("Failed to create trigger '{}' because: {}", trigger_name, e.what()); continue; @@ -336,8 +336,8 @@ void TriggerStore::AddTrigger(std::string name, const std::string &query, const std::map &user_parameters, TriggerEventType event_type, TriggerPhase phase, utils::SkipList *query_cache, DbAccessor *db_accessor, - utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config, - std::optional owner, const query::AuthChecker *auth_checker) { + const InterpreterConfig::Query &query_config, std::optional owner, + const query::AuthChecker *auth_checker) { std::unique_lock store_guard{store_lock_}; if (storage_.Get(name)) { throw utils::BasicException("Trigger with the same name already exists."); @@ -345,8 +345,8 @@ void TriggerStore::AddTrigger(std::string name, const std::string &query, std::optional trigger; try { - trigger.emplace(std::move(name), query, user_parameters, event_type, query_cache, db_accessor, antlr_lock, - query_config, std::move(owner), auth_checker); + trigger.emplace(std::move(name), query, user_parameters, event_type, query_cache, db_accessor, query_config, + std::move(owner), auth_checker); } catch (const utils::BasicException &e) { const auto identifiers = GetPredefinedIdentifiers(event_type); std::stringstream identifier_names_stream; diff --git a/src/query/trigger.hpp b/src/query/trigger.hpp index 6ed986ec7..a1b6b7012 100644 --- a/src/query/trigger.hpp +++ b/src/query/trigger.hpp @@ -34,7 +34,7 @@ namespace memgraph::query { struct Trigger { explicit Trigger(std::string name, const std::string &query, const std::map &user_parameters, TriggerEventType event_type, - utils::SkipList *query_cache, DbAccessor *db_accessor, utils::SpinLock *antlr_lock, + utils::SkipList *query_cache, DbAccessor *db_accessor, const InterpreterConfig::Query &query_config, std::optional owner, const query::AuthChecker *auth_checker); @@ -81,14 +81,13 @@ struct TriggerStore { explicit TriggerStore(std::filesystem::path directory); void RestoreTriggers(utils::SkipList *query_cache, DbAccessor *db_accessor, - utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config, - const query::AuthChecker *auth_checker); + const InterpreterConfig::Query &query_config, const query::AuthChecker *auth_checker); void AddTrigger(std::string name, const std::string &query, const std::map &user_parameters, TriggerEventType event_type, TriggerPhase phase, utils::SkipList *query_cache, DbAccessor *db_accessor, - utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config, - std::optional owner, const query::AuthChecker *auth_checker); + const InterpreterConfig::Query &query_config, std::optional owner, + const query::AuthChecker *auth_checker); void DropTrigger(const std::string &name); diff --git a/src/query/v2/CMakeLists.txt b/src/query/v2/CMakeLists.txt index 3efb0c91e..187520b5c 100644 --- a/src/query/v2/CMakeLists.txt +++ b/src/query/v2/CMakeLists.txt @@ -84,7 +84,7 @@ add_custom_command( OUTPUT ${antlr_opencypher_generated_src} ${antlr_opencypher_generated_include} COMMAND ${CMAKE_COMMAND} -E make_directory ${opencypher_generated} COMMAND - java -jar ${CMAKE_SOURCE_DIR}/libs/antlr-4.9.2-complete.jar + java -jar ${CMAKE_SOURCE_DIR}/libs/antlr-4.10.1-complete.jar -Dlanguage=Cpp -visitor -package antlropencypher -o ${opencypher_generated} ${opencypher_lexer_grammar} ${opencypher_parser_grammar} diff --git a/src/query/v2/cypher_query_interpreter.cpp b/src/query/v2/cypher_query_interpreter.cpp index 42e2b3cf3..f242e96c2 100644 --- a/src/query/v2/cypher_query_interpreter.cpp +++ b/src/query/v2/cypher_query_interpreter.cpp @@ -21,8 +21,7 @@ namespace memgraph::query::v2 { CachedPlan::CachedPlan(std::unique_ptr plan) : plan_(std::move(plan)) {} ParsedQuery ParseQuery(const std::string &query_string, const std::map ¶ms, - utils::SkipList *cache, utils::SpinLock *antlr_lock, - const InterpreterConfig::Query &query_config) { + utils::SkipList *cache, const InterpreterConfig::Query &query_config) { // Strip the query for caching purposes. The process of stripping a query // "normalizes" it by replacing any literals with new parameters. This // results in just the *structure* of the query being taken into account for @@ -63,20 +62,16 @@ ParsedQuery ParseQuery(const std::string &query_string, const std::map guard(*antlr_lock); + try { + parser = std::make_unique(stripped_query.query()); + } catch (const SyntaxException &e) { + // There is a syntax exception in the stripped query. Re-run the parser + // on the original query to get an appropriate error messsage. + parser = std::make_unique(query_string); - try { - parser = std::make_unique(stripped_query.query()); - } catch (const SyntaxException &e) { - // There is a syntax exception in the stripped query. Re-run the parser - // on the original query to get an appropriate error messsage. - parser = std::make_unique(query_string); - - // If an exception was not thrown here, the stripper messed something - // up. - LOG_FATAL("The stripped query can't be parsed, but the original can."); - } + // If an exception was not thrown here, the stripper messed something + // up. + LOG_FATAL("The stripped query can't be parsed, but the original can."); } // Convert the ANTLR4 parse tree into an AST. diff --git a/src/query/v2/cypher_query_interpreter.hpp b/src/query/v2/cypher_query_interpreter.hpp index 423eafdde..95a48a458 100644 --- a/src/query/v2/cypher_query_interpreter.hpp +++ b/src/query/v2/cypher_query_interpreter.hpp @@ -111,8 +111,7 @@ struct ParsedQuery { }; ParsedQuery ParseQuery(const std::string &query_string, const std::map ¶ms, - utils::SkipList *cache, utils::SpinLock *antlr_lock, - const InterpreterConfig::Query &query_config); + utils::SkipList *cache, const InterpreterConfig::Query &query_config); class SingleNodeLogicalPlan final : public LogicalPlan { public: diff --git a/src/query/v2/frontend/ast/cypher_main_visitor.cpp b/src/query/v2/frontend/ast/cypher_main_visitor.cpp index 8a74fbbeb..976e3abfc 100644 --- a/src/query/v2/frontend/ast/cypher_main_visitor.cpp +++ b/src/query/v2/frontend/ast/cypher_main_visitor.cpp @@ -52,7 +52,7 @@ std::optional> VisitMemoryL return std::nullopt; } - auto memory_limit = memory_limit_ctx->literal()->accept(visitor); + auto *memory_limit = std::any_cast(memory_limit_ctx->literal()->accept(visitor)); size_t memory_scale = 1024U; if (memory_limit_ctx->MB()) { memory_scale = 1024U * 1024U; @@ -77,7 +77,7 @@ std::string JoinSymbolicNames(antlr4::tree::ParseTreeVisitor *visitor, const std::vector symbolicNames, const std::string &separator = ".") { return JoinTokens( - symbolicNames, [&](auto *token) { return token->accept(visitor).template as(); }, separator); + symbolicNames, [&](auto *token) { return std::any_cast(token->accept(visitor)); }, separator); } std::string JoinSymbolicNamesWithDotsAndMinus(antlr4::tree::ParseTreeVisitor &visitor, @@ -90,7 +90,7 @@ std::string JoinSymbolicNamesWithDotsAndMinus(antlr4::tree::ParseTreeVisitor &vi antlrcpp::Any CypherMainVisitor::visitExplainQuery(MemgraphCypher::ExplainQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 2, "ExplainQuery should have exactly two children!"); - auto *cypher_query = ctx->children[1]->accept(this).as(); + auto *cypher_query = std::any_cast(ctx->children[1]->accept(this)); auto *explain_query = storage_->Create(); explain_query->cypher_query_ = cypher_query; query_ = explain_query; @@ -99,7 +99,7 @@ antlrcpp::Any CypherMainVisitor::visitExplainQuery(MemgraphCypher::ExplainQueryC antlrcpp::Any CypherMainVisitor::visitProfileQuery(MemgraphCypher::ProfileQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 2, "ProfileQuery should have exactly two children!"); - auto *cypher_query = ctx->children[1]->accept(this).as(); + auto *cypher_query = std::any_cast(ctx->children[1]->accept(this)); auto *profile_query = storage_->Create(); profile_query->cypher_query_ = cypher_query; query_ = profile_query; @@ -132,7 +132,7 @@ antlrcpp::Any CypherMainVisitor::visitConstraintQuery(MemgraphCypher::Constraint } else if (ctx->DROP()) { constraint_query->action_type_ = ConstraintQuery::ActionType::DROP; } - constraint_query->constraint_ = ctx->constraint()->accept(this).as(); + constraint_query->constraint_ = std::any_cast(ctx->constraint()->accept(this)); query_ = constraint_query; return query_; } @@ -147,16 +147,16 @@ antlrcpp::Any CypherMainVisitor::visitConstraint(MemgraphCypher::ConstraintConte } else if (ctx->NODE() && ctx->KEY()) { constraint.type = Constraint::Type::NODE_KEY; } - constraint.label = AddLabel(ctx->labelName()->accept(this)); - std::string node_name = ctx->nodeName->symbolicName()->accept(this); + constraint.label = AddLabel(std::any_cast(ctx->labelName()->accept(this))); + auto node_name = std::any_cast(ctx->nodeName->symbolicName()->accept(this)); for (const auto &var_ctx : ctx->constraintPropertyList()->variable()) { - std::string var_name = var_ctx->symbolicName()->accept(this); + auto var_name = std::any_cast(var_ctx->symbolicName()->accept(this)); if (var_name != node_name) { throw SemanticException("All constraint variable should reference node '{}'", node_name); } } for (const auto &prop_lookup : ctx->constraintPropertyList()->propertyLookup()) { - constraint.properties.push_back(prop_lookup->propertyKeyName()->accept(this)); + constraint.properties.push_back(std::any_cast(prop_lookup->propertyKeyName()->accept(this))); } return constraint; @@ -165,7 +165,7 @@ antlrcpp::Any CypherMainVisitor::visitConstraint(MemgraphCypher::ConstraintConte antlrcpp::Any CypherMainVisitor::visitCypherQuery(MemgraphCypher::CypherQueryContext *ctx) { auto *cypher_query = storage_->Create(); MG_ASSERT(ctx->singleQuery(), "Expected single query."); - cypher_query->single_query_ = ctx->singleQuery()->accept(this).as(); + cypher_query->single_query_ = std::any_cast(ctx->singleQuery()->accept(this)); // Check that union and union all dont mix bool has_union = false; @@ -179,7 +179,7 @@ antlrcpp::Any CypherMainVisitor::visitCypherQuery(MemgraphCypher::CypherQueryCon if (has_union && has_union_all) { throw SemanticException("Invalid combination of UNION and UNION ALL."); } - cypher_query->cypher_unions_.push_back(child->accept(this).as()); + cypher_query->cypher_unions_.push_back(std::any_cast(child->accept(this))); } if (auto *memory_limit_ctx = ctx->queryMemoryLimit()) { @@ -196,7 +196,7 @@ antlrcpp::Any CypherMainVisitor::visitCypherQuery(MemgraphCypher::CypherQueryCon antlrcpp::Any CypherMainVisitor::visitIndexQuery(MemgraphCypher::IndexQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 1, "IndexQuery should have exactly one child!"); - auto *index_query = ctx->children[0]->accept(this).as(); + auto *index_query = std::any_cast(ctx->children[0]->accept(this)); query_ = index_query; return index_query; } @@ -204,9 +204,9 @@ antlrcpp::Any CypherMainVisitor::visitIndexQuery(MemgraphCypher::IndexQueryConte antlrcpp::Any CypherMainVisitor::visitCreateIndex(MemgraphCypher::CreateIndexContext *ctx) { auto *index_query = storage_->Create(); index_query->action_ = IndexQuery::Action::CREATE; - index_query->label_ = AddLabel(ctx->labelName()->accept(this)); + index_query->label_ = AddLabel(std::any_cast(ctx->labelName()->accept(this))); if (ctx->propertyKeyName()) { - PropertyIx name_key = ctx->propertyKeyName()->accept(this); + auto name_key = std::any_cast(ctx->propertyKeyName()->accept(this)); index_query->properties_ = {name_key}; } return index_query; @@ -216,16 +216,16 @@ antlrcpp::Any CypherMainVisitor::visitDropIndex(MemgraphCypher::DropIndexContext auto *index_query = storage_->Create(); index_query->action_ = IndexQuery::Action::DROP; if (ctx->propertyKeyName()) { - PropertyIx key = ctx->propertyKeyName()->accept(this); + auto key = std::any_cast(ctx->propertyKeyName()->accept(this)); index_query->properties_ = {key}; } - index_query->label_ = AddLabel(ctx->labelName()->accept(this)); + index_query->label_ = AddLabel(std::any_cast(ctx->labelName()->accept(this))); return index_query; } antlrcpp::Any CypherMainVisitor::visitAuthQuery(MemgraphCypher::AuthQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 1, "AuthQuery should have exactly one child!"); - auto *auth_query = ctx->children[0]->accept(this).as(); + auto *auth_query = std::any_cast(ctx->children[0]->accept(this)); query_ = auth_query; return auth_query; } @@ -238,7 +238,7 @@ antlrcpp::Any CypherMainVisitor::visitDumpQuery(MemgraphCypher::DumpQueryContext antlrcpp::Any CypherMainVisitor::visitReplicationQuery(MemgraphCypher::ReplicationQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 1, "ReplicationQuery should have exactly one child!"); - auto *replication_query = ctx->children[0]->accept(this).as(); + auto *replication_query = std::any_cast(ctx->children[0]->accept(this)); query_ = replication_query; return replication_query; } @@ -255,7 +255,7 @@ antlrcpp::Any CypherMainVisitor::visitSetReplicationRole(MemgraphCypher::SetRepl replication_query->role_ = ReplicationQuery::ReplicationRole::REPLICA; if (ctx->WITH() && ctx->PORT()) { if (ctx->port->numberLiteral() && ctx->port->numberLiteral()->integerLiteral()) { - replication_query->port_ = ctx->port->accept(this); + replication_query->port_ = std::any_cast(ctx->port->accept(this)); } else { throw SyntaxException("Port must be an integer literal!"); } @@ -272,13 +272,13 @@ antlrcpp::Any CypherMainVisitor::visitShowReplicationRole(MemgraphCypher::ShowRe antlrcpp::Any CypherMainVisitor::visitRegisterReplica(MemgraphCypher::RegisterReplicaContext *ctx) { auto *replication_query = storage_->Create(); replication_query->action_ = ReplicationQuery::Action::REGISTER_REPLICA; - replication_query->replica_name_ = ctx->replicaName()->symbolicName()->accept(this).as(); + replication_query->replica_name_ = std::any_cast(ctx->replicaName()->symbolicName()->accept(this)); if (ctx->SYNC()) { replication_query->sync_mode_ = memgraph::query::v2::ReplicationQuery::SyncMode::SYNC; if (ctx->WITH() && ctx->TIMEOUT()) { if (ctx->timeout->numberLiteral()) { // we accept both double and integer literals - replication_query->timeout_ = ctx->timeout->accept(this); + replication_query->timeout_ = std::any_cast(ctx->timeout->accept(this)); } else { throw SemanticException("Timeout should be a integer or double literal!"); } @@ -293,7 +293,7 @@ antlrcpp::Any CypherMainVisitor::visitRegisterReplica(MemgraphCypher::RegisterRe if (!ctx->socketAddress()->literal()->StringLiteral()) { throw SemanticException("Socket address should be a string literal!"); } else { - replication_query->socket_address_ = ctx->socketAddress()->accept(this); + replication_query->socket_address_ = std::any_cast(ctx->socketAddress()->accept(this)); } return replication_query; @@ -302,7 +302,7 @@ antlrcpp::Any CypherMainVisitor::visitRegisterReplica(MemgraphCypher::RegisterRe antlrcpp::Any CypherMainVisitor::visitDropReplica(MemgraphCypher::DropReplicaContext *ctx) { auto *replication_query = storage_->Create(); replication_query->action_ = ReplicationQuery::Action::DROP_REPLICA; - replication_query->replica_name_ = ctx->replicaName()->symbolicName()->accept(this).as(); + replication_query->replica_name_ = std::any_cast(ctx->replicaName()->symbolicName()->accept(this)); return replication_query; } @@ -332,7 +332,7 @@ antlrcpp::Any CypherMainVisitor::visitLoadCsv(MemgraphCypher::LoadCsvContext *ct auto *load_csv = storage_->Create(); // handle file name if (ctx->csvFile()->literal()->StringLiteral()) { - load_csv->file_ = ctx->csvFile()->accept(this); + load_csv->file_ = std::any_cast(ctx->csvFile()->accept(this)); } else { throw SemanticException("CSV file path should be a string literal"); } @@ -349,7 +349,7 @@ antlrcpp::Any CypherMainVisitor::visitLoadCsv(MemgraphCypher::LoadCsvContext *ct // handle delimiter if (ctx->DELIMITER()) { if (ctx->delimiter()->literal()->StringLiteral()) { - load_csv->delimiter_ = ctx->delimiter()->accept(this); + load_csv->delimiter_ = std::any_cast(ctx->delimiter()->accept(this)); } else { throw SemanticException("Delimiter should be a string literal"); } @@ -358,14 +358,15 @@ antlrcpp::Any CypherMainVisitor::visitLoadCsv(MemgraphCypher::LoadCsvContext *ct // handle quote if (ctx->QUOTE()) { if (ctx->quote()->literal()->StringLiteral()) { - load_csv->quote_ = ctx->quote()->accept(this); + load_csv->quote_ = std::any_cast(ctx->quote()->accept(this)); } else { throw SemanticException("Quote should be a string literal"); } } // handle row variable - load_csv->row_var_ = storage_->Create(ctx->rowVar()->variable()->accept(this).as()); + load_csv->row_var_ = + storage_->Create(std::any_cast(ctx->rowVar()->variable()->accept(this))); return load_csv; } @@ -378,7 +379,7 @@ antlrcpp::Any CypherMainVisitor::visitFreeMemoryQuery(MemgraphCypher::FreeMemory antlrcpp::Any CypherMainVisitor::visitTriggerQuery(MemgraphCypher::TriggerQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 1, "TriggerQuery should have exactly one child!"); - auto *trigger_query = ctx->children[0]->accept(this).as(); + auto *trigger_query = std::any_cast(ctx->children[0]->accept(this)); query_ = trigger_query; return trigger_query; } @@ -386,7 +387,7 @@ antlrcpp::Any CypherMainVisitor::visitTriggerQuery(MemgraphCypher::TriggerQueryC antlrcpp::Any CypherMainVisitor::visitCreateTrigger(MemgraphCypher::CreateTriggerContext *ctx) { auto *trigger_query = storage_->Create(); trigger_query->action_ = TriggerQuery::Action::CREATE_TRIGGER; - trigger_query->trigger_name_ = ctx->triggerName()->symbolicName()->accept(this).as(); + trigger_query->trigger_name_ = std::any_cast(ctx->triggerName()->symbolicName()->accept(this)); auto *statement = ctx->triggerStatement(); antlr4::misc::Interval interval{statement->start->getStartIndex(), statement->stop->getStopIndex()}; @@ -438,7 +439,7 @@ antlrcpp::Any CypherMainVisitor::visitCreateTrigger(MemgraphCypher::CreateTrigge antlrcpp::Any CypherMainVisitor::visitDropTrigger(MemgraphCypher::DropTriggerContext *ctx) { auto *trigger_query = storage_->Create(); trigger_query->action_ = TriggerQuery::Action::DROP_TRIGGER; - trigger_query->trigger_name_ = ctx->triggerName()->symbolicName()->accept(this).as(); + trigger_query->trigger_name_ = std::any_cast(ctx->triggerName()->symbolicName()->accept(this)); return trigger_query; } @@ -482,14 +483,14 @@ antlrcpp::Any CypherMainVisitor::visitCreateSnapshotQuery(MemgraphCypher::Create antlrcpp::Any CypherMainVisitor::visitStreamQuery(MemgraphCypher::StreamQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 1, "StreamQuery should have exactly one child!"); - auto *stream_query = ctx->children[0]->accept(this).as(); + auto *stream_query = std::any_cast(ctx->children[0]->accept(this)); query_ = stream_query; return stream_query; } antlrcpp::Any CypherMainVisitor::visitCreateStream(MemgraphCypher::CreateStreamContext *ctx) { MG_ASSERT(ctx->children.size() == 1, "CreateStreamQuery should have exactly one child!"); - auto *stream_query = ctx->children[0]->accept(this).as(); + auto *stream_query = std::any_cast(ctx->children[0]->accept(this)); query_ = stream_query; return stream_query; } @@ -581,7 +582,8 @@ void MapCommonStreamConfigs(auto &memory, StreamQuery &stream_query) { antlrcpp::Any CypherMainVisitor::visitConfigKeyValuePair(MemgraphCypher::ConfigKeyValuePairContext *ctx) { MG_ASSERT(ctx->literal().size() == 2); - return std::pair{ctx->literal(0)->accept(this).as(), ctx->literal(1)->accept(this).as()}; + return std::pair{std::any_cast(ctx->literal(0)->accept(this)), + std::any_cast(ctx->literal(1)->accept(this))}; } antlrcpp::Any CypherMainVisitor::visitConfigMap(MemgraphCypher::ConfigMapContext *ctx) { @@ -589,7 +591,7 @@ antlrcpp::Any CypherMainVisitor::visitConfigMap(MemgraphCypher::ConfigMapContext for (auto *key_value_pair : ctx->configKeyValuePair()) { // If the queries are cached, then only the stripped query is parsed, so the actual keys cannot be determined // here. That means duplicates cannot be checked. - map.insert(key_value_pair->accept(this).as>()); + map.insert(std::any_cast>(key_value_pair->accept(this))); } return map; } @@ -598,7 +600,7 @@ antlrcpp::Any CypherMainVisitor::visitKafkaCreateStream(MemgraphCypher::KafkaCre auto *stream_query = storage_->Create(); stream_query->action_ = StreamQuery::Action::CREATE_STREAM; stream_query->type_ = StreamQuery::Type::KAFKA; - stream_query->stream_name_ = ctx->streamName()->symbolicName()->accept(this).as(); + stream_query->stream_name_ = std::any_cast(ctx->streamName()->symbolicName()->accept(this)); for (auto *create_config_ctx : ctx->kafkaCreateStreamConfig()) { create_config_ctx->accept(this); @@ -634,7 +636,7 @@ void GetTopicNames(auto &destination, MemgraphCypher::TopicNamesContext *topic_n if (!topic_names_ctx->literal()->StringLiteral()) { throw SemanticException("Topic names should be defined as a string literal or as symbolic names"); } - destination = topic_names_ctx->accept(&visitor).as(); + destination = std::any_cast(topic_names_ctx->accept(&visitor)); } } } // namespace @@ -661,7 +663,8 @@ antlrcpp::Any CypherMainVisitor::visitKafkaCreateStreamConfig(MemgraphCypher::Ka if (ctx->CONFIGS()) { ThrowIfExists(memory_, KafkaConfigKey::CONFIGS); static constexpr auto configs_key = static_cast(KafkaConfigKey::CONFIGS); - memory_.emplace(configs_key, ctx->configsMap->accept(this).as>()); + memory_.emplace(configs_key, + std::any_cast>(ctx->configsMap->accept(this))); return {}; } @@ -669,7 +672,7 @@ antlrcpp::Any CypherMainVisitor::visitKafkaCreateStreamConfig(MemgraphCypher::Ka ThrowIfExists(memory_, KafkaConfigKey::CREDENTIALS); static constexpr auto credentials_key = static_cast(KafkaConfigKey::CREDENTIALS); memory_.emplace(credentials_key, - ctx->credentialsMap->accept(this).as>()); + std::any_cast>(ctx->credentialsMap->accept(this))); return {}; } @@ -680,7 +683,7 @@ antlrcpp::Any CypherMainVisitor::visitKafkaCreateStreamConfig(MemgraphCypher::Ka } const auto bootstrap_servers_key = static_cast(KafkaConfigKey::BOOTSTRAP_SERVERS); - memory_[bootstrap_servers_key] = ctx->bootstrapServers->accept(this).as(); + memory_[bootstrap_servers_key] = std::any_cast(ctx->bootstrapServers->accept(this)); return {}; } @@ -701,7 +704,7 @@ antlrcpp::Any CypherMainVisitor::visitPulsarCreateStream(MemgraphCypher::PulsarC auto *stream_query = storage_->Create(); stream_query->action_ = StreamQuery::Action::CREATE_STREAM; stream_query->type_ = StreamQuery::Type::PULSAR; - stream_query->stream_name_ = ctx->streamName()->symbolicName()->accept(this).as(); + stream_query->stream_name_ = std::any_cast(ctx->streamName()->symbolicName()->accept(this)); for (auto *create_config_ctx : ctx->pulsarCreateStreamConfig()) { create_config_ctx->accept(this); @@ -733,7 +736,7 @@ antlrcpp::Any CypherMainVisitor::visitPulsarCreateStreamConfig(MemgraphCypher::P throw SemanticException("Service URL must be a string!"); } const auto service_url_key = static_cast(PulsarConfigKey::SERVICE_URL); - memory_[service_url_key] = ctx->serviceUrl->accept(this).as(); + memory_[service_url_key] = std::any_cast(ctx->serviceUrl->accept(this)); return {}; } @@ -751,7 +754,7 @@ antlrcpp::Any CypherMainVisitor::visitCommonCreateStreamConfig(MemgraphCypher::C throw SemanticException("Batch interval must be an integer literal!"); } const auto batch_interval_key = static_cast(CommonStreamConfigKey::BATCH_INTERVAL); - memory_[batch_interval_key] = ctx->batchInterval->accept(this).as(); + memory_[batch_interval_key] = std::any_cast(ctx->batchInterval->accept(this)); return {}; } @@ -761,14 +764,14 @@ antlrcpp::Any CypherMainVisitor::visitCommonCreateStreamConfig(MemgraphCypher::C throw SemanticException("Batch size must be an integer literal!"); } const auto batch_size_key = static_cast(CommonStreamConfigKey::BATCH_SIZE); - memory_[batch_size_key] = ctx->batchSize->accept(this).as(); + memory_[batch_size_key] = std::any_cast(ctx->batchSize->accept(this)); return {}; } antlrcpp::Any CypherMainVisitor::visitDropStream(MemgraphCypher::DropStreamContext *ctx) { auto *stream_query = storage_->Create(); stream_query->action_ = StreamQuery::Action::DROP_STREAM; - stream_query->stream_name_ = ctx->streamName()->symbolicName()->accept(this).as(); + stream_query->stream_name_ = std::any_cast(ctx->streamName()->symbolicName()->accept(this)); return stream_query; } @@ -780,7 +783,7 @@ antlrcpp::Any CypherMainVisitor::visitStartStream(MemgraphCypher::StartStreamCon if (!ctx->batchLimit->numberLiteral() || !ctx->batchLimit->numberLiteral()->integerLiteral()) { throw SemanticException("Batch limit should be an integer literal!"); } - stream_query->batch_limit_ = ctx->batchLimit->accept(this); + stream_query->batch_limit_ = std::any_cast(ctx->batchLimit->accept(this)); } if (ctx->TIMEOUT()) { if (!ctx->timeout->numberLiteral() || !ctx->timeout->numberLiteral()->integerLiteral()) { @@ -789,10 +792,10 @@ antlrcpp::Any CypherMainVisitor::visitStartStream(MemgraphCypher::StartStreamCon if (!ctx->BATCH_LIMIT()) { throw SemanticException("Parameter TIMEOUT can only be defined if BATCH_LIMIT is defined"); } - stream_query->timeout_ = ctx->timeout->accept(this); + stream_query->timeout_ = std::any_cast(ctx->timeout->accept(this)); } - stream_query->stream_name_ = ctx->streamName()->symbolicName()->accept(this).as(); + stream_query->stream_name_ = std::any_cast(ctx->streamName()->symbolicName()->accept(this)); return stream_query; } @@ -805,7 +808,7 @@ antlrcpp::Any CypherMainVisitor::visitStartAllStreams(MemgraphCypher::StartAllSt antlrcpp::Any CypherMainVisitor::visitStopStream(MemgraphCypher::StopStreamContext *ctx) { auto *stream_query = storage_->Create(); stream_query->action_ = StreamQuery::Action::STOP_STREAM; - stream_query->stream_name_ = ctx->streamName()->symbolicName()->accept(this).as(); + stream_query->stream_name_ = std::any_cast(ctx->streamName()->symbolicName()->accept(this)); return stream_query; } @@ -824,26 +827,26 @@ antlrcpp::Any CypherMainVisitor::visitShowStreams(MemgraphCypher::ShowStreamsCon antlrcpp::Any CypherMainVisitor::visitCheckStream(MemgraphCypher::CheckStreamContext *ctx) { auto *stream_query = storage_->Create(); stream_query->action_ = StreamQuery::Action::CHECK_STREAM; - stream_query->stream_name_ = ctx->streamName()->symbolicName()->accept(this).as(); + stream_query->stream_name_ = std::any_cast(ctx->streamName()->symbolicName()->accept(this)); if (ctx->BATCH_LIMIT()) { if (!ctx->batchLimit->numberLiteral() || !ctx->batchLimit->numberLiteral()->integerLiteral()) { throw SemanticException("Batch limit should be an integer literal!"); } - stream_query->batch_limit_ = ctx->batchLimit->accept(this); + stream_query->batch_limit_ = std::any_cast(ctx->batchLimit->accept(this)); } if (ctx->TIMEOUT()) { if (!ctx->timeout->numberLiteral() || !ctx->timeout->numberLiteral()->integerLiteral()) { throw SemanticException("Timeout should be an integer literal!"); } - stream_query->timeout_ = ctx->timeout->accept(this); + stream_query->timeout_ = std::any_cast(ctx->timeout->accept(this)); } return stream_query; } antlrcpp::Any CypherMainVisitor::visitSettingQuery(MemgraphCypher::SettingQueryContext *ctx) { MG_ASSERT(ctx->children.size() == 1, "SettingQuery should have exactly one child!"); - auto *setting_query = ctx->children[0]->accept(this).as(); + auto *setting_query = std::any_cast(ctx->children[0]->accept(this)); query_ = setting_query; return setting_query; } @@ -860,10 +863,10 @@ antlrcpp::Any CypherMainVisitor::visitSetSetting(MemgraphCypher::SetSettingConte throw SemanticException("Setting value should be a string literal"); } - setting_query->setting_name_ = ctx->settingName()->accept(this); + setting_query->setting_name_ = std::any_cast(ctx->settingName()->accept(this)); MG_ASSERT(setting_query->setting_name_); - setting_query->setting_value_ = ctx->settingValue()->accept(this); + setting_query->setting_value_ = std::any_cast(ctx->settingValue()->accept(this)); MG_ASSERT(setting_query->setting_value_); return setting_query; } @@ -876,7 +879,7 @@ antlrcpp::Any CypherMainVisitor::visitShowSetting(MemgraphCypher::ShowSettingCon throw SemanticException("Setting name should be a string literal"); } - setting_query->setting_name_ = ctx->settingName()->accept(this); + setting_query->setting_name_ = std::any_cast(ctx->settingName()->accept(this)); MG_ASSERT(setting_query->setting_name_); return setting_query; @@ -898,7 +901,7 @@ antlrcpp::Any CypherMainVisitor::visitCypherUnion(MemgraphCypher::CypherUnionCon bool distinct = !ctx->ALL(); auto *cypher_union = storage_->Create(distinct); DMG_ASSERT(ctx->singleQuery(), "Expected single query."); - cypher_union->single_query_ = ctx->singleQuery()->accept(this).as(); + cypher_union->single_query_ = std::any_cast(ctx->singleQuery()->accept(this)); return cypher_union; } @@ -906,10 +909,10 @@ antlrcpp::Any CypherMainVisitor::visitSingleQuery(MemgraphCypher::SingleQueryCon auto *single_query = storage_->Create(); for (auto *child : ctx->clause()) { antlrcpp::Any got = child->accept(this); - if (got.is()) { - single_query->clauses_.push_back(got.as()); + if (got.type() == typeid(Clause *)) { + single_query->clauses_.push_back(std::any_cast(got)); } else { - auto child_clauses = got.as>(); + auto child_clauses = std::any_cast>(got); single_query->clauses_.insert(single_query->clauses_.end(), child_clauses.begin(), child_clauses.end()); } } @@ -1021,42 +1024,42 @@ antlrcpp::Any CypherMainVisitor::visitSingleQuery(MemgraphCypher::SingleQueryCon antlrcpp::Any CypherMainVisitor::visitClause(MemgraphCypher::ClauseContext *ctx) { if (ctx->cypherReturn()) { - return static_cast(ctx->cypherReturn()->accept(this).as()); + return static_cast(std::any_cast(ctx->cypherReturn()->accept(this))); } if (ctx->cypherMatch()) { - return static_cast(ctx->cypherMatch()->accept(this).as()); + return static_cast(std::any_cast(ctx->cypherMatch()->accept(this))); } if (ctx->create()) { - return static_cast(ctx->create()->accept(this).as()); + return static_cast(std::any_cast(ctx->create()->accept(this))); } if (ctx->cypherDelete()) { - return static_cast(ctx->cypherDelete()->accept(this).as()); + return static_cast(std::any_cast(ctx->cypherDelete()->accept(this))); } if (ctx->set()) { // Different return type!!! - return ctx->set()->accept(this).as>(); + return std::any_cast>(ctx->set()->accept(this)); } if (ctx->remove()) { // Different return type!!! - return ctx->remove()->accept(this).as>(); + return std::any_cast>(ctx->remove()->accept(this)); } if (ctx->with()) { - return static_cast(ctx->with()->accept(this).as()); + return static_cast(std::any_cast(ctx->with()->accept(this))); } if (ctx->merge()) { - return static_cast(ctx->merge()->accept(this).as()); + return static_cast(std::any_cast(ctx->merge()->accept(this))); } if (ctx->unwind()) { - return static_cast(ctx->unwind()->accept(this).as()); + return static_cast(std::any_cast(ctx->unwind()->accept(this))); } if (ctx->callProcedure()) { - return static_cast(ctx->callProcedure()->accept(this).as()); + return static_cast(std::any_cast(ctx->callProcedure()->accept(this))); } if (ctx->loadCsv()) { - return static_cast(ctx->loadCsv()->accept(this).as()); + return static_cast(std::any_cast(ctx->loadCsv()->accept(this))); } if (ctx->foreach ()) { - return static_cast(ctx->foreach ()->accept(this).as()); + return static_cast(std::any_cast(ctx->foreach ()->accept(this))); } // TODO: implement other clauses. throw utils::NotYetImplemented("clause '{}'", ctx->getText()); @@ -1067,15 +1070,15 @@ antlrcpp::Any CypherMainVisitor::visitCypherMatch(MemgraphCypher::CypherMatchCon auto *match = storage_->Create(); match->optional_ = !!ctx->OPTIONAL(); if (ctx->where()) { - match->where_ = ctx->where()->accept(this); + match->where_ = std::any_cast(ctx->where()->accept(this)); } - match->patterns_ = ctx->pattern()->accept(this).as>(); + match->patterns_ = std::any_cast>(ctx->pattern()->accept(this)); return match; } antlrcpp::Any CypherMainVisitor::visitCreate(MemgraphCypher::CreateContext *ctx) { auto *create = storage_->Create(); - create->patterns_ = ctx->pattern()->accept(this).as>(); + create->patterns_ = std::any_cast>(ctx->pattern()->accept(this)); return create; } @@ -1093,7 +1096,7 @@ antlrcpp::Any CypherMainVisitor::visitCallProcedure(MemgraphCypher::CallProcedur call_proc->procedure_name_ = JoinSymbolicNames(this, ctx->procedureName()->symbolicName()); call_proc->arguments_.reserve(ctx->expression().size()); for (auto *expr : ctx->expression()) { - call_proc->arguments_.push_back(expr->accept(this)); + call_proc->arguments_.push_back(std::any_cast(expr->accept(this))); } if (auto *memory_limit_ctx = ctx->procedureMemoryLimit()) { @@ -1133,12 +1136,12 @@ antlrcpp::Any CypherMainVisitor::visitCallProcedure(MemgraphCypher::CallProcedur call_proc->result_identifiers_.reserve(yield_ctx->procedureResult().size()); for (auto *result : yield_ctx->procedureResult()) { MG_ASSERT(result->variable().size() == 1 || result->variable().size() == 2); - call_proc->result_fields_.push_back(result->variable()[0]->accept(this).as()); + call_proc->result_fields_.push_back(std::any_cast(result->variable()[0]->accept(this))); std::string result_alias; if (result->variable().size() == 2) { - result_alias = result->variable()[1]->accept(this).as(); + result_alias = std::any_cast(result->variable()[1]->accept(this)); } else { - result_alias = result->variable()[0]->accept(this).as(); + result_alias = std::any_cast(result->variable()[0]->accept(this)); } call_proc->result_identifiers_.push_back(storage_->Create(result_alias)); } @@ -1174,7 +1177,7 @@ antlrcpp::Any CypherMainVisitor::visitCallProcedure(MemgraphCypher::CallProcedur * @return std::string */ antlrcpp::Any CypherMainVisitor::visitUserOrRoleName(MemgraphCypher::UserOrRoleNameContext *ctx) { - return ctx->symbolicName()->accept(this).as(); + return std::any_cast(ctx->symbolicName()->accept(this)); } /** @@ -1183,7 +1186,7 @@ antlrcpp::Any CypherMainVisitor::visitUserOrRoleName(MemgraphCypher::UserOrRoleN antlrcpp::Any CypherMainVisitor::visitCreateRole(MemgraphCypher::CreateRoleContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::CREATE_ROLE; - auth->role_ = ctx->role->accept(this).as(); + auth->role_ = std::any_cast(ctx->role->accept(this)); return auth; } @@ -1193,7 +1196,7 @@ antlrcpp::Any CypherMainVisitor::visitCreateRole(MemgraphCypher::CreateRoleConte antlrcpp::Any CypherMainVisitor::visitDropRole(MemgraphCypher::DropRoleContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::DROP_ROLE; - auth->role_ = ctx->role->accept(this).as(); + auth->role_ = std::any_cast(ctx->role->accept(this)); return auth; } @@ -1212,12 +1215,12 @@ antlrcpp::Any CypherMainVisitor::visitShowRoles(MemgraphCypher::ShowRolesContext antlrcpp::Any CypherMainVisitor::visitCreateUser(MemgraphCypher::CreateUserContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::CREATE_USER; - auth->user_ = ctx->user->accept(this).as(); + auth->user_ = std::any_cast(ctx->user->accept(this)); if (ctx->password) { if (!ctx->password->StringLiteral() && !ctx->literal()->CYPHERNULL()) { throw SyntaxException("Password should be a string literal or null."); } - auth->password_ = ctx->password->accept(this); + auth->password_ = std::any_cast(ctx->password->accept(this)); } return auth; } @@ -1228,11 +1231,11 @@ antlrcpp::Any CypherMainVisitor::visitCreateUser(MemgraphCypher::CreateUserConte antlrcpp::Any CypherMainVisitor::visitSetPassword(MemgraphCypher::SetPasswordContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::SET_PASSWORD; - auth->user_ = ctx->user->accept(this).as(); + auth->user_ = std::any_cast(ctx->user->accept(this)); if (!ctx->password->StringLiteral() && !ctx->literal()->CYPHERNULL()) { throw SyntaxException("Password should be a string literal or null."); } - auth->password_ = ctx->password->accept(this); + auth->password_ = std::any_cast(ctx->password->accept(this)); return auth; } @@ -1242,7 +1245,7 @@ antlrcpp::Any CypherMainVisitor::visitSetPassword(MemgraphCypher::SetPasswordCon antlrcpp::Any CypherMainVisitor::visitDropUser(MemgraphCypher::DropUserContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::DROP_USER; - auth->user_ = ctx->user->accept(this).as(); + auth->user_ = std::any_cast(ctx->user->accept(this)); return auth; } @@ -1261,8 +1264,8 @@ antlrcpp::Any CypherMainVisitor::visitShowUsers(MemgraphCypher::ShowUsersContext antlrcpp::Any CypherMainVisitor::visitSetRole(MemgraphCypher::SetRoleContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::SET_ROLE; - auth->user_ = ctx->user->accept(this).as(); - auth->role_ = ctx->role->accept(this).as(); + auth->user_ = std::any_cast(ctx->user->accept(this)); + auth->role_ = std::any_cast(ctx->role->accept(this)); return auth; } @@ -1272,7 +1275,7 @@ antlrcpp::Any CypherMainVisitor::visitSetRole(MemgraphCypher::SetRoleContext *ct antlrcpp::Any CypherMainVisitor::visitClearRole(MemgraphCypher::ClearRoleContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::CLEAR_ROLE; - auth->user_ = ctx->user->accept(this).as(); + auth->user_ = std::any_cast(ctx->user->accept(this)); return auth; } @@ -1282,10 +1285,10 @@ antlrcpp::Any CypherMainVisitor::visitClearRole(MemgraphCypher::ClearRoleContext antlrcpp::Any CypherMainVisitor::visitGrantPrivilege(MemgraphCypher::GrantPrivilegeContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::GRANT_PRIVILEGE; - auth->user_or_role_ = ctx->userOrRole->accept(this).as(); + auth->user_or_role_ = std::any_cast(ctx->userOrRole->accept(this)); if (ctx->privilegeList()) { for (auto *privilege : ctx->privilegeList()->privilege()) { - auth->privileges_.push_back(privilege->accept(this)); + auth->privileges_.push_back(std::any_cast(privilege->accept(this))); } } else { /* grant all privileges */ @@ -1300,10 +1303,10 @@ antlrcpp::Any CypherMainVisitor::visitGrantPrivilege(MemgraphCypher::GrantPrivil antlrcpp::Any CypherMainVisitor::visitDenyPrivilege(MemgraphCypher::DenyPrivilegeContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::DENY_PRIVILEGE; - auth->user_or_role_ = ctx->userOrRole->accept(this).as(); + auth->user_or_role_ = std::any_cast(ctx->userOrRole->accept(this)); if (ctx->privilegeList()) { for (auto *privilege : ctx->privilegeList()->privilege()) { - auth->privileges_.push_back(privilege->accept(this)); + auth->privileges_.push_back(std::any_cast(privilege->accept(this))); } } else { /* deny all privileges */ @@ -1318,10 +1321,10 @@ antlrcpp::Any CypherMainVisitor::visitDenyPrivilege(MemgraphCypher::DenyPrivileg antlrcpp::Any CypherMainVisitor::visitRevokePrivilege(MemgraphCypher::RevokePrivilegeContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::REVOKE_PRIVILEGE; - auth->user_or_role_ = ctx->userOrRole->accept(this).as(); + auth->user_or_role_ = std::any_cast(ctx->userOrRole->accept(this)); if (ctx->privilegeList()) { for (auto *privilege : ctx->privilegeList()->privilege()) { - auth->privileges_.push_back(privilege->accept(this)); + auth->privileges_.push_back(std::any_cast(privilege->accept(this))); } } else { /* revoke all privileges */ @@ -1364,7 +1367,7 @@ antlrcpp::Any CypherMainVisitor::visitPrivilege(MemgraphCypher::PrivilegeContext antlrcpp::Any CypherMainVisitor::visitShowPrivileges(MemgraphCypher::ShowPrivilegesContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::SHOW_PRIVILEGES; - auth->user_or_role_ = ctx->userOrRole->accept(this).as(); + auth->user_or_role_ = std::any_cast(ctx->userOrRole->accept(this)); return auth; } @@ -1374,7 +1377,7 @@ antlrcpp::Any CypherMainVisitor::visitShowPrivileges(MemgraphCypher::ShowPrivile antlrcpp::Any CypherMainVisitor::visitShowRoleForUser(MemgraphCypher::ShowRoleForUserContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::SHOW_ROLE_FOR_USER; - auth->user_ = ctx->user->accept(this).as(); + auth->user_ = std::any_cast(ctx->user->accept(this)); return auth; } @@ -1384,13 +1387,13 @@ antlrcpp::Any CypherMainVisitor::visitShowRoleForUser(MemgraphCypher::ShowRoleFo antlrcpp::Any CypherMainVisitor::visitShowUsersForRole(MemgraphCypher::ShowUsersForRoleContext *ctx) { AuthQuery *auth = storage_->Create(); auth->action_ = AuthQuery::Action::SHOW_USERS_FOR_ROLE; - auth->role_ = ctx->role->accept(this).as(); + auth->role_ = std::any_cast(ctx->role->accept(this)); return auth; } antlrcpp::Any CypherMainVisitor::visitCypherReturn(MemgraphCypher::CypherReturnContext *ctx) { auto *return_clause = storage_->Create(); - return_clause->body_ = ctx->returnBody()->accept(this); + return_clause->body_ = std::any_cast(ctx->returnBody()->accept(this)); if (ctx->DISTINCT()) { return_clause->body_.distinct = true; } @@ -1400,23 +1403,23 @@ antlrcpp::Any CypherMainVisitor::visitCypherReturn(MemgraphCypher::CypherReturnC antlrcpp::Any CypherMainVisitor::visitReturnBody(MemgraphCypher::ReturnBodyContext *ctx) { ReturnBody body; if (ctx->order()) { - body.order_by = ctx->order()->accept(this).as>(); + body.order_by = std::any_cast>(ctx->order()->accept(this)); } if (ctx->skip()) { - body.skip = static_cast(ctx->skip()->accept(this)); + body.skip = static_cast(std::any_cast(ctx->skip()->accept(this))); } if (ctx->limit()) { - body.limit = static_cast(ctx->limit()->accept(this)); + body.limit = static_cast(std::any_cast(ctx->limit()->accept(this))); } std::tie(body.all_identifiers, body.named_expressions) = - ctx->returnItems()->accept(this).as>>(); + std::any_cast>>(ctx->returnItems()->accept(this)); return body; } antlrcpp::Any CypherMainVisitor::visitReturnItems(MemgraphCypher::ReturnItemsContext *ctx) { std::vector named_expressions; for (auto *item : ctx->returnItem()) { - named_expressions.push_back(item->accept(this)); + named_expressions.push_back(std::any_cast(item->accept(this))); } return std::pair>(ctx->getTokens(MemgraphCypher::ASTERISK).size(), named_expressions); @@ -1424,10 +1427,10 @@ antlrcpp::Any CypherMainVisitor::visitReturnItems(MemgraphCypher::ReturnItemsCon antlrcpp::Any CypherMainVisitor::visitReturnItem(MemgraphCypher::ReturnItemContext *ctx) { auto *named_expr = storage_->Create(); - named_expr->expression_ = ctx->expression()->accept(this); + named_expr->expression_ = std::any_cast(ctx->expression()->accept(this)); MG_ASSERT(named_expr->expression_); if (ctx->variable()) { - named_expr->name_ = std::string(ctx->variable()->accept(this).as()); + named_expr->name_ = std::string(std::any_cast(ctx->variable()->accept(this))); users_identifiers.insert(named_expr->name_); } else { if (in_with_ && !utils::IsSubtype(*named_expr->expression_, Identifier::kType)) { @@ -1442,33 +1445,34 @@ antlrcpp::Any CypherMainVisitor::visitReturnItem(MemgraphCypher::ReturnItemConte antlrcpp::Any CypherMainVisitor::visitOrder(MemgraphCypher::OrderContext *ctx) { std::vector order_by; for (auto *sort_item : ctx->sortItem()) { - order_by.push_back(sort_item->accept(this)); + order_by.push_back(std::any_cast(sort_item->accept(this))); } return order_by; } antlrcpp::Any CypherMainVisitor::visitSortItem(MemgraphCypher::SortItemContext *ctx) { - return SortItem{ctx->DESC() || ctx->DESCENDING() ? Ordering::DESC : Ordering::ASC, ctx->expression()->accept(this)}; + return SortItem{ctx->DESC() || ctx->DESCENDING() ? Ordering::DESC : Ordering::ASC, + std::any_cast(ctx->expression()->accept(this))}; } antlrcpp::Any CypherMainVisitor::visitNodePattern(MemgraphCypher::NodePatternContext *ctx) { auto *node = storage_->Create(); if (ctx->variable()) { - std::string variable = ctx->variable()->accept(this); + auto variable = std::any_cast(ctx->variable()->accept(this)); node->identifier_ = storage_->Create(variable); users_identifiers.insert(variable); } else { anonymous_identifiers.push_back(&node->identifier_); } if (ctx->nodeLabels()) { - node->labels_ = ctx->nodeLabels()->accept(this).as>(); + node->labels_ = std::any_cast>(ctx->nodeLabels()->accept(this)); } if (ctx->properties()) { // This can return either properties or parameters if (ctx->properties()->mapLiteral()) { - node->properties_ = ctx->properties()->accept(this).as>(); + node->properties_ = std::any_cast>(ctx->properties()->accept(this)); } else { - node->properties_ = ctx->properties()->accept(this).as(); + node->properties_ = std::any_cast(ctx->properties()->accept(this)); } } return node; @@ -1477,7 +1481,7 @@ antlrcpp::Any CypherMainVisitor::visitNodePattern(MemgraphCypher::NodePatternCon antlrcpp::Any CypherMainVisitor::visitNodeLabels(MemgraphCypher::NodeLabelsContext *ctx) { std::vector labels; for (auto *node_label : ctx->nodeLabel()) { - labels.push_back(AddLabel(node_label->accept(this))); + labels.push_back(AddLabel(std::any_cast(node_label->accept(this)))); } return labels; } @@ -1494,8 +1498,8 @@ antlrcpp::Any CypherMainVisitor::visitProperties(MemgraphCypher::PropertiesConte antlrcpp::Any CypherMainVisitor::visitMapLiteral(MemgraphCypher::MapLiteralContext *ctx) { std::unordered_map map; for (int i = 0; i < static_cast(ctx->propertyKeyName().size()); ++i) { - PropertyIx key = ctx->propertyKeyName()[i]->accept(this); - Expression *value = ctx->expression()[i]->accept(this); + auto key = std::any_cast(ctx->propertyKeyName()[i]->accept(this)); + auto *value = std::any_cast(ctx->expression()[i]->accept(this)); if (!map.insert({key, value}).second) { throw SemanticException("Same key can't appear twice in a map literal."); } @@ -1505,12 +1509,14 @@ antlrcpp::Any CypherMainVisitor::visitMapLiteral(MemgraphCypher::MapLiteralConte antlrcpp::Any CypherMainVisitor::visitListLiteral(MemgraphCypher::ListLiteralContext *ctx) { std::vector expressions; - for (auto expr_ctx_ptr : ctx->expression()) expressions.push_back(expr_ctx_ptr->accept(this)); + for (auto *expr_ctx : ctx->expression()) { + expressions.push_back(std::any_cast(expr_ctx->accept(this))); + } return expressions; } antlrcpp::Any CypherMainVisitor::visitPropertyKeyName(MemgraphCypher::PropertyKeyNameContext *ctx) { - return AddProperty(visitChildren(ctx)); + return AddProperty(std::any_cast(visitChildren(ctx))); } antlrcpp::Any CypherMainVisitor::visitSymbolicName(MemgraphCypher::SymbolicNameContext *ctx) { @@ -1548,15 +1554,15 @@ antlrcpp::Any CypherMainVisitor::visitSymbolicName(MemgraphCypher::SymbolicNameC antlrcpp::Any CypherMainVisitor::visitPattern(MemgraphCypher::PatternContext *ctx) { std::vector patterns; for (auto *pattern_part : ctx->patternPart()) { - patterns.push_back(pattern_part->accept(this)); + patterns.push_back(std::any_cast(pattern_part->accept(this))); } return patterns; } antlrcpp::Any CypherMainVisitor::visitPatternPart(MemgraphCypher::PatternPartContext *ctx) { - Pattern *pattern = ctx->anonymousPatternPart()->accept(this); + auto *pattern = std::any_cast(ctx->anonymousPatternPart()->accept(this)); if (ctx->variable()) { - std::string variable = ctx->variable()->accept(this); + auto variable = std::any_cast(ctx->variable()->accept(this)); pattern->identifier_ = storage_->Create(variable); users_identifiers.insert(variable); } else { @@ -1569,10 +1575,10 @@ antlrcpp::Any CypherMainVisitor::visitPatternElement(MemgraphCypher::PatternElem if (ctx->patternElement()) { return ctx->patternElement()->accept(this); } - auto pattern = storage_->Create(); - pattern->atoms_.push_back(ctx->nodePattern()->accept(this).as()); + auto *pattern = storage_->Create(); + pattern->atoms_.push_back(std::any_cast(ctx->nodePattern()->accept(this))); for (auto *pattern_element_chain : ctx->patternElementChain()) { - std::pair element = pattern_element_chain->accept(this); + auto element = std::any_cast>(pattern_element_chain->accept(this)); pattern->atoms_.push_back(element.first); pattern->atoms_.push_back(element.second); } @@ -1580,8 +1586,8 @@ antlrcpp::Any CypherMainVisitor::visitPatternElement(MemgraphCypher::PatternElem } antlrcpp::Any CypherMainVisitor::visitPatternElementChain(MemgraphCypher::PatternElementChainContext *ctx) { - return std::pair(ctx->relationshipPattern()->accept(this).as(), - ctx->nodePattern()->accept(this).as()); + return std::pair(std::any_cast(ctx->relationshipPattern()->accept(this)), + std::any_cast(ctx->nodePattern()->accept(this))); } antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(MemgraphCypher::RelationshipPatternContext *ctx) { @@ -1592,7 +1598,7 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(MemgraphCypher::Relati edge->type_ = EdgeAtom::Type::SINGLE; if (variableExpansion) std::tie(edge->type_, edge->lower_bound_, edge->upper_bound_) = - variableExpansion->accept(this).as>(); + std::any_cast>(variableExpansion->accept(this)); if (ctx->leftArrowHead() && !ctx->rightArrowHead()) { edge->direction_ = EdgeAtom::Direction::IN; @@ -1610,7 +1616,7 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(MemgraphCypher::Relati } if (relationshipDetail->name) { - std::string variable = relationshipDetail->name->accept(this); + auto variable = std::any_cast(relationshipDetail->name->accept(this)); edge->identifier_ = storage_->Create(variable); users_identifiers.insert(variable); } else { @@ -1618,7 +1624,8 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(MemgraphCypher::Relati } if (relationshipDetail->relationshipTypes()) { - edge->edge_types_ = ctx->relationshipDetail()->relationshipTypes()->accept(this).as>(); + edge->edge_types_ = + std::any_cast>(ctx->relationshipDetail()->relationshipTypes()->accept(this)); } auto relationshipLambdas = relationshipDetail->relationshipLambda(); @@ -1629,16 +1636,16 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(MemgraphCypher::Relati "path expansion."); auto visit_lambda = [this](auto *lambda) { EdgeAtom::Lambda edge_lambda; - std::string traversed_edge_variable = lambda->traversed_edge->accept(this); + auto traversed_edge_variable = std::any_cast(lambda->traversed_edge->accept(this)); edge_lambda.inner_edge = storage_->Create(traversed_edge_variable); - std::string traversed_node_variable = lambda->traversed_node->accept(this); + auto traversed_node_variable = std::any_cast(lambda->traversed_node->accept(this)); edge_lambda.inner_node = storage_->Create(traversed_node_variable); - edge_lambda.expression = lambda->expression()->accept(this); + edge_lambda.expression = std::any_cast(lambda->expression()->accept(this)); return edge_lambda; }; auto visit_total_weight = [&]() { if (relationshipDetail->total_weight) { - std::string total_weight_name = relationshipDetail->total_weight->accept(this); + auto total_weight_name = std::any_cast(relationshipDetail->total_weight->accept(this)); edge->total_weight_ = storage_->Create(total_weight_name); } else { anonymous_identifiers.push_back(&edge->total_weight_); @@ -1688,11 +1695,11 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(MemgraphCypher::Relati break; case 1: { if (properties[0]->mapLiteral()) { - edge->properties_ = properties[0]->accept(this).as>(); + edge->properties_ = std::any_cast>(properties[0]->accept(this)); break; } MG_ASSERT(properties[0]->parameter()); - edge->properties_ = properties[0]->accept(this).as(); + edge->properties_ = std::any_cast(properties[0]->accept(this)); break; } default: @@ -1715,7 +1722,7 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipLambda(MemgraphCypher::Relatio antlrcpp::Any CypherMainVisitor::visitRelationshipTypes(MemgraphCypher::RelationshipTypesContext *ctx) { std::vector types; for (auto *edge_type : ctx->relTypeName()) { - types.push_back(AddEdgeType(edge_type->accept(this))); + types.push_back(AddEdgeType(std::any_cast(edge_type->accept(this)))); } return types; } @@ -1735,7 +1742,7 @@ antlrcpp::Any CypherMainVisitor::visitVariableExpansion(MemgraphCypher::Variable // Case -[*]- } else if (ctx->expression().size() == 1U) { auto dots_tokens = ctx->getTokens(MemgraphCypher::DOTS); - Expression *bound = ctx->expression()[0]->accept(this); + auto *bound = std::any_cast(ctx->expression()[0]->accept(this)); if (!dots_tokens.size()) { // Case -[*bound]- if (edge_type != EdgeAtom::Type::WEIGHTED_SHORTEST_PATH) lower = bound; @@ -1749,8 +1756,8 @@ antlrcpp::Any CypherMainVisitor::visitVariableExpansion(MemgraphCypher::Variable } } else { // Case -[*lbound..rbound]- - lower = ctx->expression()[0]->accept(this); - upper = ctx->expression()[1]->accept(this); + lower = std::any_cast(ctx->expression()[0]->accept(this)); + upper = std::any_cast(ctx->expression()[1]->accept(this)); } if (lower && edge_type == EdgeAtom::Type::WEIGHTED_SHORTEST_PATH) throw SemanticException("Lower bound is not allowed in weighted shortest path expansion."); @@ -1759,7 +1766,7 @@ antlrcpp::Any CypherMainVisitor::visitVariableExpansion(MemgraphCypher::Variable } antlrcpp::Any CypherMainVisitor::visitExpression(MemgraphCypher::ExpressionContext *ctx) { - return static_cast(ctx->expression12()->accept(this)); + return std::any_cast(ctx->expression12()->accept(this)); } // OR. @@ -1805,11 +1812,11 @@ antlrcpp::Any CypherMainVisitor::visitExpression8(MemgraphCypher::Expression8Con // 4 <= 5 < 7 > 6 -> false // All of those comparisons evaluate to true in memgraph. std::vector children; - children.push_back(ctx->expression7()->accept(this)); + children.push_back(std::any_cast(ctx->expression7()->accept(this))); std::vector operators; auto partial_comparison_expressions = ctx->partialComparisonExpression(); for (auto *child : partial_comparison_expressions) { - children.push_back(child->expression7()->accept(this)); + children.push_back(std::any_cast(child->expression7()->accept(this))); } // First production is comparison operator. for (auto *child : partial_comparison_expressions) { @@ -1871,7 +1878,7 @@ antlrcpp::Any CypherMainVisitor::visitExpression4(MemgraphCypher::Expression4Con // IS NULL, IS NOT NULL, STARTS WITH, .. antlrcpp::Any CypherMainVisitor::visitExpression3a(MemgraphCypher::Expression3aContext *ctx) { - Expression *expression = ctx->expression3b()->accept(this); + auto *expression = std::any_cast(ctx->expression3b()->accept(this)); for (auto *op : ctx->stringAndNullOperators()) { if (op->IS() && op->NOT() && op->CYPHERNULL()) { @@ -1880,12 +1887,12 @@ antlrcpp::Any CypherMainVisitor::visitExpression3a(MemgraphCypher::Expression3aC } else if (op->IS() && op->CYPHERNULL()) { expression = static_cast(storage_->Create(expression)); } else if (op->IN()) { - expression = - static_cast(storage_->Create(expression, op->expression3b()->accept(this))); + expression = static_cast( + storage_->Create(expression, std::any_cast(op->expression3b()->accept(this)))); } else if (utils::StartsWith(op->getText(), "=~")) { auto *regex_match = storage_->Create(); regex_match->string_expr_ = expression; - regex_match->regex_ = op->expression3b()->accept(this); + regex_match->regex_ = std::any_cast(op->expression3b()->accept(this)); expression = regex_match; } else { std::string function_name; @@ -1898,7 +1905,7 @@ antlrcpp::Any CypherMainVisitor::visitExpression3a(MemgraphCypher::Expression3aC } else { throw utils::NotYetImplemented("function '{}'", op->getText()); } - auto expression2 = op->expression3b()->accept(this); + auto *expression2 = std::any_cast(op->expression3b()->accept(this)); std::vector args = {expression, expression2}; expression = static_cast(storage_->Create(function_name, args)); } @@ -1911,18 +1918,19 @@ antlrcpp::Any CypherMainVisitor::visitStringAndNullOperators(MemgraphCypher::Str } antlrcpp::Any CypherMainVisitor::visitExpression3b(MemgraphCypher::Expression3bContext *ctx) { - Expression *expression = ctx->expression2a()->accept(this); + auto *expression = std::any_cast(ctx->expression2a()->accept(this)); for (auto *list_op : ctx->listIndexingOrSlicing()) { if (list_op->getTokens(MemgraphCypher::DOTS).size() == 0U) { // If there is no '..' then we need to create list indexing operator. - expression = storage_->Create(expression, list_op->expression()[0]->accept(this)); + expression = storage_->Create( + expression, std::any_cast(list_op->expression()[0]->accept(this))); } else if (!list_op->lower_bound && !list_op->upper_bound) { throw SemanticException("List slicing operator requires at least one bound."); } else { Expression *lower_bound_ast = - list_op->lower_bound ? static_cast(list_op->lower_bound->accept(this)) : nullptr; + list_op->lower_bound ? std::any_cast(list_op->lower_bound->accept(this)) : nullptr; Expression *upper_bound_ast = - list_op->upper_bound ? static_cast(list_op->upper_bound->accept(this)) : nullptr; + list_op->upper_bound ? std::any_cast(list_op->upper_bound->accept(this)) : nullptr; expression = storage_->Create(expression, lower_bound_ast, upper_bound_ast); } } @@ -1935,18 +1943,18 @@ antlrcpp::Any CypherMainVisitor::visitListIndexingOrSlicing(MemgraphCypher::List } antlrcpp::Any CypherMainVisitor::visitExpression2a(MemgraphCypher::Expression2aContext *ctx) { - Expression *expression = ctx->expression2b()->accept(this); + auto *expression = std::any_cast(ctx->expression2b()->accept(this)); if (ctx->nodeLabels()) { - auto labels = ctx->nodeLabels()->accept(this).as>(); + auto labels = std::any_cast>(ctx->nodeLabels()->accept(this)); expression = storage_->Create(expression, labels); } return expression; } antlrcpp::Any CypherMainVisitor::visitExpression2b(MemgraphCypher::Expression2bContext *ctx) { - Expression *expression = ctx->atom()->accept(this); + auto *expression = std::any_cast(ctx->atom()->accept(this)); for (auto *lookup : ctx->propertyLookup()) { - PropertyIx key = lookup->accept(this); + auto key = std::any_cast(lookup->accept(this)); auto property_lookup = storage_->Create(expression, key); expression = property_lookup; } @@ -1957,19 +1965,19 @@ antlrcpp::Any CypherMainVisitor::visitAtom(MemgraphCypher::AtomContext *ctx) { if (ctx->literal()) { return ctx->literal()->accept(this); } else if (ctx->parameter()) { - return static_cast(ctx->parameter()->accept(this).as()); + return static_cast(std::any_cast(ctx->parameter()->accept(this))); } else if (ctx->parenthesizedExpression()) { - return static_cast(ctx->parenthesizedExpression()->accept(this)); + return static_cast(std::any_cast(ctx->parenthesizedExpression()->accept(this))); } else if (ctx->variable()) { - std::string variable = ctx->variable()->accept(this); + auto variable = std::any_cast(ctx->variable()->accept(this)); users_identifiers.insert(variable); return static_cast(storage_->Create(variable)); } else if (ctx->functionInvocation()) { - return static_cast(ctx->functionInvocation()->accept(this)); + return std::any_cast(ctx->functionInvocation()->accept(this)); } else if (ctx->COALESCE()) { std::vector exprs; for (auto *expr_context : ctx->expression()) { - exprs.emplace_back(expr_context->accept(this).as()); + exprs.emplace_back(std::any_cast(expr_context->accept(this))); } return static_cast(storage_->Create(std::move(exprs))); } else if (ctx->COUNT()) { @@ -1978,57 +1986,57 @@ antlrcpp::Any CypherMainVisitor::visitAtom(MemgraphCypher::AtomContext *ctx) { // functionInvocation and atom producions in opencypher grammar. return static_cast(storage_->Create(nullptr, nullptr, Aggregation::Op::COUNT)); } else if (ctx->ALL()) { - auto *ident = - storage_->Create(ctx->filterExpression()->idInColl()->variable()->accept(this).as()); - Expression *list_expr = ctx->filterExpression()->idInColl()->expression()->accept(this); + auto *ident = storage_->Create( + std::any_cast(ctx->filterExpression()->idInColl()->variable()->accept(this))); + auto *list_expr = std::any_cast(ctx->filterExpression()->idInColl()->expression()->accept(this)); if (!ctx->filterExpression()->where()) { throw SyntaxException("ALL(...) requires a WHERE predicate."); } - Where *where = ctx->filterExpression()->where()->accept(this); + auto *where = std::any_cast(ctx->filterExpression()->where()->accept(this)); return static_cast(storage_->Create(ident, list_expr, where)); } else if (ctx->SINGLE()) { - auto *ident = - storage_->Create(ctx->filterExpression()->idInColl()->variable()->accept(this).as()); - Expression *list_expr = ctx->filterExpression()->idInColl()->expression()->accept(this); + auto *ident = storage_->Create( + std::any_cast(ctx->filterExpression()->idInColl()->variable()->accept(this))); + auto *list_expr = std::any_cast(ctx->filterExpression()->idInColl()->expression()->accept(this)); if (!ctx->filterExpression()->where()) { throw SyntaxException("SINGLE(...) requires a WHERE predicate."); } - Where *where = ctx->filterExpression()->where()->accept(this); + auto *where = std::any_cast(ctx->filterExpression()->where()->accept(this)); return static_cast(storage_->Create(ident, list_expr, where)); } else if (ctx->ANY()) { - auto *ident = - storage_->Create(ctx->filterExpression()->idInColl()->variable()->accept(this).as()); - Expression *list_expr = ctx->filterExpression()->idInColl()->expression()->accept(this); + auto *ident = storage_->Create( + std::any_cast(ctx->filterExpression()->idInColl()->variable()->accept(this))); + auto *list_expr = std::any_cast(ctx->filterExpression()->idInColl()->expression()->accept(this)); if (!ctx->filterExpression()->where()) { throw SyntaxException("ANY(...) requires a WHERE predicate."); } - Where *where = ctx->filterExpression()->where()->accept(this); + auto *where = std::any_cast(ctx->filterExpression()->where()->accept(this)); return static_cast(storage_->Create(ident, list_expr, where)); } else if (ctx->NONE()) { - auto *ident = - storage_->Create(ctx->filterExpression()->idInColl()->variable()->accept(this).as()); - Expression *list_expr = ctx->filterExpression()->idInColl()->expression()->accept(this); + auto *ident = storage_->Create( + std::any_cast(ctx->filterExpression()->idInColl()->variable()->accept(this))); + auto *list_expr = std::any_cast(ctx->filterExpression()->idInColl()->expression()->accept(this)); if (!ctx->filterExpression()->where()) { throw SyntaxException("NONE(...) requires a WHERE predicate."); } - Where *where = ctx->filterExpression()->where()->accept(this); + auto *where = std::any_cast(ctx->filterExpression()->where()->accept(this)); return static_cast(storage_->Create(ident, list_expr, where)); } else if (ctx->REDUCE()) { auto *accumulator = - storage_->Create(ctx->reduceExpression()->accumulator->accept(this).as()); - Expression *initializer = ctx->reduceExpression()->initial->accept(this); - auto *ident = - storage_->Create(ctx->reduceExpression()->idInColl()->variable()->accept(this).as()); - Expression *list = ctx->reduceExpression()->idInColl()->expression()->accept(this); - Expression *expr = ctx->reduceExpression()->expression().back()->accept(this); + storage_->Create(std::any_cast(ctx->reduceExpression()->accumulator->accept(this))); + auto *initializer = std::any_cast(ctx->reduceExpression()->initial->accept(this)); + auto *ident = storage_->Create( + std::any_cast(ctx->reduceExpression()->idInColl()->variable()->accept(this))); + auto *list = std::any_cast(ctx->reduceExpression()->idInColl()->expression()->accept(this)); + auto *expr = std::any_cast(ctx->reduceExpression()->expression().back()->accept(this)); return static_cast(storage_->Create(accumulator, initializer, ident, list, expr)); } else if (ctx->caseExpression()) { - return static_cast(ctx->caseExpression()->accept(this)); + return std::any_cast(ctx->caseExpression()->accept(this)); } else if (ctx->extractExpression()) { - auto *ident = - storage_->Create(ctx->extractExpression()->idInColl()->variable()->accept(this).as()); - Expression *list = ctx->extractExpression()->idInColl()->expression()->accept(this); - Expression *expr = ctx->extractExpression()->expression()->accept(this); + auto *ident = storage_->Create( + std::any_cast(ctx->extractExpression()->idInColl()->variable()->accept(this))); + auto *list = std::any_cast(ctx->extractExpression()->idInColl()->expression()->accept(this)); + auto *expr = std::any_cast(ctx->extractExpression()->expression()->accept(this)); return static_cast(storage_->Create(ident, list, expr)); } // TODO: Implement this. We don't support comprehensions, filtering... at @@ -2054,34 +2062,35 @@ antlrcpp::Any CypherMainVisitor::visitLiteral(MemgraphCypher::LiteralContext *ct return static_cast(storage_->Create(token_position)); } else if (ctx->StringLiteral()) { return static_cast(storage_->Create( - visitStringLiteral(ctx->StringLiteral()->getText()).as(), token_position)); + std::any_cast(visitStringLiteral(std::any_cast(ctx->StringLiteral()->getText()))), + token_position)); } else if (ctx->booleanLiteral()) { return static_cast( - storage_->Create(ctx->booleanLiteral()->accept(this).as(), token_position)); + storage_->Create(std::any_cast(ctx->booleanLiteral()->accept(this)), token_position)); } else if (ctx->numberLiteral()) { - return static_cast( - storage_->Create(ctx->numberLiteral()->accept(this).as(), token_position)); + return static_cast(storage_->Create( + std::any_cast(ctx->numberLiteral()->accept(this)), token_position)); } LOG_FATAL("Expected to handle all cases above"); } else if (ctx->listLiteral()) { return static_cast( - storage_->Create(ctx->listLiteral()->accept(this).as>())); + storage_->Create(std::any_cast>(ctx->listLiteral()->accept(this)))); } else { return static_cast(storage_->Create( - ctx->mapLiteral()->accept(this).as>())); + std::any_cast>(ctx->mapLiteral()->accept(this)))); } return visitChildren(ctx); } antlrcpp::Any CypherMainVisitor::visitParenthesizedExpression(MemgraphCypher::ParenthesizedExpressionContext *ctx) { - return static_cast(ctx->expression()->accept(this)); + return std::any_cast(ctx->expression()->accept(this)); } antlrcpp::Any CypherMainVisitor::visitNumberLiteral(MemgraphCypher::NumberLiteralContext *ctx) { if (ctx->integerLiteral()) { - return TypedValue(ctx->integerLiteral()->accept(this).as()); + return TypedValue(std::any_cast(ctx->integerLiteral()->accept(this))); } else if (ctx->doubleLiteral()) { - return TypedValue(ctx->doubleLiteral()->accept(this).as()); + return TypedValue(std::any_cast(ctx->doubleLiteral()->accept(this))); } else { // This should never happen, except grammar changes and we don't notice // change in this production. @@ -2094,10 +2103,10 @@ antlrcpp::Any CypherMainVisitor::visitFunctionInvocation(MemgraphCypher::Functio if (ctx->DISTINCT()) { throw utils::NotYetImplemented("DISTINCT function call"); } - std::string function_name = ctx->functionName()->accept(this); + auto function_name = std::any_cast(ctx->functionName()->accept(this)); std::vector expressions; for (auto *expression : ctx->expression()) { - expressions.push_back(expression->accept(this)); + expressions.push_back(std::any_cast(expression->accept(this))); } if (expressions.size() == 1U) { if (function_name == Aggregation::kCount) { @@ -2179,21 +2188,21 @@ antlrcpp::Any CypherMainVisitor::visitCypherDelete(MemgraphCypher::CypherDeleteC del->detach_ = true; } for (auto *expression : ctx->expression()) { - del->expressions_.push_back(expression->accept(this)); + del->expressions_.push_back(std::any_cast(expression->accept(this))); } return del; } antlrcpp::Any CypherMainVisitor::visitWhere(MemgraphCypher::WhereContext *ctx) { auto *where = storage_->Create(); - where->expression_ = ctx->expression()->accept(this); + where->expression_ = std::any_cast(ctx->expression()->accept(this)); return where; } antlrcpp::Any CypherMainVisitor::visitSet(MemgraphCypher::SetContext *ctx) { std::vector set_items; for (auto *set_item : ctx->setItem()) { - set_items.push_back(set_item->accept(this)); + set_items.push_back(std::any_cast(set_item->accept(this))); } return set_items; } @@ -2202,16 +2211,17 @@ antlrcpp::Any CypherMainVisitor::visitSetItem(MemgraphCypher::SetItemContext *ct // SetProperty if (ctx->propertyExpression()) { auto *set_property = storage_->Create(); - set_property->property_lookup_ = ctx->propertyExpression()->accept(this); - set_property->expression_ = ctx->expression()->accept(this); + set_property->property_lookup_ = std::any_cast(ctx->propertyExpression()->accept(this)); + set_property->expression_ = std::any_cast(ctx->expression()->accept(this)); return static_cast(set_property); } // SetProperties either assignment or update if (ctx->getTokens(MemgraphCypher::EQ).size() || ctx->getTokens(MemgraphCypher::PLUS_EQ).size()) { auto *set_properties = storage_->Create(); - set_properties->identifier_ = storage_->Create(ctx->variable()->accept(this).as()); - set_properties->expression_ = ctx->expression()->accept(this); + set_properties->identifier_ = + storage_->Create(std::any_cast(ctx->variable()->accept(this))); + set_properties->expression_ = std::any_cast(ctx->expression()->accept(this)); if (ctx->getTokens(MemgraphCypher::PLUS_EQ).size()) { set_properties->update_ = true; } @@ -2220,15 +2230,15 @@ antlrcpp::Any CypherMainVisitor::visitSetItem(MemgraphCypher::SetItemContext *ct // SetLabels auto *set_labels = storage_->Create(); - set_labels->identifier_ = storage_->Create(ctx->variable()->accept(this).as()); - set_labels->labels_ = ctx->nodeLabels()->accept(this).as>(); + set_labels->identifier_ = storage_->Create(std::any_cast(ctx->variable()->accept(this))); + set_labels->labels_ = std::any_cast>(ctx->nodeLabels()->accept(this)); return static_cast(set_labels); } antlrcpp::Any CypherMainVisitor::visitRemove(MemgraphCypher::RemoveContext *ctx) { std::vector remove_items; for (auto *remove_item : ctx->removeItem()) { - remove_items.push_back(remove_item->accept(this)); + remove_items.push_back(std::any_cast(remove_item->accept(this))); } return remove_items; } @@ -2237,21 +2247,21 @@ antlrcpp::Any CypherMainVisitor::visitRemoveItem(MemgraphCypher::RemoveItemConte // RemoveProperty if (ctx->propertyExpression()) { auto *remove_property = storage_->Create(); - remove_property->property_lookup_ = ctx->propertyExpression()->accept(this); + remove_property->property_lookup_ = std::any_cast(ctx->propertyExpression()->accept(this)); return static_cast(remove_property); } // RemoveLabels auto *remove_labels = storage_->Create(); - remove_labels->identifier_ = storage_->Create(ctx->variable()->accept(this).as()); - remove_labels->labels_ = ctx->nodeLabels()->accept(this).as>(); + remove_labels->identifier_ = storage_->Create(std::any_cast(ctx->variable()->accept(this))); + remove_labels->labels_ = std::any_cast>(ctx->nodeLabels()->accept(this)); return static_cast(remove_labels); } antlrcpp::Any CypherMainVisitor::visitPropertyExpression(MemgraphCypher::PropertyExpressionContext *ctx) { - Expression *expression = ctx->atom()->accept(this); + auto *expression = std::any_cast(ctx->atom()->accept(this)); for (auto *lookup : ctx->propertyLookup()) { - PropertyIx key = lookup->accept(this); + auto key = std::any_cast(lookup->accept(this)); auto property_lookup = storage_->Create(expression, key); expression = property_lookup; } @@ -2260,17 +2270,18 @@ antlrcpp::Any CypherMainVisitor::visitPropertyExpression(MemgraphCypher::Propert } antlrcpp::Any CypherMainVisitor::visitCaseExpression(MemgraphCypher::CaseExpressionContext *ctx) { - Expression *test_expression = ctx->test ? ctx->test->accept(this).as() : nullptr; + Expression *test_expression = ctx->test ? std::any_cast(ctx->test->accept(this)) : nullptr; auto alternatives = ctx->caseAlternatives(); // Reverse alternatives so that tree of IfOperators can be built bottom-up. std::reverse(alternatives.begin(), alternatives.end()); - Expression *else_expression = ctx->else_expression ? ctx->else_expression->accept(this).as() + Expression *else_expression = ctx->else_expression ? std::any_cast(ctx->else_expression->accept(this)) : storage_->Create(TypedValue()); for (auto *alternative : alternatives) { Expression *condition = - test_expression ? storage_->Create(test_expression, alternative->when_expression->accept(this)) - : alternative->when_expression->accept(this).as(); - Expression *then_expression = alternative->then_expression->accept(this); + test_expression ? storage_->Create( + test_expression, std::any_cast(alternative->when_expression->accept(this))) + : std::any_cast(alternative->when_expression->accept(this)); + auto *then_expression = std::any_cast(alternative->then_expression->accept(this)); else_expression = storage_->Create(condition, then_expression, else_expression); } return else_expression; @@ -2284,22 +2295,22 @@ antlrcpp::Any CypherMainVisitor::visitCaseAlternatives(MemgraphCypher::CaseAlter antlrcpp::Any CypherMainVisitor::visitWith(MemgraphCypher::WithContext *ctx) { auto *with = storage_->Create(); in_with_ = true; - with->body_ = ctx->returnBody()->accept(this); + with->body_ = std::any_cast(ctx->returnBody()->accept(this)); in_with_ = false; if (ctx->DISTINCT()) { with->body_.distinct = true; } if (ctx->where()) { - with->where_ = ctx->where()->accept(this); + with->where_ = std::any_cast(ctx->where()->accept(this)); } return with; } antlrcpp::Any CypherMainVisitor::visitMerge(MemgraphCypher::MergeContext *ctx) { auto *merge = storage_->Create(); - merge->pattern_ = ctx->patternPart()->accept(this); + merge->pattern_ = std::any_cast(ctx->patternPart()->accept(this)); for (auto &merge_action : ctx->mergeAction()) { - auto set = merge_action->set()->accept(this).as>(); + auto set = std::any_cast>(merge_action->set()->accept(this)); if (merge_action->MATCH()) { merge->on_match_.insert(merge->on_match_.end(), set.begin(), set.end()); } else { @@ -2312,8 +2323,8 @@ antlrcpp::Any CypherMainVisitor::visitMerge(MemgraphCypher::MergeContext *ctx) { antlrcpp::Any CypherMainVisitor::visitUnwind(MemgraphCypher::UnwindContext *ctx) { auto *named_expr = storage_->Create(); - named_expr->expression_ = ctx->expression()->accept(this); - named_expr->name_ = std::string(ctx->variable()->accept(this).as()); + named_expr->expression_ = std::any_cast(ctx->expression()->accept(this)); + named_expr->name_ = std::any_cast(ctx->variable()->accept(this)); return storage_->Create(named_expr); } @@ -2326,27 +2337,27 @@ antlrcpp::Any CypherMainVisitor::visitForeach(MemgraphCypher::ForeachContext *ct auto *for_each = storage_->Create(); auto *named_expr = storage_->Create(); - named_expr->expression_ = ctx->expression()->accept(this); - named_expr->name_ = std::string(ctx->variable()->accept(this).as()); + named_expr->expression_ = std::any_cast(ctx->expression()->accept(this)); + named_expr->name_ = std::any_cast(ctx->variable()->accept(this)); for_each->named_expression_ = named_expr; for (auto *update_clause_ctx : ctx->updateClause()) { if (auto *set = update_clause_ctx->set(); set) { - auto set_items = visitSet(set).as>(); + auto set_items = std::any_cast>(visitSet(set)); std::copy(set_items.begin(), set_items.end(), std::back_inserter(for_each->clauses_)); } else if (auto *remove = update_clause_ctx->remove(); remove) { - auto remove_items = visitRemove(remove).as>(); + auto remove_items = std::any_cast>(visitRemove(remove)); std::copy(remove_items.begin(), remove_items.end(), std::back_inserter(for_each->clauses_)); } else if (auto *merge = update_clause_ctx->merge(); merge) { - for_each->clauses_.push_back(visitMerge(merge).as()); + for_each->clauses_.push_back(std::any_cast(visitMerge(merge))); } else if (auto *create = update_clause_ctx->create(); create) { - for_each->clauses_.push_back(visitCreate(create).as()); + for_each->clauses_.push_back(std::any_cast(visitCreate(create))); } else if (auto *cypher_delete = update_clause_ctx->cypherDelete(); cypher_delete) { - for_each->clauses_.push_back(visitCypherDelete(cypher_delete).as()); + for_each->clauses_.push_back(std::any_cast(visitCypherDelete(cypher_delete))); } else { auto *nested_for_each = update_clause_ctx->foreach (); MG_ASSERT(nested_for_each != nullptr, "Unexpected clause in FOREACH"); - for_each->clauses_.push_back(visitForeach(nested_for_each).as()); + for_each->clauses_.push_back(std::any_cast(visitForeach(nested_for_each))); } } diff --git a/src/query/v2/frontend/ast/cypher_main_visitor.hpp b/src/query/v2/frontend/ast/cypher_main_visitor.hpp index f0d5ba78b..767c8ce65 100644 --- a/src/query/v2/frontend/ast/cypher_main_visitor.hpp +++ b/src/query/v2/frontend/ast/cypher_main_visitor.hpp @@ -115,7 +115,7 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor { auto operators = ExtractOperators(all_children, allowed_operators); for (auto *expression : _expressions) { - expressions.push_back(expression->accept(this)); + expressions.push_back(std::any_cast(expression->accept(this))); } Expression *first_operand = expressions[0]; @@ -131,7 +131,7 @@ class CypherMainVisitor : public antlropencypher::MemgraphCypherBaseVisitor { DMG_ASSERT(_expression, "can't happen"); auto operators = ExtractOperators(all_children, allowed_operators); - Expression *expression = _expression->accept(this); + Expression *expression = std::any_cast(_expression->accept(this)); for (int i = (int)operators.size() - 1; i >= 0; --i) { expression = CreateUnaryOperatorByToken(operators[i], expression); } diff --git a/src/query/v2/interpreter.cpp b/src/query/v2/interpreter.cpp index a60d77dec..73f3e00be 100644 --- a/src/query/v2/interpreter.cpp +++ b/src/query/v2/interpreter.cpp @@ -1186,7 +1186,7 @@ PreparedQuery PrepareExplainQuery(ParsedQuery parsed_query, std::mapast_cache, &interpreter_context->antlr_lock, interpreter_context->config.query); + &interpreter_context->ast_cache, interpreter_context->config.query); auto *cypher_query = utils::Downcast(parsed_inner_query.query); MG_ASSERT(cypher_query, "Cypher grammar should not allow other queries in EXPLAIN"); @@ -1253,7 +1253,7 @@ PreparedQuery PrepareProfileQuery(ParsedQuery parsed_query, bool in_explicit_tra // full query string) when given just the inner query to execute. ParsedQuery parsed_inner_query = ParseQuery(parsed_query.query_string.substr(kProfileQueryStart.size()), parsed_query.user_parameters, - &interpreter_context->ast_cache, &interpreter_context->antlr_lock, interpreter_context->config.query); + &interpreter_context->ast_cache, interpreter_context->config.query); auto *cypher_query = utils::Downcast(parsed_inner_query.query); MG_ASSERT(cypher_query, "Cypher grammar should not allow other queries in PROFILE"); @@ -1571,8 +1571,7 @@ Callback CreateTrigger(TriggerQuery *trigger_query, interpreter_context->trigger_store.AddTrigger( std::move(trigger_name), trigger_statement, user_parameters, ToTriggerEventType(event_type), before_commit ? TriggerPhase::BEFORE_COMMIT : TriggerPhase::AFTER_COMMIT, &interpreter_context->ast_cache, - dba, &interpreter_context->antlr_lock, interpreter_context->config.query, std::move(owner), - interpreter_context->auth_checker); + dba, interpreter_context->config.query, std::move(owner), interpreter_context->auth_checker); return {}; }}; } @@ -2129,8 +2128,8 @@ Interpreter::PrepareResult Interpreter::Prepare(const std::string &query_string, query_execution->summary["cost_estimate"] = 0.0; utils::Timer parsing_timer; - ParsedQuery parsed_query = ParseQuery(query_string, params, &interpreter_context_->ast_cache, - &interpreter_context_->antlr_lock, interpreter_context_->config.query); + ParsedQuery parsed_query = + ParseQuery(query_string, params, &interpreter_context_->ast_cache, interpreter_context_->config.query); query_execution->summary["parsing_time"] = parsing_timer.Elapsed().count(); // Some queries require an active transaction in order to be prepared. diff --git a/src/query/v2/interpreter.hpp b/src/query/v2/interpreter.hpp index b1f89f22b..d3da9c724 100644 --- a/src/query/v2/interpreter.hpp +++ b/src/query/v2/interpreter.hpp @@ -171,13 +171,6 @@ struct InterpreterContext { storage::v3::Storage *db; - // ANTLR has singleton instance that is shared between threads. It is - // protected by locks inside of ANTLR. Unfortunately, they are not protected - // in a very good way. Once we have ANTLR version without race conditions we - // can remove this lock. This will probably never happen since ANTLR - // developers introduce more bugs in each version. Fortunately, we have - // cache so this lock probably won't impact performance much... - utils::SpinLock antlr_lock; std::optional tsc_frequency{utils::GetTSCFrequency()}; std::atomic is_shutting_down{false}; diff --git a/src/query/v2/trigger.cpp b/src/query/v2/trigger.cpp index 08f9ace9f..a8fe327de 100644 --- a/src/query/v2/trigger.cpp +++ b/src/query/v2/trigger.cpp @@ -153,10 +153,10 @@ std::vector> GetPredefinedIdentifier Trigger::Trigger(std::string name, const std::string &query, const std::map &user_parameters, const TriggerEventType event_type, utils::SkipList *query_cache, - DbAccessor *db_accessor, utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config, + DbAccessor *db_accessor, const InterpreterConfig::Query &query_config, std::optional owner, const query::v2::AuthChecker *auth_checker) : name_{std::move(name)}, - parsed_statements_{ParseQuery(query, user_parameters, query_cache, antlr_lock, query_config)}, + parsed_statements_{ParseQuery(query, user_parameters, query_cache, query_config)}, event_type_{event_type}, owner_{std::move(owner)} { // We check immediately if the query is valid by trying to create a plan. @@ -257,7 +257,7 @@ inline constexpr uint64_t kVersion{2}; TriggerStore::TriggerStore(std::filesystem::path directory) : storage_{std::move(directory)} {} void TriggerStore::RestoreTriggers(utils::SkipList *query_cache, DbAccessor *db_accessor, - utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config, + const InterpreterConfig::Query &query_config, const query::v2::AuthChecker *auth_checker) { MG_ASSERT(before_commit_triggers_.size() == 0 && after_commit_triggers_.size() == 0, "Cannot restore trigger when some triggers already exist!"); @@ -317,8 +317,8 @@ void TriggerStore::RestoreTriggers(utils::SkipList *query_cache std::optional trigger; try { - trigger.emplace(trigger_name, statement, user_parameters, event_type, query_cache, db_accessor, antlr_lock, - query_config, std::move(owner), auth_checker); + trigger.emplace(trigger_name, statement, user_parameters, event_type, query_cache, db_accessor, query_config, + std::move(owner), auth_checker); } catch (const utils::BasicException &e) { spdlog::warn("Failed to create trigger '{}' because: {}", trigger_name, e.what()); continue; @@ -336,8 +336,8 @@ void TriggerStore::AddTrigger(std::string name, const std::string &query, const std::map &user_parameters, TriggerEventType event_type, TriggerPhase phase, utils::SkipList *query_cache, DbAccessor *db_accessor, - utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config, - std::optional owner, const query::v2::AuthChecker *auth_checker) { + const InterpreterConfig::Query &query_config, std::optional owner, + const query::v2::AuthChecker *auth_checker) { std::unique_lock store_guard{store_lock_}; if (storage_.Get(name)) { throw utils::BasicException("Trigger with the same name already exists."); @@ -345,8 +345,8 @@ void TriggerStore::AddTrigger(std::string name, const std::string &query, std::optional trigger; try { - trigger.emplace(std::move(name), query, user_parameters, event_type, query_cache, db_accessor, antlr_lock, - query_config, std::move(owner), auth_checker); + trigger.emplace(std::move(name), query, user_parameters, event_type, query_cache, db_accessor, query_config, + std::move(owner), auth_checker); } catch (const utils::BasicException &e) { const auto identifiers = GetPredefinedIdentifiers(event_type); std::stringstream identifier_names_stream; diff --git a/src/query/v2/trigger.hpp b/src/query/v2/trigger.hpp index 5ceaaa63e..35fdf88a5 100644 --- a/src/query/v2/trigger.hpp +++ b/src/query/v2/trigger.hpp @@ -35,8 +35,8 @@ struct Trigger { explicit Trigger(std::string name, const std::string &query, const std::map &user_parameters, TriggerEventType event_type, utils::SkipList *query_cache, DbAccessor *db_accessor, - utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config, - std::optional owner, const AuthChecker *auth_checker); + const InterpreterConfig::Query &query_config, std::optional owner, + const query::v2::AuthChecker *auth_checker); void Execute(DbAccessor *dba, utils::MonotonicBufferResource *execution_memory, double max_execution_time_sec, std::atomic *is_shutting_down, const TriggerContext &context, @@ -81,14 +81,13 @@ struct TriggerStore { explicit TriggerStore(std::filesystem::path directory); void RestoreTriggers(utils::SkipList *query_cache, DbAccessor *db_accessor, - utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config, - const query::v2::AuthChecker *auth_checker); + const InterpreterConfig::Query &query_config, const query::v2::AuthChecker *auth_checker); void AddTrigger(std::string name, const std::string &query, const std::map &user_parameters, TriggerEventType event_type, TriggerPhase phase, utils::SkipList *query_cache, DbAccessor *db_accessor, - utils::SpinLock *antlr_lock, const InterpreterConfig::Query &query_config, - std::optional owner, const query::v2::AuthChecker *auth_checker); + const InterpreterConfig::Query &query_config, std::optional owner, + const query::v2::AuthChecker *auth_checker); void DropTrigger(const std::string &name); diff --git a/tests/gql_behave/tests/memgraph_V1/features/aggregations.feature b/tests/gql_behave/tests/memgraph_V1/features/aggregations.feature index 09776a466..796f598eb 100644 --- a/tests/gql_behave/tests/memgraph_V1/features/aggregations.feature +++ b/tests/gql_behave/tests/memgraph_V1/features/aggregations.feature @@ -73,6 +73,16 @@ Feature: Aggregations | n | | 5 | + Scenario: Count test 07: + Given an empty graph + When executing query: + """ + RETURN count(null) + """ + Then the result should be: + | count(null) | + | 0 | + Scenario: Sum test 01: Given an empty graph And having executed @@ -114,6 +124,16 @@ Feature: Aggregations | 4 | 0 | | 4 | 1 | + Scenario: Sum test 04: + Given an empty graph + When executing query: + """ + RETURN sum(null) + """ + Then the result should be: + | sum(null) | + | 0 | + Scenario: Avg test 01: Given an empty graph And having executed @@ -155,6 +175,16 @@ Feature: Aggregations | 2.0 | 0 | | 4.0 | 1 | + Scenario: Avg test 04: + Given an empty graph + When executing query: + """ + RETURN avg(null) + """ + Then the result should be: + | avg(null) | + | null | + Scenario: Min test 01: Given an empty graph And having executed @@ -196,6 +226,16 @@ Feature: Aggregations | 1 | 0 | | 4 | 1 | + Scenario: Min test 04: + Given an empty graph + When executing query: + """ + RETURN min(null) + """ + Then the result should be: + | min(null) | + | null | + Scenario: Max test 01: Given an empty graph And having executed @@ -237,6 +277,16 @@ Feature: Aggregations | 3 | 0 | | 4 | 1 | + Scenario: Max test 04: + Given an empty graph + When executing query: + """ + RETURN max(null) + """ + Then the result should be: + | max(null) | + | null | + Scenario: Collect test 01: Given an empty graph And having executed @@ -279,3 +329,18 @@ Feature: Aggregations | n | | {a_key: 13, b_key: 11, c_key: 12} | + Scenario: Combined aggregations - some evauluates to null: + Given an empty graph + And having executed + """ + CREATE (f) + CREATE (n {property: 1}) + """ + When executing query: + """ + MATCH (n) RETURN count(n) < n.property, count(n.property), count(n), avg(n.property), min(n.property), max(n.property), sum(n.property) + """ + Then the result should be: + | count(n) < n.property | count(n.property) | count(n) | avg(n.property) | min(n.property) | max(n.property) | sum(n.property) | + | false | 1 | 1 | 1.0 | 1 | 1 | 1 | + | null | 0 | 1 | null | null | null | 0 | diff --git a/tests/manual/antlr_sigsegv.cpp b/tests/manual/antlr_sigsegv.cpp index cd6bba3f5..234530668 100644 --- a/tests/manual/antlr_sigsegv.cpp +++ b/tests/manual/antlr_sigsegv.cpp @@ -20,6 +20,15 @@ #include "utils/signals.hpp" #include "utils/stacktrace.hpp" +// This test was introduced because Antlr Cpp runtime doesn't work well in a +// highly concurrent environment. Interpreter `interpret.hpp` contains +// `antlr_lock` used to avoid crashes. +// v4.6 and before -> Crashes. +// v4.8 -> Does NOT crash but sometimes this tests does NOT finish. +// Looks like a deadlock. -> The lock is still REQUIRED. +// v4.9 -> Seems to be working. +// v4.10 -> Seems to be working as well. -> antlr_lock removed + using namespace std::chrono_literals; TEST(Antlr, Sigsegv) { diff --git a/tests/stress/CMakeLists.txt b/tests/stress/CMakeLists.txt index f4ca745fa..18b784dc0 100644 --- a/tests/stress/CMakeLists.txt +++ b/tests/stress/CMakeLists.txt @@ -17,3 +17,6 @@ endfunction(add_stress_test) add_stress_test(long_running.cpp) target_link_libraries(${test_prefix}long_running mg-communication mg-io mg-utils) + +add_stress_test(parser.cpp) +target_link_libraries(${test_prefix}parser mg-communication mg-io mg-utils mgclient) diff --git a/tests/stress/continuous_integration b/tests/stress/continuous_integration index 697f5158d..87d5bcaf6 100755 --- a/tests/stress/continuous_integration +++ b/tests/stress/continuous_integration @@ -26,6 +26,11 @@ SMALL_DATASET = [ "options": ["--vertex-count", "40000", "--create-pack-size", "100"], "timeout": 5, }, + { + "test": "parser.cpp", + "options": ["--per-worker-query-count", "1000"], + "timeout": 5, + }, { "test": "long_running.cpp", "options": ["--vertex-count", "1000", "--edge-count", "5000", "--max-time", "1", "--verify", "20"], @@ -42,30 +47,35 @@ SMALL_DATASET = [ # bipartite.py and create_match.py run for approx. 15min # long_running runs for 5min x 6 times = 30min # long_running runs for 8h -LARGE_DATASET = [ - { - "test": "bipartite.py", - "options": ["--u-count", "300", "--v-count", "300"], - "timeout": 30, - }, - { - "test": "create_match.py", - "options": ["--vertex-count", "500000", "--create-pack-size", "500"], - "timeout": 30, - }, -] + [ - { - "test": "long_running.cpp", - "options": ["--vertex-count", "10000", "--edge-count", "40000", "--max-time", "5", "--verify", "60"], - "timeout": 16, - }, -] * 6 + [ - { - "test": "long_running.cpp", - "options": ["--vertex-count", "200000", "--edge-count", "1000000", "--max-time", "480", "--verify", "300"], - "timeout": 500, - }, -] +LARGE_DATASET = ( + [ + { + "test": "bipartite.py", + "options": ["--u-count", "300", "--v-count", "300"], + "timeout": 30, + }, + { + "test": "create_match.py", + "options": ["--vertex-count", "500000", "--create-pack-size", "500"], + "timeout": 30, + }, + ] + + [ + { + "test": "long_running.cpp", + "options": ["--vertex-count", "10000", "--edge-count", "40000", "--max-time", "5", "--verify", "60"], + "timeout": 16, + }, + ] + * 6 + + [ + { + "test": "long_running.cpp", + "options": ["--vertex-count", "200000", "--edge-count", "1000000", "--max-time", "480", "--verify", "300"], + "timeout": 500, + }, + ] +) # paths SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) @@ -101,8 +111,7 @@ def run_test(args, test, options, timeout): # find binary if test.endswith(".py"): logging = "DEBUG" if args.verbose else "WARNING" - binary = [args.python, "-u", os.path.join(SCRIPT_DIR, test), - "--logging", logging] + binary = [args.python, "-u", os.path.join(SCRIPT_DIR, test), "--logging", logging] elif test.endswith(".cpp"): exe = os.path.join(BUILD_DIR, "tests", "stress", test[:-4]) binary = [exe] @@ -112,11 +121,10 @@ def run_test(args, test, options, timeout): # start test cmd = binary + ["--worker-count", str(THREADS)] + options start = time.time() - ret_test = subprocess.run(cmd, cwd = SCRIPT_DIR, timeout = timeout * 60) + ret_test = subprocess.run(cmd, cwd=SCRIPT_DIR, timeout=timeout * 60) if ret_test.returncode != 0: - raise Exception("Test '{}' binary returned non-zero ({})!".format( - test, ret_test.returncode)) + raise Exception("Test '{}' binary returned non-zero ({})!".format(test, ret_test.returncode)) runtime = time.time() - start print(" Done after {:.3f} seconds".format(runtime)) @@ -125,39 +133,54 @@ def run_test(args, test, options, timeout): # parse arguments -parser = argparse.ArgumentParser(description = "Run stress tests on Memgraph.") -parser.add_argument("--memgraph", default = os.path.join(BUILD_DIR, - "memgraph")) -parser.add_argument("--log-file", default = "") -parser.add_argument("--data-directory", default = "") -parser.add_argument("--python", default = os.path.join(SCRIPT_DIR, - "ve3", "bin", "python3"), type = str) -parser.add_argument("--large-dataset", action = "store_const", - const = True, default = False) -parser.add_argument("--use-ssl", action = "store_const", - const = True, default = False) -parser.add_argument("--verbose", action = "store_const", - const = True, default = False) +parser = argparse.ArgumentParser(description="Run stress tests on Memgraph.") +parser.add_argument("--memgraph", default=os.path.join(BUILD_DIR, "memgraph")) +parser.add_argument("--log-file", default="") +parser.add_argument("--data-directory", default="") +parser.add_argument("--python", default=os.path.join(SCRIPT_DIR, "ve3", "bin", "python3"), type=str) +parser.add_argument("--large-dataset", action="store_const", const=True, default=False) +parser.add_argument("--use-ssl", action="store_const", const=True, default=False) +parser.add_argument("--verbose", action="store_const", const=True, default=False) args = parser.parse_args() # generate temporary SSL certs if args.use_ssl: # https://unix.stackexchange.com/questions/104171/create-ssl-certificate-non-interactively subj = "/C=HR/ST=Zagreb/L=Zagreb/O=Memgraph/CN=db.memgraph.com" - subprocess.run(["openssl", "req", "-new", "-newkey", "rsa:4096", - "-days", "365", "-nodes", "-x509", "-subj", subj, - "-keyout", KEY_FILE, "-out", CERT_FILE], check=True) + subprocess.run( + [ + "openssl", + "req", + "-new", + "-newkey", + "rsa:4096", + "-days", + "365", + "-nodes", + "-x509", + "-subj", + subj, + "-keyout", + KEY_FILE, + "-out", + CERT_FILE, + ], + check=True, + ) # start memgraph cwd = os.path.dirname(args.memgraph) -cmd = [args.memgraph, "--bolt-num-workers=" + str(THREADS), - "--storage-properties-on-edges=true", - "--storage-snapshot-on-exit=true", - "--storage-snapshot-interval-sec=600", - "--storage-snapshot-retention-count=1", - "--storage-wal-enabled=true", - "--storage-recover-on-startup=false", - "--query-execution-timeout-sec=1200"] +cmd = [ + args.memgraph, + "--bolt-num-workers=" + str(THREADS), + "--storage-properties-on-edges=true", + "--storage-snapshot-on-exit=true", + "--storage-snapshot-interval-sec=600", + "--storage-snapshot-retention-count=1", + "--storage-wal-enabled=true", + "--storage-recover-on-startup=false", + "--query-execution-timeout-sec=1200", +] if not args.verbose: cmd += ["--log-level", "WARNING"] if args.log_file: @@ -166,7 +189,7 @@ if args.data_directory: cmd += ["--data-directory", args.data_directory] if args.use_ssl: cmd += ["--bolt-cert-file", CERT_FILE, "--bolt-key-file", KEY_FILE] -proc_mg = subprocess.Popen(cmd, cwd = cwd) +proc_mg = subprocess.Popen(cmd, cwd=cwd) wait_for_server(7687) assert proc_mg.poll() is None, "The database binary died prematurely!" @@ -174,10 +197,12 @@ assert proc_mg.poll() is None, "The database binary died prematurely!" @atexit.register def cleanup(): global proc_mg - if proc_mg.poll() != None: return + if proc_mg.poll() != None: + return proc_mg.kill() proc_mg.wait() + # run tests runtimes = {} dataset = LARGE_DATASET if args.large_dataset else SMALL_DATASET diff --git a/tests/stress/parser.cpp b/tests/stress/parser.cpp new file mode 100644 index 000000000..b20cdd257 --- /dev/null +++ b/tests/stress/parser.cpp @@ -0,0 +1,79 @@ +// Copyright 2022 Memgraph Ltd. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source +// License, and you may not use this file except in compliance with the Business Source License. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +#include +#include +#include + +#include +#include + +#include "communication/bolt/client.hpp" +#include "io/network/endpoint.hpp" +#include "mgclient.hpp" +#include "utils/timer.hpp" + +DEFINE_string(address, "127.0.0.1", "Server address"); +DEFINE_int32(port, 7687, "Server port"); +DEFINE_string(username, "", "Username for the database"); +DEFINE_string(password, "", "Password for the database"); +DEFINE_bool(use_ssl, false, "Set to true to connect with SSL to the server."); +DEFINE_int32(worker_count, 1, "The number of concurrent workers executing queries against the server."); +DEFINE_int32(per_worker_query_count, 100, "The number of queries each worker will try to execute."); + +auto make_client() { + mg::Client::Params params; + params.host = FLAGS_address; + params.port = static_cast(FLAGS_port); + params.use_ssl = FLAGS_use_ssl; + return mg::Client::Connect(params); +} + +int main(int argc, char **argv) { + gflags::ParseCommandLineFlags(&argc, &argv, true); + mg::Client::Init(); + + spdlog::info("Cleaning the database instance..."); + auto client = make_client(); + client->Execute("MATCH (n) DETACH DELETE n"); + client->DiscardAll(); + + spdlog::info(fmt::format("Starting parser stress test with {} workers and {} queries per worker...", + FLAGS_worker_count, FLAGS_per_worker_query_count)); + std::vector threads; + memgraph::utils::Timer timer; + for (int i = 0; i < FLAGS_worker_count; ++i) { + threads.push_back(std::thread([]() { + auto client = make_client(); + std::mt19937 generator{std::random_device{}()}; + std::uniform_int_distribution distribution{std::numeric_limits::min(), + std::numeric_limits::max()}; + for (int i = 0; i < FLAGS_per_worker_query_count; ++i) { + try { + auto is_executed = client->Execute(fmt::format("MATCH (n:Label{}) RETURN n;", distribution(generator))); + if (!is_executed) { + LOG_FATAL("One of the parser stress test queries failed."); + } + client->FetchAll(); + } catch (const std::exception &e) { + LOG_FATAL("One of the parser stress test queries failed."); + } + } + })); + } + + std::ranges::for_each(threads, [](auto &t) { t.join(); }); + spdlog::info( + fmt::format("All queries executed in {:.4f}s. The parser managed to handle the load.", timer.Elapsed().count())); + mg::Client::Finalize(); + + return 0; +} diff --git a/tests/unit/query_plan_accumulate_aggregate.cpp b/tests/unit/query_plan_accumulate_aggregate.cpp index 04bd1cc44..08f1965f0 100644 --- a/tests/unit/query_plan_accumulate_aggregate.cpp +++ b/tests/unit/query_plan_accumulate_aggregate.cpp @@ -217,31 +217,40 @@ TEST_F(QueryPlanAggregateOps, WithData) { TEST_F(QueryPlanAggregateOps, WithoutDataWithGroupBy) { { auto results = AggregationResults(true, {Aggregation::Op::COUNT}); - EXPECT_EQ(results.size(), 0); + EXPECT_EQ(results.size(), 1); + EXPECT_EQ(results[0][0].type(), TypedValue::Type::Int); + EXPECT_EQ(results[0][0].ValueInt(), 0); } { auto results = AggregationResults(true, {Aggregation::Op::SUM}); - EXPECT_EQ(results.size(), 0); + EXPECT_EQ(results.size(), 1); + EXPECT_EQ(results[0][0].type(), TypedValue::Type::Int); + EXPECT_EQ(results[0][0].ValueInt(), 0); } { auto results = AggregationResults(true, {Aggregation::Op::AVG}); - EXPECT_EQ(results.size(), 0); + EXPECT_EQ(results.size(), 1); + EXPECT_EQ(results[0][0].type(), TypedValue::Type::Null); } { auto results = AggregationResults(true, {Aggregation::Op::MIN}); - EXPECT_EQ(results.size(), 0); + EXPECT_EQ(results.size(), 1); + EXPECT_EQ(results[0][0].type(), TypedValue::Type::Null); } { auto results = AggregationResults(true, {Aggregation::Op::MAX}); - EXPECT_EQ(results.size(), 0); + EXPECT_EQ(results.size(), 1); + EXPECT_EQ(results[0][0].type(), TypedValue::Type::Null); } { auto results = AggregationResults(true, {Aggregation::Op::COLLECT_LIST}); - EXPECT_EQ(results.size(), 0); + EXPECT_EQ(results.size(), 1); + EXPECT_EQ(results[0][0].type(), TypedValue::Type::List); } { auto results = AggregationResults(true, {Aggregation::Op::COLLECT_MAP}); - EXPECT_EQ(results.size(), 0); + EXPECT_EQ(results.size(), 1); + EXPECT_EQ(results[0][0].type(), TypedValue::Type::Map); } } @@ -260,7 +269,7 @@ TEST_F(QueryPlanAggregateOps, WithoutDataWithoutGroupBy) { // max EXPECT_TRUE(results[0][3].IsNull()); // sum - EXPECT_TRUE(results[0][4].IsNull()); + EXPECT_EQ(results[0][4].ValueInt(), 0); // avg EXPECT_TRUE(results[0][5].IsNull()); // collect list diff --git a/tests/unit/query_trigger.cpp b/tests/unit/query_trigger.cpp index 57bc4f3bc..3375515a3 100644 --- a/tests/unit/query_trigger.cpp +++ b/tests/unit/query_trigger.cpp @@ -891,7 +891,6 @@ class TriggerStoreTest : public ::testing::Test { std::optional dba; memgraph::utils::SkipList ast_cache; - memgraph::utils::SpinLock antlr_lock; memgraph::query::AllowEverythingAuthChecker auth_checker; private: @@ -909,7 +908,7 @@ TEST_F(TriggerStoreTest, Restore) { const auto reset_store = [&] { store.emplace(testing_directory); - store->RestoreTriggers(&ast_cache, &*dba, &antlr_lock, memgraph::query::InterpreterConfig::Query{}, &auth_checker); + store->RestoreTriggers(&ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, &auth_checker); }; reset_store(); @@ -930,12 +929,12 @@ TEST_F(TriggerStoreTest, Restore) { store->AddTrigger( trigger_name_before, trigger_statement, std::map{{"parameter", memgraph::storage::PropertyValue{1}}}, - event_type, memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock, + event_type, memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker); store->AddTrigger( trigger_name_after, trigger_statement, std::map{{"parameter", memgraph::storage::PropertyValue{"value"}}}, - event_type, memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock, + event_type, memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, {owner}, &auth_checker); const auto check_triggers = [&] { @@ -986,16 +985,16 @@ TEST_F(TriggerStoreTest, AddTrigger) { // Invalid query in statements ASSERT_THROW(store.AddTrigger("trigger", "RETUR 1", {}, memgraph::query::TriggerEventType::VERTEX_CREATE, - memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock, + memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker), memgraph::utils::BasicException); ASSERT_THROW(store.AddTrigger("trigger", "RETURN createdEdges", {}, memgraph::query::TriggerEventType::VERTEX_CREATE, - memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock, + memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker), memgraph::utils::BasicException); ASSERT_THROW(store.AddTrigger("trigger", "RETURN $parameter", {}, memgraph::query::TriggerEventType::VERTEX_CREATE, - memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock, + memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker), memgraph::utils::BasicException); @@ -1003,15 +1002,15 @@ TEST_F(TriggerStoreTest, AddTrigger) { "trigger", "RETURN $parameter", std::map{{"parameter", memgraph::storage::PropertyValue{1}}}, memgraph::query::TriggerEventType::VERTEX_CREATE, memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, - &antlr_lock, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker)); + memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker)); // Inserting with the same name ASSERT_THROW(store.AddTrigger("trigger", "RETURN 1", {}, memgraph::query::TriggerEventType::VERTEX_CREATE, - memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock, + memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker), memgraph::utils::BasicException); ASSERT_THROW(store.AddTrigger("trigger", "RETURN 1", {}, memgraph::query::TriggerEventType::VERTEX_CREATE, - memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock, + memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker), memgraph::utils::BasicException); @@ -1027,7 +1026,7 @@ TEST_F(TriggerStoreTest, DropTrigger) { const auto *trigger_name = "trigger"; store.AddTrigger(trigger_name, "RETURN 1", {}, memgraph::query::TriggerEventType::VERTEX_CREATE, - memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock, + memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker); ASSERT_THROW(store.DropTrigger("Unknown"), memgraph::utils::BasicException); @@ -1040,7 +1039,7 @@ TEST_F(TriggerStoreTest, TriggerInfo) { std::vector expected_info; store.AddTrigger("trigger", "RETURN 1", {}, memgraph::query::TriggerEventType::VERTEX_CREATE, - memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock, + memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker); expected_info.push_back({"trigger", "RETURN 1", memgraph::query::TriggerEventType::VERTEX_CREATE, memgraph::query::TriggerPhase::BEFORE_COMMIT}); @@ -1060,7 +1059,7 @@ TEST_F(TriggerStoreTest, TriggerInfo) { check_trigger_info(); store.AddTrigger("edge_update_trigger", "RETURN 1", {}, memgraph::query::TriggerEventType::EDGE_UPDATE, - memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock, + memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker); expected_info.push_back({"edge_update_trigger", "RETURN 1", memgraph::query::TriggerEventType::EDGE_UPDATE, memgraph::query::TriggerPhase::AFTER_COMMIT}); @@ -1174,7 +1173,7 @@ TEST_F(TriggerStoreTest, AnyTriggerAllKeywords) { for (const auto keyword : keywords) { SCOPED_TRACE(keyword); EXPECT_NO_THROW(store.AddTrigger(trigger_name, fmt::format("RETURN {}", keyword), {}, event_type, - memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock, + memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker)); store.DropTrigger(trigger_name); } @@ -1199,23 +1198,23 @@ TEST_F(TriggerStoreTest, AuthCheckerUsage) { ASSERT_NO_THROW(store->AddTrigger("successfull_trigger_1", "CREATE (n:VERTEX) RETURN n", {}, memgraph::query::TriggerEventType::EDGE_UPDATE, - memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock, + memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &mock_checker)); ASSERT_NO_THROW(store->AddTrigger("successfull_trigger_2", "CREATE (n:VERTEX) RETURN n", {}, memgraph::query::TriggerEventType::EDGE_UPDATE, - memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock, + memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, owner, &mock_checker)); EXPECT_CALL(mock_checker, IsUserAuthorized(std::optional{}, ElementsAre(Privilege::MATCH))) .Times(1) .WillOnce(Return(false)); - ASSERT_THROW(store->AddTrigger("unprivileged_trigger", "MATCH (n:VERTEX) RETURN n", {}, - memgraph::query::TriggerEventType::EDGE_UPDATE, - memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock, - memgraph::query::InterpreterConfig::Query{}, std::nullopt, &mock_checker); - , memgraph::utils::BasicException); + ASSERT_THROW( + store->AddTrigger("unprivileged_trigger", "MATCH (n:VERTEX) RETURN n", {}, + memgraph::query::TriggerEventType::EDGE_UPDATE, memgraph::query::TriggerPhase::AFTER_COMMIT, + &ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &mock_checker); + , memgraph::utils::BasicException); store.emplace(testing_directory); EXPECT_CALL(mock_checker, IsUserAuthorized(std::optional{}, ElementsAre(Privilege::CREATE))) @@ -1223,8 +1222,8 @@ TEST_F(TriggerStoreTest, AuthCheckerUsage) { .WillOnce(Return(false)); EXPECT_CALL(mock_checker, IsUserAuthorized(owner, ElementsAre(Privilege::CREATE))).Times(1).WillOnce(Return(true)); - ASSERT_NO_THROW(store->RestoreTriggers(&ast_cache, &*dba, &antlr_lock, memgraph::query::InterpreterConfig::Query{}, - &mock_checker)); + ASSERT_NO_THROW( + store->RestoreTriggers(&ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, &mock_checker)); const auto triggers = store->GetTriggerInfo(); ASSERT_EQ(triggers.size(), 1);