Execute interface

This commit is contained in:
Chris Tsang 2021-05-26 19:05:43 +08:00
parent c414928255
commit fcff91c0e4
4 changed files with 101 additions and 11 deletions

51
src/connector/executor.rs Normal file
View File

@ -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<sqlx::Error> for ExecErr {
fn from(_: sqlx::Error) -> ExecErr {
ExecErr
}
}

View File

@ -1,5 +1,7 @@
mod executor;
mod select; mod select;
pub use executor::*;
pub use select::*; pub use select::*;
use crate::{DatabaseConnection, QueryResult, Statement, TypeErr}; use crate::{DatabaseConnection, QueryResult, Statement, TypeErr};
@ -15,6 +17,8 @@ pub trait Connector {
#[async_trait] #[async_trait]
pub trait Connection { pub trait Connection {
async fn execute(&self, stmt: Statement) -> Result<ExecResult, ExecErr>;
async fn query_one(&self, stmt: Statement) -> Result<QueryResult, QueryErr>; async fn query_one(&self, stmt: Statement) -> Result<QueryResult, QueryErr>;
async fn query_all(&self, stmt: Statement) -> Result<Vec<QueryResult>, QueryErr>; async fn query_all(&self, stmt: Statement) -> Result<Vec<QueryResult>, QueryErr>;

View File

@ -3,25 +3,32 @@ use std::fmt;
pub struct Statement { pub struct Statement {
pub sql: String, pub sql: String,
pub values: Values, pub values: Option<Values>,
} }
impl From<(String, Values)> for Statement { impl From<(String, Values)> for Statement {
fn from(stmt: (String, Values)) -> Statement { fn from(stmt: (String, Values)) -> Statement {
Statement { Statement {
sql: stmt.0, sql: stmt.0,
values: stmt.1, values: Some(stmt.1),
} }
} }
} }
impl fmt::Display for Statement { impl fmt::Display for Statement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let string = inject_parameters( match &self.values {
&self.sql, Some(values) => {
self.values.0.clone(), let string = inject_parameters(
&MySqlQueryBuilder::default(), &self.sql,
); values.0.clone(),
write!(f, "{}", &string) &MySqlQueryBuilder::default(),
);
write!(f, "{}", &string)
}
None => {
write!(f, "{}", &self.sql)
}
}
} }
} }

View File

@ -1,5 +1,5 @@
use async_trait::async_trait; use async_trait::async_trait;
use sqlx::{mysql::MySqlRow, MySqlPool}; use sqlx::{mysql::{MySqlRow, MySqlArguments, MySqlQueryResult}, MySql, MySqlPool};
sea_query::sea_query_driver_mysql!(); sea_query::sea_query_driver_mysql!();
use sea_query_driver_mysql::bind_query; use sea_query_driver_mysql::bind_query;
@ -31,10 +31,22 @@ impl Connector for SqlxMySqlConnector {
#[async_trait] #[async_trait]
impl Connection for &SqlxMySqlPoolConnection { impl Connection for &SqlxMySqlPoolConnection {
async fn execute(&self, stmt: Statement) -> Result<ExecResult, ExecErr> {
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<QueryResult, QueryErr> { async fn query_one(&self, stmt: Statement) -> Result<QueryResult, QueryErr> {
debug_print!("{}", stmt); 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(conn) = &mut self.pool.acquire().await {
if let Ok(row) = query.fetch_one(conn).await { if let Ok(row) = query.fetch_one(conn).await {
return Ok(row.into()); return Ok(row.into());
@ -46,7 +58,7 @@ impl Connection for &SqlxMySqlPoolConnection {
async fn query_all(&self, stmt: Statement) -> Result<Vec<QueryResult>, QueryErr> { async fn query_all(&self, stmt: Statement) -> Result<Vec<QueryResult>, QueryErr> {
debug_print!("{}", stmt); 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(conn) = &mut self.pool.acquire().await {
if let Ok(rows) = query.fetch_all(conn).await { if let Ok(rows) = query.fetch_all(conn).await {
return Ok(rows.into_iter().map(|r| r.into()).collect()); return Ok(rows.into_iter().map(|r| r.into()).collect());
@ -63,3 +75,19 @@ impl From<MySqlRow> for QueryResult {
} }
} }
} }
impl From<MySqlQueryResult> 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
}