diff --git a/src/connector/executor.rs b/src/connector/executor.rs new file mode 100644 index 00000000..c82c3bb7 --- /dev/null +++ b/src/connector/executor.rs @@ -0,0 +1,51 @@ +use sqlx::mysql::MySqlQueryResult; +use std::{error::Error, fmt}; + +#[derive(Debug)] +pub struct ExecResult { + pub(crate) result: ExecResultHolder, +} + +#[derive(Debug)] +pub(crate) enum ExecResultHolder { + SqlxMySql(MySqlQueryResult), +} + +#[derive(Debug)] +pub struct ExecErr; + +// ExecResult // + +impl ExecResult { + pub fn last_insert_id(&self) -> u64 { + match &self.result { + ExecResultHolder::SqlxMySql(result) => { + result.last_insert_id() + } + } + } + + pub fn rows_affected(&self) -> u64 { + match &self.result { + ExecResultHolder::SqlxMySql(result) => { + result.rows_affected() + } + } + } +} + +// ExecErr // + +impl Error for ExecErr {} + +impl fmt::Display for ExecErr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +impl From for ExecErr { + fn from(_: sqlx::Error) -> ExecErr { + ExecErr + } +} diff --git a/src/connector/mod.rs b/src/connector/mod.rs index 0f5c0e54..bb1585d8 100644 --- a/src/connector/mod.rs +++ b/src/connector/mod.rs @@ -1,5 +1,7 @@ +mod executor; mod select; +pub use executor::*; pub use select::*; use crate::{DatabaseConnection, QueryResult, Statement, TypeErr}; @@ -15,6 +17,8 @@ pub trait Connector { #[async_trait] pub trait Connection { + async fn execute(&self, stmt: Statement) -> Result; + async fn query_one(&self, stmt: Statement) -> Result; async fn query_all(&self, stmt: Statement) -> Result, QueryErr>; diff --git a/src/database/statement.rs b/src/database/statement.rs index abe5066c..92f8805d 100644 --- a/src/database/statement.rs +++ b/src/database/statement.rs @@ -3,25 +3,32 @@ use std::fmt; pub struct Statement { pub sql: String, - pub values: Values, + pub values: Option, } impl From<(String, Values)> for Statement { fn from(stmt: (String, Values)) -> Statement { Statement { sql: stmt.0, - values: stmt.1, + values: Some(stmt.1), } } } impl fmt::Display for Statement { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let string = inject_parameters( - &self.sql, - self.values.0.clone(), - &MySqlQueryBuilder::default(), - ); - write!(f, "{}", &string) + match &self.values { + Some(values) => { + let string = inject_parameters( + &self.sql, + values.0.clone(), + &MySqlQueryBuilder::default(), + ); + write!(f, "{}", &string) + } + None => { + write!(f, "{}", &self.sql) + } + } } } diff --git a/src/driver/sqlx_mysql.rs b/src/driver/sqlx_mysql.rs index e7e37e29..ac510eb2 100644 --- a/src/driver/sqlx_mysql.rs +++ b/src/driver/sqlx_mysql.rs @@ -1,5 +1,5 @@ use async_trait::async_trait; -use sqlx::{mysql::MySqlRow, MySqlPool}; +use sqlx::{mysql::{MySqlRow, MySqlArguments, MySqlQueryResult}, MySql, MySqlPool}; sea_query::sea_query_driver_mysql!(); use sea_query_driver_mysql::bind_query; @@ -31,10 +31,22 @@ impl Connector for SqlxMySqlConnector { #[async_trait] impl Connection for &SqlxMySqlPoolConnection { + async fn execute(&self, stmt: Statement) -> Result { + debug_print!("{}", stmt); + + let query = sqlx_query(&stmt); + if let Ok(conn) = &mut self.pool.acquire().await { + if let Ok(res) = query.execute(conn).await { + return Ok(res.into()); + } + } + Err(ExecErr) + } + async fn query_one(&self, stmt: Statement) -> Result { debug_print!("{}", stmt); - let query = bind_query(sqlx::query(&stmt.sql), &stmt.values); + let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { if let Ok(row) = query.fetch_one(conn).await { return Ok(row.into()); @@ -46,7 +58,7 @@ impl Connection for &SqlxMySqlPoolConnection { async fn query_all(&self, stmt: Statement) -> Result, QueryErr> { debug_print!("{}", stmt); - let query = bind_query(sqlx::query(&stmt.sql), &stmt.values); + let query = sqlx_query(&stmt); if let Ok(conn) = &mut self.pool.acquire().await { if let Ok(rows) = query.fetch_all(conn).await { return Ok(rows.into_iter().map(|r| r.into()).collect()); @@ -63,3 +75,19 @@ impl From for QueryResult { } } } + +impl From for ExecResult { + fn from(result: MySqlQueryResult) -> ExecResult { + ExecResult { + result: ExecResultHolder::SqlxMySql(result), + } + } +} + +fn sqlx_query(stmt: &Statement) -> sqlx::query::Query<'_, MySql, MySqlArguments> { + let mut query = sqlx::query(&stmt.sql); + if let Some(values) = &stmt.values { + query = bind_query(query, values); + } + query +} \ No newline at end of file