diff --git a/sqlx-mysql/src/column.rs b/sqlx-mysql/src/column.rs new file mode 100644 index 00000000..e629d60c --- /dev/null +++ b/sqlx-mysql/src/column.rs @@ -0,0 +1,30 @@ +use bytestring::ByteString; +use sqlx_core::Column; + +#[allow(clippy::module_name_repetitions)] +pub struct MySqlColumn { + ordinal: usize, + name: ByteString, +} + +impl MySqlColumn { + pub fn name(&self) -> &str { + &self.name + } + + pub const fn ordinal(&self) -> usize { + self.ordinal + } +} + +impl Column for MySqlColumn { + #[inline] + fn name(&self) -> &str { + self.name() + } + + #[inline] + fn ordinal(&self) -> usize { + self.ordinal() + } +} diff --git a/sqlx-mysql/src/database.rs b/sqlx-mysql/src/database.rs index 26090753..85c7cd3e 100644 --- a/sqlx-mysql/src/database.rs +++ b/sqlx-mysql/src/database.rs @@ -1,13 +1,18 @@ use sqlx_core::{Database, HasOutput, Runtime}; +use super::{MySqlConnection, MySqlRow, MySqlColumn, MySqlQueryResult}; + #[derive(Debug)] pub struct MySql; -impl Database for MySql -where - Rt: Runtime, -{ - type Connection = super::MySqlConnection; +impl Database for MySql { + type Connection = MySqlConnection; + + type Row = MySqlRow; + + type Column = MySqlColumn; + + type QueryResult = MySqlQueryResult; } impl<'x> HasOutput<'x> for MySql { diff --git a/sqlx-mysql/src/lib.rs b/sqlx-mysql/src/lib.rs index 5ab709c1..2282351e 100644 --- a/sqlx-mysql/src/lib.rs +++ b/sqlx-mysql/src/lib.rs @@ -24,6 +24,8 @@ mod stream; mod connection; mod database; mod error; +mod column; +mod row; mod io; mod options; mod query_result; @@ -33,6 +35,8 @@ mod protocol; mod mock; pub use query_result::MySqlQueryResult; +pub use column::MySqlColumn; +pub use row::MySqlRow; pub use connection::MySqlConnection; pub use database::MySql; pub use error::MySqlDatabaseError; diff --git a/sqlx-mysql/src/query_result.rs b/sqlx-mysql/src/query_result.rs index 782a9f32..e21156a1 100644 --- a/sqlx-mysql/src/query_result.rs +++ b/sqlx-mysql/src/query_result.rs @@ -1,13 +1,15 @@ use std::fmt::{self, Debug, Formatter}; -use crate::protocol::OkPacket; +use sqlx_core::QueryResult; + +use crate::protocol::{Info, OkPacket, Status}; /// Represents the execution result of an operation on the database server. /// /// Returned from [`execute()`][sqlx_core::Executor::execute]. /// #[allow(clippy::module_name_repetitions)] -pub struct MySqlQueryResult(OkPacket); +pub struct MySqlQueryResult(pub(crate) OkPacket); impl MySqlQueryResult { /// Returns the number of rows changed, deleted, or inserted by the statement @@ -25,8 +27,8 @@ impl MySqlQueryResult { /// Return the number of rows matched by the `UPDATE` statement. /// - /// This is in contrast to [`rows_affected()`] which will return the number - /// of rows actually changed by the `UPDATE statement. + /// This is in contrast to [`rows_affected()`](#method.rows_affected) which will return the number + /// of rows actually changed by the `UPDATE` statement. /// /// Returns `0` for all other statements. /// @@ -39,7 +41,7 @@ impl MySqlQueryResult { /// or `ALTER TABLE` statement. /// /// For multi-row `INSERT`, this is not necessarily the number of rows actually - /// inserted because [`duplicates()`] can be non-zero. + /// inserted because [`duplicates()`](#method.duplicates) can be non-zero. /// /// For `ALTER TABLE`, this is the number of rows that were copied while /// making alterations. @@ -107,6 +109,45 @@ impl Debug for MySqlQueryResult { } } +impl Default for MySqlQueryResult { + fn default() -> Self { + Self(OkPacket { + affected_rows: 0, + last_insert_id: 0, + status: Status::empty(), + warnings: 0, + info: Info::default(), + }) + } +} + +impl From for MySqlQueryResult { + fn from(ok: OkPacket) -> Self { + Self(ok) + } +} + +impl Extend for MySqlQueryResult { + fn extend>(&mut self, iter: T) { + for res in iter { + self.0.affected_rows += res.0.affected_rows; + self.0.warnings += res.0.warnings; + self.0.info.records += res.0.info.records; + self.0.info.duplicates += res.0.info.duplicates; + self.0.info.matched += res.0.info.matched; + self.0.last_insert_id = res.0.last_insert_id; + self.0.status = res.0.status; + } + } +} + +impl QueryResult for MySqlQueryResult { + #[inline] + fn rows_affected(&self) -> u64 { + self.rows_affected() + } +} + #[cfg(test)] mod tests { use bytes::Bytes; @@ -134,7 +175,8 @@ mod tests { #[test] fn insert_5() -> anyhow::Result<()> { - let packet = Bytes::from(&b"\0\x05\x02\x02\0\0\0&Records: 5 Duplicates: 0 Warnings: 0"[..]); + let packet = + Bytes::from(&b"\0\x05\x02\x02\0\0\0&Records: 5 Duplicates: 0 Warnings: 0"[..]); let ok = OkPacket::deserialize_with(packet, *CAPABILITIES)?; let res = MySqlQueryResult(ok); @@ -148,7 +190,8 @@ mod tests { #[test] fn insert_5_or_update_3() -> anyhow::Result<()> { - let packet = Bytes::from(&b"\0\x08\x07\x02\0\0\0&Records: 5 Duplicates: 3 Warnings: 0"[..]); + let packet = + Bytes::from(&b"\0\x08\x07\x02\0\0\0&Records: 5 Duplicates: 3 Warnings: 0"[..]); let ok = OkPacket::deserialize_with(packet, *CAPABILITIES)?; let res = MySqlQueryResult(ok); diff --git a/sqlx-mysql/src/row.rs b/sqlx-mysql/src/row.rs new file mode 100644 index 00000000..44a3e69d --- /dev/null +++ b/sqlx-mysql/src/row.rs @@ -0,0 +1,48 @@ +use sqlx_core::Row; + +use crate::{protocol, MySqlColumn}; + +#[allow(clippy::module_name_repetitions)] +pub struct MySqlRow(pub(crate) protocol::Row); + +impl MySqlRow { + pub fn len(&self) -> usize { + self.0.values.len() + } +} + +impl Row for MySqlRow { + type Column = MySqlColumn; + + fn is_null(&self) -> bool { + todo!() + } + + fn len(&self) -> usize { + self.len() + } + + fn columns(&self) -> &[MySqlColumn] { + todo!() + } + + fn column_name_of(&self, ordinal: usize) -> &str { + todo!() + } + + fn try_column_name_of(&self, ordinal: usize) -> sqlx_core::Result<&str> { + todo!() + } + + fn ordinal_of(&self, name: &str) -> usize { + todo!() + } + + fn try_ordinal_of(&self, name: &str) -> sqlx_core::Result { + todo!() + } + + fn try_get_raw(&self) -> sqlx_core::Result<&[u8]> { + todo!() + } +} diff --git a/sqlx/src/mysql.rs b/sqlx/src/mysql.rs index e5e41e05..d7a8c258 100644 --- a/sqlx/src/mysql.rs +++ b/sqlx/src/mysql.rs @@ -10,11 +10,13 @@ mod options; #[cfg(feature = "blocking")] mod blocking; +// // these types are wrapped instead of re-exported - // this is to provide runtime-specialized inherent methods by taking advantage // of through crate-local negative reasoning - pub use connection::MySqlConnection; pub use database::MySql; pub use options::MySqlConnectOptions; +// +// re-export the remaining types from the driver +pub use sqlx_mysql::{MySqlColumn, MySqlDatabaseError, MySqlQueryResult, MySqlRow}; diff --git a/sqlx/src/mysql/database.rs b/sqlx/src/mysql/database.rs index 0b3dbc3a..3391bca8 100644 --- a/sqlx/src/mysql/database.rs +++ b/sqlx/src/mysql/database.rs @@ -1,4 +1,5 @@ use sqlx_core::HasOutput; +use sqlx_mysql::{MySqlColumn, MySqlQueryResult, MySqlRow}; use super::MySqlConnection; use crate::{Database, Runtime}; @@ -8,6 +9,9 @@ pub struct MySql; impl Database for MySql { type Connection = MySqlConnection; + type Column = MySqlColumn; + type Row = MySqlRow; + type QueryResult = MySqlQueryResult; } impl<'x> HasOutput<'x> for MySql {