Skip to content

quantifier: MATERIALIZE non-deterministic CTEs + entity-in-list property access (+18)#90

Merged
dylanbstorey merged 2 commits into
mainfrom
i0049-quantifier
Jun 1, 2026
Merged

quantifier: MATERIALIZE non-deterministic CTEs + entity-in-list property access (+18)#90
dylanbstorey merged 2 commits into
mainfrom
i0049-quantifier

Conversation

@dylanbstorey

Copy link
Copy Markdown
Contributor

Closes most of the Quantifier TCK cluster — 3758 → 3776 (+18), zero regressions. Part of GQLITE-I-0049.

1. MATERIALIZE non-deterministic CTEs (+18) — sql_builder.c

A WITH-projected value built with rand() changed on every reference. SQLite treats a multiply-referenced CTE as a view and re-runs RANDOM() per reference, so in a chain of WITH CTEs the same list yielded a different random value at each use. The quantifier algebraic-identity scenarios then broke — none(x IN list WHERE p), any(...), and NOT any(...) over the same list each saw a different random list, so none(...) = (NOT any(...)) came out false.

sql_cte/sql_pre_cte now emit AS MATERIALIZED (...) when the CTE body contains RANDOM( (gated, non-recursive only → recursive/varlen and deterministic CTEs untouched), forcing single evaluation. Fixes Quantifier9/11/12 + related.

2. Entity-in-list property access (+0 groundwork) — transform_expr_ops.c

r.name where r is a node/rel that is a list element (e.g. any(r IN relationships(p) WHERE r.name = 'a')) returned null — it used top-level json_extract($.name) but entities store props under .properties. Now routes through _gql_dyn_prop (entity → $.properties.<key>, map → $.<key>). Correct + regression-free; the Quantifier1-4 [8]/[9] scenarios additionally need varlen relationships(p) through an aggregating WITH + GROUP-BY-on-list (deferred).

Verification

Unit 944/944, functional clean. Per-fix rigorous pass-set diffs: zero regressions. Windows CI allowed to fail (known issue).

Dylan Bobby Storey added 2 commits June 1, 2026 11:08
…ble (+18 TCK)

A WITH-projected value computed with rand() (e.g.
`WITH CASE WHEN rand()<0.5 THEN reverse(list) ELSE list END + x AS list`)
changed on every reference. SQLite treats a multiply-referenced CTE as a view
and re-evaluates its body (re-running RANDOM()) per reference, so in a chain of
WITH CTEs the same `list` yielded a DIFFERENT random value at each use. The
quantifier algebraic-identity scenarios then broke: `none(x IN list WHERE p)`,
`any(x IN list WHERE p)`, and `NOT any(...)` over the SAME list each saw a
different random list, so e.g. `none(...) = (NOT any(...))` was false.

sql_cte() and sql_pre_cte() now emit `AS MATERIALIZED (...)` when the CTE body
contains a non-deterministic function (gated on the substring `RANDOM(`),
forcing SQLite to compute the CTE once. Gated to non-recursive CTEs only
(MATERIALIZED is invalid on a recursive CTE) and only when RANDOM() is present,
so recursive/varlen and ordinary deterministic CTEs are unchanged.

Rigorous full pass-set diff: zero regressions, +18 (Quantifier9/11/12 identity
cluster + Quantifier1-4 related). 3758 -> 3776. Unit 944/944, functional clean.
…roundwork)

`r.name` where r is a node/relationship that is a LIST ELEMENT (e.g. the
quantifier variable in `any(r IN relationships(p) WHERE r.name = 'a')`)
returned null: the projected-JSON property branch used top-level
`json_extract(value, '$.name')`, but an entity stores props under
`.properties`. It now routes through `_gql_dyn_prop`, which picks
`$.properties.<key>` for entity-shaped objects and `$.<key>` for plain maps
(same UDF already used for subscript bases).

Correct + regression-free (rigorous full pass-set diff: zero regressions, zero
newly-passing). Groundwork: the Quantifier1-4 [8]/[9] scenarios additionally
require varlen relationships(p)/nodes(p) through an aggregating WITH and
GROUP-BY-on-list, deferred.
@dylanbstorey dylanbstorey merged commit faa2e8f into main Jun 1, 2026
16 of 17 checks passed
@dylanbstorey dylanbstorey deleted the i0049-quantifier branch June 1, 2026 20:37
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