feat: add sqlx::Done and return from Executor::execute()

+ Done::rows_affected()

 + Done::last_insert_id()
This commit is contained in:
Ryan Leckey 2020-07-12 05:27:38 -07:00
parent 51aeee20da
commit 00137d4a04
33 changed files with 258 additions and 68 deletions

View File

@ -5,6 +5,7 @@ use std::fmt::Debug;
use crate::arguments::Arguments;
use crate::column::Column;
use crate::connection::Connection;
use crate::done::Done;
use crate::row::Row;
use crate::transaction::TransactionManager;
use crate::type_info::TypeInfo;
@ -31,6 +32,9 @@ pub trait Database:
/// The concrete `Row` implementation for this database.
type Row: Row<Database = Self>;
/// The concrete `Done` implementation for this database.
type Done: Done<Database = Self>;
/// The concrete `Column` implementation for this database.
type Column: Column<Database = Self>;

9
sqlx-core/src/done.rs Normal file
View File

@ -0,0 +1,9 @@
use crate::database::Database;
use std::iter::Extend;
pub trait Done: 'static + Sized + Send + Sync + Default + Extend<Self> {
type Database: Database;
/// Returns the number of rows affected by an `UPDATE`, `INSERT`, or `DELETE`.
fn rows_affected(&self) -> u64;
}

View File

@ -1,13 +1,11 @@
use std::fmt::Debug;
use crate::database::{Database, HasArguments};
use crate::error::Error;
use crate::statement::StatementInfo;
use either::Either;
use futures_core::future::BoxFuture;
use futures_core::stream::BoxStream;
use futures_util::{future, FutureExt, StreamExt, TryFutureExt, TryStreamExt};
use crate::database::{Database, HasArguments};
use crate::error::Error;
use crate::statement::StatementInfo;
use std::fmt::Debug;
/// A type that contains or can provide a database
/// connection to use for executing queries against the database.
@ -28,18 +26,22 @@ pub trait Executor<'c>: Send + Debug + Sized {
type Database: Database;
/// Execute the query and return the total number of rows affected.
fn execute<'e, 'q: 'e, E: 'q>(self, query: E) -> BoxFuture<'e, Result<u64, Error>>
fn execute<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxFuture<'e, Result<<Self::Database as Database>::Done, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
self.execute_many(query)
.try_fold(0, |acc, x| async move { Ok(acc + x) })
.boxed()
self.execute_many(query).try_collect().boxed()
}
/// Execute multiple queries and return the rows affected from each query, in a stream.
fn execute_many<'e, 'q: 'e, E: 'q>(self, query: E) -> BoxStream<'e, Result<u64, Error>>
fn execute_many<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxStream<'e, Result<<Self::Database as Database>::Done, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
@ -78,7 +80,13 @@ pub trait Executor<'c>: Send + Debug + Sized {
fn fetch_many<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxStream<'e, Result<Either<u64, <Self::Database as Database>::Row>, Error>>
) -> BoxStream<
'e,
Result<
Either<<Self::Database as Database>::Done, <Self::Database as Database>::Row>,
Error,
>,
>
where
'c: 'e,
E: Execute<'q, Self::Database>;

View File

@ -52,6 +52,7 @@ pub mod acquire;
pub mod column;
mod common;
pub mod database;
pub mod done;
pub mod executor;
pub mod from_row;
mod io;

View File

@ -6,7 +6,7 @@ use crate::mssql::protocol::message::Message;
use crate::mssql::protocol::packet::PacketType;
use crate::mssql::protocol::rpc::{OptionFlags, Procedure, RpcRequest};
use crate::mssql::protocol::sql_batch::SqlBatch;
use crate::mssql::{Mssql, MssqlArguments, MssqlConnection, MssqlRow};
use crate::mssql::{Mssql, MssqlArguments, MssqlConnection, MssqlDone, MssqlRow};
use crate::statement::StatementInfo;
use either::Either;
use futures_core::future::BoxFuture;
@ -66,7 +66,7 @@ impl<'c> Executor<'c> for &'c mut MssqlConnection {
fn fetch_many<'e, 'q: 'e, E: 'q>(
self,
mut query: E,
) -> BoxStream<'e, Result<Either<u64, MssqlRow>, Error>>
) -> BoxStream<'e, Result<Either<MssqlDone, MssqlRow>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
@ -94,7 +94,9 @@ impl<'c> Executor<'c> for &'c mut MssqlConnection {
}
if done.status.contains(Status::DONE_COUNT) {
r#yield!(Either::Left(done.affected_rows));
r#yield!(Either::Left(MssqlDone {
rows_affected: done.affected_rows,
}));
}
if !done.status.contains(Status::DONE_MORE) {
@ -104,7 +106,9 @@ impl<'c> Executor<'c> for &'c mut MssqlConnection {
Message::DoneInProc(done) => {
if done.status.contains(Status::DONE_COUNT) {
r#yield!(Either::Left(done.affected_rows));
r#yield!(Either::Left(MssqlDone {
rows_affected: done.affected_rows,
}));
}
}

View File

@ -1,7 +1,7 @@
use crate::database::{Database, HasArguments, HasValueRef};
use crate::mssql::{
MssqlArguments, MssqlColumn, MssqlConnection, MssqlRow, MssqlTransactionManager, MssqlTypeInfo,
MssqlValue, MssqlValueRef,
MssqlArguments, MssqlColumn, MssqlConnection, MssqlDone, MssqlRow, MssqlTransactionManager,
MssqlTypeInfo, MssqlValue, MssqlValueRef,
};
/// MSSQL database driver.
@ -15,6 +15,8 @@ impl Database for Mssql {
type Row = MssqlRow;
type Done = MssqlDone;
type Column = MssqlColumn;
type TypeInfo = MssqlTypeInfo;

View File

@ -0,0 +1,24 @@
use crate::done::Done;
use crate::mssql::Mssql;
use std::iter::{Extend, IntoIterator};
#[derive(Debug, Default)]
pub struct MssqlDone {
pub(super) rows_affected: u64,
}
impl Done for MssqlDone {
type Database = Mssql;
fn rows_affected(&self) -> u64 {
self.rows_affected
}
}
impl Extend<MssqlDone> for MssqlDone {
fn extend<T: IntoIterator<Item = MssqlDone>>(&mut self, iter: T) {
for elem in iter {
self.rows_affected += elem.rows_affected;
}
}
}

View File

@ -4,6 +4,7 @@ mod arguments;
mod column;
mod connection;
mod database;
mod done;
mod error;
mod io;
mod options;
@ -18,6 +19,7 @@ pub use arguments::MssqlArguments;
pub use column::MssqlColumn;
pub use connection::MssqlConnection;
pub use database::Mssql;
pub use done::MssqlDone;
pub use error::MssqlDatabaseError;
pub use options::MssqlConnectOptions;
pub use row::MssqlRow;

View File

@ -19,7 +19,8 @@ use crate::mysql::protocol::statement::{
use crate::mysql::protocol::text::{ColumnDefinition, ColumnFlags, Query, TextRow};
use crate::mysql::protocol::Packet;
use crate::mysql::{
MySql, MySqlArguments, MySqlColumn, MySqlConnection, MySqlRow, MySqlTypeInfo, MySqlValueFormat,
MySql, MySqlArguments, MySqlColumn, MySqlConnection, MySqlDone, MySqlRow, MySqlTypeInfo,
MySqlValueFormat,
};
use crate::statement::StatementInfo;
@ -111,7 +112,7 @@ impl MySqlConnection {
&'c mut self,
query: &str,
arguments: Option<MySqlArguments>,
) -> Result<impl Stream<Item = Result<Either<u64, MySqlRow>, Error>> + 'c, Error> {
) -> Result<impl Stream<Item = Result<Either<MySqlDone, MySqlRow>, Error>> + 'c, Error> {
self.stream.wait_until_ready().await?;
self.stream.busy = Busy::Result;
@ -145,7 +146,12 @@ impl MySqlConnection {
// this indicates either a successful query with no rows at all or a failed query
let ok = packet.ok()?;
r#yield!(Either::Left(ok.affected_rows));
let done = MySqlDone {
rows_affected: ok.affected_rows,
last_insert_id: ok.last_insert_id,
};
r#yield!(Either::Left(done));
if ok.status.contains(Status::SERVER_MORE_RESULTS_EXISTS) {
// more result sets exist, continue to the next one
@ -166,7 +172,11 @@ impl MySqlConnection {
if packet[0] == 0xfe && packet.len() < 9 {
let eof = packet.eof(self.stream.capabilities)?;
r#yield!(Either::Left(0));
r#yield!(Either::Left(MySqlDone {
rows_affected: 0,
last_insert_id: 0,
}));
if eof.status.contains(Status::SERVER_MORE_RESULTS_EXISTS) {
// more result sets exist, continue to the next one
@ -203,7 +213,7 @@ impl<'c> Executor<'c> for &'c mut MySqlConnection {
fn fetch_many<'e, 'q: 'e, E: 'q>(
self,
mut query: E,
) -> BoxStream<'e, Result<Either<u64, MySqlRow>, Error>>
) -> BoxStream<'e, Result<Either<MySqlDone, MySqlRow>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,

View File

@ -1,7 +1,8 @@
use crate::database::{Database, HasArguments, HasStatementCache, HasValueRef};
use crate::mysql::value::{MySqlValue, MySqlValueRef};
use crate::mysql::{
MySqlArguments, MySqlColumn, MySqlConnection, MySqlRow, MySqlTransactionManager, MySqlTypeInfo,
MySqlArguments, MySqlColumn, MySqlConnection, MySqlDone, MySqlRow, MySqlTransactionManager,
MySqlTypeInfo,
};
/// MySQL database driver.
@ -15,6 +16,8 @@ impl Database for MySql {
type Row = MySqlRow;
type Done = MySqlDone;
type Column = MySqlColumn;
type TypeInfo = MySqlTypeInfo;

View File

@ -0,0 +1,32 @@
use crate::done::Done;
use crate::mysql::MySql;
use std::iter::{Extend, IntoIterator};
#[derive(Debug, Default)]
pub struct MySqlDone {
pub(super) rows_affected: u64,
pub(super) last_insert_id: u64,
}
impl MySqlDone {
pub fn last_insert_id(&self) -> u64 {
self.last_insert_id
}
}
impl Done for MySqlDone {
type Database = MySql;
fn rows_affected(&self) -> u64 {
self.rows_affected
}
}
impl Extend<MySqlDone> for MySqlDone {
fn extend<T: IntoIterator<Item = MySqlDone>>(&mut self, iter: T) {
for elem in iter {
self.rows_affected += elem.rows_affected;
self.last_insert_id = elem.last_insert_id;
}
}
}

View File

@ -4,6 +4,7 @@ mod arguments;
mod column;
mod connection;
mod database;
mod done;
mod error;
mod io;
mod options;
@ -21,6 +22,7 @@ pub use arguments::MySqlArguments;
pub use column::MySqlColumn;
pub use connection::MySqlConnection;
pub use database::MySql;
pub use done::MySqlDone;
pub use error::MySqlDatabaseError;
pub use options::{MySqlConnectOptions, MySqlSslMode};
pub use row::MySqlRow;

View File

@ -18,7 +18,7 @@ where
fn fetch_many<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxStream<'e, Result<Either<u64, DB::Row>, Error>>
) -> BoxStream<'e, Result<Either<DB::Done, DB::Row>, Error>>
where
E: Execute<'q, Self::Database>,
{
@ -75,7 +75,10 @@ macro_rules! impl_executor_for_pool_connection {
query: E,
) -> futures_core::stream::BoxStream<
'e,
Result<either::Either<u64, $R>, crate::error::Error>,
Result<
either::Either<<$DB as crate::database::Database>::Done, $R>,
crate::error::Error,
>,
>
where
'c: 'e,

View File

@ -12,7 +12,7 @@ use crate::postgres::message::{
Query, RowDescription,
};
use crate::postgres::type_info::PgType;
use crate::postgres::{PgArguments, PgConnection, PgRow, PgValueFormat, Postgres};
use crate::postgres::{PgArguments, PgConnection, PgDone, PgRow, PgValueFormat, Postgres};
use crate::statement::StatementInfo;
async fn prepare(
@ -142,7 +142,7 @@ impl PgConnection {
query: &str,
arguments: Option<PgArguments>,
limit: u8,
) -> Result<impl Stream<Item = Result<Either<u64, PgRow>, Error>> + '_, Error> {
) -> Result<impl Stream<Item = Result<Either<PgDone, PgRow>, Error>> + '_, Error> {
// before we continue, wait until we are "ready" to accept more queries
self.wait_until_ready().await?;
@ -219,7 +219,9 @@ impl PgConnection {
// a SQL command completed normally
let cc: CommandComplete = message.decode()?;
r#yield!(Either::Left(cc.rows_affected()));
r#yield!(Either::Left(PgDone {
rows_affected: cc.rows_affected(),
}));
}
MessageFormat::EmptyQueryResponse => {
@ -272,7 +274,7 @@ impl<'c> Executor<'c> for &'c mut PgConnection {
fn fetch_many<'e, 'q: 'e, E: 'q>(
self,
mut query: E,
) -> BoxStream<'e, Result<Either<u64, PgRow>, Error>>
) -> BoxStream<'e, Result<Either<PgDone, PgRow>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,

View File

@ -2,7 +2,7 @@ use crate::database::{Database, HasArguments, HasStatementCache, HasValueRef};
use crate::postgres::arguments::PgArgumentBuffer;
use crate::postgres::value::{PgValue, PgValueRef};
use crate::postgres::{
PgArguments, PgColumn, PgConnection, PgRow, PgTransactionManager, PgTypeInfo,
PgArguments, PgColumn, PgConnection, PgDone, PgRow, PgTransactionManager, PgTypeInfo,
};
/// PostgreSQL database driver.
@ -16,6 +16,8 @@ impl Database for Postgres {
type Row = PgRow;
type Done = PgDone;
type Column = PgColumn;
type TypeInfo = PgTypeInfo;

View File

@ -0,0 +1,24 @@
use crate::done::Done;
use crate::postgres::Postgres;
use std::iter::{Extend, IntoIterator};
#[derive(Debug, Default)]
pub struct PgDone {
pub(super) rows_affected: u64,
}
impl Done for PgDone {
type Database = Postgres;
fn rows_affected(&self) -> u64 {
self.rows_affected
}
}
impl Extend<PgDone> for PgDone {
fn extend<T: IntoIterator<Item = PgDone>>(&mut self, iter: T) {
for elem in iter {
self.rows_affected += elem.rows_affected;
}
}
}

View File

@ -3,7 +3,7 @@ use crate::executor::{Execute, Executor};
use crate::pool::PoolOptions;
use crate::pool::{Pool, PoolConnection};
use crate::postgres::message::{MessageFormat, Notification};
use crate::postgres::{PgConnection, PgRow, Postgres};
use crate::postgres::{PgConnection, PgDone, PgRow, Postgres};
use crate::statement::StatementInfo;
use either::Either;
use futures_channel::mpsc;
@ -197,7 +197,7 @@ impl<'c> Executor<'c> for &'c mut PgListener {
fn fetch_many<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxStream<'e, Result<Either<u64, PgRow>, Error>>
) -> BoxStream<'e, Result<Either<PgDone, PgRow>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,

View File

@ -4,6 +4,7 @@ mod arguments;
mod column;
mod connection;
mod database;
mod done;
mod error;
mod io;
mod listener;
@ -22,6 +23,7 @@ pub use arguments::{PgArgumentBuffer, PgArguments};
pub use column::PgColumn;
pub use connection::PgConnection;
pub use database::Postgres;
pub use done::PgDone;
pub use error::{PgDatabaseError, PgErrorPosition};
pub use listener::{PgListener, PgNotification};
pub use message::PgSeverity;

View File

@ -104,7 +104,7 @@ where
/// Execute the query and return the total number of rows affected.
#[inline]
pub async fn execute<'e, 'c: 'e, E>(self, executor: E) -> Result<u64, Error>
pub async fn execute<'e, 'c: 'e, E>(self, executor: E) -> Result<DB::Done, Error>
where
'q: 'e,
A: 'e,
@ -115,7 +115,10 @@ where
/// Execute multiple queries and return the rows affected from each query, in a stream.
#[inline]
pub async fn execute_many<'e, 'c: 'e, E>(self, executor: E) -> BoxStream<'e, Result<u64, Error>>
pub async fn execute_many<'e, 'c: 'e, E>(
self,
executor: E,
) -> BoxStream<'e, Result<DB::Done, Error>>
where
'q: 'e,
A: 'e,
@ -141,7 +144,7 @@ where
pub fn fetch_many<'e, 'c: 'e, E>(
self,
executor: E,
) -> BoxStream<'e, Result<Either<u64, DB::Row>, Error>>
) -> BoxStream<'e, Result<Either<DB::Done, DB::Row>, Error>>
where
'q: 'e,
A: 'e,
@ -231,7 +234,7 @@ where
pub fn fetch_many<'e, 'c: 'e, E>(
self,
executor: E,
) -> BoxStream<'e, Result<Either<u64, O>, Error>>
) -> BoxStream<'e, Result<Either<DB::Done, O>, Error>>
where
'q: 'e,
E: 'e + Executor<'c, Database = DB>,

View File

@ -74,7 +74,7 @@ where
pub fn fetch_many<'e, 'c: 'e, E>(
self,
executor: E,
) -> BoxStream<'e, Result<Either<u64, O>, Error>>
) -> BoxStream<'e, Result<Either<DB::Done, O>, Error>>
where
'q: 'e,
E: 'e + Executor<'c, Database = DB>,

View File

@ -71,7 +71,7 @@ where
pub fn fetch_many<'e, 'c: 'e, E>(
self,
executor: E,
) -> BoxStream<'e, Result<Either<u64, O>, Error>>
) -> BoxStream<'e, Result<Either<DB::Done, O>, Error>>
where
'q: 'e,
E: 'e + Executor<'c, Database = DB>,

View File

@ -5,6 +5,7 @@ use futures_core::future::BoxFuture;
use futures_core::stream::BoxStream;
use futures_util::{FutureExt, TryStreamExt};
use hashbrown::HashMap;
use libsqlite3_sys::sqlite3_last_insert_rowid;
use crate::common::StatementCache;
use crate::error::Error;
@ -13,7 +14,9 @@ use crate::ext::ustr::UStr;
use crate::sqlite::connection::describe::describe;
use crate::sqlite::connection::ConnectionHandle;
use crate::sqlite::statement::{SqliteStatement, StatementHandle};
use crate::sqlite::{Sqlite, SqliteArguments, SqliteColumn, SqliteConnection, SqliteRow};
use crate::sqlite::{
Sqlite, SqliteArguments, SqliteColumn, SqliteConnection, SqliteDone, SqliteRow,
};
use crate::statement::StatementInfo;
fn prepare<'a>(
@ -92,7 +95,7 @@ impl<'c> Executor<'c> for &'c mut SqliteConnection {
fn fetch_many<'e, 'q: 'e, E: 'q>(
self,
mut query: E,
) -> BoxStream<'e, Result<Either<u64, SqliteRow>, Error>>
) -> BoxStream<'e, Result<Either<SqliteDone, SqliteRow>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
@ -145,7 +148,16 @@ impl<'c> Executor<'c> for &'c mut SqliteConnection {
match s {
Either::Left(changes) => {
r#yield!(Either::Left(changes));
let last_insert_rowid = unsafe {
sqlite3_last_insert_rowid(conn.as_ptr())
};
let done = SqliteDone {
changes: changes,
last_insert_rowid: last_insert_rowid,
};
r#yield!(Either::Left(done));
break;
}

View File

@ -1,6 +1,6 @@
use crate::database::{Database, HasArguments, HasStatementCache, HasValueRef};
use crate::sqlite::{
SqliteArgumentValue, SqliteArguments, SqliteColumn, SqliteConnection, SqliteRow,
SqliteArgumentValue, SqliteArguments, SqliteColumn, SqliteConnection, SqliteDone, SqliteRow,
SqliteTransactionManager, SqliteTypeInfo, SqliteValue, SqliteValueRef,
};
@ -15,6 +15,8 @@ impl Database for Sqlite {
type Row = SqliteRow;
type Done = SqliteDone;
type Column = SqliteColumn;
type TypeInfo = SqliteTypeInfo;

View File

@ -0,0 +1,32 @@
use crate::done::Done;
use crate::sqlite::Sqlite;
use std::iter::{Extend, IntoIterator};
#[derive(Debug, Default)]
pub struct SqliteDone {
pub(super) changes: u64,
pub(super) last_insert_rowid: i64,
}
impl SqliteDone {
pub fn last_insert_rowid(&self) -> i64 {
self.last_insert_rowid
}
}
impl Done for SqliteDone {
type Database = Sqlite;
fn rows_affected(&self) -> u64 {
self.changes
}
}
impl Extend<SqliteDone> for SqliteDone {
fn extend<T: IntoIterator<Item = SqliteDone>>(&mut self, iter: T) {
for elem in iter {
self.changes += elem.changes;
self.last_insert_rowid = elem.last_insert_rowid;
}
}
}

View File

@ -9,6 +9,7 @@ mod arguments;
mod column;
mod connection;
mod database;
mod done;
mod error;
mod options;
mod row;
@ -25,6 +26,7 @@ pub use arguments::{SqliteArgumentValue, SqliteArguments};
pub use column::SqliteColumn;
pub use connection::SqliteConnection;
pub use database::Sqlite;
pub use done::SqliteDone;
pub use error::SqliteError;
pub use options::{SqliteConnectOptions, SqliteJournalMode};
pub use row::SqliteRow;

View File

@ -108,7 +108,10 @@ macro_rules! impl_executor_for_transaction {
query: E,
) -> futures_core::stream::BoxStream<
'e,
Result<either::Either<u64, $Row>, crate::error::Error>,
Result<
either::Either<<$DB as crate::database::Database>::Done, $Row>,
crate::error::Error,
>,
>
where
't: 'e,

View File

@ -5,6 +5,7 @@ pub use sqlx_core::arguments::{Arguments, IntoArguments};
pub use sqlx_core::column::Column;
pub use sqlx_core::connection::{ConnectOptions, Connection};
pub use sqlx_core::database::{self, Database};
pub use sqlx_core::done::Done;
pub use sqlx_core::executor::{Execute, Executor};
pub use sqlx_core::from_row::FromRow;
pub use sqlx_core::pool::{self, Pool};
@ -113,7 +114,7 @@ pub mod decode {
pub use sqlx_macros::Decode;
}
/// Return types for the `query` family of functions and macros.
/// Types and traits for the `query` family of functions and macros.
pub mod query {
pub use sqlx_core::query::{Map, Query};
pub use sqlx_core::query::{MapRow, TryMapRow};
@ -126,6 +127,7 @@ pub mod prelude {
pub use super::Acquire;
pub use super::ConnectOptions;
pub use super::Connection;
pub use super::Done;
pub use super::Executor;
pub use super::FromRow;
pub use super::IntoArguments;

View File

@ -1,6 +1,6 @@
use futures::TryStreamExt;
use sqlx::mssql::Mssql;
use sqlx::{Connection, Executor, MssqlConnection, Row};
use sqlx::{Connection, Done, Executor, MssqlConnection, Row};
use sqlx_core::mssql::MssqlRow;
use sqlx_test::new;
@ -54,7 +54,7 @@ async fn it_can_fail_to_connect() -> anyhow::Result<()> {
async fn it_can_inspect_errors() -> anyhow::Result<()> {
let mut conn = new::<Mssql>().await?;
let res: Result<u64, sqlx::Error> = sqlx::query("select f").execute(&mut conn).await;
let res: Result<_, sqlx::Error> = sqlx::query("select f").execute(&mut conn).await;
let err = res.unwrap_err();
// can also do [as_database_error] or use `match ..`
@ -93,12 +93,12 @@ CREATE TABLE #users (id INTEGER PRIMARY KEY);
.await?;
for index in 1..=10_i32 {
let cnt = sqlx::query("INSERT INTO #users (id) VALUES (@p1)")
let done = sqlx::query("INSERT INTO #users (id) VALUES (@p1)")
.bind(index * 2)
.execute(&mut conn)
.await?;
assert_eq!(cnt, 1);
assert_eq!(done.rows_affected(), 1);
}
let sum: i32 = sqlx::query("SELECT id FROM #users")

View File

@ -1,6 +1,6 @@
use futures::TryStreamExt;
use sqlx::mysql::{MySql, MySqlPool, MySqlPoolOptions, MySqlRow};
use sqlx::{Connection, Executor, Row};
use sqlx::{Connection, Done, Executor, Row};
use sqlx_test::new;
#[sqlx_macros::test]
@ -55,12 +55,12 @@ CREATE TEMPORARY TABLE users (id INTEGER PRIMARY KEY);
.await?;
for index in 1..=10_i32 {
let cnt = sqlx::query("INSERT INTO users (id) VALUES (?)")
let done = sqlx::query("INSERT INTO users (id) VALUES (?)")
.bind(index)
.execute(&mut conn)
.await?;
assert_eq!(cnt, 1);
assert_eq!(done.rows_affected(), 1);
}
let sum: i32 = sqlx::query("SELECT id FROM users")
@ -102,12 +102,12 @@ async fn it_drops_results_in_affected_rows() -> anyhow::Result<()> {
let mut conn = new::<MySql>().await?;
// ~1800 rows should be iterated and dropped
let affected = conn
let done = conn
.execute("select * from mysql.time_zone limit 1575")
.await?;
// In MySQL, rows being returned isn't enough to flag it as an _affected_ row
assert_eq!(0, affected);
assert_eq!(0, done.rows_affected());
Ok(())
}

View File

@ -3,7 +3,7 @@ use sqlx::postgres::{
PgConnectOptions, PgConnection, PgDatabaseError, PgErrorPosition, PgSeverity,
};
use sqlx::postgres::{PgPoolOptions, PgRow};
use sqlx::{postgres::Postgres, Connection, Executor, Row};
use sqlx::{postgres::Postgres, Connection, Done, Executor, Row};
use sqlx_test::new;
use std::env;
use std::thread;
@ -51,7 +51,7 @@ async fn it_maths() -> anyhow::Result<()> {
async fn it_can_inspect_errors() -> anyhow::Result<()> {
let mut conn = new::<Postgres>().await?;
let res: Result<u64, sqlx::Error> = sqlx::query("select f").execute(&mut conn).await;
let res: Result<_, sqlx::Error> = sqlx::query("select f").execute(&mut conn).await;
let err = res.unwrap_err();
// can also do [as_database_error] or use `match ..`
@ -85,12 +85,12 @@ CREATE TEMPORARY TABLE users (id INTEGER PRIMARY KEY);
.await?;
for index in 1..=10_i32 {
let cnt = sqlx::query("INSERT INTO users (id) VALUES ($1)")
let done = sqlx::query("INSERT INTO users (id) VALUES ($1)")
.bind(index)
.execute(&mut conn)
.await?;
assert_eq!(cnt, 1);
assert_eq!(done.rows_affected(), 1);
}
let sum: i32 = sqlx::query("SELECT id FROM users")
@ -441,9 +441,9 @@ async fn test_invalid_query() -> anyhow::Result<()> {
#[sqlx_macros::test]
async fn test_empty_query() -> anyhow::Result<()> {
let mut conn = new::<Postgres>().await?;
let affected = conn.execute("").await?;
let done = conn.execute("").await?;
assert_eq!(affected, 0);
assert_eq!(done.rows_affected(), 0);
Ok(())
}

View File

@ -1,8 +1,8 @@
use sqlx::error::DatabaseError;
use sqlx::sqlite::{SqliteConnectOptions, SqliteError};
use sqlx::ConnectOptions;
use sqlx::TypeInfo;
use sqlx::{sqlite::Sqlite, Column, Executor};
use sqlx::{SqliteConnection, TypeInfo};
use sqlx_test::new;
use std::env;

Binary file not shown.

View File

@ -1,7 +1,7 @@
use futures::TryStreamExt;
use sqlx::sqlite::SqlitePoolOptions;
use sqlx::{
query, sqlite::Sqlite, sqlite::SqliteRow, Connection, Executor, Row, SqliteConnection,
query, sqlite::Sqlite, sqlite::SqliteRow, Connection, Done, Executor, Row, SqliteConnection,
SqlitePool,
};
use sqlx_test::new;
@ -179,9 +179,9 @@ async fn it_fails_to_parse() -> anyhow::Result<()> {
#[sqlx_macros::test]
async fn it_handles_empty_queries() -> anyhow::Result<()> {
let mut conn = new::<Sqlite>().await?;
let affected = conn.execute("").await?;
let done = conn.execute("").await?;
assert_eq!(affected, 0);
assert_eq!(done.rows_affected(), 0);
Ok(())
}
@ -221,12 +221,12 @@ CREATE TEMPORARY TABLE users (id INTEGER PRIMARY KEY)
.await?;
for index in 1..=10_i32 {
let cnt = sqlx::query("INSERT INTO users (id) VALUES (?)")
let done = sqlx::query("INSERT INTO users (id) VALUES (?)")
.bind(index * 2)
.execute(&mut conn)
.await?;
assert_eq!(cnt, 1);
assert_eq!(done.rows_affected(), 1);
}
let sum: i32 = sqlx::query_as("SELECT id FROM users")
@ -243,7 +243,7 @@ CREATE TEMPORARY TABLE users (id INTEGER PRIMARY KEY)
async fn it_can_execute_multiple_statements() -> anyhow::Result<()> {
let mut conn = new::<Sqlite>().await?;
let affected = conn
let done = conn
.execute(
r#"
CREATE TEMPORARY TABLE users (id INTEGER PRIMARY KEY, other INTEGER);
@ -252,7 +252,7 @@ INSERT INTO users DEFAULT VALUES;
)
.await?;
assert_eq!(affected, 1);
assert_eq!(done.rows_affected(), 1);
for index in 2..5_i32 {
let (id, other): (i32, i32) = sqlx::query_as(