Repository navigation
fix(oracle): require ';' after PL/SQL statements, declarations, and END (BYT-10301) - #447
Conversation
…ND (BYT-10301) omni accepted PL/SQL that Oracle rejects with PLS-00103 because three parsers recovered silently instead of failing: - the statement loop resumed after a statement that stopped early, so the words left over parsed as procedure calls (BEGIN NULL END;); - the declaration loops and the package item loop skipped what they did not recognize, and stray ';' between items; - END of a block, package, type body, and compound trigger took its ';' only when present. Each statement, declaration, package item, and END now requires its ';', and a stray ';' is an error, as on Oracle 23ai. Missing ';' is reported at the token Oracle reports: a PL/SQL reserved word after END or END LOOP is no longer taken as a label (END LOOP END;), using the reserved set measured on the engine. The leniency hid constructs omni did not parse, now implemented: - COMMIT, ROLLBACK, SAVEPOINT, SET TRANSACTION, and LOCK TABLE inside a PL/SQL body, and the INLINE, COVERAGE, DEPRECATE, and SUPPRESSES_WARNING_6009 pragmas as statements (other pragmas fail there, as in Oracle); - SUBTYPE name IS base_type [RANGE low .. high] [NOT NULL] (PLSQLSubtypeDecl); - NOT NULL on the element type of TABLE OF and VARRAY OF; - expressions as a length, precision, or scale in PL/SQL declarations (VARCHAR2(ORA_MAX_NAME_LEN + 2), varchar2(pkg.c)); SQL keeps integer literals. Reference rows ref_105 to ref_128 record the engine's answers; main disagreed with Oracle on 14 of them. In the dictionary manifest, DBMS_HADOOP's body now parses; four JSON units fail at the unsupported RETURNING clause instead of after it; STANDARD stops at its enumeration type, Oracle-internal syntax that Oracle rejects elsewhere (PLS-00505). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 19967dcecf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ess (BYT-10301) Review follow-up, each form checked on Oracle 23ai: - CASE statement arms parse through the statement list, so every arm statement needs its ';' (THEN NULL x := 1 was accepted). - END CASE and END IF are required (END; alone is PLS-00103), take an optional label as Oracle allows (END IF l;), and need their ';'. - A block body, IF and CASE branch, loop body, and exception handler hold at least one statement (BEGIN END; is PLS-00103), a CASE statement at least one WHEN, and a handler requires THEN. - SUBTYPE ... RANGE needs both bounds. - LOCK requires TABLE (ORA-00966), in SQL and in PL/SQL. - A datatype nested in a PL/SQL type-length expression, as in VARCHAR2(CAST(1 AS NUMBER(foo))), follows the SQL rules again. Reference rows ref_129 to ref_139 record the engine's answers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f771826518
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…es (BYT-10301) PL/SQL now dispatches LOCK TABLE to the shared parser, which took any words before MODE, WAIT without an interval, and anything inside the partition parentheses. Checked on Oracle 23ai: - the lock mode is one of ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE (IN FOO MODE is ORA-01737, IN SHARE EXCLUSIVE MODE ORA-01739); - WAIT takes an unsigned integer literal (WAIT, WAIT -1: ORA-30005; WAIT 2.5: ORA-02017; WAIT 1 + 1 and a PL/SQL constant are rejected); - PARTITION (name) takes one name (PARTITION () and PARTITION (p1, p2) are ORA-01738); PARTITION FOR takes key value expressions. Reference rows ref_140 to ref_146. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Next step of the BYT-10301 plan, after #443 and #446. omni's Oracle parser accepted PL/SQL that Oracle rejects with PLS-00103, because three loops recovered from errors silently instead of reporting them. This PR makes them strict. It also implements the constructs that the silent recovery had been hiding.
What was lenient
BEGIN NULL END;was accepted);DECLAREsection and subprogram declarations;ran into the next one;;between items, were skipped;, is an errorENDof a block, package, type body, compound trigger;taken only when presentEND/END LOOPEND LOOP END;the secondENDwas taken as a label and the error appeared at end of inputEND, where Oracle reports it. The reserved set was measured on the engine: 85 words. Oracle allowsTYPEandLOOPas labels but rejectsPRIORWhat the leniency hid, now parsed
COMMIT,ROLLBACK,SAVEPOINT,SET TRANSACTION,LOCK TABLEin a PL/SQL bodyLOCK TABLE)PRAGMA INLINE/COVERAGE/DEPRECATE/SUPPRESSES_WARNING_6009as statementsPLSQLPragma. All other pragmas are rejected in a body, as Oracle rejects them (PLS-00710 etc.)SUBTYPE name IS base_type [RANGE lo .. hi] [NOT NULL]PLSQLSubtypeDecl. 34 Oracle-shipped packages declare oneTABLE OF t NOT NULL,VARRAY(n) OF t NOT NULLPLSQLTypeDecl.ElementNotNullVARCHAR2(ORA_MAX_NAME_LEN + 2),varchar2(pkg.c))CREATE TABLE t (c VARCHAR2(10 + 2))is ORA-00907)Engine evidence
ref_105toref_128inreference_oracle.tsvare checked against the pinned Oracle image. Main disagreed with Oracle on 14 of the 24:LOCK TABLE,SUBTYPE, expression lengths, collectionNOT NULL.;after a statement, after a declaration, afterEND IF, after a unit'sEND, and after a package'sEND; a stray;in a package; a non-declaration package item; a body-only pragma; a reserved word used as anENDlabel.plsql_terminator_test.gopins the error position of 25 malformed inputs, plus the AST of the new forms.plsql_dictionary_known_failures.tsv, 875 Oracle-shipped units): no unit went from passing to failing.DBMS_HADOOPbody now parses.DBMS_HADOOP_INTERNALnow fails later, at a parenthesizedUNION ALLinsideIN.DBMS_FEATURE_*units now fail at the unsupportedJSON_SERIALIZE(... RETURNING ...). Before, the parser silently skipped past that clause and failed after it.STANDARDnow stops attype BOOLEAN is (FALSE, TRUE), an enumeration type outside STANDARD (PLS-00505). It is filed under Oracle-internal syntax, and the category name now mentions enumeration types.Impact on Bytebase
A PL/SQL unit without its final
;is now a syntax error:Oracle compiles this with PLS-00103, so omni now agrees with the engine. Bytebase up to 3.18, which parsed with ANTLR, appended a missing final
;to PL/SQL units. Whether to restore that is a Bytebase decision, handled in the omni bump PR.Verification
make test-oraclepasses, includingTestOracleReference,TestOraclePLSQLDictionary, and the keyword-column audit, all against the pinned container.TestOracleCompatibilityReferenceReportoutcome counts are identical to main:match_accept=361, match_reject=182.go vet ./oracle/ast/ ./oracle/parser/has the same 13 findings as main.go generate ./oracle/ast/...is in sync,gofmtis clean, andgo build ./...passes.Left for later
These are outside this PR:
BEGIN/END.ISandOFare optional inTYPE ... IS TABLE OF.ISis optional.).CHARACTER SET ANY_CS(27),PIPELINED/AGGREGATE USING(24),ACCESSIBLE BY(19), and others.🤖 Generated with Claude Code