Repository navigation
Read the variables a CALL imports apart from its aggregate, so sum() and collect() of one aren't 0 and [] on Oracle and count() of one compiles on Postgres - #278
Merged
Conversation
…and collect() of one aren't 0 and [] on Oracle and count() of one compiles on Postgres
Where a WITH or the RETURN in a CALL { } aggregates, the row's variables are read first into a query of no table,
kept apart by bound_select (NO_MERGE on Oracle, OFFSET 0 on Postgres), made the call's first source, and bound from
there as the call's own. Names the call binds itself (an UNWIND variable, what a CALL within it returns) are left out,
and so is a call whose WITHs and RETURN are all *. Port of liberation-data/drivine4j#406
(liberation-data/drivine4j#368).
Fixes #253
…sion and a CASE, and a renamed, boolean and path import
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #253. Port of liberation-data/drivine4j#406 (liberation-data/drivine4j#368).
The bug. An aggregate inside
CALL { }of a variable the call imports went wrong:sum()gave 0 andcollect()gave[]. Oracle 23 reads a JSON_TABLE outer column as null inside a lateral aggregate that is joined to another source.CALL (o) { … count(o) }failed with "aggregate functions are not allowed in FROM clause of their own query level".The fix. A new
_imports_apart, called from_called_part(drivine/cypher/sql/sql_cypher_compiler.py). When aWITHor theRETURNin the call holds an aggregate, the row's imported variables are read first into a query of no table, kept apart bybound_select(NO_MERGEon Oracle,OFFSET 0on Postgres). That query is the call's first source, and the call binds the variables from it as its own.Two cases are left out:
UNWINDvariable, or what aCALLwithin it returns or yields;WITH, and itsRETURN, is*.The code and its doc comment match drivine4j's. As
_matchdoes, the columns are written withself._identities, so theUNIONrecompile without identities applies to them too.SQL. Every statement of the spec (v0.6.19) was compiled on Postgres and Oracle before and after the change. Only one statement changes on each store:
MATCH (p:Person) CALL { WITH p MATCH (p)-[:ACTED_IN]->(m:Movie) RETURN count(m) AS movies } …(queries.yaml, "CALL subqueries", step 1). That is the same statement drivine4j's change touched, and it now readspfrom(SELECT /*+ NO_MERGE */ n1.nid AS v2_nid, …) i3on Oracle and from(SELECT … OFFSET 0) i3on Postgres. The goldens are unchanged.Tests. drivine4j's cross-engine "an aggregate in a CALL reads the variables the CALL imports" is ported with Neo4j's rows, in
tests/integration/test_cypher_compiled.py(and its unasync copy intests/sync_integration),test_an_aggregate_in_a_call_reads_the_variables_the_call_imports. It runs on Neo4j, Postgres and Oracle, async and sync and covers:WITHandCALL (o)forms;sum,collect,countandmax;OPTIONAL CALL;RETURN *cases;UNIONinside the CALL;Gate.
scripts/check_cypher_spec.py(v0.6.19),ruff check,ruff format --check,pyright,scripts/unasync.py --check, andORACLE_TESTS=true uv run pytest -q(FalkorDB 6.0.3) all pass: 5,161 passed, 298 skipped. After the run, oracledb's pool threads print DPY-4011 tracebacks as the Oracle container stops; they come after the summary and don't fail it.Drivine for TypeScript's port is for liberation-data/drivine#429.