You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Preserve null-valued keys in map literals (#2391) (#2412)
* Preserve null-valued keys in map literals (#2391)
Map literals such as RETURN {a: null} previously dropped keys whose
values were null, producing {} instead of {"a": null}. This
diverged from the openCypher / Neo4j semantics where map literals
preserve every key the user wrote, including those bound to null.
Root cause: cypher_map.keep_null defaulted to false (zero-initialised),
so the grammar-produced node fed agtype_build_map_nonull, which strips
null entries. Call sites that legitimately need strip-null semantics
(CREATE node/edge property maps and SET = assignments) already set
keep_null=false explicitly, and the MATCH pattern path sets it to true
explicitly. Flipping the grammar default to true therefore only affects
the cases that were buggy (bare map expressions and nested map values),
and leaves CREATE/SET behaviour unchanged.
Two preexisting tests encoded the old buggy output and are updated:
expr.out (bare RETURN maps now keep the null value) and agtype.out
(a nested map inside an orderability test no longer drops its null
entry, shifting one row in the ORDER BY result). Dedicated regression
coverage for #2391 is added to regress/sql/expr.sql.
* Address review: move 'End of tests' marker and drop order claim
- Move 'End of tests' to after the Issue 2391 test block so it marks
the actual end of the file.
- Remove 'in order' from the mixed-values comment since map key
ordering is not guaranteed.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update accessor EXPLAIN expected output for null-preserving map literals
Map literals now build with agtype_build_map (keep_null) instead of
agtype_build_map_nonull, so the accessor-optimization EXPLAIN plan in
expr.out must reflect the new function name. Also strip a stray trailing
CRLF on the last line of expr.sql/expr.out that leaked a carriage return
into the regression output.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add nested-map write coverage and clarify top-level strip wording
A reviewer noted the keep_null=true default reaches further than the
PR summary stated: CREATE / SET = only override keep_null=false on the
top-level property map, not recursively. A nested map value is its own
cypher_map node, so it now inherits the new default and preserves its
null-valued keys (e.g. CREATE (n {a: {b: null}}) stores a -> {"b": null}).
- regress/sql/expr.sql, regress/expected/expr.out: pin the nested case
under a write with CREATE (n:Nested {a: {b: null}}), MATCH ... SET
n = {a: {b: null}}, and a MATCH verify.
- src/backend/parser/cypher_gram.y: clarify the map: rule comment to
state the CREATE / SET override is top-level only and nested map
values keep the null-preserving default.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
0 commit comments