Skip to content

cypher-codegen: account for fallback argument types in coalesce inference#86

Merged
jbmusso merged 2 commits into
mainfrom
fix/coalesce-integer-inference
Jun 6, 2026
Merged

cypher-codegen: account for fallback argument types in coalesce inference#86
jbmusso merged 2 commits into
mainfrom
fix/coalesce-integer-inference

Conversation

@jbmusso

@jbmusso jbmusso commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Problem

coalesce(x, ...) inferred its result type as the first argument only, stripped of nullable — ignoring the fallback arguments. When a nullable Double property is coalesced with an integer literal (coalesce(n.score, 0)), the property's type (Double) wins, so the emitted column is Schema.Number. But at runtime, when the property is null, the database returns the integer literal 0 as an Integer object, which Schema.Number rejects → decode crash.

Fix

coalesce returns the first non-null argument, so the result type must unify the candidates:

  • Walk arguments left→right, each stripped of nullable, stopping at the first non-nullable one (later args are unreachable).
  • Unify scalars: equal types collapse to that type; two numeric scalars (Long/Double in any mix) collapse to Long — the integer-tolerant decoder is the numeric superset (accepts database integers, passes floats through); anything else keeps the leading argument's type.

So coalesce(<nullable Double>, 0) → Long, while coalesce(<non-null Double>, …) → Double and coalesce(<String>, …) → String are unchanged. The decoded TS type stays number, so there's no consumer type breakage.

Tests

  • Red test: coalesce(s.nullableDouble, 0) must infer Long (failed before, returned Double).
  • Regression guards (stay green): nullable Long, non-null Long, non-null String.
  • Fixture uses a synthetic Sample vertex whose properties are named by their type/nullability role — no domain concepts.

Patch changeset included (0.4.1 → 0.4.2).

Generated with AI

jbmusso and others added 2 commits June 6, 2026 14:14
coalesce(<nullable Double>, 0) currently infers Double, ignoring the
integer-literal fallback. When the property is null the runtime yields
the integer literal as a database Integer object, which the Double
decoder rejects. The leading-arg type must widen to Long to stay
decodable.

Adds a synthetic Sample vertex whose properties are named by their type
and nullability role (no domain concepts), plus regression guards for
the non-null and same-type cases that must stay unchanged.

Generated with AI

Co-Authored-By: AI <ai@example.com>
coalesce returns the first non-null argument, so its result type must
unify the candidates, not just take the leading one. Walk arguments
left→right (stopping at the first non-nullable one — later ones are
unreachable), stripping nullable and unifying scalars: equal types
collapse to that type; two numeric scalars (Long/Double in any mix)
collapse to Long, the integer-tolerant superset that accepts database
integers and passes floats through; anything else keeps the leading
type.

This makes coalesce(<nullable Double>, 0) infer Long so the emitted
column decodes the integer literal the runtime yields when the property
is null, while leaving non-nullable and same-type cases unchanged.

Generated with AI

Co-Authored-By: AI <ai@example.com>
@jbmusso
jbmusso force-pushed the fix/coalesce-integer-inference branch from 2d738f5 to 7cb5199 Compare June 6, 2026 12:14
@jbmusso
jbmusso merged commit 5c1c286 into main Jun 6, 2026
8 checks passed
@jbmusso
jbmusso deleted the fix/coalesce-integer-inference branch June 6, 2026 12:16
@github-actions github-actions Bot mentioned this pull request Jun 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant