mirror of
https://github.com/launchbadge/sqlx
synced 2024-11-10 06:24:16 +00:00
feat(any): introduce the Any database driver which enables choosing the database driver at runtime
This commit is contained in:
parent
62d02e9450
commit
a7117dd71b
20 changed files with 2236 additions and 2 deletions
|
@ -57,6 +57,7 @@ runtime-actix = [ "sqlx-core/runtime-actix", "sqlx-macros/runtime-actix" ]
|
|||
runtime-tokio = [ "sqlx-core/runtime-tokio", "sqlx-macros/runtime-tokio" ]
|
||||
|
||||
# database
|
||||
any = [ "sqlx-core/any" ]
|
||||
postgres = [ "sqlx-core/postgres", "sqlx-macros/postgres" ]
|
||||
mysql = [ "sqlx-core/mysql", "sqlx-macros/mysql" ]
|
||||
sqlite = [ "sqlx-core/sqlite", "sqlx-macros/sqlite" ]
|
||||
|
@ -89,6 +90,14 @@ paste = "0.1.16"
|
|||
serde = { version = "1.0.111", features = [ "derive" ] }
|
||||
serde_json = "1.0.53"
|
||||
|
||||
#
|
||||
# Any
|
||||
#
|
||||
|
||||
[[test]]
|
||||
name = "any"
|
||||
path = "tests/any/any.rs"
|
||||
|
||||
#
|
||||
# SQLite
|
||||
#
|
||||
|
|
|
@ -21,6 +21,7 @@ postgres = [ "md-5", "sha2", "base64", "sha-1", "rand", "hmac", "futures-channel
|
|||
mysql = [ "sha-1", "sha2", "generic-array", "num-bigint", "base64", "digest", "rand", "rsa" ]
|
||||
sqlite = [ "libsqlite3-sys" ]
|
||||
mssql = [ "uuid", "encoding_rs", "regex" ]
|
||||
any = []
|
||||
|
||||
# types
|
||||
all-types = [ "chrono", "time", "bigdecimal", "ipnetwork", "json", "uuid" ]
|
||||
|
|
133
sqlx-core/src/any/arguments.rs
Normal file
133
sqlx-core/src/any/arguments.rs
Normal file
|
@ -0,0 +1,133 @@
|
|||
use crate::any::Any;
|
||||
use crate::arguments::Arguments;
|
||||
use crate::encode::Encode;
|
||||
use crate::types::Type;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct AnyArguments<'q> {
|
||||
values: Vec<Box<dyn Encode<'q, Any> + Send + 'q>>,
|
||||
}
|
||||
|
||||
impl<'q> Arguments<'q> for AnyArguments<'q> {
|
||||
type Database = Any;
|
||||
|
||||
fn reserve(&mut self, additional: usize, _size: usize) {
|
||||
self.values.reserve(additional);
|
||||
}
|
||||
|
||||
fn add<T>(&mut self, value: T)
|
||||
where
|
||||
T: 'q + Send + Encode<'q, Self::Database> + Type<Self::Database>,
|
||||
{
|
||||
self.values.push(Box::new(value));
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AnyArgumentBuffer<'q>(pub(crate) AnyArgumentBufferKind<'q>);
|
||||
|
||||
pub(crate) enum AnyArgumentBufferKind<'q> {
|
||||
#[cfg(feature = "postgres")]
|
||||
Postgres(
|
||||
crate::postgres::PgArguments,
|
||||
std::marker::PhantomData<&'q ()>,
|
||||
),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
MySql(
|
||||
crate::mysql::MySqlArguments,
|
||||
std::marker::PhantomData<&'q ()>,
|
||||
),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
Sqlite(crate::sqlite::SqliteArguments<'q>),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
Mssql(
|
||||
crate::mssql::MssqlArguments,
|
||||
std::marker::PhantomData<&'q ()>,
|
||||
),
|
||||
}
|
||||
|
||||
// control flow inferred type bounds would be fun
|
||||
// the compiler should know the branch is totally unreachable
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
impl<'q> From<AnyArguments<'q>> for crate::sqlite::SqliteArguments<'q> {
|
||||
fn from(args: AnyArguments<'q>) -> Self {
|
||||
let mut buf = AnyArgumentBuffer(AnyArgumentBufferKind::Sqlite(Default::default()));
|
||||
|
||||
for value in args.values {
|
||||
let _ = value.encode_by_ref(&mut buf);
|
||||
}
|
||||
|
||||
if let AnyArgumentBufferKind::Sqlite(args) = buf.0 {
|
||||
args
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
impl<'q> From<AnyArguments<'q>> for crate::mysql::MySqlArguments {
|
||||
fn from(args: AnyArguments<'q>) -> Self {
|
||||
let mut buf = AnyArgumentBuffer(AnyArgumentBufferKind::MySql(
|
||||
Default::default(),
|
||||
std::marker::PhantomData,
|
||||
));
|
||||
|
||||
for value in args.values {
|
||||
let _ = value.encode_by_ref(&mut buf);
|
||||
}
|
||||
|
||||
if let AnyArgumentBufferKind::MySql(args, _) = buf.0 {
|
||||
args
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
impl<'q> From<AnyArguments<'q>> for crate::mssql::MssqlArguments {
|
||||
fn from(args: AnyArguments<'q>) -> Self {
|
||||
let mut buf = AnyArgumentBuffer(AnyArgumentBufferKind::Mssql(
|
||||
Default::default(),
|
||||
std::marker::PhantomData,
|
||||
));
|
||||
|
||||
for value in args.values {
|
||||
let _ = value.encode_by_ref(&mut buf);
|
||||
}
|
||||
|
||||
if let AnyArgumentBufferKind::Mssql(args, _) = buf.0 {
|
||||
args
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
impl<'q> From<AnyArguments<'q>> for crate::postgres::PgArguments {
|
||||
fn from(args: AnyArguments<'q>) -> Self {
|
||||
let mut buf = AnyArgumentBuffer(AnyArgumentBufferKind::Postgres(
|
||||
Default::default(),
|
||||
std::marker::PhantomData,
|
||||
));
|
||||
|
||||
for value in args.values {
|
||||
let _ = value.encode_by_ref(&mut buf);
|
||||
}
|
||||
|
||||
if let AnyArgumentBufferKind::Postgres(args, _) = buf.0 {
|
||||
args
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
40
sqlx-core/src/any/connection/establish.rs
Normal file
40
sqlx-core/src/any/connection/establish.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
use crate::any::connection::AnyConnectionKind;
|
||||
use crate::any::options::{AnyConnectOptions, AnyConnectOptionsKind};
|
||||
use crate::any::AnyConnection;
|
||||
use crate::connection::Connect;
|
||||
use crate::error::Error;
|
||||
|
||||
impl AnyConnection {
|
||||
pub(crate) async fn establish(options: &AnyConnectOptions) -> Result<Self, Error> {
|
||||
match &options.0 {
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyConnectOptionsKind::MySql(options) => {
|
||||
crate::mysql::MySqlConnection::connect_with(options)
|
||||
.await
|
||||
.map(AnyConnectionKind::MySql)
|
||||
}
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyConnectOptionsKind::Postgres(options) => {
|
||||
crate::postgres::PgConnection::connect_with(options)
|
||||
.await
|
||||
.map(AnyConnectionKind::Postgres)
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyConnectOptionsKind::Sqlite(options) => {
|
||||
crate::sqlite::SqliteConnection::connect_with(options)
|
||||
.await
|
||||
.map(AnyConnectionKind::Sqlite)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyConnectOptionsKind::Mssql(options) => {
|
||||
crate::mssql::MssqlConnection::connect_with(options)
|
||||
.await
|
||||
.map(AnyConnectionKind::Mssql)
|
||||
}
|
||||
}
|
||||
.map(AnyConnection)
|
||||
}
|
||||
}
|
221
sqlx-core/src/any/connection/executor.rs
Normal file
221
sqlx-core/src/any/connection/executor.rs
Normal file
|
@ -0,0 +1,221 @@
|
|||
use either::Either;
|
||||
use futures_core::future::BoxFuture;
|
||||
use futures_core::stream::BoxStream;
|
||||
use futures_util::{StreamExt, TryStreamExt};
|
||||
|
||||
use crate::any::connection::AnyConnectionKind;
|
||||
use crate::any::row::AnyRowKind;
|
||||
use crate::any::type_info::AnyTypeInfoKind;
|
||||
use crate::any::{Any, AnyConnection, AnyRow, AnyTypeInfo};
|
||||
use crate::describe::{Column, Describe};
|
||||
use crate::error::Error;
|
||||
use crate::executor::{Execute, Executor};
|
||||
|
||||
// FIXME: Some of the below, describe especially, is very messy/duplicated; perhaps we should have
|
||||
// an `Into` that goes from `PgTypeInfo` to `AnyTypeInfo` and so on
|
||||
|
||||
impl<'c> Executor<'c> for &'c mut AnyConnection {
|
||||
type Database = Any;
|
||||
|
||||
fn fetch_many<'e, 'q: 'e, E: 'q>(
|
||||
self,
|
||||
mut query: E,
|
||||
) -> BoxStream<'e, Result<Either<u64, AnyRow>, Error>>
|
||||
where
|
||||
'c: 'e,
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
let arguments = query.take_arguments();
|
||||
let query = query.query();
|
||||
|
||||
match &mut self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyConnectionKind::Postgres(conn) => conn
|
||||
.fetch_many((query, arguments.map(Into::into)))
|
||||
.map_ok(|v| match v {
|
||||
Either::Right(row) => Either::Right(AnyRow(AnyRowKind::Postgres(row))),
|
||||
Either::Left(count) => Either::Left(count),
|
||||
})
|
||||
.boxed(),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyConnectionKind::MySql(conn) => conn
|
||||
.fetch_many((query, arguments.map(Into::into)))
|
||||
.map_ok(|v| match v {
|
||||
Either::Right(row) => Either::Right(AnyRow(AnyRowKind::MySql(row))),
|
||||
Either::Left(count) => Either::Left(count),
|
||||
})
|
||||
.boxed(),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyConnectionKind::Sqlite(conn) => conn
|
||||
.fetch_many((query, arguments.map(Into::into)))
|
||||
.map_ok(|v| match v {
|
||||
Either::Right(row) => Either::Right(AnyRow(AnyRowKind::Sqlite(row))),
|
||||
Either::Left(count) => Either::Left(count),
|
||||
})
|
||||
.boxed(),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyConnectionKind::Mssql(conn) => conn
|
||||
.fetch_many((query, arguments.map(Into::into)))
|
||||
.map_ok(|v| match v {
|
||||
Either::Right(row) => Either::Right(AnyRow(AnyRowKind::Mssql(row))),
|
||||
Either::Left(count) => Either::Left(count),
|
||||
})
|
||||
.boxed(),
|
||||
}
|
||||
}
|
||||
|
||||
fn fetch_optional<'e, 'q: 'e, E: 'q>(
|
||||
self,
|
||||
mut query: E,
|
||||
) -> BoxFuture<'e, Result<Option<AnyRow>, Error>>
|
||||
where
|
||||
'c: 'e,
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
let arguments = query.take_arguments();
|
||||
let query = query.query();
|
||||
|
||||
Box::pin(async move {
|
||||
Ok(match &mut self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyConnectionKind::Postgres(conn) => conn
|
||||
.fetch_optional((query, arguments.map(Into::into)))
|
||||
.await?
|
||||
.map(AnyRowKind::Postgres),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyConnectionKind::MySql(conn) => conn
|
||||
.fetch_optional((query, arguments.map(Into::into)))
|
||||
.await?
|
||||
.map(AnyRowKind::MySql),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyConnectionKind::Sqlite(conn) => conn
|
||||
.fetch_optional((query, arguments.map(Into::into)))
|
||||
.await?
|
||||
.map(AnyRowKind::Sqlite),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyConnectionKind::Mssql(conn) => conn
|
||||
.fetch_optional((query, arguments.map(Into::into)))
|
||||
.await?
|
||||
.map(AnyRowKind::Mssql),
|
||||
}
|
||||
.map(AnyRow))
|
||||
})
|
||||
}
|
||||
|
||||
fn describe<'e, 'q: 'e, E: 'q>(
|
||||
self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, Result<Describe<Self::Database>, Error>>
|
||||
where
|
||||
'c: 'e,
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
let query = query.query();
|
||||
|
||||
Box::pin(async move {
|
||||
Ok(match &mut self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyConnectionKind::Postgres(conn) => {
|
||||
conn.describe(query).await.map(|desc| Describe {
|
||||
params: desc
|
||||
.params
|
||||
.into_iter()
|
||||
.map(|ty| ty.map(AnyTypeInfoKind::Postgres).map(AnyTypeInfo))
|
||||
.collect(),
|
||||
|
||||
columns: desc
|
||||
.columns
|
||||
.into_iter()
|
||||
.map(|column| Column {
|
||||
name: column.name,
|
||||
not_null: column.not_null,
|
||||
type_info: column
|
||||
.type_info
|
||||
.map(AnyTypeInfoKind::Postgres)
|
||||
.map(AnyTypeInfo),
|
||||
})
|
||||
.collect(),
|
||||
})?
|
||||
}
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyConnectionKind::MySql(conn) => {
|
||||
conn.describe(query).await.map(|desc| Describe {
|
||||
params: desc
|
||||
.params
|
||||
.into_iter()
|
||||
.map(|ty| ty.map(AnyTypeInfoKind::MySql).map(AnyTypeInfo))
|
||||
.collect(),
|
||||
|
||||
columns: desc
|
||||
.columns
|
||||
.into_iter()
|
||||
.map(|column| Column {
|
||||
name: column.name,
|
||||
not_null: column.not_null,
|
||||
type_info: column
|
||||
.type_info
|
||||
.map(AnyTypeInfoKind::MySql)
|
||||
.map(AnyTypeInfo),
|
||||
})
|
||||
.collect(),
|
||||
})?
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyConnectionKind::Sqlite(conn) => {
|
||||
conn.describe(query).await.map(|desc| Describe {
|
||||
params: desc
|
||||
.params
|
||||
.into_iter()
|
||||
.map(|ty| ty.map(AnyTypeInfoKind::Sqlite).map(AnyTypeInfo))
|
||||
.collect(),
|
||||
|
||||
columns: desc
|
||||
.columns
|
||||
.into_iter()
|
||||
.map(|column| Column {
|
||||
name: column.name,
|
||||
not_null: column.not_null,
|
||||
type_info: column
|
||||
.type_info
|
||||
.map(AnyTypeInfoKind::Sqlite)
|
||||
.map(AnyTypeInfo),
|
||||
})
|
||||
.collect(),
|
||||
})?
|
||||
}
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyConnectionKind::Mssql(conn) => {
|
||||
conn.describe(query).await.map(|desc| Describe {
|
||||
params: desc
|
||||
.params
|
||||
.into_iter()
|
||||
.map(|ty| ty.map(AnyTypeInfoKind::Mssql).map(AnyTypeInfo))
|
||||
.collect(),
|
||||
|
||||
columns: desc
|
||||
.columns
|
||||
.into_iter()
|
||||
.map(|column| Column {
|
||||
name: column.name,
|
||||
not_null: column.not_null,
|
||||
type_info: column
|
||||
.type_info
|
||||
.map(AnyTypeInfoKind::Mssql)
|
||||
.map(AnyTypeInfo),
|
||||
})
|
||||
.collect(),
|
||||
})?
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
170
sqlx-core/src/any/connection/mod.rs
Normal file
170
sqlx-core/src/any/connection/mod.rs
Normal file
|
@ -0,0 +1,170 @@
|
|||
use futures_core::future::BoxFuture;
|
||||
|
||||
use crate::any::{Any, AnyConnectOptions};
|
||||
use crate::connection::{Connect, Connection};
|
||||
use crate::error::Error;
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
use crate::postgres;
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
use crate::sqlite;
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
use crate::mssql;
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
use crate::mysql;
|
||||
|
||||
mod establish;
|
||||
mod executor;
|
||||
|
||||
/// A connection to _any_ SQLx database.
|
||||
///
|
||||
/// The database driver used is determined by the scheme
|
||||
/// of the connection url.
|
||||
///
|
||||
/// ```text
|
||||
/// postgres://postgres@localhost/test
|
||||
/// sqlite://a.sqlite
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct AnyConnection(pub(super) AnyConnectionKind);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum AnyConnectionKind {
|
||||
#[cfg(feature = "postgres")]
|
||||
Postgres(postgres::PgConnection),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
Mssql(mssql::MssqlConnection),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
MySql(mysql::MySqlConnection),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
Sqlite(sqlite::SqliteConnection),
|
||||
}
|
||||
|
||||
macro_rules! delegate_to {
|
||||
($self:ident.$method:ident($($arg:ident),*)) => {
|
||||
match &$self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyConnectionKind::Postgres(conn) => conn.$method($($arg),*),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyConnectionKind::MySql(conn) => conn.$method($($arg),*),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyConnectionKind::Sqlite(conn) => conn.$method($($arg),*),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyConnectionKind::Mssql(conn) => conn.$method($($arg),*),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! delegate_to_mut {
|
||||
($self:ident.$method:ident($($arg:ident),*)) => {
|
||||
match &mut $self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyConnectionKind::Postgres(conn) => conn.$method($($arg),*),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyConnectionKind::MySql(conn) => conn.$method($($arg),*),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyConnectionKind::Sqlite(conn) => conn.$method($($arg),*),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyConnectionKind::Mssql(conn) => conn.$method($($arg),*),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl Connection for AnyConnection {
|
||||
type Database = Any;
|
||||
|
||||
fn close(self) -> BoxFuture<'static, Result<(), Error>> {
|
||||
match self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyConnectionKind::Postgres(conn) => conn.close(),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyConnectionKind::MySql(conn) => conn.close(),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyConnectionKind::Sqlite(conn) => conn.close(),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyConnectionKind::Mssql(conn) => conn.close(),
|
||||
}
|
||||
}
|
||||
|
||||
fn ping(&mut self) -> BoxFuture<'_, Result<(), Error>> {
|
||||
delegate_to_mut!(self.ping())
|
||||
}
|
||||
|
||||
fn cached_statements_size(&self) -> usize {
|
||||
match &self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyConnectionKind::Postgres(conn) => conn.cached_statements_size(),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyConnectionKind::MySql(conn) => conn.cached_statements_size(),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyConnectionKind::Sqlite(conn) => conn.cached_statements_size(),
|
||||
|
||||
// no cache
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyConnectionKind::Mssql(_) => 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_cached_statements(&mut self) -> BoxFuture<'_, Result<(), Error>> {
|
||||
match &mut self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyConnectionKind::Postgres(conn) => conn.clear_cached_statements(),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyConnectionKind::MySql(conn) => conn.clear_cached_statements(),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyConnectionKind::Sqlite(conn) => conn.clear_cached_statements(),
|
||||
|
||||
// no cache
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyConnectionKind::Mssql(_) => Box::pin(futures_util::future::ok(())),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn flush(&mut self) -> BoxFuture<'_, Result<(), Error>> {
|
||||
delegate_to_mut!(self.flush())
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn should_flush(&self) -> bool {
|
||||
delegate_to!(self.should_flush())
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn get_ref(&self) -> &Self {
|
||||
self
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn get_mut(&mut self) -> &mut Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Connect for AnyConnection {
|
||||
type Options = AnyConnectOptions;
|
||||
|
||||
#[inline]
|
||||
fn connect_with(options: &Self::Options) -> BoxFuture<'_, Result<Self, Error>> {
|
||||
Box::pin(AnyConnection::establish(options))
|
||||
}
|
||||
}
|
39
sqlx-core/src/any/database.rs
Normal file
39
sqlx-core/src/any/database.rs
Normal file
|
@ -0,0 +1,39 @@
|
|||
use crate::any::{
|
||||
AnyArgumentBuffer, AnyArguments, AnyConnection, AnyRow, AnyTransactionManager, AnyTypeInfo,
|
||||
AnyValue, AnyValueRef,
|
||||
};
|
||||
use crate::database::{Database, HasArguments, HasStatementCache, HasValueRef};
|
||||
|
||||
/// Opaque database driver. Capable of being used in place of any SQLx database driver. The actual
|
||||
/// driver used will be selected at runtime, from the connection uri.
|
||||
#[derive(Debug)]
|
||||
pub struct Any;
|
||||
|
||||
impl Database for Any {
|
||||
type Connection = AnyConnection;
|
||||
|
||||
type TransactionManager = AnyTransactionManager;
|
||||
|
||||
type Row = AnyRow;
|
||||
|
||||
type TypeInfo = AnyTypeInfo;
|
||||
|
||||
type Value = AnyValue;
|
||||
}
|
||||
|
||||
impl<'r> HasValueRef<'r> for Any {
|
||||
type Database = Any;
|
||||
|
||||
type ValueRef = AnyValueRef<'r>;
|
||||
}
|
||||
|
||||
impl<'q> HasArguments<'q> for Any {
|
||||
type Database = Any;
|
||||
|
||||
type Arguments = AnyArguments<'q>;
|
||||
|
||||
type ArgumentBuffer = AnyArgumentBuffer<'q>;
|
||||
}
|
||||
|
||||
// This _may_ be true, depending on the selected database
|
||||
impl HasStatementCache for Any {}
|
356
sqlx-core/src/any/decode.rs
Normal file
356
sqlx-core/src/any/decode.rs
Normal file
|
@ -0,0 +1,356 @@
|
|||
use crate::any::value::AnyValueRefKind;
|
||||
use crate::any::{Any, AnyValueRef};
|
||||
use crate::decode::Decode;
|
||||
use crate::error::BoxDynError;
|
||||
use crate::types::Type;
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
use crate::postgres::Postgres;
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
use crate::mysql::MySql;
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
use crate::mssql::Mssql;
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
use crate::sqlite::Sqlite;
|
||||
|
||||
// Implements Decode for any T where T supports Decode for any database that has support currently
|
||||
// compiled into SQLx
|
||||
impl<'r, T> Decode<'r, Any> for T
|
||||
where
|
||||
T: AnyDecode<'r>,
|
||||
{
|
||||
fn decode(value: AnyValueRef<'r>) -> Result<Self, BoxDynError> {
|
||||
match value.0 {
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyValueRefKind::MySql(value) => <T as Decode<'r, crate::mysql::MySql>>::decode(value),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyValueRefKind::Sqlite(value) => {
|
||||
<T as Decode<'r, crate::sqlite::Sqlite>>::decode(value)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyValueRefKind::Mssql(value) => <T as Decode<'r, crate::mssql::Mssql>>::decode(value),
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyValueRefKind::Postgres(value) => {
|
||||
<T as Decode<'r, crate::postgres::Postgres>>::decode(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Find a nice way to auto-generate the below or petition Rust to add support for #[cfg]
|
||||
// to trait bounds
|
||||
|
||||
// all 4
|
||||
|
||||
#[cfg(all(
|
||||
feature = "postgres",
|
||||
feature = "mysql",
|
||||
feature = "mssql",
|
||||
feature = "sqlite"
|
||||
))]
|
||||
pub trait AnyDecode<'r>:
|
||||
Decode<'r, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Decode<'r, MySql>
|
||||
+ Type<MySql>
|
||||
+ Decode<'r, Mssql>
|
||||
+ Type<Mssql>
|
||||
+ Decode<'r, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
feature = "postgres",
|
||||
feature = "mysql",
|
||||
feature = "mssql",
|
||||
feature = "sqlite"
|
||||
))]
|
||||
impl<'r, T> AnyDecode<'r> for T where
|
||||
T: Decode<'r, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Decode<'r, MySql>
|
||||
+ Type<MySql>
|
||||
+ Decode<'r, Mssql>
|
||||
+ Type<Mssql>
|
||||
+ Decode<'r, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
// only 3 (4)
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "mssql"),
|
||||
all(feature = "postgres", feature = "mysql", feature = "sqlite")
|
||||
))]
|
||||
pub trait AnyDecode<'r>:
|
||||
Decode<'r, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Decode<'r, MySql>
|
||||
+ Type<MySql>
|
||||
+ Decode<'r, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "mssql"),
|
||||
all(feature = "postgres", feature = "mysql", feature = "sqlite")
|
||||
))]
|
||||
impl<'r, T> AnyDecode<'r> for T where
|
||||
T: Decode<'r, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Decode<'r, MySql>
|
||||
+ Type<MySql>
|
||||
+ Decode<'r, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "mysql"),
|
||||
all(feature = "postgres", feature = "mssql", feature = "sqlite")
|
||||
))]
|
||||
pub trait AnyDecode<'r>:
|
||||
Decode<'r, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Decode<'r, Mssql>
|
||||
+ Type<Mssql>
|
||||
+ Decode<'r, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "mysql"),
|
||||
all(feature = "postgres", feature = "mssql", feature = "sqlite")
|
||||
))]
|
||||
impl<'r, T> AnyDecode<'r> for T where
|
||||
T: Decode<'r, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Decode<'r, Mssql>
|
||||
+ Type<Mssql>
|
||||
+ Decode<'r, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "sqlite"),
|
||||
all(feature = "postgres", feature = "mysql", feature = "mssql")
|
||||
))]
|
||||
pub trait AnyDecode<'r>:
|
||||
Decode<'r, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Decode<'r, MySql>
|
||||
+ Type<MySql>
|
||||
+ Decode<'r, Mssql>
|
||||
+ Type<Mssql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "sqlite"),
|
||||
all(feature = "postgres", feature = "mysql", feature = "mssql")
|
||||
))]
|
||||
impl<'r, T> AnyDecode<'r> for T where
|
||||
T: Decode<'r, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Decode<'r, MySql>
|
||||
+ Type<MySql>
|
||||
+ Decode<'r, Mssql>
|
||||
+ Type<Mssql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "postgres"),
|
||||
all(feature = "sqlite", feature = "mysql", feature = "mssql")
|
||||
))]
|
||||
pub trait AnyDecode<'r>:
|
||||
Decode<'r, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
+ Decode<'r, MySql>
|
||||
+ Type<MySql>
|
||||
+ Decode<'r, Mssql>
|
||||
+ Type<Mssql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "postgres"),
|
||||
all(feature = "sqlite", feature = "mysql", feature = "mssql")
|
||||
))]
|
||||
impl<'r, T> AnyDecode<'r> for T where
|
||||
T: Decode<'r, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
+ Decode<'r, MySql>
|
||||
+ Type<MySql>
|
||||
+ Decode<'r, Mssql>
|
||||
+ Type<Mssql>
|
||||
{
|
||||
}
|
||||
|
||||
// only 2 (6)
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mssql", feature = "sqlite")),
|
||||
all(feature = "postgres", feature = "mysql")
|
||||
))]
|
||||
pub trait AnyDecode<'r>:
|
||||
Decode<'r, Postgres> + Type<Postgres> + Decode<'r, MySql> + Type<MySql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mssql", feature = "sqlite")),
|
||||
all(feature = "postgres", feature = "mysql")
|
||||
))]
|
||||
impl<'r, T> AnyDecode<'r> for T where
|
||||
T: Decode<'r, Postgres> + Type<Postgres> + Decode<'r, MySql> + Type<MySql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "sqlite")),
|
||||
all(feature = "postgres", feature = "mssql")
|
||||
))]
|
||||
pub trait AnyDecode<'r>:
|
||||
Decode<'r, Postgres> + Type<Postgres> + Decode<'r, Mssql> + Type<Mssql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "sqlite")),
|
||||
all(feature = "postgres", feature = "mssql")
|
||||
))]
|
||||
impl<'r, T> AnyDecode<'r> for T where
|
||||
T: Decode<'r, Postgres> + Type<Postgres> + Decode<'r, Mssql> + Type<Mssql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql")),
|
||||
all(feature = "postgres", feature = "sqlite")
|
||||
))]
|
||||
pub trait AnyDecode<'r>:
|
||||
Decode<'r, Postgres> + Type<Postgres> + Decode<'r, Sqlite> + Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql")),
|
||||
all(feature = "postgres", feature = "sqlite")
|
||||
))]
|
||||
impl<'r, T> AnyDecode<'r> for T where
|
||||
T: Decode<'r, Postgres> + Type<Postgres> + Decode<'r, Sqlite> + Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "sqlite")),
|
||||
all(feature = "mssql", feature = "mysql")
|
||||
))]
|
||||
pub trait AnyDecode<'r>: Decode<'r, Mssql> + Type<Mssql> + Decode<'r, MySql> + Type<MySql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "sqlite")),
|
||||
all(feature = "mssql", feature = "mysql")
|
||||
))]
|
||||
impl<'r, T> AnyDecode<'r> for T where
|
||||
T: Decode<'r, Mssql> + Type<Mssql> + Decode<'r, MySql> + Type<MySql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mysql")),
|
||||
all(feature = "mssql", feature = "sqlite")
|
||||
))]
|
||||
pub trait AnyDecode<'r>:
|
||||
Decode<'r, Mssql> + Type<Mssql> + Decode<'r, Sqlite> + Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mysql")),
|
||||
all(feature = "mssql", feature = "sqlite")
|
||||
))]
|
||||
impl<'r, T> AnyDecode<'r> for T where
|
||||
T: Decode<'r, Mssql> + Type<Mssql> + Decode<'r, Sqlite> + Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mssql")),
|
||||
all(feature = "mysql", feature = "sqlite")
|
||||
))]
|
||||
pub trait AnyDecode<'r>:
|
||||
Decode<'r, MySql> + Type<MySql> + Decode<'r, Sqlite> + Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mssql")),
|
||||
all(feature = "mysql", feature = "sqlite")
|
||||
))]
|
||||
impl<'r, T> AnyDecode<'r> for T where
|
||||
T: Decode<'r, MySql> + Type<MySql> + Decode<'r, Sqlite> + Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
// only 1 (4)
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql", feature = "sqlite")),
|
||||
feature = "postgres"
|
||||
))]
|
||||
pub trait AnyDecode<'r>: Decode<'r, Postgres> + Type<Postgres> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql", feature = "sqlite")),
|
||||
feature = "postgres"
|
||||
))]
|
||||
impl<'r, T> AnyDecode<'r> for T where T: Decode<'r, Postgres> + Type<Postgres> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mssql", feature = "sqlite")),
|
||||
feature = "mysql"
|
||||
))]
|
||||
pub trait AnyDecode<'r>: Decode<'r, MySql> + Type<MySql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mssql", feature = "sqlite")),
|
||||
feature = "mysql"
|
||||
))]
|
||||
impl<'r, T> AnyDecode<'r> for T where T: Decode<'r, MySql> + Type<MySql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "postgres", feature = "sqlite")),
|
||||
feature = "mssql"
|
||||
))]
|
||||
pub trait AnyDecode<'r>: Decode<'r, Mssql> + Type<Mssql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "postgres", feature = "sqlite")),
|
||||
feature = "mssql"
|
||||
))]
|
||||
impl<'r, T> AnyDecode<'r> for T where T: Decode<'r, Mssql> + Type<Mssql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql", feature = "postgres")),
|
||||
feature = "sqlite"
|
||||
))]
|
||||
pub trait AnyDecode<'r>: Decode<'r, Sqlite> + Type<Sqlite> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql", feature = "postgres")),
|
||||
feature = "sqlite"
|
||||
))]
|
||||
impl<'r, T> AnyDecode<'r> for T where T: Decode<'r, Sqlite> + Type<Sqlite> {}
|
354
sqlx-core/src/any/encode.rs
Normal file
354
sqlx-core/src/any/encode.rs
Normal file
|
@ -0,0 +1,354 @@
|
|||
use crate::any::arguments::AnyArgumentBufferKind;
|
||||
use crate::any::{Any, AnyArgumentBuffer};
|
||||
use crate::encode::{Encode, IsNull};
|
||||
use crate::types::Type;
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
use crate::postgres::Postgres;
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
use crate::mysql::MySql;
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
use crate::mssql::Mssql;
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
use crate::sqlite::Sqlite;
|
||||
|
||||
// Implements Encode for any T where T supports Encode for any database that has support currently
|
||||
// compiled into SQLx
|
||||
impl<'q, T> Encode<'q, Any> for T
|
||||
where
|
||||
T: AnyEncode<'q>,
|
||||
{
|
||||
fn encode_by_ref(&self, buf: &mut AnyArgumentBuffer<'q>) -> IsNull {
|
||||
match &mut buf.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyArgumentBufferKind::Postgres(args, _) => args.add(self),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyArgumentBufferKind::MySql(args, _) => args.add(self),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyArgumentBufferKind::Mssql(args, _) => args.add(self),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyArgumentBufferKind::Sqlite(args) => args.add(self),
|
||||
}
|
||||
|
||||
// unused
|
||||
IsNull::No
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Find a nice way to auto-generate the below or petition Rust to add support for #[cfg]
|
||||
// to trait bounds
|
||||
|
||||
// all 4
|
||||
|
||||
#[cfg(all(
|
||||
feature = "postgres",
|
||||
feature = "mysql",
|
||||
feature = "mssql",
|
||||
feature = "sqlite"
|
||||
))]
|
||||
pub trait AnyEncode<'q>:
|
||||
Encode<'q, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Encode<'q, MySql>
|
||||
+ Type<MySql>
|
||||
+ Encode<'q, Mssql>
|
||||
+ Type<Mssql>
|
||||
+ Encode<'q, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
feature = "postgres",
|
||||
feature = "mysql",
|
||||
feature = "mssql",
|
||||
feature = "sqlite"
|
||||
))]
|
||||
impl<'q, T> AnyEncode<'q> for T where
|
||||
T: Encode<'q, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Encode<'q, MySql>
|
||||
+ Type<MySql>
|
||||
+ Encode<'q, Mssql>
|
||||
+ Type<Mssql>
|
||||
+ Encode<'q, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
// only 3 (4)
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "mssql"),
|
||||
all(feature = "postgres", feature = "mysql", feature = "sqlite")
|
||||
))]
|
||||
pub trait AnyEncode<'q>:
|
||||
Encode<'q, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Encode<'q, MySql>
|
||||
+ Type<MySql>
|
||||
+ Encode<'q, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "mssql"),
|
||||
all(feature = "postgres", feature = "mysql", feature = "sqlite")
|
||||
))]
|
||||
impl<'q, T> AnyEncode<'q> for T where
|
||||
T: Encode<'q, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Encode<'q, MySql>
|
||||
+ Type<MySql>
|
||||
+ Encode<'q, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "mysql"),
|
||||
all(feature = "postgres", feature = "mssql", feature = "sqlite")
|
||||
))]
|
||||
pub trait AnyEncode<'q>:
|
||||
Encode<'q, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Encode<'q, Mssql>
|
||||
+ Type<Mssql>
|
||||
+ Encode<'q, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "mysql"),
|
||||
all(feature = "postgres", feature = "mssql", feature = "sqlite")
|
||||
))]
|
||||
impl<'q, T> AnyEncode<'q> for T where
|
||||
T: Encode<'q, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Encode<'q, Mssql>
|
||||
+ Type<Mssql>
|
||||
+ Encode<'q, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "sqlite"),
|
||||
all(feature = "postgres", feature = "mysql", feature = "mssql")
|
||||
))]
|
||||
pub trait AnyEncode<'q>:
|
||||
Encode<'q, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Encode<'q, MySql>
|
||||
+ Type<MySql>
|
||||
+ Encode<'q, Mssql>
|
||||
+ Type<Mssql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "sqlite"),
|
||||
all(feature = "postgres", feature = "mysql", feature = "mssql")
|
||||
))]
|
||||
impl<'q, T> AnyEncode<'q> for T where
|
||||
T: Encode<'q, Postgres>
|
||||
+ Type<Postgres>
|
||||
+ Encode<'q, MySql>
|
||||
+ Type<MySql>
|
||||
+ Encode<'q, Mssql>
|
||||
+ Type<Mssql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "postgres"),
|
||||
all(feature = "sqlite", feature = "mysql", feature = "mssql")
|
||||
))]
|
||||
pub trait AnyEncode<'q>:
|
||||
Encode<'q, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
+ Encode<'q, MySql>
|
||||
+ Type<MySql>
|
||||
+ Encode<'q, Mssql>
|
||||
+ Type<Mssql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "postgres"),
|
||||
all(feature = "sqlite", feature = "mysql", feature = "mssql")
|
||||
))]
|
||||
impl<'q, T> AnyEncode<'q> for T where
|
||||
T: Encode<'q, Sqlite>
|
||||
+ Type<Sqlite>
|
||||
+ Encode<'q, MySql>
|
||||
+ Type<MySql>
|
||||
+ Encode<'q, Mssql>
|
||||
+ Type<Mssql>
|
||||
{
|
||||
}
|
||||
|
||||
// only 2 (6)
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mssql", feature = "sqlite")),
|
||||
all(feature = "postgres", feature = "mysql")
|
||||
))]
|
||||
pub trait AnyEncode<'q>:
|
||||
Encode<'q, Postgres> + Type<Postgres> + Encode<'q, MySql> + Type<MySql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mssql", feature = "sqlite")),
|
||||
all(feature = "postgres", feature = "mysql")
|
||||
))]
|
||||
impl<'q, T> AnyEncode<'q> for T where
|
||||
T: Encode<'q, Postgres> + Type<Postgres> + Encode<'q, MySql> + Type<MySql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "sqlite")),
|
||||
all(feature = "postgres", feature = "mssql")
|
||||
))]
|
||||
pub trait AnyEncode<'q>:
|
||||
Encode<'q, Postgres> + Type<Postgres> + Encode<'q, Mssql> + Type<Mssql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "sqlite")),
|
||||
all(feature = "postgres", feature = "mssql")
|
||||
))]
|
||||
impl<'q, T> AnyEncode<'q> for T where
|
||||
T: Encode<'q, Postgres> + Type<Postgres> + Encode<'q, Mssql> + Type<Mssql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql")),
|
||||
all(feature = "postgres", feature = "sqlite")
|
||||
))]
|
||||
pub trait AnyEncode<'q>:
|
||||
Encode<'q, Postgres> + Type<Postgres> + Encode<'q, Sqlite> + Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql")),
|
||||
all(feature = "postgres", feature = "sqlite")
|
||||
))]
|
||||
impl<'q, T> AnyEncode<'q> for T where
|
||||
T: Encode<'q, Postgres> + Type<Postgres> + Encode<'q, Sqlite> + Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "sqlite")),
|
||||
all(feature = "mssql", feature = "mysql")
|
||||
))]
|
||||
pub trait AnyEncode<'q>: Encode<'q, Mssql> + Type<Mssql> + Encode<'q, MySql> + Type<MySql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "sqlite")),
|
||||
all(feature = "mssql", feature = "mysql")
|
||||
))]
|
||||
impl<'q, T> AnyEncode<'q> for T where
|
||||
T: Encode<'q, Mssql> + Type<Mssql> + Encode<'q, MySql> + Type<MySql>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mysql")),
|
||||
all(feature = "mssql", feature = "sqlite")
|
||||
))]
|
||||
pub trait AnyEncode<'q>:
|
||||
Encode<'q, Mssql> + Type<Mssql> + Encode<'q, Sqlite> + Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mysql")),
|
||||
all(feature = "mssql", feature = "sqlite")
|
||||
))]
|
||||
impl<'q, T> AnyEncode<'q> for T where
|
||||
T: Encode<'q, Mssql> + Type<Mssql> + Encode<'q, Sqlite> + Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mssql")),
|
||||
all(feature = "mysql", feature = "sqlite")
|
||||
))]
|
||||
pub trait AnyEncode<'q>:
|
||||
Encode<'q, MySql> + Type<MySql> + Encode<'q, Sqlite> + Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mssql")),
|
||||
all(feature = "mysql", feature = "sqlite")
|
||||
))]
|
||||
impl<'q, T> AnyEncode<'q> for T where
|
||||
T: Encode<'q, MySql> + Type<MySql> + Encode<'q, Sqlite> + Type<Sqlite>
|
||||
{
|
||||
}
|
||||
|
||||
// only 1 (4)
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql", feature = "sqlite")),
|
||||
feature = "postgres"
|
||||
))]
|
||||
pub trait AnyEncode<'q>: Encode<'q, Postgres> + Type<Postgres> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql", feature = "sqlite")),
|
||||
feature = "postgres"
|
||||
))]
|
||||
impl<'q, T> AnyEncode<'q> for T where T: Encode<'q, Postgres> + Type<Postgres> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mssql", feature = "sqlite")),
|
||||
feature = "mysql"
|
||||
))]
|
||||
pub trait AnyEncode<'q>: Encode<'q, MySql> + Type<MySql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mssql", feature = "sqlite")),
|
||||
feature = "mysql"
|
||||
))]
|
||||
impl<'q, T> AnyEncode<'q> for T where T: Encode<'q, MySql> + Type<MySql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "postgres", feature = "sqlite")),
|
||||
feature = "mssql"
|
||||
))]
|
||||
pub trait AnyEncode<'q>: Encode<'q, Mssql> + Type<Mssql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "postgres", feature = "sqlite")),
|
||||
feature = "mssql"
|
||||
))]
|
||||
impl<'q, T> AnyEncode<'q> for T where T: Encode<'q, Mssql> + Type<Mssql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql", feature = "postgres")),
|
||||
feature = "sqlite"
|
||||
))]
|
||||
pub trait AnyEncode<'q>: Encode<'q, Sqlite> + Type<Sqlite> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql", feature = "postgres")),
|
||||
feature = "sqlite"
|
||||
))]
|
||||
impl<'q, T> AnyEncode<'q> for T where T: Encode<'q, Sqlite> + Type<Sqlite> {}
|
29
sqlx-core/src/any/mod.rs
Normal file
29
sqlx-core/src/any/mod.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
mod arguments;
|
||||
mod connection;
|
||||
mod database;
|
||||
mod decode;
|
||||
mod encode;
|
||||
mod options;
|
||||
mod row;
|
||||
mod transaction;
|
||||
mod type_info;
|
||||
mod types;
|
||||
mod value;
|
||||
|
||||
pub use arguments::{AnyArgumentBuffer, AnyArguments};
|
||||
pub use connection::AnyConnection;
|
||||
pub use database::Any;
|
||||
pub use decode::AnyDecode;
|
||||
pub use encode::AnyEncode;
|
||||
pub use options::AnyConnectOptions;
|
||||
pub use row::AnyRow;
|
||||
pub use transaction::AnyTransactionManager;
|
||||
pub use type_info::AnyTypeInfo;
|
||||
pub use value::{AnyValue, AnyValueRef};
|
||||
|
||||
pub type AnyPool = crate::pool::Pool<Any>;
|
||||
|
||||
// NOTE: required due to the lack of lazy normalization
|
||||
impl_into_arguments_for_arguments!(AnyArguments<'q>);
|
||||
impl_executor_for_pool_connection!(Any, AnyConnection, AnyRow);
|
||||
impl_executor_for_transaction!(Any, AnyRow);
|
88
sqlx-core/src/any/options.rs
Normal file
88
sqlx-core/src/any/options.rs
Normal file
|
@ -0,0 +1,88 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use crate::error::BoxDynError;
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
use crate::postgres::PgConnectOptions;
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
use crate::mysql::MySqlConnectOptions;
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
use crate::sqlite::SqliteConnectOptions;
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
use crate::mssql::MssqlConnectOptions;
|
||||
|
||||
/// Opaque options for connecting to a database. These may only be constructed by parsing from
|
||||
/// a connection uri.
|
||||
///
|
||||
/// ```text
|
||||
/// postgres://postgres:password@localhost/database
|
||||
/// mysql://root:password@localhost/database
|
||||
/// ```
|
||||
pub struct AnyConnectOptions(pub(crate) AnyConnectOptionsKind);
|
||||
|
||||
pub(crate) enum AnyConnectOptionsKind {
|
||||
#[cfg(feature = "postgres")]
|
||||
Postgres(PgConnectOptions),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
MySql(MySqlConnectOptions),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
Sqlite(SqliteConnectOptions),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
Mssql(MssqlConnectOptions),
|
||||
}
|
||||
|
||||
impl FromStr for AnyConnectOptions {
|
||||
type Err = BoxDynError;
|
||||
|
||||
fn from_str(url: &str) -> Result<Self, Self::Err> {
|
||||
match url {
|
||||
#[cfg(feature = "postgres")]
|
||||
_ if url.starts_with("postgres:") || url.starts_with("postgresql:") => {
|
||||
PgConnectOptions::from_str(url).map(AnyConnectOptionsKind::Postgres)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "postgres"))]
|
||||
_ if url.starts_with("postgres:") || url.starts_with("postgresql:") => {
|
||||
Err("database URL has the scheme of a PostgreSQL database but the `postgres` feature is not enabled".into())
|
||||
}
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
_ if url.starts_with("mysql:") || url.starts_with("mariadb:") => {
|
||||
MySqlConnectOptions::from_str(url).map(AnyConnectOptionsKind::MySql)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mysql"))]
|
||||
_ if url.starts_with("mysql:") || url.starts_with("mariadb:") => {
|
||||
Err("database URL has the scheme of a MySQL database but the `mysql` feature is not enabled".into())
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
_ if url.starts_with("sqlite:") => {
|
||||
SqliteConnectOptions::from_str(url).map(AnyConnectOptionsKind::Sqlite)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "sqlite"))]
|
||||
_ if url.starts_with("sqlite:") => {
|
||||
Err("database URL has the scheme of a SQLite database but the `sqlite` feature is not enabled".into())
|
||||
}
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
_ if url.starts_with("mssql:") || url.starts_with("sqlserver:") => {
|
||||
MssqlConnectOptions::from_str(url).map(AnyConnectOptionsKind::Mssql)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mssql"))]
|
||||
_ if url.starts_with("mssql:") || url.starts_with("sqlserver:") => {
|
||||
Err("database URL has the scheme of a MSSQL database but the `mssql` feature is not enabled".into())
|
||||
}
|
||||
|
||||
_ => Err(format!("unrecognized database url: {:?}", url).into())
|
||||
}.map(AnyConnectOptions)
|
||||
}
|
||||
}
|
80
sqlx-core/src/any/row.rs
Normal file
80
sqlx-core/src/any/row.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
use crate::any::value::AnyValueRefKind;
|
||||
use crate::any::{Any, AnyValueRef};
|
||||
use crate::database::HasValueRef;
|
||||
use crate::error::Error;
|
||||
use crate::row::{ColumnIndex, Row};
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
use crate::postgres::PgRow;
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
use crate::mysql::MySqlRow;
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
use crate::sqlite::SqliteRow;
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
use crate::mssql::MssqlRow;
|
||||
|
||||
pub struct AnyRow(pub(crate) AnyRowKind);
|
||||
|
||||
impl crate::row::private_row::Sealed for AnyRow {}
|
||||
|
||||
pub(crate) enum AnyRowKind {
|
||||
#[cfg(feature = "postgres")]
|
||||
Postgres(PgRow),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
MySql(MySqlRow),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
Sqlite(SqliteRow),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
Mssql(MssqlRow),
|
||||
}
|
||||
|
||||
impl Row for AnyRow {
|
||||
type Database = Any;
|
||||
|
||||
fn len(&self) -> usize {
|
||||
match &self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyRowKind::Postgres(row) => row.len(),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyRowKind::MySql(row) => row.len(),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyRowKind::Sqlite(row) => row.len(),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyRowKind::Mssql(row) => row.len(),
|
||||
}
|
||||
}
|
||||
|
||||
fn try_get_raw<I>(
|
||||
&self,
|
||||
index: I,
|
||||
) -> Result<<Self::Database as HasValueRef<'_>>::ValueRef, Error>
|
||||
where
|
||||
I: ColumnIndex<Self>,
|
||||
{
|
||||
let index = index.index(self)?;
|
||||
|
||||
match &self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyRowKind::Postgres(row) => row.try_get_raw(index).map(AnyValueRefKind::Postgres),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyRowKind::MySql(row) => row.try_get_raw(index).map(AnyValueRefKind::MySql),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyRowKind::Sqlite(row) => row.try_get_raw(index).map(AnyValueRefKind::Sqlite),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyRowKind::Mssql(row) => row.try_get_raw(index).map(AnyValueRefKind::Mssql),
|
||||
}
|
||||
.map(AnyValueRef)
|
||||
}
|
||||
}
|
111
sqlx-core/src/any/transaction.rs
Normal file
111
sqlx-core/src/any/transaction.rs
Normal file
|
@ -0,0 +1,111 @@
|
|||
use futures_util::future::BoxFuture;
|
||||
|
||||
use crate::any::connection::AnyConnectionKind;
|
||||
use crate::any::{Any, AnyConnection};
|
||||
use crate::database::Database;
|
||||
use crate::error::Error;
|
||||
use crate::transaction::TransactionManager;
|
||||
|
||||
pub struct AnyTransactionManager;
|
||||
|
||||
impl TransactionManager for AnyTransactionManager {
|
||||
type Database = Any;
|
||||
|
||||
fn begin(conn: &mut AnyConnection, depth: usize) -> BoxFuture<'_, Result<(), Error>> {
|
||||
match &mut conn.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyConnectionKind::Postgres(conn) => {
|
||||
<crate::postgres::Postgres as Database>::TransactionManager::begin(conn, depth)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyConnectionKind::MySql(conn) => {
|
||||
<crate::mysql::MySql as Database>::TransactionManager::begin(conn, depth)
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyConnectionKind::Sqlite(conn) => {
|
||||
<crate::sqlite::Sqlite as Database>::TransactionManager::begin(conn, depth)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyConnectionKind::Mssql(conn) => {
|
||||
<crate::mssql::Mssql as Database>::TransactionManager::begin(conn, depth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn commit(conn: &mut AnyConnection, depth: usize) -> BoxFuture<'_, Result<(), Error>> {
|
||||
match &mut conn.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyConnectionKind::Postgres(conn) => {
|
||||
<crate::postgres::Postgres as Database>::TransactionManager::commit(conn, depth)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyConnectionKind::MySql(conn) => {
|
||||
<crate::mysql::MySql as Database>::TransactionManager::commit(conn, depth)
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyConnectionKind::Sqlite(conn) => {
|
||||
<crate::sqlite::Sqlite as Database>::TransactionManager::commit(conn, depth)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyConnectionKind::Mssql(conn) => {
|
||||
<crate::mssql::Mssql as Database>::TransactionManager::commit(conn, depth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn rollback(conn: &mut AnyConnection, depth: usize) -> BoxFuture<'_, Result<(), Error>> {
|
||||
match &mut conn.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyConnectionKind::Postgres(conn) => {
|
||||
<crate::postgres::Postgres as Database>::TransactionManager::rollback(conn, depth)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyConnectionKind::MySql(conn) => {
|
||||
<crate::mysql::MySql as Database>::TransactionManager::rollback(conn, depth)
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyConnectionKind::Sqlite(conn) => {
|
||||
<crate::sqlite::Sqlite as Database>::TransactionManager::rollback(conn, depth)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyConnectionKind::Mssql(conn) => {
|
||||
<crate::mssql::Mssql as Database>::TransactionManager::rollback(conn, depth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn start_rollback(conn: &mut AnyConnection, depth: usize) {
|
||||
match &mut conn.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyConnectionKind::Postgres(conn) => {
|
||||
<crate::postgres::Postgres as Database>::TransactionManager::start_rollback(
|
||||
conn, depth,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyConnectionKind::MySql(conn) => {
|
||||
<crate::mysql::MySql as Database>::TransactionManager::start_rollback(conn, depth)
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyConnectionKind::Sqlite(conn) => {
|
||||
<crate::sqlite::Sqlite as Database>::TransactionManager::start_rollback(conn, depth)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyConnectionKind::Mssql(conn) => {
|
||||
<crate::mssql::Mssql as Database>::TransactionManager::start_rollback(conn, depth)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
69
sqlx-core/src/any/type_info.rs
Normal file
69
sqlx-core/src/any/type_info.rs
Normal file
|
@ -0,0 +1,69 @@
|
|||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
use crate::type_info::TypeInfo;
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
use crate::postgres::PgTypeInfo;
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
use crate::mysql::MySqlTypeInfo;
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
use crate::sqlite::SqliteTypeInfo;
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
use crate::mssql::MssqlTypeInfo;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct AnyTypeInfo(pub(crate) AnyTypeInfoKind);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub(crate) enum AnyTypeInfoKind {
|
||||
#[cfg(feature = "postgres")]
|
||||
Postgres(PgTypeInfo),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
MySql(MySqlTypeInfo),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
Sqlite(SqliteTypeInfo),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
Mssql(MssqlTypeInfo),
|
||||
}
|
||||
|
||||
impl TypeInfo for AnyTypeInfo {
|
||||
fn name(&self) -> &str {
|
||||
match &self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyTypeInfoKind::Postgres(ty) => ty.name(),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyTypeInfoKind::MySql(ty) => ty.name(),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyTypeInfoKind::Sqlite(ty) => ty.name(),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyTypeInfoKind::Mssql(ty) => ty.name(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for AnyTypeInfo {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match &self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyTypeInfoKind::Postgres(ty) => ty.fmt(f),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyTypeInfoKind::MySql(ty) => ty.fmt(f),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyTypeInfoKind::Sqlite(ty) => ty.fmt(f),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyTypeInfoKind::Mssql(ty) => ty.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
243
sqlx-core/src/any/types.rs
Normal file
243
sqlx-core/src/any/types.rs
Normal file
|
@ -0,0 +1,243 @@
|
|||
use crate::any::type_info::AnyTypeInfoKind;
|
||||
use crate::any::{Any, AnyTypeInfo};
|
||||
use crate::database::Database;
|
||||
use crate::types::Type;
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
use crate::postgres::Postgres;
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
use crate::mysql::MySql;
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
use crate::mssql::Mssql;
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
use crate::sqlite::Sqlite;
|
||||
|
||||
// Type is required by the bounds of the [Row] and [Arguments] trait but its been overridden in
|
||||
// AnyRow and AnyArguments to not use this implementation; but instead, delegate to the
|
||||
// database-specific implementation.
|
||||
//
|
||||
// The other use of this trait is for compile-time verification which is not feasible to support
|
||||
// for the [Any] driver.
|
||||
impl<T> Type<Any> for T
|
||||
where
|
||||
T: AnyType,
|
||||
{
|
||||
fn type_info() -> <Any as Database>::TypeInfo {
|
||||
// FIXME: nicer panic explaining why this isn't possible
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn compatible(ty: &AnyTypeInfo) -> bool {
|
||||
match &ty.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyTypeInfoKind::Postgres(ty) => <T as Type<Postgres>>::compatible(&ty),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyTypeInfoKind::MySql(ty) => <T as Type<MySql>>::compatible(&ty),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyTypeInfoKind::Sqlite(ty) => <T as Type<Sqlite>>::compatible(&ty),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyTypeInfoKind::Mssql(ty) => <T as Type<Mssql>>::compatible(&ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Find a nice way to auto-generate the below or petition Rust to add support for #[cfg]
|
||||
// to trait bounds
|
||||
|
||||
// all 4
|
||||
|
||||
#[cfg(all(
|
||||
feature = "postgres",
|
||||
feature = "mysql",
|
||||
feature = "mssql",
|
||||
feature = "sqlite"
|
||||
))]
|
||||
pub trait AnyType: Type<Postgres> + Type<MySql> + Type<Mssql> + Type<Sqlite> {}
|
||||
|
||||
#[cfg(all(
|
||||
feature = "postgres",
|
||||
feature = "mysql",
|
||||
feature = "mssql",
|
||||
feature = "sqlite"
|
||||
))]
|
||||
impl<T> AnyType for T where T: Type<Postgres> + Type<MySql> + Type<Mssql> + Type<Sqlite> {}
|
||||
|
||||
// only 3 (4)
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "mssql"),
|
||||
all(feature = "postgres", feature = "mysql", feature = "sqlite")
|
||||
))]
|
||||
pub trait AnyType: Type<Postgres> + Type<MySql> + Type<Sqlite> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "mssql"),
|
||||
all(feature = "postgres", feature = "mysql", feature = "sqlite")
|
||||
))]
|
||||
impl<T> AnyType for T where T: Type<Postgres> + Type<MySql> + Type<Sqlite> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "mysql"),
|
||||
all(feature = "postgres", feature = "mssql", feature = "sqlite")
|
||||
))]
|
||||
pub trait AnyType: Type<Postgres> + Type<Mssql> + Type<Sqlite> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "mysql"),
|
||||
all(feature = "postgres", feature = "mssql", feature = "sqlite")
|
||||
))]
|
||||
impl<T> AnyType for T where T: Type<Postgres> + Type<Mssql> + Type<Sqlite> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "sqlite"),
|
||||
all(feature = "postgres", feature = "mysql", feature = "mssql")
|
||||
))]
|
||||
pub trait AnyType: Type<Postgres> + Type<MySql> + Type<Mssql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "sqlite"),
|
||||
all(feature = "postgres", feature = "mysql", feature = "mssql")
|
||||
))]
|
||||
impl<T> AnyType for T where T: Type<Postgres> + Type<MySql> + Type<Mssql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "postgres"),
|
||||
all(feature = "sqlite", feature = "mysql", feature = "mssql")
|
||||
))]
|
||||
pub trait AnyType: Type<Sqlite> + Type<MySql> + Type<Mssql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "postgres"),
|
||||
all(feature = "sqlite", feature = "mysql", feature = "mssql")
|
||||
))]
|
||||
impl<T> AnyType for T where T: Type<Sqlite> + Type<MySql> + Type<Mssql> {}
|
||||
|
||||
// only 2 (6)
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mssql", feature = "sqlite")),
|
||||
all(feature = "postgres", feature = "mysql")
|
||||
))]
|
||||
pub trait AnyType: Type<Postgres> + Type<MySql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mssql", feature = "sqlite")),
|
||||
all(feature = "postgres", feature = "mysql")
|
||||
))]
|
||||
impl<T> AnyType for T where T: Type<Postgres> + Type<MySql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "sqlite")),
|
||||
all(feature = "postgres", feature = "mssql")
|
||||
))]
|
||||
pub trait AnyType: Type<Postgres> + Type<Mssql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "sqlite")),
|
||||
all(feature = "postgres", feature = "mssql")
|
||||
))]
|
||||
impl<T> AnyType for T where T: Type<Postgres> + Type<Mssql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql")),
|
||||
all(feature = "postgres", feature = "sqlite")
|
||||
))]
|
||||
pub trait AnyType: Type<Postgres> + Type<Sqlite> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql")),
|
||||
all(feature = "postgres", feature = "sqlite")
|
||||
))]
|
||||
impl<T> AnyType for T where T: Type<Postgres> + Type<Sqlite> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "sqlite")),
|
||||
all(feature = "mssql", feature = "mysql")
|
||||
))]
|
||||
pub trait AnyType: Type<Mssql> + Type<MySql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "sqlite")),
|
||||
all(feature = "mssql", feature = "mysql")
|
||||
))]
|
||||
impl<T> AnyType for T where T: Type<Mssql> + Type<MySql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mysql")),
|
||||
all(feature = "mssql", feature = "sqlite")
|
||||
))]
|
||||
pub trait AnyType: Type<Mssql> + Type<Sqlite> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mysql")),
|
||||
all(feature = "mssql", feature = "sqlite")
|
||||
))]
|
||||
impl<T> AnyType for T where T: Type<Mssql> + Type<Sqlite> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mssql")),
|
||||
all(feature = "mysql", feature = "sqlite")
|
||||
))]
|
||||
pub trait AnyType: Type<MySql> + Type<Sqlite> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mssql")),
|
||||
all(feature = "mysql", feature = "sqlite")
|
||||
))]
|
||||
impl<T> AnyType for T where T: Type<MySql> + Type<Sqlite> {}
|
||||
|
||||
// only 1 (4)
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql", feature = "sqlite")),
|
||||
feature = "postgres"
|
||||
))]
|
||||
pub trait AnyType: Type<Postgres> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql", feature = "sqlite")),
|
||||
feature = "postgres"
|
||||
))]
|
||||
impl<T> AnyType for T where T: Type<Postgres> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mssql", feature = "sqlite")),
|
||||
feature = "mysql"
|
||||
))]
|
||||
pub trait AnyType: Type<MySql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "postgres", feature = "mssql", feature = "sqlite")),
|
||||
feature = "mysql"
|
||||
))]
|
||||
impl<T> AnyType for T where T: Type<MySql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "postgres", feature = "sqlite")),
|
||||
feature = "mssql"
|
||||
))]
|
||||
pub trait AnyType: Type<Mssql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "postgres", feature = "sqlite")),
|
||||
feature = "mssql"
|
||||
))]
|
||||
impl<T> AnyType for T where T: Type<Mssql> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql", feature = "postgres")),
|
||||
feature = "sqlite"
|
||||
))]
|
||||
pub trait AnyType: Type<Sqlite> {}
|
||||
|
||||
#[cfg(all(
|
||||
not(any(feature = "mysql", feature = "mssql", feature = "postgres")),
|
||||
feature = "sqlite"
|
||||
))]
|
||||
impl<T> AnyType for T where T: Type<Sqlite> {}
|
174
sqlx-core/src/any/value.rs
Normal file
174
sqlx-core/src/any/value.rs
Normal file
|
@ -0,0 +1,174 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use crate::any::type_info::AnyTypeInfoKind;
|
||||
use crate::any::{Any, AnyTypeInfo};
|
||||
use crate::database::HasValueRef;
|
||||
use crate::value::{Value, ValueRef};
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
use crate::postgres::{PgValue, PgValueRef};
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
use crate::mysql::{MySqlValue, MySqlValueRef};
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
use crate::sqlite::{SqliteValue, SqliteValueRef};
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
use crate::mssql::{MssqlValue, MssqlValueRef};
|
||||
|
||||
pub struct AnyValue(AnyValueKind);
|
||||
|
||||
pub(crate) enum AnyValueKind {
|
||||
#[cfg(feature = "postgres")]
|
||||
Postgres(PgValue),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
MySql(MySqlValue),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
Sqlite(SqliteValue),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
Mssql(MssqlValue),
|
||||
}
|
||||
|
||||
pub struct AnyValueRef<'r>(pub(crate) AnyValueRefKind<'r>);
|
||||
|
||||
pub(crate) enum AnyValueRefKind<'r> {
|
||||
#[cfg(feature = "postgres")]
|
||||
Postgres(PgValueRef<'r>),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
MySql(MySqlValueRef<'r>),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
Sqlite(SqliteValueRef<'r>),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
Mssql(MssqlValueRef<'r>),
|
||||
}
|
||||
|
||||
impl Value for AnyValue {
|
||||
type Database = Any;
|
||||
|
||||
fn as_ref(&self) -> <Self::Database as HasValueRef<'_>>::ValueRef {
|
||||
AnyValueRef(match &self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyValueKind::Postgres(value) => AnyValueRefKind::Postgres(value.as_ref()),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyValueKind::MySql(value) => AnyValueRefKind::MySql(value.as_ref()),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyValueKind::Sqlite(value) => AnyValueRefKind::Sqlite(value.as_ref()),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyValueKind::Mssql(value) => AnyValueRefKind::Mssql(value.as_ref()),
|
||||
})
|
||||
}
|
||||
|
||||
fn type_info(&self) -> Option<Cow<'_, AnyTypeInfo>> {
|
||||
match &self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyValueKind::Postgres(value) => value
|
||||
.type_info()
|
||||
.map(|ty| AnyTypeInfoKind::Postgres(ty.into_owned())),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyValueKind::MySql(value) => value
|
||||
.type_info()
|
||||
.map(|ty| AnyTypeInfoKind::MySql(ty.into_owned())),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyValueKind::Sqlite(value) => value
|
||||
.type_info()
|
||||
.map(|ty| AnyTypeInfoKind::Sqlite(ty.into_owned())),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyValueKind::Mssql(value) => value
|
||||
.type_info()
|
||||
.map(|ty| AnyTypeInfoKind::Mssql(ty.into_owned())),
|
||||
}
|
||||
.map(AnyTypeInfo)
|
||||
.map(Cow::Owned)
|
||||
}
|
||||
|
||||
fn is_null(&self) -> bool {
|
||||
match &self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyValueKind::Postgres(value) => value.is_null(),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyValueKind::MySql(value) => value.is_null(),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyValueKind::Sqlite(value) => value.is_null(),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyValueKind::Mssql(value) => value.is_null(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> ValueRef<'r> for AnyValueRef<'r> {
|
||||
type Database = Any;
|
||||
|
||||
fn to_owned(&self) -> AnyValue {
|
||||
AnyValue(match &self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyValueRefKind::Postgres(value) => AnyValueKind::Postgres(ValueRef::to_owned(value)),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyValueRefKind::MySql(value) => AnyValueKind::MySql(ValueRef::to_owned(value)),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyValueRefKind::Sqlite(value) => AnyValueKind::Sqlite(ValueRef::to_owned(value)),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyValueRefKind::Mssql(value) => AnyValueKind::Mssql(ValueRef::to_owned(value)),
|
||||
})
|
||||
}
|
||||
|
||||
fn type_info(&self) -> Option<Cow<'_, AnyTypeInfo>> {
|
||||
match &self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyValueRefKind::Postgres(value) => value
|
||||
.type_info()
|
||||
.map(|ty| AnyTypeInfoKind::Postgres(ty.into_owned())),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyValueRefKind::MySql(value) => value
|
||||
.type_info()
|
||||
.map(|ty| AnyTypeInfoKind::MySql(ty.into_owned())),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyValueRefKind::Sqlite(value) => value
|
||||
.type_info()
|
||||
.map(|ty| AnyTypeInfoKind::Sqlite(ty.into_owned())),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyValueRefKind::Mssql(value) => value
|
||||
.type_info()
|
||||
.map(|ty| AnyTypeInfoKind::Mssql(ty.into_owned())),
|
||||
}
|
||||
.map(AnyTypeInfo)
|
||||
.map(Cow::Owned)
|
||||
}
|
||||
|
||||
fn is_null(&self) -> bool {
|
||||
match &self.0 {
|
||||
#[cfg(feature = "postgres")]
|
||||
AnyValueRefKind::Postgres(value) => value.is_null(),
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
AnyValueRefKind::MySql(value) => value.is_null(),
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
AnyValueRefKind::Sqlite(value) => value.is_null(),
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
AnyValueRefKind::Mssql(value) => value.is_null(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,9 +37,14 @@ pub mod transaction;
|
|||
#[macro_use]
|
||||
pub mod encode;
|
||||
|
||||
#[macro_use]
|
||||
pub mod decode;
|
||||
|
||||
#[macro_use]
|
||||
pub mod types;
|
||||
|
||||
mod common;
|
||||
pub mod database;
|
||||
pub mod decode;
|
||||
pub mod describe;
|
||||
pub mod executor;
|
||||
pub mod from_row;
|
||||
|
@ -50,9 +55,19 @@ pub mod query_as;
|
|||
pub mod query_scalar;
|
||||
pub mod row;
|
||||
pub mod type_info;
|
||||
pub mod types;
|
||||
pub mod value;
|
||||
|
||||
#[cfg(all(
|
||||
any(
|
||||
feature = "postgres",
|
||||
feature = "mysql",
|
||||
feature = "mssql",
|
||||
feature = "sqlite"
|
||||
),
|
||||
feature = "any"
|
||||
))]
|
||||
pub mod any;
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "postgres")))]
|
||||
pub mod postgres;
|
||||
|
|
11
src/lib.rs
11
src/lib.rs
|
@ -21,6 +21,17 @@ pub use sqlx_core::describe;
|
|||
#[doc(inline)]
|
||||
pub use sqlx_core::error::{self, Error, Result};
|
||||
|
||||
#[cfg(all(
|
||||
any(
|
||||
feature = "mysql",
|
||||
feature = "sqlite",
|
||||
feature = "postgres",
|
||||
feature = "mssql"
|
||||
),
|
||||
feature = "any"
|
||||
))]
|
||||
pub use sqlx_core::any::{self, Any, AnyConnection, AnyPool};
|
||||
|
||||
#[cfg(feature = "mysql")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "mysql")))]
|
||||
pub use sqlx_core::mysql::{self, MySql, MySqlConnection, MySqlPool};
|
||||
|
|
87
tests/any/any.rs
Normal file
87
tests/any/any.rs
Normal file
|
@ -0,0 +1,87 @@
|
|||
use sqlx::any::AnyRow;
|
||||
use sqlx::{Any, Connection, Executor, Row};
|
||||
use sqlx_test::new;
|
||||
|
||||
#[sqlx_macros::test]
|
||||
async fn it_connects() -> anyhow::Result<()> {
|
||||
let mut conn = new::<Any>().await?;
|
||||
|
||||
let value = sqlx::query("select 1 + 5")
|
||||
.try_map(|row: AnyRow| row.try_get::<i32, _>(0))
|
||||
.fetch_one(&mut conn)
|
||||
.await?;
|
||||
|
||||
assert_eq!(6i32, value);
|
||||
|
||||
conn.close().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[sqlx_macros::test]
|
||||
async fn it_pings() -> anyhow::Result<()> {
|
||||
let mut conn = new::<Any>().await?;
|
||||
|
||||
conn.ping().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[sqlx_macros::test]
|
||||
async fn it_executes_with_pool() -> anyhow::Result<()> {
|
||||
let pool = sqlx_test::pool::<Any>().await?;
|
||||
|
||||
let rows = pool.fetch_all("SELECT 1; SElECT 2").await?;
|
||||
|
||||
assert_eq!(rows.len(), 2);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[sqlx_macros::test]
|
||||
async fn it_can_fail_and_recover() -> anyhow::Result<()> {
|
||||
let mut conn = new::<Any>().await?;
|
||||
|
||||
for i in 0..10 {
|
||||
// make a query that will fail
|
||||
let res = conn
|
||||
.execute("INSERT INTO not_found (column) VALUES (10)")
|
||||
.await;
|
||||
|
||||
assert!(res.is_err());
|
||||
|
||||
// now try and use the connection
|
||||
let val: i32 = conn
|
||||
.fetch_one(&*format!("SELECT {}", i))
|
||||
.await?
|
||||
.get_unchecked(0);
|
||||
|
||||
assert_eq!(val, i);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[sqlx_macros::test]
|
||||
async fn it_can_fail_and_recover_with_pool() -> anyhow::Result<()> {
|
||||
let pool = sqlx_test::pool::<Any>().await?;
|
||||
|
||||
for i in 0..10 {
|
||||
// make a query that will fail
|
||||
let res = pool
|
||||
.execute("INSERT INTO not_found (column) VALUES (10)")
|
||||
.await;
|
||||
|
||||
assert!(res.is_err());
|
||||
|
||||
// now try and use the connection
|
||||
let val: i32 = pool
|
||||
.fetch_one(&*format!("SELECT {}", i))
|
||||
.await?
|
||||
.get_unchecked(0);
|
||||
|
||||
assert_eq!(val, i);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -153,6 +153,7 @@ async fn it_can_fail_and_recover() -> anyhow::Result<()> {
|
|||
let res = conn
|
||||
.execute("INSERT INTO not_found (column) VALUES (10)")
|
||||
.await;
|
||||
|
||||
assert!(res.is_err());
|
||||
|
||||
// now try and use the connection
|
||||
|
@ -160,6 +161,7 @@ async fn it_can_fail_and_recover() -> anyhow::Result<()> {
|
|||
.fetch_one(&*format!("SELECT {}::int4", i))
|
||||
.await?
|
||||
.get(0);
|
||||
|
||||
assert_eq!(val, i);
|
||||
}
|
||||
|
||||
|
@ -175,6 +177,7 @@ async fn it_can_fail_and_recover_with_pool() -> anyhow::Result<()> {
|
|||
let res = pool
|
||||
.execute("INSERT INTO not_found (column) VALUES (10)")
|
||||
.await;
|
||||
|
||||
assert!(res.is_err());
|
||||
|
||||
// now try and use the connection
|
||||
|
@ -182,6 +185,7 @@ async fn it_can_fail_and_recover_with_pool() -> anyhow::Result<()> {
|
|||
.fetch_one(&*format!("SELECT {}::int4", i))
|
||||
.await?
|
||||
.get(0);
|
||||
|
||||
assert_eq!(val, i);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue