oracle: support <<label>> on every PL/SQL statement - #390
Conversation
Statement labels were only recognized as block prefixes: the label branch of parsePLSQLStatement dispatched straight to parsePLSQLBlock, so a label before any other statement — assignment, NULL, procedure call, IF, a GOTO target — failed to parse. Engine-verified on Oracle 23ai Free: one or more labels are legal before ANY statement, and a customer package failed review at exactly this shape (<<end_check>> followed by a record-field assignment). Consume all leading labels, parse the following statement, and attach: blocks and loops keep their first label on their own Label field (END-label matching unchanged), and any other statement — or labels beyond the first — ride on a new PLSQLLabeledStatement wrapper node, serialized with :labels/:statement. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
INSERT INTO t VALUES record required a parenthesized tuple, rejecting
the documented record form at the record's name — the error text
matches two statements in the same customer report (BYT-9909), whose
packages fill %ROWTYPE records field by field before inserting them.
When VALUES is not followed by '(', parse an expression as the record
source: bare records, package-qualified records, and FORALL collection
elements (VALUES arr(i)) — all engine-verified on Oracle 23ai Free,
including RETURNING after the record. The value lands on a new
InsertStmt.ValuesRecord field so consumers can tell the record form
from the tuple list.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Second commit folds in the VALUES-record fix (BYT-9909 statements 4/5 hypothesis, error text byte-identical): |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 28a082ced9
ℹ️ 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".
Co-Authored-By: Claude Fable 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: 89aa57b2f7
ℹ️ 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".
- NodeLoc knows PLSQLLabeledStatement, so location consumers keep the statement range for labeled non-block statements. - A labeled block or loop extends its Loc.Start to the label position, restoring the pre-change property that the node's range covers its own Label field. - <<>> is rejected (engine: PLS-00103); label names must be nonempty. - :labels entries are %q-quoted — <<"a b">> is a legal quoted label (engine-verified) and was serialized ambiguously. - Mismatched END LOOP labels stay ACCEPTED, refuting the review suggestion with engine evidence: Oracle runs <<a>> LOOP ... END LOOP b; successfully. Fenced so it is not "fixed" into a rejection later. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 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: 1d81724a3d
ℹ️ 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".
| return p.parsePLSQLBlock() | ||
| start := p.pos() | ||
| var labels []string | ||
| for p.cur.Type == tokLABELOPEN { |
There was a problem hiding this comment.
Route top-level labels through the multi-label parser
This multi-label path runs only from parsePLSQLStatements; the top-level tokLABELOPEN dispatch in oracle/parser/parser.go still calls parsePLSQLBlock directly, which consumes only one label. Consequently an engine-supported anonymous block such as <<a>> <<b>> BEGIN NULL; END; fails when parsePLSQLBlock encounters the second <<, despite the new one-or-more-label guarantee. Route the top-level label case through equivalent multi-label handling.
Useful? React with 👍 / 👎.
variable constraints Picks up three engine-verified parser fixes (bytebase/omni#390-#392): - PL/SQL statement labels (<<label>>) parse as labeled statements or attach to blocks and loops; labeled non-block statements are wrapped in a PLSQLLabeledStatement node that generic AST walkers traverse transparently. - Local procedure/function declarations in PL/SQL declaration sections parse via the package-item parsers, closing both the rejection of parameterized forms and the silent mis-parse of parameterless forms into variable-declaration fragments. - MSSQL table variables accept table-level constraints and indexes (unnamed, engine-verified; the named-constraint form stays rejected like the engine). No Bytebase-side consumer changes: advisor and span walkers use generic AST traversal, verified against the new node shapes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fixes the confirmed defect from BYT-9909 statement 3 (customer package failing SQL review at line 498,
<<end_check>>followed by a record-field assignment).Problem
parsePLSQLStatementtreatedtokLABELOPENas "labeled block" and dispatched toparsePLSQLBlockunconditionally, so a<<label>>before any non-block statement failed. Systematic probe: labeled assignment / NULL / procedure call / IF / double labels all rejected, while the same statements without labels pass. Engine-verified on Oracle 23ai Free: one or more labels are legal before ANY statement (GOTO targets included, multi-label included).Fix
Consume all leading
<<ident>>labels, recurse into statement parsing, then attach:PLSQLBlock/PLSQLLoopkeep their first label on their existingLabelfield (END-label matching untouched); any other statement — or labels beyond the first — ride on a newPLSQLLabeledStatementwrapper (Labels []string+Statement), serialized with:labels/:statementand wired into the generated walker.With this fix the customer's package body parses past the failing line (the truncated attachment text now errors only at its Excel truncation point).
Tests
TestPLSQLStatementLabels: 12 accept shapes (every statement kind, GOTO-target flow, loop END-label matching, the customer's package-body shape), unclosed-label reject, and AST-shape assertions (loop keepsLabel, wrapper carries multi-labels,:labelsserialized).Consumer note for the next bytebase bump: walkthrough/span switches should treat
PLSQLLabeledStatementas transparent (recurse into.Statement); labels carry no data flow.🤖 Generated with Claude Code