mysql: auto-reprepare prepared statements on ER_NEED_REPREPARE to keep scans correct after DDL #1740
+319
−79
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Title
mysql: auto-reprepare prepared statements on ER_NEED_REPREPARE to keep scans correct after DDL
Summary
This PR makes prepared statements resilient to schema changes by automatically re-preparing and retrying once when the server returns ER_NEED_REPREPARE (1615). It fixes incorrect scan results after DDL (e.g., changing a column type) without requiring an app restart. Adds integration tests reproducing and verifying the behavior.
Fixes #563
Background
Some servers invalidate prepared-statement metadata after DDL (e.g., ALTER TABLE ... MODIFY column TYPE). Applications may then see wrong values (e.g., zero timestamps) or receive ER_NEED_REPREPARE until they restart. The driver previously didn’t auto-reprepare.
Changes
queryString stringtomysqlStmt, set inmysqlConn.Prepare.mysqlStmt.reprepare()to close the current stmt ID and prepare again (same connection, same SQL).mysqlStmt.ExecandmysqlStmt.Queryto retry the operation once whenreadResultSetHeaderPacket()returns ER_NEED_REPREPARE (1615).TestPreparedStmtReprepareAfterDDL: verifies scans remain correct across a type change withparseTime=true.TestPreparedStmtExecReprepareAfterDDL: verifies Exec continues to work after a type change.TestPreparedStmtReprepareMultipleScansAfterDDL_NullTime: repeated scans across DDL usingsql.NullTime.Behavior
database/sql.Compatibility
clientCacheMetadata).Performance impact
COM_STMT_CLOSE+COM_STMT_PREPAREroundtrip and a single retry.Edge cases and safeguards
driver.ErrBadConn/ErrInvalidConnas before if the statement/connection is invalid.Files touched
statement.go: addqueryString, implementreprepare, add single-retry inExec/Query.connection.go: setstmt.queryString = queryinPrepare.reprepare_test.go: new integration tests.README.md: note about prepared statements being resilient to DDL (ER_NEED_REPREPARE).Testing
go test -run Reprepare -count=1 ./...passes with a live MySQL.SELECT, run it,ALTER TABLE ... MODIFY state INT, scan again; values remain correct.INSERT,ALTER TABLE ... MODIFY value BIGINT, insert again; succeeds.