Skip to content

fix: allow REPLACE in binary-protocol COM_STMT_PREPARE (#25429)#25453

Merged
XuPeng-SH merged 5 commits into
matrixorigin:mainfrom
ck89119:issue-25429-main
Jul 6, 2026
Merged

fix: allow REPLACE in binary-protocol COM_STMT_PREPARE (#25429)#25453
XuPeng-SH merged 5 commits into
matrixorigin:mainfrom
ck89119:issue-25429-main

Conversation

@ck89119

@ck89119 ck89119 commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?

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

Which issue(s) this PR fixes:

fixes #25429

What this PR does / why we need it:

Preparing a REPLACE statement through the MySQL binary protocol
(COM_STMT_PREPARE, i.e. go-sql-driver with default settings, JDBC with
useServerPrepStmts=true, etc.) failed with a 1064 syntax error:

Error 1064 (HY000): SQL parser error: ... syntax error ... near " replace into t values (?, ?)"

Root cause: the frontend rewrites COM_STMT_PREPARE into an unquoted
prepare <name> from <raw sql>, which is parsed via the
prepareable_stmt grammar rule in mysql_sql.y. That rule was missing
replace_stmt (it is present only in explainable_stmt), so the wrapped
statement failed to parse. The quoted text-protocol form
PREPARE s FROM 'replace ...' worked because it goes through the
FROM STRING rule and parses the inner statement separately.

REPLACE is a preparable statement in MySQL, so this diverges from MySQL
behavior.

Fix

  • Add replace_stmt to prepareable_stmt and regenerate the parser.
  • No execute-side change is needed: getPreparePlan / BuildPlan /
    bindAndOptimizeReplaceQuery already handle *tree.Replace for
    prepared statements (which is why the quoted text-protocol form already
    worked end-to-end).

Tests

  • Parser unit tests for prepared REPLACE (VALUES and SELECT sources).
  • BVT coverage in prepare/prepare_all.sql for prepared REPLACE
    (VALUES and SELECT sources), verified via mo-tester.
  • Verified end-to-end with go-sql-driver (interpolateParams=false,
    real binary-protocol COM_STMT_PREPARE): replace into t values (?, ?)
    now prepares and executes correctly.

…25429)

COM_STMT_PREPARE is rewritten into an unquoted `prepare <name> from
<sql>` and parsed via the `prepareable_stmt` grammar rule, which was
missing `replace_stmt`. As a result, preparing a REPLACE statement
through the MySQL binary protocol (go-sql-driver default, JDBC with
useServerPrepStmts=true, etc.) failed with a 1064 syntax error, while
the text-protocol `PREPARE s FROM 'replace ...'` form worked.

Add `replace_stmt` to `prepareable_stmt` and regenerate the parser. The
execute side already handles `*tree.Replace` for prepared statements
(getPreparePlan / BuildPlan / bindAndOptimizeReplaceQuery), so no
execute-side change is needed.

Add parser unit tests and BVT coverage for prepared REPLACE (VALUES and
SELECT sources).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@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 →

…sult

The UNION ALL result for 'execute s2 using @A1, @b1' in prepare_all.result
had unintentional order drift (t5/t6 halves swapped) from a regenerated
result. Restore the original order from origin/main.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@XuPeng-SH XuPeng-SH merged commit fc8bdf3 into matrixorigin:main Jul 6, 2026
11 of 20 checks passed
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/XXL Denotes a PR that changes 2000+ lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Binary-protocol COM_STMT_PREPARE rejects REPLACE (missing replace_stmt in prepareable_stmt grammar)

4 participants