diff --git a/src/common/expression/PredicateExpression.cpp b/src/common/expression/PredicateExpression.cpp index d2ede313a12..bf133a75361 100644 --- a/src/common/expression/PredicateExpression.cpp +++ b/src/common/expression/PredicateExpression.cpp @@ -94,10 +94,11 @@ const Value& PredicateExpression::eval(ExpressionContext& ctx) { auto& v = list[i]; ctx.setInnerVar(innerVar_, v); auto& filterVal = filter_->eval(ctx); - if (!filterVal.empty() && !filterVal.isNull() && !filterVal.isImplicitBool()) { + if (filterVal.empty() || filterVal.isNull()) { + return Value::kNullValue; + } else if (!filterVal.isImplicitBool()) { return Value::kNullBadType; - } - if (filterVal.empty() || filterVal.isNull() || !filterVal.implicitBool()) { + } else if (!filterVal.implicitBool()) { result_ = false; return result_; } @@ -110,10 +111,11 @@ const Value& PredicateExpression::eval(ExpressionContext& ctx) { auto& v = list[i]; ctx.setInnerVar(innerVar_, v); auto& filterVal = filter_->eval(ctx); - if (!filterVal.empty() && !filterVal.isNull() && !filterVal.isImplicitBool()) { + if (filterVal.empty() || filterVal.isNull()) { + result_ = Value::kNullValue; + } else if (!filterVal.isImplicitBool()) { return Value::kNullBadType; - } - if (filterVal.isBool() && filterVal.implicitBool()) { + } else if (filterVal.implicitBool()) { result_ = true; return result_; } @@ -121,23 +123,30 @@ const Value& PredicateExpression::eval(ExpressionContext& ctx) { return result_; } case Type::SINGLE: { - result_ = false; + bool hasNull = false; + // If there are more than one satisfied, the result is false + bool hasSatisfied = false; for (size_t i = 0; i < list.size(); ++i) { auto& v = list[i]; ctx.setInnerVar(innerVar_, v); auto& filterVal = filter_->eval(ctx); - if (!filterVal.empty() && !filterVal.isNull() && !filterVal.isImplicitBool()) { + if (filterVal.empty() || filterVal.isNull()) { + hasNull = true; + } else if (!filterVal.isImplicitBool()) { return Value::kNullBadType; - } - if (filterVal.isBool() && filterVal.implicitBool()) { - if (result_ == false) { - result_ = true; - } else { + } else if (filterVal.implicitBool()) { + if (hasSatisfied) { result_ = false; return result_; } + hasSatisfied = true; } } + if (hasNull) { + result_ = Value::kNullValue; + } else { + result_ = hasSatisfied; + } return result_; } case Type::NONE: { @@ -146,10 +155,12 @@ const Value& PredicateExpression::eval(ExpressionContext& ctx) { auto& v = list[i]; ctx.setInnerVar(innerVar_, v); auto& filterVal = filter_->eval(ctx); - if (!filterVal.empty() && !filterVal.isNull() && !filterVal.isImplicitBool()) { + if (filterVal.empty() || filterVal.isNull()) { + result_ = Value::kNullValue; + return result_; + } else if (!filterVal.isImplicitBool()) { return Value::kNullBadType; - } - if (filterVal.isBool() && filterVal.implicitBool()) { + } else if (filterVal.implicitBool()) { result_ = false; return result_; } @@ -159,7 +170,6 @@ const Value& PredicateExpression::eval(ExpressionContext& ctx) { // no default so the compiler will warning when lack } - result_ = Value::kNullBadType; return result_; } diff --git a/tests/tck/features/expression/Predicate.feature b/tests/tck/features/expression/Predicate.feature index 5324ca1a836..a059899f1d2 100644 --- a/tests/tck/features/expression/Predicate.feature +++ b/tests/tck/features/expression/Predicate.feature @@ -55,6 +55,13 @@ Feature: Predicate Then the result should be, in any order: | r | | False | + When executing query: + """ + RETURN ALL(a IN [2, 3, NULL] WHERE a > 0) AS r + """ + Then the result should be, in any order: + | r | + | NULL | When executing query: """ RETURN Any(a IN [2, 3] WHERE a > 1) AS r diff --git a/tests/tck/features/match/PipeAndVariable.feature b/tests/tck/features/match/PipeAndVariable.feature index 6a4cd19f813..c35cd31a6cd 100644 --- a/tests/tck/features/match/PipeAndVariable.feature +++ b/tests/tck/features/match/PipeAndVariable.feature @@ -135,7 +135,7 @@ Feature: Pipe/Variable $v1 = YIELD "Tony Parker" AS a; LOOKUP ON player WHERE player.name == "Tim Duncan" YIELD player.name AS name, $v1.a """ - Then a SemanticError should be raised at runtime: unsupport input/variable property expression in yield. + Then a SemanticError should be raised at runtime: unsupported input/variable property expression in yield. @skip Scenario: pipe lookup results