diff --git a/sqlx-core/src/blocking.rs b/sqlx-core/src/blocking.rs index e8459653..e0287831 100644 --- a/sqlx-core/src/blocking.rs +++ b/sqlx-core/src/blocking.rs @@ -1,11 +1,18 @@ //! Types and traits used to implement a database driver with **blocking** I/O. //! -pub(crate) mod runtime; - mod connection; mod options; +mod runtime; pub use connection::Connection; pub use options::ConnectOptions; -pub use runtime::Runtime; +pub use runtime::{Blocking, Runtime}; + +pub mod prelude { + pub use crate::Database as _; + + pub use super::ConnectOptions as _; + pub use super::Connection as _; + pub use super::Runtime as _; +} diff --git a/sqlx-core/src/blocking/connection.rs b/sqlx-core/src/blocking/connection.rs index 15b48938..c7f21f9d 100644 --- a/sqlx-core/src/blocking/connection.rs +++ b/sqlx-core/src/blocking/connection.rs @@ -5,7 +5,7 @@ use super::{ConnectOptions, Runtime}; /// For detailed information, refer to the asynchronous version of /// this: [`Connection`][crate::Connection]. /// -pub trait Connection: 'static + Send +pub trait Connection: crate::Connection where Rt: Runtime, { @@ -20,7 +20,7 @@ where where Self: Sized, { - url.parse::()?.connect() + url.parse::<>::Options>()?.connect() } /// Explicitly close this database connection. diff --git a/sqlx-core/src/blocking/options.rs b/sqlx-core/src/blocking/options.rs index b1749808..67f8ca1d 100644 --- a/sqlx-core/src/blocking/options.rs +++ b/sqlx-core/src/blocking/options.rs @@ -1,20 +1,14 @@ -use std::fmt::Debug; -use std::str::FromStr; - -use super::{Connection, Runtime}; +use super::Runtime; /// Options which can be used to configure how a SQL connection is opened. /// /// For detailed information, refer to the asynchronous version of /// this: [`ConnectOptions`][crate::ConnectOptions]. /// -pub trait ConnectOptions: - 'static + Send + Sync + Default + Debug + Clone + FromStr +pub trait ConnectOptions: crate::ConnectOptions where Rt: Runtime, { - type Connection: Connection + ?Sized; - /// Establish a connection to the database. /// /// For detailed information, refer to the asynchronous version of diff --git a/sqlx-core/src/blocking/runtime.rs b/sqlx-core/src/blocking/runtime.rs index d4b3c7c7..40cd8498 100644 --- a/sqlx-core/src/blocking/runtime.rs +++ b/sqlx-core/src/blocking/runtime.rs @@ -2,23 +2,25 @@ use std::io; use std::net::TcpStream; /// Describes a set of types and functions used to open and manage -/// resources within SQLx using blocking I/O. +/// resources within SQLx. /// -pub trait Runtime { - type TcpStream; - +/// For detailed information, refer to the asynchronous version of +/// this: [`Runtime`][crate::Runtime]. +/// +pub trait Runtime: crate::Runtime { /// Opens a TCP connection to a remote host at the specified port. fn connect_tcp(host: &str, port: u16) -> io::Result; } /// Uses the `std::net` primitives to implement a blocking runtime for SQLx. -#[cfg_attr(doc_cfg, doc(cfg(feature = "blocking")))] #[derive(Debug)] pub struct Blocking; -impl Runtime for Blocking { +impl crate::Runtime for Blocking { type TcpStream = TcpStream; +} +impl Runtime for Blocking { fn connect_tcp(host: &str, port: u16) -> io::Result { TcpStream::connect((host, port)) } diff --git a/sqlx-core/src/connection.rs b/sqlx-core/src/connection.rs index 0eaa863d..80ab99f4 100644 --- a/sqlx-core/src/connection.rs +++ b/sqlx-core/src/connection.rs @@ -1,6 +1,7 @@ -use futures_util::future::BoxFuture; +use crate::{ConnectOptions, Database, Runtime}; -use crate::{ConnectOptions, Runtime}; +#[cfg(feature = "async")] +use futures_util::future::BoxFuture; /// A unique connection (session) with a specific database. /// @@ -14,6 +15,8 @@ pub trait Connection: 'static + Send where Rt: Runtime, { + type Database: Database; + type Options: ConnectOptions; /// Establish a new database connection. @@ -43,9 +46,11 @@ where /// .connect().await?; /// ``` /// + #[cfg(feature = "async")] fn connect(url: &str) -> BoxFuture<'_, crate::Result> where Self: Sized, + Rt: crate::Async, { let options = url.parse::(); Box::pin(async move { options?.connect().await }) @@ -57,7 +62,10 @@ where /// recommended to call it instead of letting a connection `drop` as the database backend /// will be faster at cleaning up resources. /// - fn close(self) -> BoxFuture<'static, crate::Result<()>>; + #[cfg(feature = "async")] + fn close(self) -> BoxFuture<'static, crate::Result<()>> + where + Rt: crate::Async; /// Checks if a connection to the database is still valid. /// @@ -66,5 +74,8 @@ where /// PostgreSQL, `ping` will issue a query consisting of a comment `/* SQLx ping */` which, /// in effect, does nothing apart from getting a response from the server. /// - fn ping(&mut self) -> BoxFuture<'_, crate::Result<()>>; + #[cfg(feature = "async")] + fn ping(&mut self) -> BoxFuture<'_, crate::Result<()>> + where + Rt: crate::Async; } diff --git a/sqlx-core/src/database.rs b/sqlx-core/src/database.rs new file mode 100644 index 00000000..2d86d22c --- /dev/null +++ b/sqlx-core/src/database.rs @@ -0,0 +1,25 @@ +use std::fmt::Debug; + +use crate::{Connection, Runtime}; + +/// A database driver. +/// +/// This trait encapsulates a complete set of traits that implement a driver for a +/// specific database (e.g., MySQL, PostgreSQL). +/// +// 'x: execution +pub trait Database: 'static + Sized + Debug + for<'x> HasOutput<'x> +where + Rt: Runtime, +{ + /// The concrete [`Connection`] implementation for this database. + type Connection: Connection + ?Sized; +} + +/// Associates [`Database`] with a `Output` of a generic lifetime. +/// 'x: single execution +pub trait HasOutput<'x> { + /// The concrete type to hold the output for `Encode` for this database. This may be + /// a simple alias to `&'x mut Vec`. + type Output; +} diff --git a/sqlx-core/src/lib.rs b/sqlx-core/src/lib.rs index 631ef2df..d4c31c5b 100644 --- a/sqlx-core/src/lib.rs +++ b/sqlx-core/src/lib.rs @@ -27,34 +27,51 @@ extern crate _async_std as async_std; #[cfg(feature = "tokio")] extern crate _tokio as tokio; +mod connection; +mod database; mod error; - -pub use error::{Error, Result}; - -#[cfg(feature = "async")] +mod options; mod runtime; -#[cfg(feature = "async")] -mod connection; - -#[cfg(feature = "async")] -mod options; - #[cfg(feature = "blocking")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "blocking")))] pub mod blocking; -#[cfg(feature = "blocking")] -pub use blocking::runtime::Blocking; +pub use connection::Connection; +pub use database::Database; +pub use error::{Error, Result}; +pub use options::ConnectOptions; +pub use runtime::Runtime; + +#[cfg(feature = "async-std")] +pub use runtime::AsyncStd; + +#[cfg(feature = "tokio")] +pub use runtime::Tokio; + +#[cfg(feature = "actix")] +pub use runtime::Actix; #[cfg(feature = "async")] -pub use {connection::Connection, options::ConnectOptions, runtime::Runtime}; +pub(crate) use runtime::Async; -#[cfg(all(feature = "async", feature = "async-std"))] -pub use runtime::async_std::AsyncStd; +#[cfg(feature = "async-std")] +pub type DefaultRuntime = AsyncStd; -#[cfg(all(feature = "async", feature = "tokio"))] -pub use runtime::tokio::Tokio; +#[cfg(all(not(feature = "async-std"), feature = "tokio"))] +pub type DefaultRuntime = Tokio; -#[cfg(all(feature = "async", feature = "actix"))] -pub use runtime::actix::Actix; +#[cfg(all(not(all(feature = "async-std", feature = "tokio")), feature = "actix"))] +pub type DefaultRuntime = Actix; + +#[cfg(not(feature = "async"))] +pub type DefaultRuntime = blocking::Blocking; + +pub mod prelude { + pub use super::ConnectOptions as _; + pub use super::Connection as _; + pub use super::Database as _; + pub use super::Runtime as _; + + #[cfg(all(not(feature = "async"), feature = "blocking"))] + pub use super::blocking::prelude::*; +} diff --git a/sqlx-core/src/options.rs b/sqlx-core/src/options.rs index 58469ef7..0741408c 100644 --- a/sqlx-core/src/options.rs +++ b/sqlx-core/src/options.rs @@ -1,8 +1,6 @@ use std::fmt::Debug; use std::str::FromStr; -use futures_util::future::BoxFuture; - use crate::{Connection, Runtime}; /// Options which can be used to configure how a SQL connection is opened. @@ -14,7 +12,9 @@ where type Connection: Connection + ?Sized; /// Establish a connection to the database. - fn connect(&self) -> BoxFuture<'_, crate::Result> + #[cfg(feature = "async")] + fn connect(&self) -> futures_util::future::BoxFuture<'_, crate::Result> where - Self::Connection: Sized; + Self::Connection: Sized, + Rt: crate::Async; } diff --git a/sqlx-core/src/runtime.rs b/sqlx-core/src/runtime.rs index ebbea8b2..d50ab0f5 100644 --- a/sqlx-core/src/runtime.rs +++ b/sqlx-core/src/runtime.rs @@ -1,25 +1,40 @@ -use std::io; - -use futures_util::future::BoxFuture; - #[cfg(feature = "async-std")] -pub(crate) mod async_std; +mod async_std; #[cfg(feature = "actix")] -pub(crate) mod actix; +mod actix; #[cfg(feature = "tokio")] -pub(crate) mod tokio; +mod tokio; + +#[cfg(feature = "async-std")] +pub use self::async_std::AsyncStd; + +#[cfg(feature = "tokio")] +pub use self::tokio::Tokio; + +#[cfg(feature = "actix")] +pub use self::actix::Actix; /// Describes a set of types and functions used to open and manage -/// resources within SQLx using asynchronous I/O. -#[cfg_attr( - doc_cfg, - doc(cfg(any(feature = "async-std", feature = "tokio", feature = "actix"))) -)] +/// resources within SQLx. pub trait Runtime { type TcpStream; /// Opens a TCP connection to a remote host at the specified port. - fn connect_tcp(host: &str, port: u16) -> BoxFuture<'_, io::Result>; + #[cfg(feature = "async")] + #[allow(unused_variables)] + fn connect_tcp( + host: &str, + port: u16, + ) -> futures_util::future::BoxFuture<'_, std::io::Result> + where + Self: Async, + { + unimplemented!() + } } + +/// Marker trait that identifies a `Runtime` as supporting asynchronous I/O. +#[cfg(feature = "async")] +pub trait Async: Runtime {} diff --git a/sqlx-core/src/runtime/actix.rs b/sqlx-core/src/runtime/actix.rs index fb8c02b0..cdc6ad30 100644 --- a/sqlx-core/src/runtime/actix.rs +++ b/sqlx-core/src/runtime/actix.rs @@ -3,7 +3,7 @@ use std::io; use actix_rt::net::TcpStream; use futures_util::{future::BoxFuture, FutureExt}; -use crate::runtime::Runtime; +use crate::{Async, Runtime}; /// Actix SQLx runtime. Uses [`actix-rt`][actix_rt] to provide [`Runtime`]. /// @@ -15,6 +15,8 @@ use crate::runtime::Runtime; #[derive(Debug)] pub struct Actix; +impl Async for Actix {} + impl Runtime for Actix { type TcpStream = TcpStream; diff --git a/sqlx-core/src/runtime/async_std.rs b/sqlx-core/src/runtime/async_std.rs index fc0df244..b4dcec53 100644 --- a/sqlx-core/src/runtime/async_std.rs +++ b/sqlx-core/src/runtime/async_std.rs @@ -3,13 +3,15 @@ use std::io; use async_std::{net::TcpStream, task::block_on}; use futures_util::{future::BoxFuture, FutureExt}; -use crate::runtime::Runtime; +use crate::{Async, Runtime}; /// [`async-std`](async_std) implementation of [`Runtime`]. #[cfg_attr(doc_cfg, doc(cfg(feature = "async-std")))] #[derive(Debug)] pub struct AsyncStd; +impl Async for AsyncStd {} + impl Runtime for AsyncStd { type TcpStream = TcpStream; @@ -20,8 +22,6 @@ impl Runtime for AsyncStd { #[cfg(feature = "blocking")] impl crate::blocking::Runtime for AsyncStd { - type TcpStream = TcpStream; - fn connect_tcp(host: &str, port: u16) -> io::Result { block_on(::connect_tcp(host, port)) } diff --git a/sqlx-core/src/runtime/tokio.rs b/sqlx-core/src/runtime/tokio.rs index 31ef67a9..3ccba2ed 100644 --- a/sqlx-core/src/runtime/tokio.rs +++ b/sqlx-core/src/runtime/tokio.rs @@ -3,7 +3,7 @@ use std::io; use futures_util::{future::BoxFuture, FutureExt}; use tokio::net::TcpStream; -use crate::runtime::Runtime; +use crate::{Async, Runtime}; /// Tokio SQLx runtime. Uses [`tokio`] to provide [`Runtime`]. /// @@ -13,6 +13,8 @@ use crate::runtime::Runtime; #[derive(Debug)] pub struct Tokio; +impl Async for Tokio {} + impl Runtime for Tokio { type TcpStream = TcpStream; diff --git a/sqlx/src/lib.rs b/sqlx/src/lib.rs index 22625795..716c1550 100644 --- a/sqlx/src/lib.rs +++ b/sqlx/src/lib.rs @@ -16,11 +16,12 @@ #![warn(clippy::useless_let_if_seq)] #![allow(clippy::doc_markdown)] -#[cfg(feature = "blocking")] -pub use sqlx_core::{blocking, Blocking}; +pub use sqlx_core::{ + prelude, ConnectOptions, Connection, Database, DefaultRuntime, Error, Result, Runtime, +}; -#[cfg(any(feature = "async-std", feature = "tokio", feature = "actix"))] -pub use sqlx_core::Runtime; +#[cfg(feature = "blocking")] +pub use sqlx_core::blocking; #[cfg(feature = "async-std")] pub use sqlx_core::AsyncStd;