Select
This commit is contained in:
parent
28b82fa6ed
commit
7d99d33aa2
@ -1,6 +1,7 @@
|
||||
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;
|
||||
|
||||
@ -12,6 +13,8 @@ pub struct SqlxMySqlExecutor {
|
||||
|
||||
#[async_trait]
|
||||
impl Executor for SqlxMySqlExecutor {
|
||||
type QueryBuilder = MysqlQueryBuilder;
|
||||
|
||||
async fn query_one(&self, stmt: Statement) -> Result<QueryResult, ExecErr> {
|
||||
debug_print!("{}, {:?}", sql, values);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use super::{Column, Identity, Relation};
|
||||
use crate::Select;
|
||||
use sea_query::Iden;
|
||||
use std::fmt::Debug;
|
||||
use strum::IntoEnumIterator;
|
||||
@ -10,11 +11,13 @@ pub trait Entity: Iden + Default + Debug {
|
||||
|
||||
type Relation: Relation + IntoEnumIterator;
|
||||
|
||||
fn table_name() -> Self;
|
||||
|
||||
fn primary_key() -> Identity;
|
||||
|
||||
fn auto_increment() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn find<'s>() -> Select<'s, Self> {
|
||||
Select::new(Self::default())
|
||||
}
|
||||
}
|
||||
|
@ -11,19 +11,19 @@ pub enum RelationType {
|
||||
}
|
||||
|
||||
pub trait Relation {
|
||||
fn rel_def() -> RelationDef;
|
||||
fn rel_def(&self) -> RelationDef;
|
||||
}
|
||||
|
||||
pub struct RelationDef {
|
||||
rel_type: RelationType,
|
||||
from_tbl: Rc<dyn Iden>,
|
||||
from_col: Identity,
|
||||
to_col: Identity,
|
||||
pub rel_type: RelationType,
|
||||
pub to_tbl: Rc<dyn Iden>,
|
||||
pub from_col: Identity,
|
||||
pub to_col: Identity,
|
||||
}
|
||||
|
||||
pub struct RelationBuilder {
|
||||
rel_type: RelationType,
|
||||
from_tbl: Rc<dyn Iden>,
|
||||
to_tbl: Rc<dyn Iden>,
|
||||
from_col: Option<Identity>,
|
||||
to_col: Option<Identity>,
|
||||
}
|
||||
@ -56,7 +56,7 @@ impl RelationBuilder {
|
||||
{
|
||||
Self {
|
||||
rel_type,
|
||||
from_tbl: entity.into_iden(),
|
||||
to_tbl: entity.into_iden(),
|
||||
from_col: None,
|
||||
to_col: None,
|
||||
}
|
||||
@ -83,7 +83,7 @@ impl From<RelationBuilder> for RelationDef {
|
||||
fn from(b: RelationBuilder) -> Self {
|
||||
RelationDef {
|
||||
rel_type: b.rel_type,
|
||||
from_tbl: b.from_tbl,
|
||||
to_tbl: b.to_tbl,
|
||||
from_col: b.from_col.unwrap(),
|
||||
to_col: b.to_col.unwrap(),
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
mod query;
|
||||
|
||||
pub use query::*;
|
||||
|
||||
use crate::QueryResult;
|
||||
use async_trait::async_trait;
|
||||
use sea_query::Values;
|
||||
use sea_query::{GenericBuilder, Values};
|
||||
use std::{error::Error, fmt};
|
||||
|
||||
pub struct Statement {
|
||||
@ -10,6 +14,8 @@ pub struct Statement {
|
||||
|
||||
#[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>;
|
1
src/executor/query.rs
Normal file
1
src/executor/query.rs
Normal file
@ -0,0 +1 @@
|
||||
|
5
src/query/mod.rs
Normal file
5
src/query/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
mod select;
|
||||
mod types;
|
||||
|
||||
pub use select::*;
|
||||
pub use types::*;
|
77
src/query/select.rs
Normal file
77
src/query/select.rs
Normal file
@ -0,0 +1,77 @@
|
||||
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 std::rc::Rc;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Select<'s, E: 'static>
|
||||
where
|
||||
E: Entity,
|
||||
{
|
||||
select: SelectStatement,
|
||||
entity: PhantomData<&'s E>,
|
||||
}
|
||||
|
||||
impl<E: 'static> Select<'_, E>
|
||||
where
|
||||
E: Entity,
|
||||
{
|
||||
pub(crate) fn new(_: E) -> Self {
|
||||
Self {
|
||||
select: SelectStatement::new(),
|
||||
entity: PhantomData,
|
||||
}
|
||||
.prepare_select()
|
||||
.prepare_from()
|
||||
}
|
||||
|
||||
fn prepare_select(mut self) -> Self {
|
||||
let table = E::default().into_iden();
|
||||
let columns: Vec<(Rc<dyn Iden>, E::Column)> =
|
||||
E::Column::iter().map(|c| (Rc::clone(&table), c)).collect();
|
||||
self.select.columns(columns);
|
||||
self
|
||||
}
|
||||
|
||||
fn prepare_from(mut self) -> Self {
|
||||
self.select.from(E::default().into_iden());
|
||||
self
|
||||
}
|
||||
|
||||
fn prepare_join(mut self, join: JoinType, relation: RelationDef) -> Self {
|
||||
let own_tbl = E::default().into_iden();
|
||||
let to_tbl = &relation.to_tbl;
|
||||
let owner_keys = relation.from_col;
|
||||
let foreign_keys = relation.to_col;
|
||||
let condition = match (owner_keys, foreign_keys) {
|
||||
(Identity::Unary(o1), Identity::Unary(f1)) => {
|
||||
Expr::tbl(Rc::clone(&own_tbl), o1).equals(Rc::clone(to_tbl), f1)
|
||||
} // _ => panic!("Owner key and foreign key mismatch"),
|
||||
};
|
||||
self.select.join(join, Rc::clone(to_tbl), condition);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn left_join(self, relation: RelationDef) -> Self {
|
||||
self.prepare_join(JoinType::LeftJoin, relation)
|
||||
}
|
||||
|
||||
pub fn right_join(self, relation: RelationDef) -> Self {
|
||||
self.prepare_join(JoinType::RightJoin, relation)
|
||||
}
|
||||
|
||||
pub fn inner_join(self, relation: RelationDef) -> Self {
|
||||
self.prepare_join(JoinType::InnerJoin, relation)
|
||||
}
|
||||
|
||||
pub fn query(&mut self) -> &mut SelectStatement {
|
||||
&mut self.select
|
||||
}
|
||||
|
||||
pub fn into_query(self) -> SelectStatement {
|
||||
self.select
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user