Skip to content

none() returns null instead of false when a leading null element is followed by true #6167

Description

@ting668

Reporter: ting668

Environment

  • OS: Linux (WSL2 host); NebulaGraph services inside Docker containers
  • Docker images: vesoft/nebula-graphd:v3.8.0, vesoft/nebula-metad:v3.8.0, vesoft/nebula-storaged:v3.8.0 (Docker Compose)
  • NebulaGraph Version: 3.8.0 (Git 7458486)

Description

While testing NebulaGraph using a method based on attribute-constraint analysis, I found that the none() list predicate returns null as soon as the list contains a null element, so a later definite true is never observed.

Under Cypher's three-valued logic, none(x IN list WHERE x) must be false when the inner predicate is definitely true for at least one element, even if other elements are null. In the example below the list [NULL, true] contains a definite true, so the result should be false; NebulaGraph returns null. The equivalent expression NOT any(x IN [NULL, true] WHERE x) evaluated in the same query returns false, so the two forms disagree within a single row.

How to Reproduce and Expected Behavior

Note: The queries below are a minimized, simplified example reproducing the bug.

Buggy query (no data needed):

RETURN none(x IN [NULL,true] WHERE x) AS actual,
       NOT any(x IN [NULL,true] WHERE x) AS oracle;

Expected behavior: the list contains a definite true, so none(...) is false:

actual=false, oracle=false

Actual behavior: none(...) returns null while the equivalent any() form in the same row returns false:

actual=NULL, oracle=false

This also affects WHERE filtering. With a tag demo (name: STRING, flag: BOOL) and the two vertices below:

CREATE SPACE repro(partition_num=1,replica_factor=1,vid_type=FIXED_STRING(32));
USE repro;
CREATE TAG demo(name string, flag bool);
-- Wait for the schema to propagate to storage via heartbeat before inserting.
INSERT VERTEX demo(name,flag) VALUES "vfalse":("vfalse",false), "vtrue":("vtrue",true);

MATCH (v:demo) WHERE NOT none(x IN [NULL, v.demo.flag] WHERE x) RETURN id(v) AS id;

Expected behavior: for "vtrue", flag is true, so none([NULL, true]) is false and NOT false keeps the row; for "vfalse", none([NULL, false]) is null, so that row is filtered:

id="vtrue"

Actual behavior:

(empty result)

This suggests that none() short-circuits to null on the first null element and never evaluates the remaining elements, so a definite true later in the list cannot produce the required false, and rows that NOT none(...) should keep are dropped.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    affects/nonePR/issue: this bug affects none version.severity/noneSeverity of bugtype/bugType: something is unexpected

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions