Fix any function implementation
Summary: Change any function's handling of Null elements in a list Reviewers: mferencevic Reviewed By: mferencevic Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D2787
This commit is contained in:
parent
098333f735
commit
21cee1eaec
@ -534,6 +534,7 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
|
||||
}
|
||||
const auto &list = list_value.ValueList();
|
||||
const auto &symbol = symbol_table_->at(*any.identifier_);
|
||||
bool has_value = false;
|
||||
for (const auto &element : list) {
|
||||
frame_->at(symbol) = element;
|
||||
auto result = any.where_->expression_->Accept(*this);
|
||||
@ -542,11 +543,19 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
|
||||
"Predicate of ANY must evaluate to boolean, got {}.",
|
||||
result.type());
|
||||
}
|
||||
if (result.IsNull() || result.ValueBool()) {
|
||||
return result;
|
||||
if (!result.IsNull()) {
|
||||
has_value = true;
|
||||
if (result.ValueBool()) {
|
||||
return TypedValue(true, ctx_->memory);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TypedValue(false, ctx_->memory);
|
||||
// Return Null if all elements are Null
|
||||
if (!has_value) {
|
||||
return TypedValue(ctx_->memory);
|
||||
} else {
|
||||
return TypedValue(false, ctx_->memory);
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue Visit(ParameterLookup ¶m_lookup) override {
|
||||
|
@ -38,7 +38,7 @@ class UsedSymbolsCollector : public HierarchicalTreeVisitor {
|
||||
}
|
||||
|
||||
bool PostVisit(Any &any) override {
|
||||
// Remove the symbol which is bound by all, because we are only interested
|
||||
// Remove the symbol which is bound by any, because we are only interested
|
||||
// in free (unbound) symbols.
|
||||
symbols_.erase(symbol_table_.at(*any.identifier_));
|
||||
return true;
|
||||
|
@ -712,6 +712,80 @@ Feature: Functions
|
||||
"""
|
||||
Then an error should be raised
|
||||
|
||||
Scenario: Any test 01:
|
||||
When executing query:
|
||||
"""
|
||||
RETURN any(x IN [1, 2, 3] WHERE x > 0) AS a
|
||||
"""
|
||||
Then the result should be:
|
||||
| a |
|
||||
| true |
|
||||
|
||||
Scenario: Any test 02:
|
||||
When executing query:
|
||||
"""
|
||||
RETURN any(x IN [1, 2, 3] WHERE x = 0) AS a
|
||||
"""
|
||||
Then the result should be:
|
||||
| a |
|
||||
| false |
|
||||
|
||||
Scenario: Any test 03:
|
||||
When executing query:
|
||||
"""
|
||||
RETURN any(x IN ["a", "b", "c"] WHERE x = 1) AS a
|
||||
"""
|
||||
Then the result should be:
|
||||
| a |
|
||||
| false |
|
||||
|
||||
|
||||
Scenario: Any test 04:
|
||||
When executing query:
|
||||
"""
|
||||
RETURN any(x IN [Null, Null, Null] WHERE x = 0) AS a
|
||||
"""
|
||||
Then the result should be:
|
||||
| a |
|
||||
| null |
|
||||
|
||||
Scenario: Any test 05:
|
||||
When executing query:
|
||||
"""
|
||||
RETURN any(x IN [Null, Null, 0] WHERE x = 0) AS a
|
||||
"""
|
||||
Then the result should be:
|
||||
| a |
|
||||
| true |
|
||||
|
||||
Scenario: Any test 06:
|
||||
When executing query:
|
||||
"""
|
||||
RETURN any(x IN [Null, Null, 0] WHERE x > 0) AS a
|
||||
"""
|
||||
Then the result should be:
|
||||
| a |
|
||||
| false |
|
||||
|
||||
Scenario: Any test 07:
|
||||
When executing query:
|
||||
"""
|
||||
RETURN any(x IN [Null, Null, Null] WHERE x = Null) AS a
|
||||
"""
|
||||
Then the result should be:
|
||||
| a |
|
||||
| null |
|
||||
|
||||
Scenario: Any test 08:
|
||||
When executing query:
|
||||
"""
|
||||
RETURN any(x IN ["a", "b", "c"] WHERE x = Null) AS a
|
||||
"""
|
||||
Then the result should be:
|
||||
| a |
|
||||
| null |
|
||||
|
||||
|
||||
Scenario: Reduce test 01:
|
||||
When executing query:
|
||||
"""
|
||||
|
@ -804,6 +804,30 @@ TEST_F(ExpressionEvaluatorTest, FunctionAnyNullList) {
|
||||
EXPECT_TRUE(value.IsNull());
|
||||
}
|
||||
|
||||
TEST_F(ExpressionEvaluatorTest, FunctionAnyNullElementInList1) {
|
||||
AstStorage storage;
|
||||
auto *ident_x = IDENT("x");
|
||||
auto *any = ANY("x", LIST(LITERAL(0), LITERAL(storage::PropertyValue())),
|
||||
WHERE(EQ(ident_x, LITERAL(0))));
|
||||
const auto x_sym = symbol_table.CreateSymbol("x", true);
|
||||
any->identifier_->MapTo(x_sym);
|
||||
ident_x->MapTo(x_sym);
|
||||
auto value = Eval(any);
|
||||
EXPECT_TRUE(value.ValueBool());
|
||||
}
|
||||
|
||||
TEST_F(ExpressionEvaluatorTest, FunctionAnyNullElementInList2) {
|
||||
AstStorage storage;
|
||||
auto *ident_x = IDENT("x");
|
||||
auto *any = ANY("x", LIST(LITERAL(1), LITERAL(storage::PropertyValue())),
|
||||
WHERE(EQ(ident_x, LITERAL(0))));
|
||||
const auto x_sym = symbol_table.CreateSymbol("x", true);
|
||||
any->identifier_->MapTo(x_sym);
|
||||
ident_x->MapTo(x_sym);
|
||||
auto value = Eval(any);
|
||||
EXPECT_FALSE(value.ValueBool());
|
||||
}
|
||||
|
||||
TEST_F(ExpressionEvaluatorTest, FunctionAnyWhereWrongType) {
|
||||
AstStorage storage;
|
||||
auto *any = ANY("x", LIST(LITERAL(1)), WHERE(LITERAL(2)));
|
||||
|
Loading…
Reference in New Issue
Block a user