Repository navigation
Compile randomUUID() to Oracle's UUID(), a random v4, and need Oracle 23.9 - #273
Merged
Merged
Conversation
… 23.9 On Oracle, compiled Cypher's randomUUID() was SYS_GUID() written as a UUID: version 0, consecutive values sharing all but a counter's digits, so the token stamps.set_clause and links_clause make changed in about 16 bits, in order. It is now Oracle's UUID(), a random version 4 UUID, 92 characters, so it is written where it is read and each row gets its own. UUID() arrived in Oracle 23.9. The provider reads connection.version on its first connection, once per pool, with no grant. On an older Oracle plain SQL still runs, and a Cypher statement is refused with the version found. A version that cannot be read refuses nothing. Port of liberation-data/drivine4j#401 (PR #402). Fixes #252
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 #252
Port of liberation-data/drivine4j#401 (PR liberation-data/drivine4j#402).
On Oracle, compiled Cypher's
randomUUID()wasSYS_GUID()written as a UUID. That value is version 0, and consecutive values share all but a counter's digits. The stamp token thatstamps.set_clauseandstamps.links_clausemake,left(replace(randomUUID(), '-', ''), 16), therefore changed in only about 16 bits, and in order.The change.
OracleCypherCompiler.uuid()is now Oracle's ownUUID(), a random version 4 UUID:It is 92 characters, under
SHARED_ABOVE(200). So it is written where it is read and not bound once for the statement, and each row gets a UUID of its own. The stamp clauses compile to it unchanged in length, so they aren't hoisted either.Drivine now needs Oracle 23.9 or later, because
UUID()arrived in 23.9.OracleConnectionProvider._check_versionreadsconnection.version(python-oracledb gives "23.26.3.0.0"), which needs no grant. It runs in_ensure, on the first connection, once per pool:GraphTablesruns it once, and again afterend(). On an older Oracle it logs a warning, hands connections out, and plain SQL runs.OracleConnection._compiled, which serves bothqueryandopen_cursor, refuses a Cypher statement with:A version that can't be read refuses nothing. The object manager writes its own SQL, so it is not refused. The sync copy is written by
scripts/unasync.py. The README, the introduction,docs/03-cypher-on-a-relational-database.md(with the reason) anddocs/design.mdnow say 23.9 or later.Tests
test_cypher_compiled.py, on Neo4j, Postgres and Oracle:randomUUID()values are distinct lower-case version 4 UUIDs, and at most 2 consecutive pairs share more than 4 leading characters;randomUUID() + ''and'id-' + randomUUID()overUNWIND range(1, 100)give 100 distinct values;set_clauseand thenlinks_clauseover 1,000 nodes give 1,000 distinct stamps and 2,000 distinct tokens. Every hex position except the version digit takes at least 12 values, and 20 saves of one node in a row seldom share a long prefix.The sync copies run the same tests.
tests/unit/test_oracle_version.py:oracle_refusal: 23.8 and 19.3 are refused with the message; 23.9, 23.26 and 26.1 pass;None,""and an unparseable version refuse nothing.test_oracle_connection.py: on the test image, the version passes andRETURN randomUUID()gives a version 4 UUID.Compiled SQL. Every statement of the four spec files at v0.6.19, plus the two stamp clauses (1,033 statements), was compiled with the Oracle and Postgres compilers on
mainand on this branch.randomUUID()differ (Functions of numbers, steps 6 and 7; A random value bound by a WITH in a write, step 1), plus the two stamp clauses. WithSYS_GUID()replaced byUUID(), the output is byte-identical.Gates:
check_cypher_spec.py(v0.6.19), ruff check and format, pyright (0 errors),unasync.py --check, andORACLE_TESTS=true uv run pytest -q: 5181 passed, 298 skipped.