mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-10-27 11:32:59 +00:00
feat: add sqlx::Done and return from Executor::execute()
+ Done::rows_affected() + Done::last_insert_id()
This commit is contained in:
parent
51aeee20da
commit
00137d4a04
@ -5,6 +5,7 @@ use std::fmt::Debug;
|
|||||||
use crate::arguments::Arguments;
|
use crate::arguments::Arguments;
|
||||||
use crate::column::Column;
|
use crate::column::Column;
|
||||||
use crate::connection::Connection;
|
use crate::connection::Connection;
|
||||||
|
use crate::done::Done;
|
||||||
use crate::row::Row;
|
use crate::row::Row;
|
||||||
use crate::transaction::TransactionManager;
|
use crate::transaction::TransactionManager;
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
@ -31,6 +32,9 @@ pub trait Database:
|
|||||||
/// The concrete `Row` implementation for this database.
|
/// The concrete `Row` implementation for this database.
|
||||||
type Row: Row<Database = Self>;
|
type Row: Row<Database = Self>;
|
||||||
|
|
||||||
|
/// The concrete `Done` implementation for this database.
|
||||||
|
type Done: Done<Database = Self>;
|
||||||
|
|
||||||
/// The concrete `Column` implementation for this database.
|
/// The concrete `Column` implementation for this database.
|
||||||
type Column: Column<Database = Self>;
|
type Column: Column<Database = Self>;
|
||||||
|
|
||||||
|
|||||||
9
sqlx-core/src/done.rs
Normal file
9
sqlx-core/src/done.rs
Normal 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;
|
||||||
|
}
|
||||||
@ -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 either::Either;
|
||||||
use futures_core::future::BoxFuture;
|
use futures_core::future::BoxFuture;
|
||||||
use futures_core::stream::BoxStream;
|
use futures_core::stream::BoxStream;
|
||||||
use futures_util::{future, FutureExt, StreamExt, TryFutureExt, TryStreamExt};
|
use futures_util::{future, FutureExt, StreamExt, TryFutureExt, TryStreamExt};
|
||||||
|
use std::fmt::Debug;
|
||||||
use crate::database::{Database, HasArguments};
|
|
||||||
use crate::error::Error;
|
|
||||||
use crate::statement::StatementInfo;
|
|
||||||
|
|
||||||
/// A type that contains or can provide a database
|
/// A type that contains or can provide a database
|
||||||
/// connection to use for executing queries against the database.
|
/// connection to use for executing queries against the database.
|
||||||
@ -28,18 +26,22 @@ pub trait Executor<'c>: Send + Debug + Sized {
|
|||||||
type Database: Database;
|
type Database: Database;
|
||||||
|
|
||||||
/// Execute the query and return the total number of rows affected.
|
/// 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
|
where
|
||||||
'c: 'e,
|
'c: 'e,
|
||||||
E: Execute<'q, Self::Database>,
|
E: Execute<'q, Self::Database>,
|
||||||
{
|
{
|
||||||
self.execute_many(query)
|
self.execute_many(query).try_collect().boxed()
|
||||||
.try_fold(0, |acc, x| async move { Ok(acc + x) })
|
|
||||||
.boxed()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute multiple queries and return the rows affected from each query, in a stream.
|
/// 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
|
where
|
||||||
'c: 'e,
|
'c: 'e,
|
||||||
E: Execute<'q, Self::Database>,
|
E: Execute<'q, Self::Database>,
|
||||||
@ -78,7 +80,13 @@ pub trait Executor<'c>: Send + Debug + Sized {
|
|||||||
fn fetch_many<'e, 'q: 'e, E: 'q>(
|
fn fetch_many<'e, 'q: 'e, E: 'q>(
|
||||||
self,
|
self,
|
||||||
query: E,
|
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
|
where
|
||||||
'c: 'e,
|
'c: 'e,
|
||||||
E: Execute<'q, Self::Database>;
|
E: Execute<'q, Self::Database>;
|
||||||
|
|||||||
@ -52,6 +52,7 @@ pub mod acquire;
|
|||||||
pub mod column;
|
pub mod column;
|
||||||
mod common;
|
mod common;
|
||||||
pub mod database;
|
pub mod database;
|
||||||
|
pub mod done;
|
||||||
pub mod executor;
|
pub mod executor;
|
||||||
pub mod from_row;
|
pub mod from_row;
|
||||||
mod io;
|
mod io;
|
||||||
|
|||||||
@ -6,7 +6,7 @@ use crate::mssql::protocol::message::Message;
|
|||||||
use crate::mssql::protocol::packet::PacketType;
|
use crate::mssql::protocol::packet::PacketType;
|
||||||
use crate::mssql::protocol::rpc::{OptionFlags, Procedure, RpcRequest};
|
use crate::mssql::protocol::rpc::{OptionFlags, Procedure, RpcRequest};
|
||||||
use crate::mssql::protocol::sql_batch::SqlBatch;
|
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 crate::statement::StatementInfo;
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use futures_core::future::BoxFuture;
|
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>(
|
fn fetch_many<'e, 'q: 'e, E: 'q>(
|
||||||
self,
|
self,
|
||||||
mut query: E,
|
mut query: E,
|
||||||
) -> BoxStream<'e, Result<Either<u64, MssqlRow>, Error>>
|
) -> BoxStream<'e, Result<Either<MssqlDone, MssqlRow>, Error>>
|
||||||
where
|
where
|
||||||
'c: 'e,
|
'c: 'e,
|
||||||
E: Execute<'q, Self::Database>,
|
E: Execute<'q, Self::Database>,
|
||||||
@ -94,7 +94,9 @@ impl<'c> Executor<'c> for &'c mut MssqlConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if done.status.contains(Status::DONE_COUNT) {
|
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) {
|
if !done.status.contains(Status::DONE_MORE) {
|
||||||
@ -104,7 +106,9 @@ impl<'c> Executor<'c> for &'c mut MssqlConnection {
|
|||||||
|
|
||||||
Message::DoneInProc(done) => {
|
Message::DoneInProc(done) => {
|
||||||
if done.status.contains(Status::DONE_COUNT) {
|
if done.status.contains(Status::DONE_COUNT) {
|
||||||
r#yield!(Either::Left(done.affected_rows));
|
r#yield!(Either::Left(MssqlDone {
|
||||||
|
rows_affected: done.affected_rows,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::database::{Database, HasArguments, HasValueRef};
|
use crate::database::{Database, HasArguments, HasValueRef};
|
||||||
use crate::mssql::{
|
use crate::mssql::{
|
||||||
MssqlArguments, MssqlColumn, MssqlConnection, MssqlRow, MssqlTransactionManager, MssqlTypeInfo,
|
MssqlArguments, MssqlColumn, MssqlConnection, MssqlDone, MssqlRow, MssqlTransactionManager,
|
||||||
MssqlValue, MssqlValueRef,
|
MssqlTypeInfo, MssqlValue, MssqlValueRef,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// MSSQL database driver.
|
/// MSSQL database driver.
|
||||||
@ -15,6 +15,8 @@ impl Database for Mssql {
|
|||||||
|
|
||||||
type Row = MssqlRow;
|
type Row = MssqlRow;
|
||||||
|
|
||||||
|
type Done = MssqlDone;
|
||||||
|
|
||||||
type Column = MssqlColumn;
|
type Column = MssqlColumn;
|
||||||
|
|
||||||
type TypeInfo = MssqlTypeInfo;
|
type TypeInfo = MssqlTypeInfo;
|
||||||
|
|||||||
24
sqlx-core/src/mssql/done.rs
Normal file
24
sqlx-core/src/mssql/done.rs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ mod arguments;
|
|||||||
mod column;
|
mod column;
|
||||||
mod connection;
|
mod connection;
|
||||||
mod database;
|
mod database;
|
||||||
|
mod done;
|
||||||
mod error;
|
mod error;
|
||||||
mod io;
|
mod io;
|
||||||
mod options;
|
mod options;
|
||||||
@ -18,6 +19,7 @@ pub use arguments::MssqlArguments;
|
|||||||
pub use column::MssqlColumn;
|
pub use column::MssqlColumn;
|
||||||
pub use connection::MssqlConnection;
|
pub use connection::MssqlConnection;
|
||||||
pub use database::Mssql;
|
pub use database::Mssql;
|
||||||
|
pub use done::MssqlDone;
|
||||||
pub use error::MssqlDatabaseError;
|
pub use error::MssqlDatabaseError;
|
||||||
pub use options::MssqlConnectOptions;
|
pub use options::MssqlConnectOptions;
|
||||||
pub use row::MssqlRow;
|
pub use row::MssqlRow;
|
||||||
|
|||||||
@ -19,7 +19,8 @@ use crate::mysql::protocol::statement::{
|
|||||||
use crate::mysql::protocol::text::{ColumnDefinition, ColumnFlags, Query, TextRow};
|
use crate::mysql::protocol::text::{ColumnDefinition, ColumnFlags, Query, TextRow};
|
||||||
use crate::mysql::protocol::Packet;
|
use crate::mysql::protocol::Packet;
|
||||||
use crate::mysql::{
|
use crate::mysql::{
|
||||||
MySql, MySqlArguments, MySqlColumn, MySqlConnection, MySqlRow, MySqlTypeInfo, MySqlValueFormat,
|
MySql, MySqlArguments, MySqlColumn, MySqlConnection, MySqlDone, MySqlRow, MySqlTypeInfo,
|
||||||
|
MySqlValueFormat,
|
||||||
};
|
};
|
||||||
use crate::statement::StatementInfo;
|
use crate::statement::StatementInfo;
|
||||||
|
|
||||||
@ -111,7 +112,7 @@ impl MySqlConnection {
|
|||||||
&'c mut self,
|
&'c mut self,
|
||||||
query: &str,
|
query: &str,
|
||||||
arguments: Option<MySqlArguments>,
|
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.wait_until_ready().await?;
|
||||||
self.stream.busy = Busy::Result;
|
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
|
// this indicates either a successful query with no rows at all or a failed query
|
||||||
let ok = packet.ok()?;
|
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) {
|
if ok.status.contains(Status::SERVER_MORE_RESULTS_EXISTS) {
|
||||||
// more result sets exist, continue to the next one
|
// more result sets exist, continue to the next one
|
||||||
@ -166,7 +172,11 @@ impl MySqlConnection {
|
|||||||
|
|
||||||
if packet[0] == 0xfe && packet.len() < 9 {
|
if packet[0] == 0xfe && packet.len() < 9 {
|
||||||
let eof = packet.eof(self.stream.capabilities)?;
|
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) {
|
if eof.status.contains(Status::SERVER_MORE_RESULTS_EXISTS) {
|
||||||
// more result sets exist, continue to the next one
|
// 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>(
|
fn fetch_many<'e, 'q: 'e, E: 'q>(
|
||||||
self,
|
self,
|
||||||
mut query: E,
|
mut query: E,
|
||||||
) -> BoxStream<'e, Result<Either<u64, MySqlRow>, Error>>
|
) -> BoxStream<'e, Result<Either<MySqlDone, MySqlRow>, Error>>
|
||||||
where
|
where
|
||||||
'c: 'e,
|
'c: 'e,
|
||||||
E: Execute<'q, Self::Database>,
|
E: Execute<'q, Self::Database>,
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
use crate::database::{Database, HasArguments, HasStatementCache, HasValueRef};
|
use crate::database::{Database, HasArguments, HasStatementCache, HasValueRef};
|
||||||
use crate::mysql::value::{MySqlValue, MySqlValueRef};
|
use crate::mysql::value::{MySqlValue, MySqlValueRef};
|
||||||
use crate::mysql::{
|
use crate::mysql::{
|
||||||
MySqlArguments, MySqlColumn, MySqlConnection, MySqlRow, MySqlTransactionManager, MySqlTypeInfo,
|
MySqlArguments, MySqlColumn, MySqlConnection, MySqlDone, MySqlRow, MySqlTransactionManager,
|
||||||
|
MySqlTypeInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// MySQL database driver.
|
/// MySQL database driver.
|
||||||
@ -15,6 +16,8 @@ impl Database for MySql {
|
|||||||
|
|
||||||
type Row = MySqlRow;
|
type Row = MySqlRow;
|
||||||
|
|
||||||
|
type Done = MySqlDone;
|
||||||
|
|
||||||
type Column = MySqlColumn;
|
type Column = MySqlColumn;
|
||||||
|
|
||||||
type TypeInfo = MySqlTypeInfo;
|
type TypeInfo = MySqlTypeInfo;
|
||||||
|
|||||||
32
sqlx-core/src/mysql/done.rs
Normal file
32
sqlx-core/src/mysql/done.rs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ mod arguments;
|
|||||||
mod column;
|
mod column;
|
||||||
mod connection;
|
mod connection;
|
||||||
mod database;
|
mod database;
|
||||||
|
mod done;
|
||||||
mod error;
|
mod error;
|
||||||
mod io;
|
mod io;
|
||||||
mod options;
|
mod options;
|
||||||
@ -21,6 +22,7 @@ pub use arguments::MySqlArguments;
|
|||||||
pub use column::MySqlColumn;
|
pub use column::MySqlColumn;
|
||||||
pub use connection::MySqlConnection;
|
pub use connection::MySqlConnection;
|
||||||
pub use database::MySql;
|
pub use database::MySql;
|
||||||
|
pub use done::MySqlDone;
|
||||||
pub use error::MySqlDatabaseError;
|
pub use error::MySqlDatabaseError;
|
||||||
pub use options::{MySqlConnectOptions, MySqlSslMode};
|
pub use options::{MySqlConnectOptions, MySqlSslMode};
|
||||||
pub use row::MySqlRow;
|
pub use row::MySqlRow;
|
||||||
|
|||||||
@ -18,7 +18,7 @@ where
|
|||||||
fn fetch_many<'e, 'q: 'e, E: 'q>(
|
fn fetch_many<'e, 'q: 'e, E: 'q>(
|
||||||
self,
|
self,
|
||||||
query: E,
|
query: E,
|
||||||
) -> BoxStream<'e, Result<Either<u64, DB::Row>, Error>>
|
) -> BoxStream<'e, Result<Either<DB::Done, DB::Row>, Error>>
|
||||||
where
|
where
|
||||||
E: Execute<'q, Self::Database>,
|
E: Execute<'q, Self::Database>,
|
||||||
{
|
{
|
||||||
@ -75,7 +75,10 @@ macro_rules! impl_executor_for_pool_connection {
|
|||||||
query: E,
|
query: E,
|
||||||
) -> futures_core::stream::BoxStream<
|
) -> futures_core::stream::BoxStream<
|
||||||
'e,
|
'e,
|
||||||
Result<either::Either<u64, $R>, crate::error::Error>,
|
Result<
|
||||||
|
either::Either<<$DB as crate::database::Database>::Done, $R>,
|
||||||
|
crate::error::Error,
|
||||||
|
>,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
'c: 'e,
|
'c: 'e,
|
||||||
|
|||||||
@ -12,7 +12,7 @@ use crate::postgres::message::{
|
|||||||
Query, RowDescription,
|
Query, RowDescription,
|
||||||
};
|
};
|
||||||
use crate::postgres::type_info::PgType;
|
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;
|
use crate::statement::StatementInfo;
|
||||||
|
|
||||||
async fn prepare(
|
async fn prepare(
|
||||||
@ -142,7 +142,7 @@ impl PgConnection {
|
|||||||
query: &str,
|
query: &str,
|
||||||
arguments: Option<PgArguments>,
|
arguments: Option<PgArguments>,
|
||||||
limit: u8,
|
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
|
// before we continue, wait until we are "ready" to accept more queries
|
||||||
self.wait_until_ready().await?;
|
self.wait_until_ready().await?;
|
||||||
|
|
||||||
@ -219,7 +219,9 @@ impl PgConnection {
|
|||||||
// a SQL command completed normally
|
// a SQL command completed normally
|
||||||
let cc: CommandComplete = message.decode()?;
|
let cc: CommandComplete = message.decode()?;
|
||||||
|
|
||||||
r#yield!(Either::Left(cc.rows_affected()));
|
r#yield!(Either::Left(PgDone {
|
||||||
|
rows_affected: cc.rows_affected(),
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageFormat::EmptyQueryResponse => {
|
MessageFormat::EmptyQueryResponse => {
|
||||||
@ -272,7 +274,7 @@ impl<'c> Executor<'c> for &'c mut PgConnection {
|
|||||||
fn fetch_many<'e, 'q: 'e, E: 'q>(
|
fn fetch_many<'e, 'q: 'e, E: 'q>(
|
||||||
self,
|
self,
|
||||||
mut query: E,
|
mut query: E,
|
||||||
) -> BoxStream<'e, Result<Either<u64, PgRow>, Error>>
|
) -> BoxStream<'e, Result<Either<PgDone, PgRow>, Error>>
|
||||||
where
|
where
|
||||||
'c: 'e,
|
'c: 'e,
|
||||||
E: Execute<'q, Self::Database>,
|
E: Execute<'q, Self::Database>,
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use crate::database::{Database, HasArguments, HasStatementCache, HasValueRef};
|
|||||||
use crate::postgres::arguments::PgArgumentBuffer;
|
use crate::postgres::arguments::PgArgumentBuffer;
|
||||||
use crate::postgres::value::{PgValue, PgValueRef};
|
use crate::postgres::value::{PgValue, PgValueRef};
|
||||||
use crate::postgres::{
|
use crate::postgres::{
|
||||||
PgArguments, PgColumn, PgConnection, PgRow, PgTransactionManager, PgTypeInfo,
|
PgArguments, PgColumn, PgConnection, PgDone, PgRow, PgTransactionManager, PgTypeInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// PostgreSQL database driver.
|
/// PostgreSQL database driver.
|
||||||
@ -16,6 +16,8 @@ impl Database for Postgres {
|
|||||||
|
|
||||||
type Row = PgRow;
|
type Row = PgRow;
|
||||||
|
|
||||||
|
type Done = PgDone;
|
||||||
|
|
||||||
type Column = PgColumn;
|
type Column = PgColumn;
|
||||||
|
|
||||||
type TypeInfo = PgTypeInfo;
|
type TypeInfo = PgTypeInfo;
|
||||||
|
|||||||
24
sqlx-core/src/postgres/done.rs
Normal file
24
sqlx-core/src/postgres/done.rs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,7 +3,7 @@ use crate::executor::{Execute, Executor};
|
|||||||
use crate::pool::PoolOptions;
|
use crate::pool::PoolOptions;
|
||||||
use crate::pool::{Pool, PoolConnection};
|
use crate::pool::{Pool, PoolConnection};
|
||||||
use crate::postgres::message::{MessageFormat, Notification};
|
use crate::postgres::message::{MessageFormat, Notification};
|
||||||
use crate::postgres::{PgConnection, PgRow, Postgres};
|
use crate::postgres::{PgConnection, PgDone, PgRow, Postgres};
|
||||||
use crate::statement::StatementInfo;
|
use crate::statement::StatementInfo;
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use futures_channel::mpsc;
|
use futures_channel::mpsc;
|
||||||
@ -197,7 +197,7 @@ impl<'c> Executor<'c> for &'c mut PgListener {
|
|||||||
fn fetch_many<'e, 'q: 'e, E: 'q>(
|
fn fetch_many<'e, 'q: 'e, E: 'q>(
|
||||||
self,
|
self,
|
||||||
query: E,
|
query: E,
|
||||||
) -> BoxStream<'e, Result<Either<u64, PgRow>, Error>>
|
) -> BoxStream<'e, Result<Either<PgDone, PgRow>, Error>>
|
||||||
where
|
where
|
||||||
'c: 'e,
|
'c: 'e,
|
||||||
E: Execute<'q, Self::Database>,
|
E: Execute<'q, Self::Database>,
|
||||||
|
|||||||
@ -4,6 +4,7 @@ mod arguments;
|
|||||||
mod column;
|
mod column;
|
||||||
mod connection;
|
mod connection;
|
||||||
mod database;
|
mod database;
|
||||||
|
mod done;
|
||||||
mod error;
|
mod error;
|
||||||
mod io;
|
mod io;
|
||||||
mod listener;
|
mod listener;
|
||||||
@ -22,6 +23,7 @@ pub use arguments::{PgArgumentBuffer, PgArguments};
|
|||||||
pub use column::PgColumn;
|
pub use column::PgColumn;
|
||||||
pub use connection::PgConnection;
|
pub use connection::PgConnection;
|
||||||
pub use database::Postgres;
|
pub use database::Postgres;
|
||||||
|
pub use done::PgDone;
|
||||||
pub use error::{PgDatabaseError, PgErrorPosition};
|
pub use error::{PgDatabaseError, PgErrorPosition};
|
||||||
pub use listener::{PgListener, PgNotification};
|
pub use listener::{PgListener, PgNotification};
|
||||||
pub use message::PgSeverity;
|
pub use message::PgSeverity;
|
||||||
|
|||||||
@ -104,7 +104,7 @@ where
|
|||||||
|
|
||||||
/// Execute the query and return the total number of rows affected.
|
/// Execute the query and return the total number of rows affected.
|
||||||
#[inline]
|
#[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
|
where
|
||||||
'q: 'e,
|
'q: 'e,
|
||||||
A: 'e,
|
A: 'e,
|
||||||
@ -115,7 +115,10 @@ where
|
|||||||
|
|
||||||
/// Execute multiple queries and return the rows affected from each query, in a stream.
|
/// Execute multiple queries and return the rows affected from each query, in a stream.
|
||||||
#[inline]
|
#[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
|
where
|
||||||
'q: 'e,
|
'q: 'e,
|
||||||
A: 'e,
|
A: 'e,
|
||||||
@ -141,7 +144,7 @@ where
|
|||||||
pub fn fetch_many<'e, 'c: 'e, E>(
|
pub fn fetch_many<'e, 'c: 'e, E>(
|
||||||
self,
|
self,
|
||||||
executor: E,
|
executor: E,
|
||||||
) -> BoxStream<'e, Result<Either<u64, DB::Row>, Error>>
|
) -> BoxStream<'e, Result<Either<DB::Done, DB::Row>, Error>>
|
||||||
where
|
where
|
||||||
'q: 'e,
|
'q: 'e,
|
||||||
A: 'e,
|
A: 'e,
|
||||||
@ -231,7 +234,7 @@ where
|
|||||||
pub fn fetch_many<'e, 'c: 'e, E>(
|
pub fn fetch_many<'e, 'c: 'e, E>(
|
||||||
self,
|
self,
|
||||||
executor: E,
|
executor: E,
|
||||||
) -> BoxStream<'e, Result<Either<u64, O>, Error>>
|
) -> BoxStream<'e, Result<Either<DB::Done, O>, Error>>
|
||||||
where
|
where
|
||||||
'q: 'e,
|
'q: 'e,
|
||||||
E: 'e + Executor<'c, Database = DB>,
|
E: 'e + Executor<'c, Database = DB>,
|
||||||
|
|||||||
@ -74,7 +74,7 @@ where
|
|||||||
pub fn fetch_many<'e, 'c: 'e, E>(
|
pub fn fetch_many<'e, 'c: 'e, E>(
|
||||||
self,
|
self,
|
||||||
executor: E,
|
executor: E,
|
||||||
) -> BoxStream<'e, Result<Either<u64, O>, Error>>
|
) -> BoxStream<'e, Result<Either<DB::Done, O>, Error>>
|
||||||
where
|
where
|
||||||
'q: 'e,
|
'q: 'e,
|
||||||
E: 'e + Executor<'c, Database = DB>,
|
E: 'e + Executor<'c, Database = DB>,
|
||||||
|
|||||||
@ -71,7 +71,7 @@ where
|
|||||||
pub fn fetch_many<'e, 'c: 'e, E>(
|
pub fn fetch_many<'e, 'c: 'e, E>(
|
||||||
self,
|
self,
|
||||||
executor: E,
|
executor: E,
|
||||||
) -> BoxStream<'e, Result<Either<u64, O>, Error>>
|
) -> BoxStream<'e, Result<Either<DB::Done, O>, Error>>
|
||||||
where
|
where
|
||||||
'q: 'e,
|
'q: 'e,
|
||||||
E: 'e + Executor<'c, Database = DB>,
|
E: 'e + Executor<'c, Database = DB>,
|
||||||
|
|||||||
@ -5,6 +5,7 @@ use futures_core::future::BoxFuture;
|
|||||||
use futures_core::stream::BoxStream;
|
use futures_core::stream::BoxStream;
|
||||||
use futures_util::{FutureExt, TryStreamExt};
|
use futures_util::{FutureExt, TryStreamExt};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
use libsqlite3_sys::sqlite3_last_insert_rowid;
|
||||||
|
|
||||||
use crate::common::StatementCache;
|
use crate::common::StatementCache;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
@ -13,7 +14,9 @@ use crate::ext::ustr::UStr;
|
|||||||
use crate::sqlite::connection::describe::describe;
|
use crate::sqlite::connection::describe::describe;
|
||||||
use crate::sqlite::connection::ConnectionHandle;
|
use crate::sqlite::connection::ConnectionHandle;
|
||||||
use crate::sqlite::statement::{SqliteStatement, StatementHandle};
|
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;
|
use crate::statement::StatementInfo;
|
||||||
|
|
||||||
fn prepare<'a>(
|
fn prepare<'a>(
|
||||||
@ -92,7 +95,7 @@ impl<'c> Executor<'c> for &'c mut SqliteConnection {
|
|||||||
fn fetch_many<'e, 'q: 'e, E: 'q>(
|
fn fetch_many<'e, 'q: 'e, E: 'q>(
|
||||||
self,
|
self,
|
||||||
mut query: E,
|
mut query: E,
|
||||||
) -> BoxStream<'e, Result<Either<u64, SqliteRow>, Error>>
|
) -> BoxStream<'e, Result<Either<SqliteDone, SqliteRow>, Error>>
|
||||||
where
|
where
|
||||||
'c: 'e,
|
'c: 'e,
|
||||||
E: Execute<'q, Self::Database>,
|
E: Execute<'q, Self::Database>,
|
||||||
@ -145,7 +148,16 @@ impl<'c> Executor<'c> for &'c mut SqliteConnection {
|
|||||||
|
|
||||||
match s {
|
match s {
|
||||||
Either::Left(changes) => {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::database::{Database, HasArguments, HasStatementCache, HasValueRef};
|
use crate::database::{Database, HasArguments, HasStatementCache, HasValueRef};
|
||||||
use crate::sqlite::{
|
use crate::sqlite::{
|
||||||
SqliteArgumentValue, SqliteArguments, SqliteColumn, SqliteConnection, SqliteRow,
|
SqliteArgumentValue, SqliteArguments, SqliteColumn, SqliteConnection, SqliteDone, SqliteRow,
|
||||||
SqliteTransactionManager, SqliteTypeInfo, SqliteValue, SqliteValueRef,
|
SqliteTransactionManager, SqliteTypeInfo, SqliteValue, SqliteValueRef,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -15,6 +15,8 @@ impl Database for Sqlite {
|
|||||||
|
|
||||||
type Row = SqliteRow;
|
type Row = SqliteRow;
|
||||||
|
|
||||||
|
type Done = SqliteDone;
|
||||||
|
|
||||||
type Column = SqliteColumn;
|
type Column = SqliteColumn;
|
||||||
|
|
||||||
type TypeInfo = SqliteTypeInfo;
|
type TypeInfo = SqliteTypeInfo;
|
||||||
|
|||||||
32
sqlx-core/src/sqlite/done.rs
Normal file
32
sqlx-core/src/sqlite/done.rs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,6 +9,7 @@ mod arguments;
|
|||||||
mod column;
|
mod column;
|
||||||
mod connection;
|
mod connection;
|
||||||
mod database;
|
mod database;
|
||||||
|
mod done;
|
||||||
mod error;
|
mod error;
|
||||||
mod options;
|
mod options;
|
||||||
mod row;
|
mod row;
|
||||||
@ -25,6 +26,7 @@ pub use arguments::{SqliteArgumentValue, SqliteArguments};
|
|||||||
pub use column::SqliteColumn;
|
pub use column::SqliteColumn;
|
||||||
pub use connection::SqliteConnection;
|
pub use connection::SqliteConnection;
|
||||||
pub use database::Sqlite;
|
pub use database::Sqlite;
|
||||||
|
pub use done::SqliteDone;
|
||||||
pub use error::SqliteError;
|
pub use error::SqliteError;
|
||||||
pub use options::{SqliteConnectOptions, SqliteJournalMode};
|
pub use options::{SqliteConnectOptions, SqliteJournalMode};
|
||||||
pub use row::SqliteRow;
|
pub use row::SqliteRow;
|
||||||
|
|||||||
@ -108,7 +108,10 @@ macro_rules! impl_executor_for_transaction {
|
|||||||
query: E,
|
query: E,
|
||||||
) -> futures_core::stream::BoxStream<
|
) -> futures_core::stream::BoxStream<
|
||||||
'e,
|
'e,
|
||||||
Result<either::Either<u64, $Row>, crate::error::Error>,
|
Result<
|
||||||
|
either::Either<<$DB as crate::database::Database>::Done, $Row>,
|
||||||
|
crate::error::Error,
|
||||||
|
>,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
't: 'e,
|
't: 'e,
|
||||||
|
|||||||
@ -5,6 +5,7 @@ pub use sqlx_core::arguments::{Arguments, IntoArguments};
|
|||||||
pub use sqlx_core::column::Column;
|
pub use sqlx_core::column::Column;
|
||||||
pub use sqlx_core::connection::{ConnectOptions, Connection};
|
pub use sqlx_core::connection::{ConnectOptions, Connection};
|
||||||
pub use sqlx_core::database::{self, Database};
|
pub use sqlx_core::database::{self, Database};
|
||||||
|
pub use sqlx_core::done::Done;
|
||||||
pub use sqlx_core::executor::{Execute, Executor};
|
pub use sqlx_core::executor::{Execute, Executor};
|
||||||
pub use sqlx_core::from_row::FromRow;
|
pub use sqlx_core::from_row::FromRow;
|
||||||
pub use sqlx_core::pool::{self, Pool};
|
pub use sqlx_core::pool::{self, Pool};
|
||||||
@ -113,7 +114,7 @@ pub mod decode {
|
|||||||
pub use sqlx_macros::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 mod query {
|
||||||
pub use sqlx_core::query::{Map, Query};
|
pub use sqlx_core::query::{Map, Query};
|
||||||
pub use sqlx_core::query::{MapRow, TryMapRow};
|
pub use sqlx_core::query::{MapRow, TryMapRow};
|
||||||
@ -126,6 +127,7 @@ pub mod prelude {
|
|||||||
pub use super::Acquire;
|
pub use super::Acquire;
|
||||||
pub use super::ConnectOptions;
|
pub use super::ConnectOptions;
|
||||||
pub use super::Connection;
|
pub use super::Connection;
|
||||||
|
pub use super::Done;
|
||||||
pub use super::Executor;
|
pub use super::Executor;
|
||||||
pub use super::FromRow;
|
pub use super::FromRow;
|
||||||
pub use super::IntoArguments;
|
pub use super::IntoArguments;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use futures::TryStreamExt;
|
use futures::TryStreamExt;
|
||||||
use sqlx::mssql::Mssql;
|
use sqlx::mssql::Mssql;
|
||||||
use sqlx::{Connection, Executor, MssqlConnection, Row};
|
use sqlx::{Connection, Done, Executor, MssqlConnection, Row};
|
||||||
use sqlx_core::mssql::MssqlRow;
|
use sqlx_core::mssql::MssqlRow;
|
||||||
use sqlx_test::new;
|
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<()> {
|
async fn it_can_inspect_errors() -> anyhow::Result<()> {
|
||||||
let mut conn = new::<Mssql>().await?;
|
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();
|
let err = res.unwrap_err();
|
||||||
|
|
||||||
// can also do [as_database_error] or use `match ..`
|
// can also do [as_database_error] or use `match ..`
|
||||||
@ -93,12 +93,12 @@ CREATE TABLE #users (id INTEGER PRIMARY KEY);
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
for index in 1..=10_i32 {
|
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)
|
.bind(index * 2)
|
||||||
.execute(&mut conn)
|
.execute(&mut conn)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
assert_eq!(cnt, 1);
|
assert_eq!(done.rows_affected(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let sum: i32 = sqlx::query("SELECT id FROM #users")
|
let sum: i32 = sqlx::query("SELECT id FROM #users")
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use futures::TryStreamExt;
|
use futures::TryStreamExt;
|
||||||
use sqlx::mysql::{MySql, MySqlPool, MySqlPoolOptions, MySqlRow};
|
use sqlx::mysql::{MySql, MySqlPool, MySqlPoolOptions, MySqlRow};
|
||||||
use sqlx::{Connection, Executor, Row};
|
use sqlx::{Connection, Done, Executor, Row};
|
||||||
use sqlx_test::new;
|
use sqlx_test::new;
|
||||||
|
|
||||||
#[sqlx_macros::test]
|
#[sqlx_macros::test]
|
||||||
@ -55,12 +55,12 @@ CREATE TEMPORARY TABLE users (id INTEGER PRIMARY KEY);
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
for index in 1..=10_i32 {
|
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)
|
.bind(index)
|
||||||
.execute(&mut conn)
|
.execute(&mut conn)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
assert_eq!(cnt, 1);
|
assert_eq!(done.rows_affected(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let sum: i32 = sqlx::query("SELECT id FROM users")
|
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?;
|
let mut conn = new::<MySql>().await?;
|
||||||
|
|
||||||
// ~1800 rows should be iterated and dropped
|
// ~1800 rows should be iterated and dropped
|
||||||
let affected = conn
|
let done = conn
|
||||||
.execute("select * from mysql.time_zone limit 1575")
|
.execute("select * from mysql.time_zone limit 1575")
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// In MySQL, rows being returned isn't enough to flag it as an _affected_ row
|
// 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use sqlx::postgres::{
|
|||||||
PgConnectOptions, PgConnection, PgDatabaseError, PgErrorPosition, PgSeverity,
|
PgConnectOptions, PgConnection, PgDatabaseError, PgErrorPosition, PgSeverity,
|
||||||
};
|
};
|
||||||
use sqlx::postgres::{PgPoolOptions, PgRow};
|
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 sqlx_test::new;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
@ -51,7 +51,7 @@ async fn it_maths() -> anyhow::Result<()> {
|
|||||||
async fn it_can_inspect_errors() -> anyhow::Result<()> {
|
async fn it_can_inspect_errors() -> anyhow::Result<()> {
|
||||||
let mut conn = new::<Postgres>().await?;
|
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();
|
let err = res.unwrap_err();
|
||||||
|
|
||||||
// can also do [as_database_error] or use `match ..`
|
// can also do [as_database_error] or use `match ..`
|
||||||
@ -85,12 +85,12 @@ CREATE TEMPORARY TABLE users (id INTEGER PRIMARY KEY);
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
for index in 1..=10_i32 {
|
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)
|
.bind(index)
|
||||||
.execute(&mut conn)
|
.execute(&mut conn)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
assert_eq!(cnt, 1);
|
assert_eq!(done.rows_affected(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let sum: i32 = sqlx::query("SELECT id FROM users")
|
let sum: i32 = sqlx::query("SELECT id FROM users")
|
||||||
@ -441,9 +441,9 @@ async fn test_invalid_query() -> anyhow::Result<()> {
|
|||||||
#[sqlx_macros::test]
|
#[sqlx_macros::test]
|
||||||
async fn test_empty_query() -> anyhow::Result<()> {
|
async fn test_empty_query() -> anyhow::Result<()> {
|
||||||
let mut conn = new::<Postgres>().await?;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
use sqlx::error::DatabaseError;
|
use sqlx::error::DatabaseError;
|
||||||
use sqlx::sqlite::{SqliteConnectOptions, SqliteError};
|
use sqlx::sqlite::{SqliteConnectOptions, SqliteError};
|
||||||
use sqlx::ConnectOptions;
|
use sqlx::ConnectOptions;
|
||||||
|
use sqlx::TypeInfo;
|
||||||
use sqlx::{sqlite::Sqlite, Column, Executor};
|
use sqlx::{sqlite::Sqlite, Column, Executor};
|
||||||
use sqlx::{SqliteConnection, TypeInfo};
|
|
||||||
use sqlx_test::new;
|
use sqlx_test::new;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@ -1,7 +1,7 @@
|
|||||||
use futures::TryStreamExt;
|
use futures::TryStreamExt;
|
||||||
use sqlx::sqlite::SqlitePoolOptions;
|
use sqlx::sqlite::SqlitePoolOptions;
|
||||||
use sqlx::{
|
use sqlx::{
|
||||||
query, sqlite::Sqlite, sqlite::SqliteRow, Connection, Executor, Row, SqliteConnection,
|
query, sqlite::Sqlite, sqlite::SqliteRow, Connection, Done, Executor, Row, SqliteConnection,
|
||||||
SqlitePool,
|
SqlitePool,
|
||||||
};
|
};
|
||||||
use sqlx_test::new;
|
use sqlx_test::new;
|
||||||
@ -179,9 +179,9 @@ async fn it_fails_to_parse() -> anyhow::Result<()> {
|
|||||||
#[sqlx_macros::test]
|
#[sqlx_macros::test]
|
||||||
async fn it_handles_empty_queries() -> anyhow::Result<()> {
|
async fn it_handles_empty_queries() -> anyhow::Result<()> {
|
||||||
let mut conn = new::<Sqlite>().await?;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -221,12 +221,12 @@ CREATE TEMPORARY TABLE users (id INTEGER PRIMARY KEY)
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
for index in 1..=10_i32 {
|
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)
|
.bind(index * 2)
|
||||||
.execute(&mut conn)
|
.execute(&mut conn)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
assert_eq!(cnt, 1);
|
assert_eq!(done.rows_affected(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let sum: i32 = sqlx::query_as("SELECT id FROM users")
|
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<()> {
|
async fn it_can_execute_multiple_statements() -> anyhow::Result<()> {
|
||||||
let mut conn = new::<Sqlite>().await?;
|
let mut conn = new::<Sqlite>().await?;
|
||||||
|
|
||||||
let affected = conn
|
let done = conn
|
||||||
.execute(
|
.execute(
|
||||||
r#"
|
r#"
|
||||||
CREATE TEMPORARY TABLE users (id INTEGER PRIMARY KEY, other INTEGER);
|
CREATE TEMPORARY TABLE users (id INTEGER PRIMARY KEY, other INTEGER);
|
||||||
@ -252,7 +252,7 @@ INSERT INTO users DEFAULT VALUES;
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
assert_eq!(affected, 1);
|
assert_eq!(done.rows_affected(), 1);
|
||||||
|
|
||||||
for index in 2..5_i32 {
|
for index in 2..5_i32 {
|
||||||
let (id, other): (i32, i32) = sqlx::query_as(
|
let (id, other): (i32, i32) = sqlx::query_as(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user