Add Syntax to Statement

This commit is contained in:
Chris Tsang 2021-07-13 22:38:50 +08:00
parent b5f4d69c3b
commit bcd221a915
7 changed files with 102 additions and 33 deletions

View File

@ -15,7 +15,7 @@ impl EntityName for Entity {
pub struct Model { pub struct Model {
pub id: i32, pub id: i32,
pub name: String, pub name: String,
pub cake_id: Option<i32> , pub cake_id: Option<i32>,
} }
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]

View File

@ -15,7 +15,7 @@ impl EntityName for Entity {
pub struct Model { pub struct Model {
pub id: i32, pub id: i32,
pub name: String, pub name: String,
pub fruit_id: Option<i32> , pub fruit_id: Option<i32>,
} }
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]

View File

@ -1,4 +1,4 @@
use crate::{error::*, ExecResult, QueryResult, Statement}; use crate::{error::*, ExecResult, QueryResult, Statement, Syntax};
use sea_query::{ use sea_query::{
MysqlQueryBuilder, PostgresQueryBuilder, QueryStatementBuilder, SchemaStatementBuilder, MysqlQueryBuilder, PostgresQueryBuilder, QueryStatementBuilder, SchemaStatementBuilder,
SqliteQueryBuilder, SqliteQueryBuilder,
@ -134,29 +134,49 @@ impl DatabaseConnection {
} }
impl QueryBuilderBackend { impl QueryBuilderBackend {
pub fn syntax(&self) -> Syntax {
match self {
Self::MySql => Syntax::MySql,
Self::Postgres => Syntax::Postgres,
Self::Sqlite => Syntax::Sqlite,
}
}
pub fn build<S>(&self, statement: &S) -> Statement pub fn build<S>(&self, statement: &S) -> Statement
where where
S: QueryStatementBuilder, S: QueryStatementBuilder,
{ {
match self { Statement::from_string_values_tuple(
Self::MySql => statement.build(MysqlQueryBuilder), self.syntax(),
Self::Postgres => statement.build(PostgresQueryBuilder), match self {
Self::Sqlite => statement.build(SqliteQueryBuilder), Self::MySql => statement.build(MysqlQueryBuilder),
} Self::Postgres => statement.build(PostgresQueryBuilder),
.into() Self::Sqlite => statement.build(SqliteQueryBuilder),
},
)
} }
} }
impl SchemaBuilderBackend { impl SchemaBuilderBackend {
pub fn syntax(&self) -> Syntax {
match self {
Self::MySql => Syntax::MySql,
Self::Postgres => Syntax::Postgres,
Self::Sqlite => Syntax::Sqlite,
}
}
pub fn build<S>(&self, statement: &S) -> Statement pub fn build<S>(&self, statement: &S) -> Statement
where where
S: SchemaStatementBuilder, S: SchemaStatementBuilder,
{ {
match self { Statement::from_string(
Self::MySql => statement.build(MysqlQueryBuilder), self.syntax(),
Self::Postgres => statement.build(PostgresQueryBuilder), match self {
Self::Sqlite => statement.build(SqliteQueryBuilder), Self::MySql => statement.build(MysqlQueryBuilder),
} Self::Postgres => statement.build(PostgresQueryBuilder),
.into() Self::Sqlite => statement.build(SqliteQueryBuilder),
},
)
} }
} }

View File

@ -1,26 +1,38 @@
use sea_query::{inject_parameters, MySqlQueryBuilder, Values}; use crate::QueryBuilderWithSyntax;
use sea_query::{
inject_parameters, MysqlQueryBuilder, PostgresQueryBuilder, QueryBuilder, SqliteQueryBuilder,
Values,
};
use std::fmt; use std::fmt;
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Syntax {
MySql,
Postgres,
Sqlite,
}
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct Statement { pub struct Statement {
pub sql: String, pub sql: String,
pub values: Option<Values>, pub values: Option<Values>,
pub syntax: Syntax,
} }
impl From<String> for Statement { impl Statement {
fn from(stmt: String) -> Statement { pub fn from_string(syntax: Syntax, stmt: String) -> Statement {
Statement { Statement {
sql: stmt, sql: stmt,
values: None, values: None,
syntax,
} }
} }
}
impl From<(String, Values)> for Statement { pub fn from_string_values_tuple(syntax: Syntax, stmt: (String, Values)) -> Statement {
fn from(stmt: (String, Values)) -> Statement {
Statement { Statement {
sql: stmt.0, sql: stmt.0,
values: Some(stmt.1), values: Some(stmt.1),
syntax,
} }
} }
} }
@ -29,8 +41,11 @@ impl fmt::Display for Statement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self.values { match &self.values {
Some(values) => { Some(values) => {
let string = let string = inject_parameters(
inject_parameters(&self.sql, values.0.clone(), &MySqlQueryBuilder::default()); &self.sql,
values.0.clone(),
self.syntax.get_query_builder().as_ref(),
);
write!(f, "{}", &string) write!(f, "{}", &string)
} }
None => { None => {
@ -39,3 +54,31 @@ impl fmt::Display for Statement {
} }
} }
} }
impl Syntax {
pub fn get_query_builder(&self) -> Box<dyn QueryBuilder> {
match self {
Self::MySql => Box::new(MysqlQueryBuilder),
Self::Postgres => Box::new(PostgresQueryBuilder),
Self::Sqlite => Box::new(SqliteQueryBuilder),
}
}
}
impl QueryBuilderWithSyntax for MysqlQueryBuilder {
fn syntax(&self) -> Syntax {
Syntax::MySql
}
}
impl QueryBuilderWithSyntax for PostgresQueryBuilder {
fn syntax(&self) -> Syntax {
Syntax::Postgres
}
}
impl QueryBuilderWithSyntax for SqliteQueryBuilder {
fn syntax(&self) -> Syntax {
Syntax::Sqlite
}
}

View File

@ -1,4 +1,4 @@
use crate::Statement; use crate::{Statement, Syntax};
use sea_query::{Value, Values}; use sea_query::{Value, Values};
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -11,10 +11,10 @@ impl Transaction {
where where
I: IntoIterator<Item = Value>, I: IntoIterator<Item = Value>,
{ {
Self::one(Statement { Self::one(Statement::from_string_values_tuple(
sql: sql.to_owned(), Syntax::Postgres,
values: Some(Values(values.into_iter().collect())), (sql.to_string(), Values(values.into_iter().collect())),
}) ))
} }
/// Create a Transaction with one statement /// Create a Transaction with one statement

View File

@ -1,4 +1,4 @@
use crate::Statement; use crate::{Statement, Syntax};
use sea_query::{QueryBuilder, QueryStatementBuilder}; use sea_query::{QueryBuilder, QueryStatementBuilder};
pub trait QueryTrait { pub trait QueryTrait {
@ -16,8 +16,12 @@ pub trait QueryTrait {
/// Build the query as [`Statement`] /// Build the query as [`Statement`]
fn build<B>(&self, builder: B) -> Statement fn build<B>(&self, builder: B) -> Statement
where where
B: QueryBuilder, B: QueryBuilderWithSyntax,
{ {
self.as_query().build(builder).into() Statement::from_string_values_tuple(builder.syntax(), self.as_query().build(builder))
} }
} }
pub trait QueryBuilderWithSyntax: QueryBuilder {
fn syntax(&self) -> Syntax;
}

View File

@ -1,4 +1,4 @@
use sea_orm::{entity::*, error::*, sea_query, tests_cfg::*, DbConn}; use sea_orm::{entity::*, error::*, sea_query, tests_cfg::*, DbConn, Statement, Syntax};
mod setup; mod setup;
@ -27,7 +27,9 @@ async fn setup_schema(db: &DbConn) {
.col(ColumnDef::new(cake::Column::Name).string()) .col(ColumnDef::new(cake::Column::Name).string())
.build(SqliteQueryBuilder); .build(SqliteQueryBuilder);
let result = db.execute(stmt.into()).await; let result = db
.execute(Statement::from_string(Syntax::Sqlite, stmt))
.await;
println!("Create table cake: {:?}", result); println!("Create table cake: {:?}", result);
} }