diff --git a/sqlx-core/src/blocking/executor.rs b/sqlx-core/src/blocking/executor.rs index a95d140e..429d4930 100644 --- a/sqlx-core/src/blocking/executor.rs +++ b/sqlx-core/src/blocking/executor.rs @@ -1,12 +1,14 @@ -use crate::Database; - use super::Runtime; +use crate::Database; pub trait Executor: crate::Executor where Self::Database: Database, { - fn execute<'x, 'e, 'q>(&'e mut self, sql: &'q str) -> crate::Result<()> + fn execute<'x, 'e, 'q>( + &'e mut self, + sql: &'q str, + ) -> crate::Result<>::QueryResult> where 'e: 'x, 'q: 'x; diff --git a/sqlx-core/src/column.rs b/sqlx-core/src/column.rs new file mode 100644 index 00000000..5ab144ea --- /dev/null +++ b/sqlx-core/src/column.rs @@ -0,0 +1,7 @@ +pub trait Column { + /// Returns the name or alias of the column. + fn name(&self) -> &str; + + /// Returns the ordinal (also known as the index) of the column. + fn ordinal(&self) -> usize; +} diff --git a/sqlx-core/src/database.rs b/sqlx-core/src/database.rs index d3938959..b2033bd3 100644 --- a/sqlx-core/src/database.rs +++ b/sqlx-core/src/database.rs @@ -1,6 +1,6 @@ use std::fmt::Debug; -use crate::{Connection, Runtime}; +use crate::{Column, Connection, QueryResult, Row, Runtime}; /// A database driver. /// @@ -13,6 +13,15 @@ where { /// The concrete [`Connection`] implementation for this database. type Connection: Connection + ?Sized; + + /// The concrete [`Column`] implementation for this database. + type Column: Column; + + /// The concrete [`Row`] implementation for this database. + type Row: Row; + + /// The concrete [`QueryResult`] implementation for this database. + type QueryResult: QueryResult; } /// Associates [`Database`] with a `Output` of a generic lifetime. diff --git a/sqlx-core/src/executor.rs b/sqlx-core/src/executor.rs index 1c3c0b0f..6151306f 100644 --- a/sqlx-core/src/executor.rs +++ b/sqlx-core/src/executor.rs @@ -11,13 +11,47 @@ use crate::{Database, Result, Runtime}; /// A [`Connection`] is an `Executor` that guarantees that successive queries are ran on the /// same physical database connection. /// +#[allow(clippy::type_complexity)] pub trait Executor { type Database: Database; /// Execute the SQL query and return information about the result, including /// the number of rows affected, if any. #[cfg(feature = "async")] - fn execute<'x, 'e, 'q>(&'e mut self, sql: &'q str) -> BoxFuture<'x, Result<()>> + fn execute<'x, 'e, 'q>( + &'e mut self, + sql: &'q str, + ) -> BoxFuture<'x, Result<>::QueryResult>> + where + Rt: crate::Async, + 'e: 'x, + 'q: 'x; + + #[cfg(feature = "async")] + fn fetch_all<'x, 'e, 'q>( + &'e mut self, + sql: &'q str, + ) -> BoxFuture<'x, Result>::Row>>> + where + Rt: crate::Async, + 'e: 'x, + 'q: 'x; + + #[cfg(feature = "async")] + fn fetch_optional<'x, 'e, 'q>( + &'e mut self, + sql: &'q str, + ) -> BoxFuture<'x, Result>::Row>>> + where + Rt: crate::Async, + 'e: 'x, + 'q: 'x; + + #[cfg(feature = "async")] + fn fetch_one<'x, 'e, 'q>( + &'e mut self, + sql: &'q str, + ) -> BoxFuture<'x, Result<>::Row>> where Rt: crate::Async, 'e: 'x, diff --git a/sqlx-core/src/lib.rs b/sqlx-core/src/lib.rs index fec6168f..586f471d 100644 --- a/sqlx-core/src/lib.rs +++ b/sqlx-core/src/lib.rs @@ -28,6 +28,10 @@ mod executor; mod options; mod pool; mod runtime; +mod decode; +mod row; +mod query_result; +mod column; #[doc(hidden)] pub mod io; @@ -47,10 +51,13 @@ pub use acquire::Acquire; pub use blocking::runtime::Blocking; pub use close::Close; pub use connect::Connect; +pub use column::Column; pub use connection::Connection; pub use database::{Database, HasOutput}; pub use error::{DatabaseError, Error, Result}; pub use executor::Executor; +pub use query_result::QueryResult; +pub use row::Row; pub use options::ConnectOptions; pub use pool::Pool; #[cfg(feature = "actix")] diff --git a/sqlx-core/src/query_result.rs b/sqlx-core/src/query_result.rs new file mode 100644 index 00000000..2a487a55 --- /dev/null +++ b/sqlx-core/src/query_result.rs @@ -0,0 +1,12 @@ +use std::fmt::Debug; + +/// Represents the execution result of an operation on the database server. +/// +/// Returned from [`execute()`][crate::Executor::execute]. +/// +pub trait QueryResult: 'static + Sized + Debug + Extend { + /// Returns the number of rows changed, deleted, or inserted by the statement + /// if it was an `UPDATE`, `DELETE` or `INSERT`. For `SELECT` statements, returns + /// the number of rows returned. + fn rows_affected(&self) -> u64; +} diff --git a/sqlx-core/src/row.rs b/sqlx-core/src/row.rs new file mode 100644 index 00000000..7bbeefa4 --- /dev/null +++ b/sqlx-core/src/row.rs @@ -0,0 +1,37 @@ +use crate::{Column, Database, Runtime}; + +pub trait Row { + type Column: Column; + + /// Returns `true` if the row contains only `NULL` values. + fn is_null(&self) -> bool; + + /// Returns the number of columns in the row. + fn len(&self) -> usize; + + /// Returns `true` if there are no columns in the row. + fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Returns a reference to the columns in the row. + fn columns(&self) -> &[Self::Column]; + + /// Returns the column name, given the ordinal (also known as index) of the column. + fn column_name_of(&self, ordinal: usize) -> &str; + + /// Returns the column name, given the ordinal (also known as index) of the column. + fn try_column_name_of(&self, ordinal: usize) -> crate::Result<&str>; + + /// Returns the column ordinal, given the name of the column. + fn ordinal_of(&self, name: &str) -> usize; + + /// Returns the column ordinal, given the name of the column. + fn try_ordinal_of(&self, name: &str) -> crate::Result; + + fn try_get_raw(&self) -> crate::Result<&[u8]>; +} + +// TODO: fn type_info_of(index) +// TODO: fn try_type_info_of(index) +// TODO: trait ColumnIndex diff --git a/sqlx-core/src/runtime/async_std.rs b/sqlx-core/src/runtime/async_std.rs index 6f71c517..21f32f84 100644 --- a/sqlx-core/src/runtime/async_std.rs +++ b/sqlx-core/src/runtime/async_std.rs @@ -88,7 +88,7 @@ impl<'s> Stream<'s, AsyncStd> for TcpStream { #[doc(hidden)] fn shutdown_async(&'s mut self) -> Self::ShutdownFuture { - future::ready(TcpStream::shutdown(self, Shutdown::Both)) + future::ready(Self::shutdown(self, Shutdown::Both)) } #[doc(hidden)] @@ -134,7 +134,7 @@ impl<'s> Stream<'s, AsyncStd> for UnixStream { #[doc(hidden)] fn shutdown_async(&'s mut self) -> Self::ShutdownFuture { - future::ready(UnixStream::shutdown(self, Shutdown::Both)) + future::ready(Self::shutdown(self, Shutdown::Both)) } #[doc(hidden)]