diff --git a/sqlx-mysql/src/connection/executor.rs b/sqlx-mysql/src/connection/executor.rs index 4f5af4bf6d..8bbbb21cba 100644 --- a/sqlx-mysql/src/connection/executor.rs +++ b/sqlx-mysql/src/connection/executor.rs @@ -123,6 +123,16 @@ impl MySqlConnection { .get_or_prepare_statement(sql) .await?; + if arguments.types.len() != metadata.parameters { + return Err( + err_protocol!( + "prepared statement expected {} parameters but {} parameters were provided", + metadata.parameters, + arguments.types.len() + ) + ); + } + // https://dev.mysql.com/doc/internals/en/com-stmt-execute.html self.inner.stream .send_packet(StatementExecute { @@ -137,6 +147,16 @@ impl MySqlConnection { .prepare_statement(sql) .await?; + if arguments.types.len() != metadata.parameters { + return Err( + err_protocol!( + "prepared statement expected {} parameters but {} parameters were provided", + metadata.parameters, + arguments.types.len() + ) + ); + } + // https://dev.mysql.com/doc/internals/en/com-stmt-execute.html self.inner.stream .send_packet(StatementExecute { diff --git a/tests/mysql/error.rs b/tests/mysql/error.rs index 3ee1024fc8..f75e9513a6 100644 --- a/tests/mysql/error.rs +++ b/tests/mysql/error.rs @@ -100,3 +100,50 @@ async fn it_fails_with_invalid_save_point_statement() -> anyhow::Result<()> { Ok(()) } + +#[sqlx_macros::test] +async fn it_fails_with_parameter_count_mismatch_too_few() -> anyhow::Result<()> { + let mut conn = new::().await?; + let res: Result<_, sqlx::Error> = + sqlx::query("SELECT * FROM tweet WHERE id = ? AND owner_id = ?") + .bind(1_i64) + .execute(&mut conn) + .await; + + let err = res.unwrap_err(); + + assert!(matches!(err, Error::Protocol(_)), "{err}"); + + Ok(()) +} + +#[sqlx_macros::test] +async fn it_fails_with_parameter_count_mismatch_too_many() -> anyhow::Result<()> { + let mut conn = new::().await?; + let res: Result<_, sqlx::Error> = sqlx::query("SELECT * FROM tweet WHERE id = ?") + .bind(1_i64) + .bind(2_i64) + .execute(&mut conn) + .await; + + let err = res.unwrap_err(); + + assert!(matches!(err, Error::Protocol(_)), "{err}"); + + Ok(()) +} + +#[sqlx_macros::test] +async fn it_fails_with_parameter_count_mismatch_zero_expected() -> anyhow::Result<()> { + let mut conn = new::().await?; + let res: Result<_, sqlx::Error> = sqlx::query("SELECT COUNT(*) FROM tweet") + .bind(1_i64) + .execute(&mut conn) + .await; + + let err = res.unwrap_err(); + + assert!(matches!(err, Error::Protocol(_)), "{err}"); + + Ok(()) +}