Skip to content

fix(oracle): re-run LOB queries after a failed define without ORA-01002 - #18

Merged
FabioHAraujo merged 3 commits into
mainfrom
fix/oracle-clob-reexecute
Oct 23, 2026
Merged

FabioHAraujo merged 3 commits into
mainfrom
fix/oracle-clob-reexecute

Conversation

@FabioHAraujo

@FabioHAraujo FabioHAraujo commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Closes #17

The first time a query with LOB columns runs, it takes two round trips: an execute that returns the column descriptions, then a second execute that defines the LOB columns (as text here). Temporary protocol traces on 23ai and 21c in CI (not part of this PR) showed two ways the vendored driver later sent a define-only execute on a cursor that had nothing left to fetch, which the server answers with ORA-01002 (fetch out of sequence):

  1. The query is described again. When the server parses a cached query again (statistics feedback after the first runs, new statistics, other invalidations), the next execute response carries the column descriptions again (LOB columns as CLOB), along with the rows already returned as LONG and ORA-1403. The driver read that description as a new LOB column, flagged a define, and sent it after the fetch had ended. On 23ai this tends to happen around the third run, which is the original Show DDL symptom. Fix: port python-oracledb's _adjust_metadata. On a cursor that already ran, a column described as CLOB/BLOB whose previous type was string/LONG (or RAW/LONG RAW) keeps the LONG type and needs no define.
  2. The define round trip failed (for example ORA-31608 from get_dependent_ddl on a table without comments, or any error raised while the first rows are fetched). The statement went back to the cache still flagged as needing a define, so every later run sent only the define and failed. Fix: close that cursor so the next run parses again, as python-oracledb does after errors.

Both fixes are in src-tauri/vendor/oracledb and recorded as patches 3 and 4 in LOWQUERY.md. first_texts (Show DDL) no longer uses exclude_from_cache().

New test oracle_clob_queries_run_repeatedly covers: dbms_metadata.get_ddl, to_clob(...), and a table with CLOBs over 4000 characters (all rows, and the first row only with the cursor left open), 5 runs each, with dbms_stats.gather_table_stats(no_invalidate => false) before run 3 to force the re-describe; a CLOB query that fails with ORA-01476 twice, then succeeds 3 times; and Show DDL 5 times through the statement cache. Before the fixes it failed on both 23ai and 21c (run 3 after the invalidation, and run 2 after the failed define).

CHANGELOG entry under [Unreleased]; it ships in 0.5.2 together with export/import.

@FabioHAraujo
FabioHAraujo force-pushed the fix/oracle-clob-reexecute branch from 80feb44 to a072083 Compare October 23, 2026 03:47
@FabioHAraujo FabioHAraujo changed the title fix(oracle): re-run queries returning CLOBs without ORA-01002 fix(oracle): re-run LOB queries after a failed define without ORA-01002 Oct 23, 2026
@FabioHAraujo
FabioHAraujo force-pushed the fix/oracle-clob-reexecute branch 2 times, most recently from d559662 to b45611f Compare October 23, 2026 03:50
A query with LOB columns is executed, then sent again to define them. When
either step failed, the statement went back to the driver's cache still
marked as needing a define: its next execution only sent the define and
fetched from a cursor that was never executed (ORA-01002), and so did every
later run of the same SQL in the session. The vendored driver now closes
that cursor so the next run parses the statement again, and Show DDL uses
the statement cache again.

Closes #17
@FabioHAraujo
FabioHAraujo force-pushed the fix/oracle-clob-reexecute branch from b45611f to 62525d3 Compare October 23, 2026 03:58
… again

When the server parses a query again (statistics feedback, new statistics),
it describes the columns again on the next execution, LOB columns as
CLOB/BLOB, while the cursor keeps its define and returns them as LONG with
the rows. The vendored driver took that as a new LOB column and sent a
define after the rows were fetched (ORA-01002). Like python-oracledb's
_adjust_metadata, such a column now keeps its LONG type.

Refs #17
@FabioHAraujo
FabioHAraujo force-pushed the fix/oracle-clob-reexecute branch from 62525d3 to 17d1c66 Compare October 23, 2026 04:07
@FabioHAraujo
FabioHAraujo marked this pull request as ready for review October 23, 2026 04:25
@FabioHAraujo
FabioHAraujo merged commit 17d1c66 into main Oct 23, 2026
15 checks passed
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.

Oracle 23ai: ORA-01002 when a query returning a CLOB runs a third time in a session

1 participant