diff --git a/sqlx-core/src/sqlite/arguments.rs b/sqlx-core/src/sqlite/arguments.rs index 7ae9b6fe..cff26143 100644 --- a/sqlx-core/src/sqlite/arguments.rs +++ b/sqlx-core/src/sqlite/arguments.rs @@ -55,7 +55,7 @@ impl SqliteArguments<'_> { let mut arg_i = 0; for handle in &statement.handles { let cnt = handle.bind_parameter_count(); - for param_i in 0..cnt { + for param_i in 1..=cnt { // figure out the index of this bind parameter into our argument tuple let n: usize = if let Some(name) = handle.bind_parameter_name(param_i) { if name.starts_with('?') { @@ -77,7 +77,7 @@ impl SqliteArguments<'_> { )); } - self.values[n - 1].bind(handle, param_i + 1)?; + self.values[n - 1].bind(handle, param_i)?; } } diff --git a/sqlx-core/src/sqlite/statement/handle.rs b/sqlx-core/src/sqlite/statement/handle.rs index 99edc352..c4f9325e 100644 --- a/sqlx-core/src/sqlite/statement/handle.rs +++ b/sqlx-core/src/sqlite/statement/handle.rs @@ -142,6 +142,7 @@ impl StatementHandle { } // Name Of A Host Parameter + // NOTE: The first host parameter has an index of 1, not 0. #[inline] pub(crate) fn bind_parameter_name(&self, index: usize) -> Option<&str> { unsafe { diff --git a/tests/sqlite/sqlite.rs b/tests/sqlite/sqlite.rs index 35db78de..3a2cf453 100644 --- a/tests/sqlite/sqlite.rs +++ b/tests/sqlite/sqlite.rs @@ -1,7 +1,6 @@ use futures::TryStreamExt; -use sqlx::{ - query, sqlite::Sqlite, Connect, Connection, Executor, Row, SqliteConnection, SqlitePool, -}; +use sqlx::sqlite::{Sqlite, SqliteConnection, SqlitePool, SqliteRow}; +use sqlx::{query, Connect, Connection, Executor, Row}; use sqlx_test::new; #[sqlx_macros::test] @@ -75,6 +74,40 @@ async fn it_fetches_and_inflates_row() -> anyhow::Result<()> { Ok(()) } +#[sqlx_macros::test] +async fn it_maths() -> anyhow::Result<()> { + let mut conn = new::().await?; + + let value = sqlx::query("select 1 + ?1") + .bind(5_i32) + .try_map(|row: SqliteRow| row.try_get::(0)) + .fetch_one(&mut conn) + .await?; + + assert_eq!(6i32, value); + + Ok(()) +} + +#[sqlx_macros::test] +async fn it_binds_positional_parameters_issue_467() -> anyhow::Result<()> { + let mut conn = new::().await?; + + let row: (i32, i32, i32, i32) = sqlx::query_as("select ?1, ?1, ?3, ?2") + .bind(5_i32) + .bind(500_i32) + .bind(1020_i32) + .fetch_one(&mut conn) + .await?; + + assert_eq!(row.0, 5); + assert_eq!(row.1, 5); + assert_eq!(row.2, 1020); + assert_eq!(row.3, 500); + + Ok(()) +} + #[sqlx_macros::test] async fn it_fetches_in_loop() -> anyhow::Result<()> { // this is trying to check for any data races