DatabaseConnection
This commit is contained in:
parent
7d99d33aa2
commit
6ffed93b46
@ -24,7 +24,7 @@ path = "src/lib.rs"
|
|||||||
async-trait = "^0.1"
|
async-trait = "^0.1"
|
||||||
async-std = { version = "^1.9", features = [ "attributes" ] }
|
async-std = { version = "^1.9", features = [ "attributes" ] }
|
||||||
futures = { version = "^0.3" }
|
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" }
|
# sea-schema = { path = "../sea-schema" }
|
||||||
serde = { version = "^1.0", features = [ "derive" ] }
|
serde = { version = "^1.0", features = [ "derive" ] }
|
||||||
sqlx = { version = "^0.5", features = [ "runtime-async-std-native-tls", "mysql", "any", "chrono", "time", "bigdecimal", "decimal", "uuid", "json" ] }
|
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 async_trait::async_trait;
|
||||||
use sqlx::{mysql::MySqlRow, MySqlPool};
|
use sqlx::{mysql::MySqlRow, MySqlPool};
|
||||||
|
|
||||||
use sea_query::MysqlQueryBuilder;
|
|
||||||
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;
|
||||||
|
|
||||||
use crate::{debug_print, executor::*, query::*};
|
use crate::{connector::*, debug_print, query::*, DatabaseConnection};
|
||||||
|
|
||||||
pub struct SqlxMySqlExecutor {
|
pub struct SqlxMySqlConnector;
|
||||||
|
|
||||||
|
pub struct SqlxMySqlPoolConnection {
|
||||||
pool: MySqlPool,
|
pool: MySqlPool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Executor for SqlxMySqlExecutor {
|
impl Connector for SqlxMySqlConnector {
|
||||||
type QueryBuilder = MysqlQueryBuilder;
|
fn accepts(string: &str) -> bool {
|
||||||
|
string.starts_with("mysql://")
|
||||||
|
}
|
||||||
|
|
||||||
async fn query_one(&self, stmt: Statement) -> Result<QueryResult, ExecErr> {
|
async fn connect(string: &str) -> Result<DatabaseConnection, ConnectionErr> {
|
||||||
debug_print!("{}, {:?}", sql, values);
|
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);
|
let query = bind_query(sqlx::query(&stmt.sql), &stmt.values);
|
||||||
if let Ok(row) = query
|
if let Ok(conn) = &mut self.pool.acquire().await {
|
||||||
.fetch_one(&mut self.pool.acquire().await.unwrap())
|
if let Ok(row) = query.fetch_one(conn).await {
|
||||||
.await
|
return Ok(row.into());
|
||||||
{
|
|
||||||
Ok(row.into())
|
|
||||||
} else {
|
|
||||||
Err(ExecErr)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(QueryErr)
|
||||||
|
}
|
||||||
|
|
||||||
async fn query_all(&self, stmt: Statement) -> Result<Vec<QueryResult>, ExecErr> {
|
async fn query_all(&self, stmt: Statement) -> Result<Vec<QueryResult>, QueryErr> {
|
||||||
debug_print!("{}, {:?}", sql, values);
|
debug_print!("{}", stmt);
|
||||||
|
|
||||||
let query = bind_query(sqlx::query(&stmt.sql), &stmt.values);
|
let query = bind_query(sqlx::query(&stmt.sql), &stmt.values);
|
||||||
if let Ok(rows) = query
|
if let Ok(conn) = &mut self.pool.acquire().await {
|
||||||
.fetch_all(&mut self.pool.acquire().await.unwrap())
|
if let Ok(rows) = query.fetch_all(conn).await {
|
||||||
.await
|
return Ok(rows.into_iter().map(|r| r.into()).collect());
|
||||||
{
|
|
||||||
Ok(rows.into_iter().map(|r| r.into()).collect())
|
|
||||||
} else {
|
|
||||||
Err(ExecErr)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(QueryErr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<MySqlRow> for QueryResult {
|
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 driver;
|
||||||
mod entity;
|
mod entity;
|
||||||
mod executor;
|
|
||||||
mod query;
|
mod query;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
pub use connector::*;
|
||||||
|
pub use database::*;
|
||||||
pub use driver::*;
|
pub use driver::*;
|
||||||
pub use entity::*;
|
pub use entity::*;
|
||||||
pub use executor::*;
|
|
||||||
pub use query::*;
|
pub use query::*;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
mod result;
|
||||||
mod select;
|
mod select;
|
||||||
mod types;
|
|
||||||
|
|
||||||
|
pub use result::*;
|
||||||
pub use select::*;
|
pub use select::*;
|
||||||
pub use types::*;
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
|
use crate::Statement;
|
||||||
use crate::{entity::*, RelationDef};
|
use crate::{entity::*, RelationDef};
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
pub use sea_query::JoinType;
|
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 std::rc::Rc;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
@ -71,7 +72,18 @@ where
|
|||||||
&mut self.select
|
&mut self.select
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_query(&self) -> &SelectStatement {
|
||||||
|
&self.select
|
||||||
|
}
|
||||||
|
|
||||||
pub fn into_query(self) -> SelectStatement {
|
pub fn into_query(self) -> SelectStatement {
|
||||||
self.select
|
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