Repository navigation
[Bug]: SQL PREPARE maps inner SQL syntax errors to 1105/HY000 instead of 1064/42000 #30434
Description
Summary
SQL PREPARE name FROM '...' reports an inner SQL syntax error as generic MySQL error 1105 / HY000, instead of 1064 / 42000. The SQL is correctly rejected and the connection remains usable, but clients cannot reliably classify the failure using the normal syntax-error code/SQLSTATE.
Found while independently validating PR #30151. This is separate from the empty-CTE panic fixed there; an unrelated malformed SQL control reproduces the mapping problem without an empty CTE.
Verified revision / environment
- Commit:
f149b512a6d24b0f1af22aa86f781833221c6608(PR fix(parser): reject empty CTE bodies to avoid Format panic #30151, main-based). - Linux amd64, Go 1.27.1; native prerequisites built from this revision.
- Real single-CN embedded MatrixOne cluster, MySQL TCP frontend, go-sql-driver/mysql client; one pinned physical
sql.Connthroughout. - No claim that latest main or 4.2-dev was independently executed for this issue.
Minimal reproduction
Execute through the MySQL client on the same connection:
PREPARE unrelated_syntax FROM 'SELECT FROM';
SELECT 1;Actual error (independently observed):
Error 1105 (HY000): You have an error in your SQL syntax; check the manual that corresponds to your MatrixOne server version for the right syntax to use. syntax error at line 1 column 11 near " from";
SELECT 1 then succeeds. The failure is error classification, not a disconnect or panic.
Additional observed comparison on this revision:
| Entry point | Input | Result |
|---|---|---|
| Direct SQL | WITH a AS () SELECT 1 |
1064 / 42000 |
| CTAS | CREATE TABLE bad_ctas AS WITH a AS () SELECT 1 |
1064 / 42000; no table created |
| SQL PREPARE | PREPARE bad_stmt FROM 'WITH a AS () SELECT 1' |
1105 / HY000 with syntax-error message, no panic |
| Binary COM_STMT_PREPARE | WITH a AS () SELECT 1 |
1064 / 42000 |
Expected behavior
An inner SQL parser error in SQL PREPARE should retain syntax-error classification: 1064 / 42000, consistent with the other parser-facing entry points. Preserve the useful parser diagnostic and position. Do not rewrite unrelated planning, authorization, cancellation or runtime errors as syntax errors.
Root-cause analysis / existing ownership
The inner parse in pkg/sql/plan/build_dcl.go (buildPrepare, *tree.PrepareString case) calls mysql.ParseWithSQLMode and returns its parser error directly. pkg/sql/parsers/dialect/mysql/mysql_lexer.go (Lexer.Error) constructs a PositionedErr. In pkg/frontend/util.go, RewriteError recognizes *moerr.Error, while its default branch maps an untyped/non-moerr error to the generic MySQL error. The inner PREPARE parse error therefore loses SQL syntax-error classification at the frontend boundary.
Check other existing inner-parse entry points, including parsePreparedStatement, before choosing the narrowest shared correction. Prefer the existing parser-error conversion owner; avoid matching error-message strings, duplicating conversion rules, or adding work to successful SQL execution.
These files/paths are unchanged between PR #30151 and its merge base a53390c57de48ac280249ff0e88831e502e20fb0. This is an existing error-mapping gap, not a new mapping branch introduced by #30151. Historical introduction commit is not established.
Acceptance / focused validation
- Public SQL PREPARE of ordinary malformed SQL returns 1064 / 42000.
- Cover empty-CTE inner SQL where the parser fix is present; no internal-panic response.
- Same physical connection executes
SELECT 1immediately after rejection. - Valid SQL PREPARE / EXECUTE / DEALLOCATE still works.
- Direct SQL and binary COM_STMT_PREPARE syntax-error behavior remains correct.
- Confirm unrelated error classes retain their codes; no broad error conversion or success-path parsing/allocation overhead.
- Add a small regression through the real frontend entry point; parser-only assertions do not prove the client-visible mapping.
Evidence
Independent review and executed public-path results: #30151 (review)
The review includes the complete temporary test source, exact revision, commands and terminal results. Parser packages passed; public SQL probe passed after explicitly distinguishing the observed entrypoint-specific error codes. The original 1064 assertion on SQL PREPARE failed and prompted this investigation.
Activity
fix(frontend): report PREPARE inner syntax errors as 1064 instead of …
XuPeng-SH commentedon Oct 19, 2026
功能验证结果(2026-10-19 UTC):PR #30543 的修复在最新 main 上通过真实 MySQL 协议与 race 复测。分支
main,完整 SHA8e63625c4e9baeb1d28c1095c07732f056c04895;Linux/amd64、Go 1.27.1,隔离嵌入式单 CN、MySQL TCP、MO_TEST_CLUSTER_TCP_ONLY=1。在已提交的
TestPreparedSyntaxErrorOverMySQLProtocol上用 Go overlay 加入 issue 原始空 CTE 用例WITH a AS () SELECT 1,并按实际 parser 诊断断言empty common table expression body。真实 SQL PREPARE 返回 1064/42000;直接 SQL、SQL 字符串 PREPARE、用户变量 PREPARE、二进制 COM_STMT_PREPARE、类型参数溢出、活动事务中的失败与连接/事务恢复均通过。包含空 CTE 的完整协议测试 exit 0。命令:
原始日志 SHA-256
01f087b4495fd8c3283e93d0cfe7e46c0b1fce52e0f9300524793e9c50e5938f;测试源和 overlay、命令、环境及退出码已归档在continue22/runs/30543-main-race-original-cte-corrected/。该 PR 的目标分支是 main,本项不需要 4.2 回移验证。Ariznawlll commentedon Oct 19, 2026
测试版本
main8e63625c4e9baeb1d28c1095c07732f056c0489557fb9530859d92791100098d312ea8cacc671910经 GitHub compare 确认为该 main 的祖先。原问题验证
同一物理 SQL 连接中执行原始
PREPARE unrelated_syntax FROM 'SELECT FROM',独立 3/3 返回ERROR 1064 (42000),保留syntax error at line 1 column 11定位信息;旧错码 1105/HY000 未出现。每轮紧接的SELECT 1均返回 1。Happy Path 覆盖
PREPARE good FROM 'SELECT ? AS v'、EXECUTE USING @n=42、DEALLOCATE各 3/3,实际值 42。TestPreparedSyntaxErrorOverMySQLProtocol以-race -count=3PASS,覆盖 SQL 字符串与用户变量 PREPARE、二进制 COM_STMT_PREPARE、活动事务中的 admission、替换语句清理以及连接恢复;不是只检查 parser 内部错误文本。Unhappy Path 覆盖
PREPARE ... FROM 'WITH a AS () SELECT 1'、用户变量形式和直接SELECT FROM各 3/3 返回 1064/42000,且报文包含对应 parser 位置。CREATE TABLE bad_ctas AS WITH a AS () SELECT 1各 3/3 返回 1064/42000;随后information_schema.tables查得目标表 0 个,验证失败无部分建表。白盒验证
在该完整 SHA 上以仓库 CGo wrapper 运行
MO_TEST_CLUSTER_TCP_ONLY=1 ... -race -p 1 -count=3 -run '^TestPreparedSyntaxErrorOverMySQLProtocol$' ./pkg/embed,PASS。此测试对客户端可见的 MySQL 错误号、SQLSTATE、诊断内容和后续可用性均有明确断言。回归测试
修复 PR #30543 已提交
pkg/embed/prepared_syntax_error_test.go真实客户端协议回归,覆盖原始路径及关键错误/恢复边界;依据你允许的“现有 Go 用例完整覆盖则不重复补 MOTR”规则,本轮未新增等价 MOTR。MatrixOne 全量 BVT/集成 CI 本轮未执行。测试证据
-count=3返回ok github.com/matrixorigin/matrixone/pkg/embed。bad_ctas_exists=0、恢复查询 1/2/3、合法预处理值 42。未声称其他发布线已验收。测试结论
测试通过。
daviszhen commentedon Oct 20, 2026
最新 main 验证(2026-10-20)
基线:
309f618995af4ee23e3b9149365f4af77264090d;关联修复 PR:#30543。结论:原问题已解决。对
PREPARE 'SELECT FROM'返回 1064/42000,随后同一连接执行SELECT 1正常,连接/session 没有被错误状态污染。