From fdbc390d534620a3997b441bbf6463524373b269 Mon Sep 17 00:00:00 2001 From: Andi Date: Thu, 2 Nov 2023 12:18:15 +0100 Subject: [PATCH] Throw when reduce inside exists (#1392) --- .../frontend/semantic/symbol_generator.cpp | 18 +++++++++++++++--- .../frontend/semantic/symbol_generator.hpp | 2 ++ .../memgraph_V1/features/functions.feature | 12 ++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/query/frontend/semantic/symbol_generator.cpp b/src/query/frontend/semantic/symbol_generator.cpp index 8a555d96e..30790ee4e 100644 --- a/src/query/frontend/semantic/symbol_generator.cpp +++ b/src/query/frontend/semantic/symbol_generator.cpp @@ -480,12 +480,20 @@ bool SymbolGenerator::PreVisit(None &none) { } bool SymbolGenerator::PreVisit(Reduce &reduce) { + auto &scope = scopes_.back(); + scope.in_reduce = true; reduce.initializer_->Accept(*this); reduce.list_->Accept(*this); VisitWithIdentifiers(reduce.expression_, {reduce.accumulator_, reduce.identifier_}); return false; } +bool SymbolGenerator::PostVisit(Reduce & /*reduce*/) { + auto &scope = scopes_.back(); + scope.in_reduce = false; + return true; +} + bool SymbolGenerator::PreVisit(Extract &extract) { extract.list_->Accept(*this); VisitWithIdentifiers(extract.expression_, {extract.identifier_}); @@ -496,15 +504,19 @@ bool SymbolGenerator::PreVisit(Exists &exists) { auto &scope = scopes_.back(); if (scope.in_set_property) { - throw utils::NotYetImplemented("Set property can not be used with exists, but only during matching!"); + throw utils::NotYetImplemented("Exists cannot be used within SET clause.!"); } if (scope.in_with) { - throw utils::NotYetImplemented("WITH can not be used with exists, but only during matching!"); + throw utils::NotYetImplemented("Exists cannot be used within WITH!"); } if (scope.in_return) { - throw utils::NotYetImplemented("RETURN can not be used with exists, but only during matching!"); + throw utils::NotYetImplemented("Exists cannot be used within RETURN!"); + } + + if (scope.in_reduce) { + throw utils::NotYetImplemented("Exists cannot be used within REDUCE!"); } if (scope.num_if_operators) { diff --git a/src/query/frontend/semantic/symbol_generator.hpp b/src/query/frontend/semantic/symbol_generator.hpp index 9e4fc32b5..c69d8729e 100644 --- a/src/query/frontend/semantic/symbol_generator.hpp +++ b/src/query/frontend/semantic/symbol_generator.hpp @@ -84,6 +84,7 @@ class SymbolGenerator : public HierarchicalTreeVisitor { bool PreVisit(Any &) override; bool PreVisit(None &) override; bool PreVisit(Reduce &) override; + bool PostVisit(Reduce &) override; bool PreVisit(Extract &) override; bool PreVisit(Exists & /*exists*/) override; bool PostVisit(Exists & /*exists*/) override; @@ -123,6 +124,7 @@ class SymbolGenerator : public HierarchicalTreeVisitor { bool in_match{false}; bool in_foreach{false}; bool in_exists{false}; + bool in_reduce{false}; bool in_set_property{false}; bool in_call_subquery{false}; bool has_return{false}; diff --git a/tests/gql_behave/tests/memgraph_V1/features/functions.feature b/tests/gql_behave/tests/memgraph_V1/features/functions.feature index d9348518f..bc9121676 100644 --- a/tests/gql_behave/tests/memgraph_V1/features/functions.feature +++ b/tests/gql_behave/tests/memgraph_V1/features/functions.feature @@ -1158,3 +1158,15 @@ Feature: Functions Then the result should be: | A_COUNT | B_COUNT | | 3 | 15 | + + Scenario: Exists is forbidden within reduce: + Given an empty graph + And having executed: + """ + CREATE () + """ + When executing query: + """ + MATCH () WHERE reduce(a=exists(()),b in []|a) RETURN 1; + """ + Then an error should be raised