diff --git a/flex/engines/graph_db/runtime/adhoc/expr_impl.cc b/flex/engines/graph_db/runtime/adhoc/expr_impl.cc index 7df4cdbeed15..dc64449d632c 100644 --- a/flex/engines/graph_db/runtime/adhoc/expr_impl.cc +++ b/flex/engines/graph_db/runtime/adhoc/expr_impl.cc @@ -206,6 +206,9 @@ RTAny UnaryLogicalExpr::eval_edge(const LabelTriplet& label, vid_t src, if (logic_ == common::Logical::NOT) { return RTAny::from_bool( !expr_->eval_edge(label, src, dst, data, idx).as_bool()); + } else if (logic_ == common::Logical::ISNULL) { + return RTAny::from_bool( + expr_->eval_edge(label, src, dst, data, idx, 0).is_null()); } LOG(FATAL) << "not support" << static_cast(logic_); return RTAny::from_bool(false); diff --git a/flex/engines/graph_db/runtime/common/rt_any.cc b/flex/engines/graph_db/runtime/common/rt_any.cc index e3cf4a1d55d8..3fb774bb1ffc 100644 --- a/flex/engines/graph_db/runtime/common/rt_any.cc +++ b/flex/engines/graph_db/runtime/common/rt_any.cc @@ -119,6 +119,8 @@ RTAny::RTAny(const Any& val) { } else if (val.type == PropertyType::Bool()) { type_ = RTAnyType::kBoolValue; value_.b_val = val.AsBool(); + } else if (val.type == PropertyType::Empty()) { + type_ = RTAnyType::kNull; } else { LOG(FATAL) << "Any value: " << val.to_string() << ", type = " << val.type.type_enum; @@ -355,6 +357,8 @@ std::string_view RTAny::as_string() const { return value_.str_val; } else if (type_ == RTAnyType::kUnknown) { return std::string_view(); + } else if (type_ == RTAnyType::kNull) { + return std::string_view(); } else { LOG(FATAL) << "unexpected type" << static_cast(type_.type_enum_); return std::string_view(); diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/integration/suite/movie/MovieQueries.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/integration/suite/movie/MovieQueries.java index d4db0275b34f..f51c7c386b1a 100644 --- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/integration/suite/movie/MovieQueries.java +++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/integration/suite/movie/MovieQueries.java @@ -399,4 +399,10 @@ public static QueryContext get_movie_query28_test() { List expected = Arrays.asList("Record<{typeA: \"Person\", typeC: \"Movie\"}>"); return new QueryContext(query, expected); } + + public static QueryContext get_movie_query29_test() { + String query = "MATCH(a)-[r]->(b) where r.rating is null return count(r) as count;"; + List expected = Arrays.asList("Record<{count: 249}>"); + return new QueryContext(query, expected); + } } diff --git a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/cypher/integration/movie/MovieTest.java b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/cypher/integration/movie/MovieTest.java index 7f5ea090886d..84a3d4721c89 100644 --- a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/cypher/integration/movie/MovieTest.java +++ b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/cypher/integration/movie/MovieTest.java @@ -218,6 +218,13 @@ public void run_movie_query28_test() { Assert.assertEquals(testQuery.getExpectedResult().toString(), result.list().toString()); } + @Test + public void run_movie_query29_test() { + QueryContext testQuery = MovieQueries.get_movie_query29_test(); + Result result = session.run(testQuery.getQuery()); + Assert.assertEquals(testQuery.getExpectedResult().toString(), result.list().toString()); + } + @AfterClass public static void afterClass() { if (session != null) {