Insert POC

This commit is contained in:
Chris Tsang 2021-05-28 00:33:04 +08:00
parent 2bfc7f9a9f
commit d3ee74cbe5
10 changed files with 153 additions and 19 deletions

View File

@ -36,11 +36,7 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result<Token
#(pub #field: sea_orm::Action<#ty>),*
}
impl sea_orm::ActiveModelOf<#ident> for ActiveModel {
fn from_model(m: #ident) -> Self {
Self::from(m)
}
}
impl sea_orm::ActiveModelOf<Entity> for ActiveModel {}
impl From<#ident> for ActiveModel {
fn from(m: #ident) -> Self {
@ -53,6 +49,12 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result<Token
impl sea_orm::ActiveModelTrait for ActiveModel {
type Column = Column;
fn take(&mut self, c: Self::Column) -> sea_orm::Action<sea_orm::Value> {
match c {
#(Self::Column::#name => std::mem::take(&mut self.#field).into_action_value()),*
}
}
fn get(&self, c: Self::Column) -> sea_orm::Action<sea_orm::Value> {
match c {
#(Self::Column::#name => self.#field.clone().into_action_value()),*

View File

@ -1,4 +1,4 @@
use crate::{ColumnTrait, ModelTrait, Value};
use crate::{ColumnTrait, EntityTrait, Value};
use std::fmt::Debug;
#[derive(Clone, Debug)]
@ -7,6 +7,12 @@ pub enum Action<V> {
Unset,
}
impl<V> Default for Action<V> {
fn default() -> Self {
Self::Unset
}
}
impl<V> Action<V>
where
V: Into<Value>,
@ -19,16 +25,17 @@ where
}
}
pub trait ActiveModelOf<M>
pub trait ActiveModelOf<E>
where
M: ModelTrait,
E: EntityTrait,
{
fn from_model(m: M) -> Self;
}
pub trait ActiveModelTrait: Clone + Debug {
type Column: ColumnTrait;
fn take(&mut self, c: Self::Column) -> Action<Value>;
fn get(&self, c: Self::Column) -> Action<Value>;
fn set(&mut self, c: Self::Column, v: Value);

View File

@ -15,11 +15,11 @@ pub trait EntityName: IdenStatic + Default {}
pub trait EntityTrait: EntityName {
type Model: ModelTrait;
type Column: ColumnTrait + Iterable;
type Column: ColumnTrait;
type Relation: RelationTrait + Iterable;
type Relation: RelationTrait;
type PrimaryKey: PrimaryKeyTrait + Iterable;
type PrimaryKey: PrimaryKeyTrait;
fn has_one<R>(entity: R) -> RelationBuilder<Self, R>
where

View File

@ -1,4 +1,4 @@
use crate::{EntityName, IdenStatic};
use crate::{EntityName, IdenStatic, Iterable};
pub use sea_query::ColumnType;
use sea_query::{Expr, Iden, SimpleExpr, Value};
@ -36,7 +36,7 @@ macro_rules! bind_vec_func {
};
}
pub trait ColumnTrait: IdenStatic {
pub trait ColumnTrait: IdenStatic + Iterable {
type EntityName: EntityName;
fn def(&self) -> ColumnType;

View File

@ -1,6 +1,6 @@
use super::{IdenStatic, ModelTrait};
use super::{IdenStatic, Iterable, ModelTrait};
pub trait PrimaryKeyTrait: IdenStatic {}
pub trait PrimaryKeyTrait: IdenStatic + Iterable {}
pub trait PrimaryKeyOfModel<M>
where

View File

@ -1,4 +1,4 @@
use crate::{EntityTrait, Identity, IntoIdentity, QueryHelper, Select};
use crate::{EntityTrait, Identity, IntoIdentity, Iterable, QueryHelper, Select};
use core::marker::PhantomData;
use sea_query::{Iden, IntoIden, JoinType};
use std::fmt::Debug;
@ -10,7 +10,7 @@ pub enum RelationType {
HasMany,
}
pub trait RelationTrait: Debug + 'static {
pub trait RelationTrait: Iterable + Debug + 'static {
fn def(&self) -> RelationDef;
}

View File

@ -2,6 +2,7 @@ mod connector;
mod database;
mod driver;
pub mod entity;
mod operation;
mod query;
pub mod tests_cfg;
mod util;
@ -10,6 +11,7 @@ pub use connector::*;
pub use database::*;
pub use driver::*;
pub use entity::*;
pub use operation::*;
pub use query::*;
pub use sea_orm_macros::{

120
src/operation/insert.rs Normal file
View File

@ -0,0 +1,120 @@
use crate::{Action, ActiveModelOf, ActiveModelTrait, EntityTrait, Iterable, Statement};
use core::marker::PhantomData;
use sea_query::{InsertStatement, IntoIden, QueryBuilder};
#[derive(Clone, Debug)]
pub struct Insert<A>
where
A: ActiveModelTrait,
{
pub(crate) query: InsertStatement,
pub(crate) model: PhantomData<A>,
}
impl<A> Insert<A>
where
A: ActiveModelTrait,
{
pub fn new<E>() -> Self
where
E: EntityTrait,
A: ActiveModelOf<E>,
{
Self {
query: InsertStatement::new()
.into_table(E::default().into_iden())
.to_owned(),
model: PhantomData,
}
}
pub fn one<M>(mut self, m: M) -> Self
where
M: Into<A>,
{
let mut am: A = m.into();
let mut columns = Vec::new();
let mut values = Vec::new();
for col in A::Column::iter() {
if let Action::Set(val) = am.take(col) {
columns.push(col);
values.push(val);
}
}
self.query.columns(columns);
self.query.values_panic(values);
self
}
/// Get a mutable ref to the query builder
pub fn query(&mut self) -> &mut InsertStatement {
&mut self.query
}
/// Get an immutable ref to the query builder
pub fn as_query(&self) -> &InsertStatement {
&self.query
}
/// Take ownership of the query builder
pub fn into_query(self) -> InsertStatement {
self.query
}
/// Build the query as [`Statement`]
pub fn build<B>(&self, builder: B) -> Statement
where
B: QueryBuilder,
{
self.as_query().build(builder).into()
}
}
#[cfg(test)]
mod tests {
use crate::tests_cfg::cake;
use crate::{Action, Insert};
use sea_query::PostgresQueryBuilder;
#[test]
fn insert_1() {
assert_eq!(
Insert::<cake::ActiveModel>::new()
.one(cake::ActiveModel {
id: Action::Unset,
name: Action::Set("Apple Pie".to_owned()),
})
.build(PostgresQueryBuilder)
.to_string(),
r#"INSERT INTO "cake" ("name") VALUES ('Apple Pie')"#,
);
}
#[test]
fn insert_2() {
assert_eq!(
Insert::<cake::ActiveModel>::new()
.one(cake::ActiveModel {
id: Action::Set(1),
name: Action::Set("Apple Pie".to_owned()),
})
.build(PostgresQueryBuilder)
.to_string(),
r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie')"#,
);
}
#[test]
fn insert_3() {
assert_eq!(
Insert::<cake::ActiveModel>::new()
.one(cake::Model {
id: 1,
name: "Apple Pie".to_owned(),
})
.build(PostgresQueryBuilder)
.to_string(),
r#"INSERT INTO "cake" ("id", "name") VALUES (1, 'Apple Pie')"#,
);
}
}

3
src/operation/mod.rs Normal file
View File

@ -0,0 +1,3 @@
mod insert;
pub use insert::*;

View File

@ -6,7 +6,7 @@ mod json;
mod result;
mod select;
pub use combine::*;
// pub use combine::*;
pub use helper::*;
pub use join::*;
#[cfg(feature = "with-json")]