Skip to content

cypher-codegen: infer nullability for SET-clause params#78

Merged
jbmusso merged 2 commits into
mainfrom
cypher-codegen-set-param-nullability
Jun 3, 2026
Merged

cypher-codegen: infer nullability for SET-clause params#78
jbmusso merged 2 commits into
mainfrom
cypher-codegen-set-param-nullability

Conversation

@jbmusso

@jbmusso jbmusso commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Problem

QueryAnalyzer.extractParams typed query parameters from two sources only:

  1. Pass 1 — params inside node-pattern property maps: (n:Label {prop: $p}) (covers CREATE/MATCH constraints).
  2. Pass 2expr.prop IN $param list expressions.

Params bound via a SET clause — MATCH (n:Label {id: $id}) SET n.prop = $p — were not analyzed. The backend regex scan still surfaced the param name, so it appeared in the generated signature, but with the fallback type { type: "String", nullable: false }.

Net effect: a param assigned to an optional vertex property was typed non-nullable (e.g. prop: string) when it should be prop: string | null — the adapter must be able to persist null to clear such a property.

Fix

Add a Pass 3 to extractParams, mirroring Pass 1 but walking SET items:

  • Walks SetItemContext nodes, handling only the propertyExpression ASSIGN expression alternative (<var>.<prop> = $param).
  • Resolves <var> → label via the existing buildVarLabelMap, then types the param via lookupParamType exactly as Pass 1 does — emitting the property's type and nullable flag.
  • SET n += $map (map-merge) is naturally excluded: that alternative has no propertyExpression(), so it never enters Pass 3 (map params remain a separate feature).
  • The shared seenParams set prevents double-counting a param used in both a pattern and a SET.
  • Left-hand sides that can't be resolved to a labelled schema property keep the prior non-nullable String fallback, so behaviour is unchanged for untyped params.

Tests

New describe("analyzeQuery — SET-clause param nullability") block in QueryAnalyzer.node.unit.test.ts, written test-first (verified red for the right reason — SET params were absent from analyzer output — before implementing):

  • SET param on an optional vertex property → nullable: true.
  • SET param on a mandatory vertex property → nullable: false.
  • Multi-property SET types each item independently.
  • A param constrained in both a MATCH pattern and a SET is not double-counted.

Existing Pass 1 (CREATE/MATCH) and Pass 2 (IN) param typing is unchanged. Full package unit suite: 178/178 green; pnpm check clean.

Release

Changeset included: minor bump for @evryg/effect-cypher-codegen (0.2.00.3.0).

Commits

  • cypher-codegen: infer nullability for SET-clause params — Pass 3 implementation + unit tests
  • cypher-codegen: changeset for SET-clause param nullability — release changeset

jbmusso and others added 2 commits June 3, 2026 23:28
QueryAnalyzer.extractParams typed params only from node-pattern property
maps (Pass 1) and `expr.prop IN $param` list expressions (Pass 2). Params
bound via a SET clause (`MATCH (n:Label {...}) SET n.prop = $param`) were
not analyzed, so they fell back to a non-nullable `String`, even when
assigned to an optional vertex property that must accept `null`.

Add Pass 3, mirroring Pass 1 over SET items: resolve `<var>.<prop>` to a
labelled schema property via the existing buildVarLabelMap / lookupParamType,
emitting the property's type and nullability. Only the
`propertyExpression ASSIGN expression` alternative is handled, so map-merge
(`SET n += $map`) is naturally excluded; the shared seenParams set prevents
double-counting a param used in both a pattern and a SET. Unresolvable
left-hand sides keep the prior non-nullable `String` fallback.

Covered by new unit tests in QueryAnalyzer.node.unit.test.ts.

Generated with AI

Co-Authored-By: AI <ai@example.com>
Minor bump: parameters bound in a SET clause now infer their type and
nullability from the schema.

Generated with AI

Co-Authored-By: AI <ai@example.com>
@jbmusso
jbmusso merged commit 27d7647 into main Jun 3, 2026
8 checks passed
@github-actions github-actions Bot mentioned this pull request Jun 3, 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