Skip to content

fix(frontend): locate PREPARE delimiter by token#25919

Open
VioletQwQ-0 wants to merge 3 commits into
matrixorigin:mainfrom
VioletQwQ-0:codex/issue-25900-prepare-from-name
Open

fix(frontend): locate PREPARE delimiter by token#25919
VioletQwQ-0 wants to merge 3 commits into
matrixorigin:mainfrom
VioletQwQ-0:codex/issue-25900-prepare-from-name

Conversation

@VioletQwQ-0

Copy link
Copy Markdown
Collaborator

What type of PR is this?

  • API-change
  • BUG
  • Improvement
  • Documentation
  • Feature
  • Test and CI
  • Code Refactoring

Which issue(s) this PR fixes:

Fixes #25900

What this PR does / why we need it:

doPrepareStmt previously searched for the first from substring in the original SQL. A statement name such as fromx was mistaken for the delimiter, so the cached inner SQL became from select 1.

This PR:

  • locates the PREPARE delimiter using the MySQL scanner and the session SQL mode;
  • preserves the original inner SQL text, including comments, instead of rebuilding it from the AST;
  • covers substring-containing names, quoted names, ANSI_QUOTES, comments, whitespace, and invalid helper inputs;
  • adds an end-to-end distributed PREPARE/EXECUTE regression.

Validation:

  • go test ./pkg/frontend -count=1
  • go test -race ./pkg/frontend -run '^(TestHandlePrepareStmtNameContainingFrom|TestExtractPrepareStmtSQL|TestExtractPrepareStmtSQLRejectsInvalidInput)$' -count=1
  • go vet ./pkg/frontend
  • go build ./pkg/frontend
  • git diff --check

@mergify mergify Bot added the kind/bug Something isn't working label Jul 20, 2026
@matrix-meow matrix-meow added the size/M Denotes a PR that changes [100,499] lines label Jul 20, 2026
@VioletQwQ-0
VioletQwQ-0 marked this pull request as ready for review July 20, 2026 17:07
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@XuPeng-SH XuPeng-SH left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The token-based approach fixes the reported fromx case, but one supported token layout still stores malformed inner SQL. Details are attached inline.

Comment thread pkg/frontend/mysql_cmd_executor.go Outdated

@gouhongshen gouhongshen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex automated review

The token-based extraction fixes the reported basic case, but remains incorrect for valid MySQL executable-comment syntax.

P2 - Account for executable-comment boundaries after FROM (pkg/frontend/mysql_cmd_executor.go:1559)

For valid input prepare fromx /*! from */ select 1, Scan returns the FROM token inside the executable comment with scanner.Pos immediately after from, before the closing */. The parser subsequently consumes that terminator and builds the expected select 1 AST, but this slice produces */ select 1. Consequently the prepared statement stores malformed SQL that can reach recording and rebuild paths. Derive the source offset past the executable-comment boundary and add an end-to-end regression for this layout.

@gouhongshen gouhongshen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex automated review

The reported delimiter bug and simple executable-comment case are fixed, but executable-comment boundary detection still corrupts valid inner SQL containing */ inside a quoted string.

P2 - Find the executable-comment terminator lexically (pkg/frontend/mysql_cmd_executor.go:1561)

When FROM is tokenized inside /*! ... */, this uses strings.Index to find the first */ bytes. The parser's scanner instead consumes quoted strings while CommentFlag is set, so prepare fromx /*! from select 'x*/y' */ is accepted with the real terminator at the end. This code stops at the */ inside the string and constructs malformed SQL such as select 'x y' */, causing the stored/precompiled statement to diverge from the parsed AST or fail preparation. Derive the boundary using scanner state and add a regression test.

@VioletQwQ-0

Copy link
Copy Markdown
Collaborator Author

@gouhongshen @XuPeng-SH Addressed the executable-comment boundary CR in 25226fb. The frontend no longer searches raw bytes for */; the MySQL scanner now records the first executable-comment terminator it actually crosses, so quoted */ bytes remain part of the prepared SQL. Added the exact prepare fromx /*! from select 'x*/y' */ full-handler regression, helper coverage that preserves a following ordinary comment, scanner boundary/pool-reset tests, and retained the unterminated-comment rejection. Validation: full frontend UT, full parser UT, focused scanner race, go vet/build for frontend and mysql parser, git diff --check, historical-CR preflight, and mo-self-review.

@gouhongshen gouhongshen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex automated review

No findings. The token-based extraction fixes the prior substring bug and correctly handles executable-comment boundaries, including quoted */; existing review findings are addressed. Focused tests could not run locally because go is unavailable, but CI is passing.

@VioletQwQ-0
VioletQwQ-0 requested review from XuPeng-SH and removed request for XuPeng-SH July 21, 2026 09:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/bug Something isn't working size/M Denotes a PR that changes [100,499] lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: PREPARE stores invalid inner SQL when statement name contains from

5 participants