Skip to content

Simple CASE form matches WHEN NULL when the operand is null (null treated as equal to null) #6168

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 simple CASE form (CASE expr WHEN value THEN ...) matches a WHEN NULL branch when the operand is null.

Under Cypher's three-valued logic, the operand comparison in a simple CASE is an equality that is not true when either side is null, so CASE null WHEN null ... must fall through to ELSE. In the example below the simple form returns the THEN value, while the searched form CASE WHEN NULL == NULL ... in the same query correctly falls through to ELSE.

How to Reproduce and Expected Behavior

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

Buggy query (no data needed):

RETURN CASE NULL WHEN NULL THEN 1 ELSE 2 END AS simple,
       CASE WHEN NULL == NULL THEN 1 ELSE 2 END AS generic;

Expected behavior: both forms use the same three-valued equality, so neither takes the THEN branch:

simple=2, generic=2

Actual behavior: the simple form takes the WHEN NULL branch while the searched form falls through to ELSE:

simple=1, generic=2

This also affects WHERE filtering. With a tag demo (name: STRING, i: INT) and two vertices, one with i = null and one with i = 1:

CREATE SPACE repro(partition_num=1,replica_factor=1,vid_type=FIXED_STRING(32));
USE repro;
CREATE TAG demo(name string, i int);
-- Wait for the schema to propagate to storage via heartbeat before inserting.
INSERT VERTEX demo(name,i) VALUES "vnull":("vnull",NULL), "vone":("vone",1);

MATCH (v:demo) WHERE CASE v.demo.i WHEN NULL THEN 1 ELSE 2 END == 2 RETURN id(v) AS id;

Expected behavior: null does not equal NULL and 1 does not equal NULL, so both inputs take ELSE 2 and both rows pass the == 2 test:

id="vone"
id="vnull"

Actual behavior: the vertex whose i is null takes the WHEN NULL branch (1), fails the == 2 test, and is dropped:

id="vone"

This suggests that the simple CASE form compares the operand to each WHEN value with an equality that treats null as equal to null, instead of the three-valued equality followed by the searched CASE form and by the explicit NULL == NULL comparison observed in the same queries.

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