Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ required-features = ["sqlite"]
[[test]]
name = "sqlite-any"
path = "tests/sqlite/any.rs"
required-features = ["sqlite"]
required-features = ["sqlite", "any"]

[[test]]
name = "sqlite-types"
Expand Down Expand Up @@ -401,6 +401,11 @@ name = "mysql-rustsec"
path = "tests/mysql/rustsec.rs"
required-features = ["mysql"]

[[test]]
name = "mysql-any"
path = "tests/mysql/any.rs"
required-features = ["mysql", "any"]

#
# PostgreSQL
#
Expand Down Expand Up @@ -454,3 +459,8 @@ required-features = ["postgres"]
name = "postgres-rustsec"
path = "tests/postgres/rustsec.rs"
required-features = ["postgres", "macros", "migrate"]

[[test]]
name = "postgres-any"
path = "tests/postgres/any.rs"
required-features = ["postgres", "any"]
15 changes: 8 additions & 7 deletions sqlx-mysql/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl AnyConnectionBackend for MySqlConnection {
.try_flatten_stream()
.map(|res| {
Ok(match res? {
Either::Left(result) => Either::Left(map_result(result)),
Either::Left(result) => Either::Left(result.into()),
Either::Right(row) => Either::Right(AnyRow::try_from(&row)?),
})
}),
Expand Down Expand Up @@ -210,11 +210,12 @@ impl<'a> TryFrom<&'a AnyConnectOptions> for MySqlConnectOptions {
}
}

fn map_result(result: MySqlQueryResult) -> AnyQueryResult {
AnyQueryResult {
rows_affected: result.rows_affected,
// Don't expect this to be a problem
#[allow(clippy::cast_possible_wrap)]
last_insert_id: Some(result.last_insert_id as i64),
/// This conversion attempts to save last_insert_id by converting to i64.
impl From<MySqlQueryResult> for AnyQueryResult {
fn from(done: MySqlQueryResult) -> Self {
AnyQueryResult {
rows_affected: done.rows_affected(),
last_insert_id: done.last_insert_id().try_into().ok(),
}
}
}
10 changes: 0 additions & 10 deletions sqlx-mysql/src/query_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,3 @@ impl Extend<MySqlQueryResult> for MySqlQueryResult {
}
}
}
#[cfg(feature = "any")]
/// This conversion attempts to save last_insert_id by converting to i64.
impl From<MySqlQueryResult> for sqlx_core::any::AnyQueryResult {
fn from(done: MySqlQueryResult) -> Self {
sqlx_core::any::AnyQueryResult {
rows_affected: done.rows_affected(),
last_insert_id: done.last_insert_id().try_into().ok(),
}
}
}
12 changes: 7 additions & 5 deletions sqlx-postgres/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl AnyConnectionBackend for PgConnection {
.try_flatten_stream()
.map(
move |res: sqlx_core::Result<Either<PgQueryResult, PgRow>>| match res? {
Either::Left(result) => Ok(Either::Left(map_result(result))),
Either::Left(result) => Ok(Either::Left(result.into())),
Either::Right(row) => Ok(Either::Right(AnyRow::try_from(&row)?)),
},
),
Expand Down Expand Up @@ -243,9 +243,11 @@ impl<'a> TryFrom<&'a AnyConnectOptions> for PgConnectOptions {
}
}

fn map_result(res: PgQueryResult) -> AnyQueryResult {
AnyQueryResult {
rows_affected: res.rows_affected(),
last_insert_id: None,
impl From<PgQueryResult> for AnyQueryResult {
fn from(done: PgQueryResult) -> Self {
AnyQueryResult {
rows_affected: done.rows_affected(),
last_insert_id: None,
}
}
}
10 changes: 0 additions & 10 deletions sqlx-postgres/src/query_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,3 @@ impl Extend<PgQueryResult> for PgQueryResult {
}
}
}

#[cfg(feature = "any")]
impl From<PgQueryResult> for sqlx_core::any::AnyQueryResult {
fn from(done: PgQueryResult) -> Self {
sqlx_core::any::AnyQueryResult {
rows_affected: done.rows_affected,
last_insert_id: None,
}
}
}
17 changes: 12 additions & 5 deletions sqlx-sqlite/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl AnyConnectionBackend for SqliteConnection {
.try_flatten_stream()
.map(
move |res: sqlx_core::Result<Either<SqliteQueryResult, SqliteRow>>| match res? {
Either::Left(result) => Ok(Either::Left(map_result(result))),
Either::Left(result) => Ok(Either::Left(result.into())),
Either::Right(row) => Ok(Either::Right(AnyRow::try_from(&row)?)),
},
),
Expand Down Expand Up @@ -231,9 +231,16 @@ fn map_arguments(args: AnyArguments) -> SqliteArguments {
}
}

fn map_result(res: SqliteQueryResult) -> AnyQueryResult {
AnyQueryResult {
rows_affected: res.rows_affected(),
last_insert_id: None,
impl From<SqliteQueryResult> for AnyQueryResult {
fn from(done: SqliteQueryResult) -> Self {
// logic as per: https://www.sqlite.org/c3ref/last_insert_rowid.html
let last_insert_id = match done.last_insert_rowid() {
0 => None,
n => Some(n),
};
AnyQueryResult {
rows_affected: done.rows_affected(),
last_insert_id,
}
}
}
14 changes: 0 additions & 14 deletions sqlx-sqlite/src/query_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,3 @@ impl Extend<SqliteQueryResult> for SqliteQueryResult {
}
}
}

#[cfg(feature = "any")]
impl From<SqliteQueryResult> for sqlx_core::any::AnyQueryResult {
fn from(done: SqliteQueryResult) -> Self {
let last_insert_id = match done.last_insert_rowid() {
0 => None,
n => Some(n),
};
sqlx_core::any::AnyQueryResult {
rows_affected: done.rows_affected(),
last_insert_id,
}
}
}
28 changes: 28 additions & 0 deletions tests/mysql/any.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use sqlx::Any;
use sqlx_test::new;

/// ensure Any type with MySQL backing returns last_insert_id properly
/// https://github.com/launchbadge/sqlx/issues/2982
#[sqlx_macros::test]
async fn any_sets_last_insert_id() -> anyhow::Result<()> {
sqlx::any::install_default_drivers();

let mut conn = new::<Any>().await?;
// syntax as per: https://dev.mysql.com/doc/refman/9.6/en/example-auto-increment.html
let _ = conn
.execute(
r#"
CREATE TEMPORARY TABLE users (id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, name TEXT NOT NULL)
"#,
)
.await?;

let result = sqlx::query("INSERT INTO users (name) VALUES (?)")
.bind("Glorbo")
.execute(&mut conn)
.await?;

assert_eq!(result.last_insert_id(), Some(1));

Ok(())
}
29 changes: 29 additions & 0 deletions tests/postgres/any.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use sqlx::Any;
use sqlx_test::new;

/// ensure Any type with PostgreSQL backing returns last_insert_id properly
/// https://github.com/launchbadge/sqlx/issues/2982
#[sqlx_macros::test]
async fn any_sets_last_insert_id() -> anyhow::Result<()> {
sqlx::any::install_default_drivers();

let mut conn = new::<Any>().await?;
// syntax as per: https://www.postgresql.org/docs/current/ddl-identity-columns.html
let _ = conn
.execute(
r#"
CREATE TEMPORARY TABLE users (id INTEGER GENERATED ALWAYS AS IDENTITY, name TEXT NOT NULL)
"#,
)
.await?;

let result = sqlx::query("INSERT INTO users (name) VALUES (?)")
.bind("Glorbo")
.execute(&mut conn)
.await?;

// NOTE: PgQueryResult does not implement an equivalent concept and can only return None
assert_eq!(result.last_insert_id(), None);

Ok(())
}
26 changes: 26 additions & 0 deletions tests/sqlite/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,29 @@ async fn issue_3179() -> anyhow::Result<()> {

Ok(())
}

/// ensure Any type with SQLite backing returns last_insert_id properly
/// https://github.com/launchbadge/sqlx/issues/2982
#[sqlx_macros::test]
async fn any_sets_last_insert_id() -> anyhow::Result<()> {
sqlx::any::install_default_drivers();

let mut conn = new::<Any>().await?;
// syntax as per: https://sqlite.org/autoinc.html
let _ = conn
.execute(
r#"
CREATE TEMPORARY TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)
"#,
)
.await?;

let result = sqlx::query("INSERT INTO users (name) VALUES (?)")
.bind("Glorbo")
.execute(&mut conn)
.await?;

assert_eq!(result.last_insert_id(), Some(1));

Ok(())
}