Skip to content

Work out keys()' data guide per row on Oracle, so each row has its own keys - #282

Open
jasperblues wants to merge 1 commit into
mainfrom
fix/257-oracle-keys-per-row
Open

jasperblues wants to merge 1 commit into
mainfrom
fix/257-oracle-keys-per-row

Conversation

@jasperblues

Copy link
Copy Markdown
Member

Port of liberation-data/drivine4j#414's fix (liberation-data/drivine4j#430).

The bug. On Oracle, keys() gave every row the first row's keys. With four nodes whose keys differ, MATCH (n:CyKeyed) UNWIND keys(n) AS k RETURN n.id, k ORDER BY n.id, k gave node 1's keys (id, name, surname) for node 2 as well, and for the rest. Neo4j and Postgres gave each node its own keys. The new test failed on Oracle before the fix and passed on Neo4j and Postgres.

Cause. _map_keys read the data guide through temporal_elements, as LATERAL (SELECT /*+ NO_MERGE */ (SELECT JSON_DATAGUIDE(x, 2) FROM DUAL) AS list FROM DUAL). Oracle 23 works out that scalar subquery in the view's select list once per statement.

The fix. JSON_DATAGUIDE is now the lateral view's own aggregate, LATERAL (SELECT /*+ NO_MERGE */ JSON_DATAGUIDE(x, 2) AS list FROM DUAL), so it is worked out for each row. This is drivine4j's change exactly.

Tests. drivine4j's test from #430, in test_cypher_compiled.py. It runs on Neo4j, Postgres and Oracle, async and sync, and checks the keys of nodes, relationships, maps and parameters on each row, in a comprehension, a quantifier, a DISTINCT and an order. The test includes TCK Graph8 #2. The unit test of the keys' SQL now also checks that the data guide is worked out in the lateral view.

WHERE 'b' IN keys(n) still leaves rows out on Oracle. That is liberation-data/drivine4j#433, which has a different cause and isn't part of this port.

SQL, spec v0.6.19. I compiled every statement before and after the change. Postgres is unchanged. On Oracle, four statements changed, the four that call keys(): the spec's three keys() steps and Projections of null #0. Each changed only by the data guide's subquery.

Fixes #257

…n keys

On Oracle, keys() gave every row the first row's keys. The map's data guide
was worked out by a scalar subquery in the select list of temporal_elements'
first lateral view, and Oracle 23 works that subquery out once per statement.
JSON_DATAGUIDE is now that view's own aggregate over DUAL, so it is worked out
for each row, as drivine4j does since #430.

Tests ported from drivine4j#430: keys of nodes, relationships, maps and
parameters on each row, in a comprehension, a quantifier, a DISTINCT and an
order.

Fixes #257

This branch has not been deployed

No deployments
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.

Cypher on Oracle: keys() gives the first row's keys for every row

1 participant