diff --git a/sqlx-mysql/src/connection/executor.rs b/sqlx-mysql/src/connection/executor.rs index a6f8c201..e29b231d 100644 --- a/sqlx-mysql/src/connection/executor.rs +++ b/sqlx-mysql/src/connection/executor.rs @@ -124,6 +124,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 { @@ -138,6 +148,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 3ee1024f..f75e9513 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(()) +}