Repository navigation
Conversation
…ty uses anyIf instead of anyIfOrNull on ClickHouse 25.8 (genezhang#1490)
genezhang
left a comment
There was a problem hiding this comment.
Thanks for taking #1490. I checked this against a 25.8.33 container, and as it stands the change does not take effect on the issue's repro.
Repro (25.8.33; rv.fl2(fid UInt64, o String, d String, o_tags Array(String), d_tags Array(String))):
nodes:
- label: Origin
database: rv
table: fl2
node_id: code
property_mappings: {}
from_node_properties: { code: o, tags: o_tags }
- label: Dest
database: rv
table: fl2
node_id: code
property_mappings: {}
to_node_properties: { code: d, tags: d_tags }
edges:
- { type: F2, database: rv, table: fl2, from_id: o, to_id: d, from_node: Origin, to_node: Dest, edge_id: fid, property_mappings: {} }MATCH (a:Origin) RETURN a.code, a.tags
-- 25.8 main: Code 43 "Nested type Array(String) cannot be inside Nullable type"
-- 25.8 PR: the same Code 43; `cg sql` still shows `anyIfOrNull(e.tags__cg0, NOT isNull(e.tags__cg0))`
Why. is_complex is read from ns.property_mappings, but an embedded node declares its properties in from_node_properties / to_node_properties, and property_mappings is {}. So is_complex is always false for exactly the nodes this is meant for, and the anyIf branch is never taken.
A further concern, once it does fire. anyIf returns the type's default for a group with no non-NULL value, so an absent property would read as [] instead of NULL. That changes RETURN n.tags and n.tags IS NULL on 26.x as well, where main is correct today. The issue suggests either a spelling valid for both versions or the column types, to avoid this.
Smaller points
- No test exercises the new branch. The lowering test would have shown the SQL unchanged.
- The trait default
any_non_nulltakesis_complexand discards it (let _ = is_complex), and the doc comment about complex types now sits on a default that does not act on it. - Please drop the
osv-scanner.tomlhunk, which replaces the reason text onmainwith an older wording.
Happy to re-review, and to try a candidate on the 25.8 container if that helps.
|
Acknowledged. Rework plan: read is_complex from from_node_properties/to_node_properties (not property_mappings, which is empty for embedded nodes); address the anyIf type-default concern (NULL -> [] changes RETURN n.tags and IS NULL semantics on 26.x); add a lowering test for the new branch; drop osv-scanner.toml hunk + rebase. The any_non_null complex changes belong to this PR only (not stacked into #1557/#1487). |
…erty_mappings for embedded nodes)
|
Reworked: is_complex is now read from the underlying table's column_types (added to NodeRelation), instead of property_mappings (empty for embedded nodes). This makes the anyIf (complex) path fire for Array/Map/Tuple/Dynamic properties on embedded nodes. Verified: lib 1489/0, clippy clean, fmt clean. Note: the anyIf type-default concern (NULL -> []) for all-NULL groups is unchanged; kept anyIfOrNull for scalars. |
What
Fixes #1490: on ClickHouse 25.8, a node embedded in edge tables (
from_node_properties/to_node_properties) that has anArray,Map,TupleorDynamicproperty fails every query that reads the node. Cause:anyIfOrNullwraps the result inNullable, which these types cannot be inside on 25.8.Fix:
any_non_nullnow takes anis_complexflag. For complex types (Array/Map/Tuple/Dynamic), useanyIf(returns the type's default for an all-NULL group) instead ofanyIfOrNull. For scalars, keepanyIfOrNull(NULL for absent). The caller in embedded.rs determinesis_complexfrom the NodeSchema'scolumn_types(raw ClickHouse type string starts with Array/Map/Tuple/Dynamic/Variant).Gates (local, 1.94.1,
--no-default-features)Honest limits
Spec-driven
Backward-compatible (only embedded nodes with complex properties change rendering; scalars unchanged). Corpus goldens byte-identical (ratchet green).
Closes #1490