DatabaseConnection
This commit is contained in:
parent
7d99d33aa2
commit
6ffed93b46
@ -24,7 +24,7 @@ path = "src/lib.rs"
|
||||
async-trait = "^0.1"
|
||||
async-std = { version = "^1.9", features = [ "attributes" ] }
|
||||
futures = { version = "^0.3" }
|
||||
sea-query = { version = "^0.10", features = [ "sqlx-mysql" ] }
|
||||
sea-query = { path = "../sea-query", version = "^0.10", features = [ "sqlx-mysql" ] }
|
||||
# sea-schema = { path = "../sea-schema" }
|
||||
serde = { version = "^1.0", features = [ "derive" ] }
|
||||
sqlx = { version = "^0.5", features = [ "runtime-async-std-native-tls", "mysql", "any", "chrono", "time", "bigdecimal", "decimal", "uuid", "json" ] }
|
||||
|
68
src/connector/mod.rs
Normal file
68
src/connector/mod.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use crate::{DatabaseConnection, QueryResult};
|
||||
use async_trait::async_trait;
|
||||
use sea_query::{inject_parameters, MySqlQueryBuilder, Values};
|
||||
use std::{error::Error, fmt};
|
||||
|
||||
pub struct Statement {
|
||||
pub sql: String,
|
||||
pub values: Values,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait Connector {
|
||||
fn accepts(string: &str) -> bool;
|
||||
|
||||
async fn connect(string: &str) -> Result<DatabaseConnection, ConnectionErr>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait Connection {
|
||||
async fn query_one(&self, stmt: Statement) -> Result<QueryResult, QueryErr>;
|
||||
|
||||
async fn query_all(&self, stmt: Statement) -> Result<Vec<QueryResult>, QueryErr>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct QueryErr;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ConnectionErr;
|
||||
|
||||
// Statement //
|
||||
|
||||
impl From<(String, Values)> for Statement {
|
||||
fn from(stmt: (String, Values)) -> Statement {
|
||||
Statement {
|
||||
sql: stmt.0,
|
||||
values: stmt.1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Statement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let builder = MySqlQueryBuilder::default();
|
||||
let string = inject_parameters(&self.sql, self.values.0.clone(), &builder);
|
||||
write!(f, "{}", &string)
|
||||
}
|
||||
}
|
||||
|
||||
// QueryErr //
|
||||
|
||||
impl Error for QueryErr {}
|
||||
|
||||
impl fmt::Display for QueryErr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// ConnectionErr //
|
||||
|
||||
impl Error for ConnectionErr {}
|
||||
|
||||
impl fmt::Display for ConnectionErr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
51
src/database/mod.rs
Normal file
51
src/database/mod.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use crate::{Connection, ConnectionErr, Connector, SqlxMySqlConnector, SqlxMySqlPoolConnection};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Database {
|
||||
connection: DatabaseConnection,
|
||||
}
|
||||
|
||||
pub enum DatabaseConnection {
|
||||
SqlxMySqlPoolConnection(SqlxMySqlPoolConnection),
|
||||
Disconnected,
|
||||
}
|
||||
|
||||
// DatabaseConnection //
|
||||
|
||||
impl Default for DatabaseConnection {
|
||||
fn default() -> Self {
|
||||
Self::Disconnected
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for DatabaseConnection {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Self::SqlxMySqlPoolConnection(_) => "SqlxMySqlPoolConnection",
|
||||
Self::Disconnected => "Disconnected",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Database //
|
||||
|
||||
impl Database {
|
||||
pub async fn connect(&mut self, string: &str) -> Result<(), ConnectionErr> {
|
||||
if SqlxMySqlConnector::accepts(string) {
|
||||
self.connection = SqlxMySqlConnector::connect(string).await?;
|
||||
return Ok(());
|
||||
}
|
||||
Err(ConnectionErr)
|
||||
}
|
||||
|
||||
pub fn get_connection(&self) -> impl Connection + '_ {
|
||||
match &self.connection {
|
||||
DatabaseConnection::SqlxMySqlPoolConnection(conn) => conn,
|
||||
DatabaseConnection::Disconnected => panic!("Disconnected"),
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +1,3 @@
|
||||
pub mod sqlx_mysql;
|
||||
mod sqlx_mysql;
|
||||
|
||||
pub use sqlx_mysql::*;
|
||||
|
@ -1,47 +1,59 @@
|
||||
use async_trait::async_trait;
|
||||
use sqlx::{mysql::MySqlRow, MySqlPool};
|
||||
|
||||
use sea_query::MysqlQueryBuilder;
|
||||
sea_query::sea_query_driver_mysql!();
|
||||
use sea_query_driver_mysql::bind_query;
|
||||
|
||||
use crate::{debug_print, executor::*, query::*};
|
||||
use crate::{connector::*, debug_print, query::*, DatabaseConnection};
|
||||
|
||||
pub struct SqlxMySqlExecutor {
|
||||
pub struct SqlxMySqlConnector;
|
||||
|
||||
pub struct SqlxMySqlPoolConnection {
|
||||
pool: MySqlPool,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Executor for SqlxMySqlExecutor {
|
||||
type QueryBuilder = MysqlQueryBuilder;
|
||||
impl Connector for SqlxMySqlConnector {
|
||||
fn accepts(string: &str) -> bool {
|
||||
string.starts_with("mysql://")
|
||||
}
|
||||
|
||||
async fn query_one(&self, stmt: Statement) -> Result<QueryResult, ExecErr> {
|
||||
debug_print!("{}, {:?}", sql, values);
|
||||
async fn connect(string: &str) -> Result<DatabaseConnection, ConnectionErr> {
|
||||
if let Ok(conn) = MySqlPool::connect(string).await {
|
||||
Ok(DatabaseConnection::SqlxMySqlPoolConnection(
|
||||
SqlxMySqlPoolConnection { pool: conn },
|
||||
))
|
||||
} else {
|
||||
Err(ConnectionErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Connection for &SqlxMySqlPoolConnection {
|
||||
async fn query_one(&self, stmt: Statement) -> Result<QueryResult, QueryErr> {
|
||||
debug_print!("{}", stmt);
|
||||
|
||||
let query = bind_query(sqlx::query(&stmt.sql), &stmt.values);
|
||||
if let Ok(row) = query
|
||||
.fetch_one(&mut self.pool.acquire().await.unwrap())
|
||||
.await
|
||||
{
|
||||
Ok(row.into())
|
||||
} else {
|
||||
Err(ExecErr)
|
||||
if let Ok(conn) = &mut self.pool.acquire().await {
|
||||
if let Ok(row) = query.fetch_one(conn).await {
|
||||
return Ok(row.into());
|
||||
}
|
||||
}
|
||||
Err(QueryErr)
|
||||
}
|
||||
|
||||
async fn query_all(&self, stmt: Statement) -> Result<Vec<QueryResult>, ExecErr> {
|
||||
debug_print!("{}, {:?}", sql, values);
|
||||
async fn query_all(&self, stmt: Statement) -> Result<Vec<QueryResult>, QueryErr> {
|
||||
debug_print!("{}", stmt);
|
||||
|
||||
let query = bind_query(sqlx::query(&stmt.sql), &stmt.values);
|
||||
if let Ok(rows) = query
|
||||
.fetch_all(&mut self.pool.acquire().await.unwrap())
|
||||
.await
|
||||
{
|
||||
Ok(rows.into_iter().map(|r| r.into()).collect())
|
||||
} else {
|
||||
Err(ExecErr)
|
||||
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());
|
||||
}
|
||||
}
|
||||
Err(QueryErr)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MySqlRow> for QueryResult {
|
||||
|
@ -1,44 +0,0 @@
|
||||
mod query;
|
||||
|
||||
pub use query::*;
|
||||
|
||||
use crate::QueryResult;
|
||||
use async_trait::async_trait;
|
||||
use sea_query::{GenericBuilder, Values};
|
||||
use std::{error::Error, fmt};
|
||||
|
||||
pub struct Statement {
|
||||
pub sql: String,
|
||||
pub values: Values,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait Executor {
|
||||
type QueryBuilder: GenericBuilder;
|
||||
|
||||
async fn query_one(&self, stmt: Statement) -> Result<QueryResult, ExecErr>;
|
||||
|
||||
async fn query_all(&self, stmt: Statement) -> Result<Vec<QueryResult>, ExecErr>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ExecErr;
|
||||
|
||||
// ----- //
|
||||
|
||||
impl From<(String, Values)> for Statement {
|
||||
fn from(stmt: (String, Values)) -> Statement {
|
||||
Statement {
|
||||
sql: stmt.0,
|
||||
values: stmt.1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ExecErr {}
|
||||
|
||||
impl fmt::Display for ExecErr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
|
@ -1,10 +1,12 @@
|
||||
mod connector;
|
||||
mod database;
|
||||
mod driver;
|
||||
mod entity;
|
||||
mod executor;
|
||||
mod query;
|
||||
mod util;
|
||||
|
||||
pub use connector::*;
|
||||
pub use database::*;
|
||||
pub use driver::*;
|
||||
pub use entity::*;
|
||||
pub use executor::*;
|
||||
pub use query::*;
|
||||
|
@ -1,5 +1,5 @@
|
||||
mod result;
|
||||
mod select;
|
||||
mod types;
|
||||
|
||||
pub use result::*;
|
||||
pub use select::*;
|
||||
pub use types::*;
|
||||
|
@ -1,8 +1,9 @@
|
||||
use crate::Statement;
|
||||
use crate::{entity::*, RelationDef};
|
||||
use core::fmt::Debug;
|
||||
use core::marker::PhantomData;
|
||||
pub use sea_query::JoinType;
|
||||
use sea_query::{Expr, Iden, IntoIden, SelectStatement};
|
||||
use sea_query::{Expr, Iden, IntoIden, QueryBuilder, SelectStatement};
|
||||
use std::rc::Rc;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
@ -71,7 +72,18 @@ where
|
||||
&mut self.select
|
||||
}
|
||||
|
||||
pub fn as_query(&self) -> &SelectStatement {
|
||||
&self.select
|
||||
}
|
||||
|
||||
pub fn into_query(self) -> SelectStatement {
|
||||
self.select
|
||||
}
|
||||
|
||||
pub fn build<B>(&self, builder: B) -> Statement
|
||||
where
|
||||
B: QueryBuilder,
|
||||
{
|
||||
self.as_query().build(builder).into()
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user