fix(mysql): keep unknown prepare placeholders#8150
Conversation
There was a problem hiding this comment.
Code Review
This pull request enhances the MySQL handler to correctly support prepared statements with untyped placeholders, ensuring they are properly reported to clients by using a default null datatype when inference fails. It also introduces a SQL string escaping utility for the statement fallback path and includes comprehensive unit and integration tests. Review feedback focuses on optimizing the string escaping logic to reduce allocations and improving variable naming to avoid shadowing and enhance code clarity.
ffcd3cc to
e45b5c6
Compare
There was a problem hiding this comment.
Pull request overview
This PR fixes MySQL prepared-statement behavior so that the server advertises all ? placeholders found in the SQL (even when DataFusion cannot infer a concrete parameter type), preventing client-side “expected N arguments, got M” errors. It also hardens the statement-fallback execution path by replacing placeholders using AST spans and emitting properly escaped SQL literals for bytes/strings.
Changes:
- Count placeholders from the parsed SQL AST and always return one MySQL parameter column per placeholder, using
NULLtype metadata when the type is unknown. - Avoid caching
SqlPlan::Planunless all placeholders have inferred concrete types; otherwise keep the statement-fallback path and preserve raw SQL. - Improve fallback parameter substitution by replacing
?ranges from right-to-left using AST spans, and escape bytes/strings viamysql_common::Value::as_sql(false); add extensive tests.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/servers/tests/mysql/mysql_server_test.rs |
Adds integration coverage for unknown placeholders, mixed known/unknown placeholders, comments/literals, UTF-8/CRLF spans, binary bytes, NULL, and LIMIT placeholders. |
src/servers/src/mysql/helper.rs |
Adds placeholder counting and placeholder span collection utilities used by prepare/execute. |
src/servers/src/mysql/handler.rs |
Updates prepare/execute logic to advertise unknown placeholders, gate plan caching on full typing, and replace fallback params by span; uses mysql_common for SQL literal escaping. |
src/servers/Cargo.toml |
Adds mysql_common dependency. |
Cargo.lock |
Locks mysql_common version resolution. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
It's better to add some black-box tests to https://github.com/GreptimeTeam/greptimedb-tests
Signed-off-by: discord9 <discord9@163.com>
Signed-off-by: discord9 <discord9@163.com>
Signed-off-by: discord9 <discord9@163.com>
5d82c3a to
495d914
Compare
Signed-off-by: discord9 <discord9@163.com>
I hereby agree to the terms of the GreptimeDB CLA.
Refer to a related PR or issue link (optional)
Fixes #8142.
Related history:
LIMIT.LIMIT ?type inference regressed.LIMIT/OFFSET ?inference behavior.What's changed and what's your intention?
This PR fixes MySQL prepared statements whose placeholders are present in the SQL but do not have concrete types inferred by the planner.
Before this change, the MySQL prepare response only advertised placeholders with concrete inferred types. If DataFusion returned
Nonefor a placeholder type,prepared_params()skipped it, so the client could see fewer parameters than the SQL actually contains and fail before execution with an argument count mismatch.The changes are:
NULLmetadata for unknown placeholder types.SqlPlan::Planonly when all placeholders have concrete inferred types; otherwise keep the statement fallback path.to_string()round-trips.?in the original SQL.mysql_common::Value::as_sql(false).NULL, binary bytes, andLIMIT ?.This does not change public APIs, schemas, or persisted data.
PR Checklist
Please convert it to a draft if some of the following conditions are not met.
Tests:
cargo fmt --checkcargo check -p serverscargo test -p servers --lib mysql::handler::testscargo test -p servers --features testing --test mod mysql::mysql_server_test::test_query_prepared