Merge pull request #2185 from SeaQL/pk-arity-trait
`PrimaryKeyArity` trait
This commit is contained in:
commit
c2b8c44118
@ -1,5 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::*, ConnectionTrait, DeleteResult, EntityTrait, Iterable, PrimaryKeyToColumn, Value,
|
error::*, ConnectionTrait, DeleteResult, EntityTrait, Iterable, PrimaryKeyArity,
|
||||||
|
PrimaryKeyToColumn, PrimaryKeyTrait, Value,
|
||||||
};
|
};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use sea_query::{Nullable, ValueTuple};
|
use sea_query::{Nullable, ValueTuple};
|
||||||
@ -139,7 +140,7 @@ pub trait ActiveModelTrait: Clone + Debug {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
match <Self::Entity as EntityTrait>::PrimaryKey::iter().count() {
|
match <<<Self::Entity as EntityTrait>::PrimaryKey as PrimaryKeyTrait>::ValueType as PrimaryKeyArity>::ARITY {
|
||||||
1 => {
|
1 => {
|
||||||
let s1 = next!();
|
let s1 = next!();
|
||||||
Some(ValueTuple::One(s1))
|
Some(ValueTuple::One(s1))
|
||||||
|
@ -4,8 +4,8 @@ pub use crate::{
|
|||||||
ActiveEnum, ActiveModelBehavior, ActiveModelTrait, ColumnDef, ColumnTrait, ColumnType,
|
ActiveEnum, ActiveModelBehavior, ActiveModelTrait, ColumnDef, ColumnTrait, ColumnType,
|
||||||
ColumnTypeTrait, ConnectionTrait, CursorTrait, DatabaseConnection, DbConn, EntityName,
|
ColumnTypeTrait, ConnectionTrait, CursorTrait, DatabaseConnection, DbConn, EntityName,
|
||||||
EntityTrait, EnumIter, ForeignKeyAction, Iden, IdenStatic, Linked, LoaderTrait, ModelTrait,
|
EntityTrait, EnumIter, ForeignKeyAction, Iden, IdenStatic, Linked, LoaderTrait, ModelTrait,
|
||||||
PaginatorTrait, PrimaryKeyToColumn, PrimaryKeyTrait, QueryFilter, QueryResult, Related,
|
PaginatorTrait, PrimaryKeyArity, PrimaryKeyToColumn, PrimaryKeyTrait, QueryFilter, QueryResult,
|
||||||
RelationDef, RelationTrait, Select, Value,
|
Related, RelationDef, RelationTrait, Select, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "macros")]
|
#[cfg(feature = "macros")]
|
||||||
|
@ -46,9 +46,10 @@ pub trait PrimaryKeyTrait: IdenStatic + Iterable {
|
|||||||
+ IntoValueTuple
|
+ IntoValueTuple
|
||||||
+ FromValueTuple
|
+ FromValueTuple
|
||||||
+ TryGetableMany
|
+ TryGetableMany
|
||||||
+ TryFromU64;
|
+ TryFromU64
|
||||||
|
+ PrimaryKeyArity;
|
||||||
|
|
||||||
/// Method to call to perform `AUTOINCREMENT` operation on a Primary Kay
|
/// Method to call to perform `AUTOINCREMENT` operation on a Primary Key
|
||||||
fn auto_increment() -> bool;
|
fn auto_increment() -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +67,40 @@ pub trait PrimaryKeyToColumn {
|
|||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// How many columns this Primary Key comprises
|
||||||
|
pub trait PrimaryKeyArity {
|
||||||
|
/// Arity of the Primary Key
|
||||||
|
const ARITY: usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V> PrimaryKeyArity for V
|
||||||
|
where
|
||||||
|
V: crate::TryGetable,
|
||||||
|
{
|
||||||
|
const ARITY: usize = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_pk_arity {
|
||||||
|
($len:expr, $($tuple_arg:ident),*) => {
|
||||||
|
impl<$($tuple_arg: crate::TryGetableMany,)*> PrimaryKeyArity for ($($tuple_arg,)*) {
|
||||||
|
const ARITY: usize = $len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_pk_arity!(1, T1);
|
||||||
|
impl_pk_arity!(2, T1, T2);
|
||||||
|
impl_pk_arity!(3, T1, T2, T3);
|
||||||
|
impl_pk_arity!(4, T1, T2, T3, T4);
|
||||||
|
impl_pk_arity!(5, T1, T2, T3, T4, T5);
|
||||||
|
impl_pk_arity!(6, T1, T2, T3, T4, T5, T6);
|
||||||
|
impl_pk_arity!(7, T1, T2, T3, T4, T5, T6, T7);
|
||||||
|
impl_pk_arity!(8, T1, T2, T3, T4, T5, T6, T7, T8);
|
||||||
|
impl_pk_arity!(9, T1, T2, T3, T4, T5, T6, T7, T8, T9);
|
||||||
|
impl_pk_arity!(10, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
|
||||||
|
impl_pk_arity!(11, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
|
||||||
|
impl_pk_arity!(12, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -116,7 +116,7 @@ where
|
|||||||
{
|
{
|
||||||
// so that self is dropped before entering await
|
// so that self is dropped before entering await
|
||||||
let mut query = self.query;
|
let mut query = self.query;
|
||||||
if db.support_returning() && <A::Entity as EntityTrait>::PrimaryKey::iter().count() > 0 {
|
if db.support_returning() {
|
||||||
let db_backend = db.get_database_backend();
|
let db_backend = db.get_database_backend();
|
||||||
let returning =
|
let returning =
|
||||||
Query::returning().exprs(<A::Entity as EntityTrait>::PrimaryKey::iter().map(|c| {
|
Query::returning().exprs(<A::Entity as EntityTrait>::PrimaryKey::iter().map(|c| {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::*, ConnectionTrait, DbBackend, EntityTrait, FromQueryResult, IdenStatic, Iterable,
|
error::*, ConnectionTrait, DbBackend, EntityTrait, FromQueryResult, IdenStatic, Iterable,
|
||||||
ModelTrait, PartialModelTrait, PrimaryKeyToColumn, QueryResult, QuerySelect, Select, SelectA,
|
ModelTrait, PartialModelTrait, PrimaryKeyArity, PrimaryKeyToColumn, PrimaryKeyTrait,
|
||||||
SelectB, SelectTwo, SelectTwoMany, Statement, StreamTrait, TryGetableMany,
|
QueryResult, QuerySelect, Select, SelectA, SelectB, SelectTwo, SelectTwoMany, Statement,
|
||||||
|
StreamTrait, TryGetableMany,
|
||||||
};
|
};
|
||||||
use futures::{Stream, TryStreamExt};
|
use futures::{Stream, TryStreamExt};
|
||||||
use sea_query::{SelectStatement, Value};
|
use sea_query::{SelectStatement, Value};
|
||||||
@ -990,6 +991,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
fn consolidate_query_result<L, R>(
|
fn consolidate_query_result<L, R>(
|
||||||
rows: Vec<(L::Model, Option<R::Model>)>,
|
rows: Vec<(L::Model, Option<R::Model>)>,
|
||||||
) -> Vec<(L::Model, Vec<R::Model>)>
|
) -> Vec<(L::Model, Vec<R::Model>)>
|
||||||
@ -997,15 +999,26 @@ where
|
|||||||
L: EntityTrait,
|
L: EntityTrait,
|
||||||
R: EntityTrait,
|
R: EntityTrait,
|
||||||
{
|
{
|
||||||
// This is a strong point to consider adding a trait associated constant
|
match <<L::PrimaryKey as PrimaryKeyTrait>::ValueType as PrimaryKeyArity>::ARITY {
|
||||||
// to PrimaryKeyTrait to indicate the arity
|
1 => {
|
||||||
let pkcol: Vec<_> = <L::PrimaryKey as Iterable>::iter()
|
let col = <L::PrimaryKey as Iterable>::iter()
|
||||||
.map(|pk| pk.into_column())
|
.next()
|
||||||
.collect();
|
.unwrap()
|
||||||
if pkcol.len() == 1 {
|
.into_column();
|
||||||
consolidate_query_result_of::<L, R, UnitPk<L>>(rows, UnitPk(pkcol[0]))
|
consolidate_query_result_of::<L, R, UnitPk<L>>(rows, UnitPk(col))
|
||||||
} else {
|
}
|
||||||
consolidate_query_result_of::<L, R, TuplePk<L>>(rows, TuplePk(pkcol))
|
2 => {
|
||||||
|
let mut iter = <L::PrimaryKey as Iterable>::iter();
|
||||||
|
let col1 = iter.next().unwrap().into_column();
|
||||||
|
let col2 = iter.next().unwrap().into_column();
|
||||||
|
consolidate_query_result_of::<L, R, PairPk<L>>(rows, PairPk(col1, col2))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let cols: Vec<_> = <L::PrimaryKey as Iterable>::iter()
|
||||||
|
.map(|pk| pk.into_column())
|
||||||
|
.collect();
|
||||||
|
consolidate_query_result_of::<L, R, TuplePk<L>>(rows, TuplePk(cols))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1014,8 +1027,9 @@ trait ModelKey<E: EntityTrait> {
|
|||||||
fn get(&self, model: &E::Model) -> Self::Type;
|
fn get(&self, model: &E::Model) -> Self::Type;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This could have been an array of [E::Column; <E::PrimaryKey as PrimaryKeyTrait>::ARITY]
|
// This could have been an array of [E::Column; <E::PrimaryKey as PrimaryKeyTrait>::ARITY], but it still doesn't compile
|
||||||
struct UnitPk<E: EntityTrait>(E::Column);
|
struct UnitPk<E: EntityTrait>(E::Column);
|
||||||
|
struct PairPk<E: EntityTrait>(E::Column, E::Column);
|
||||||
struct TuplePk<E: EntityTrait>(Vec<E::Column>);
|
struct TuplePk<E: EntityTrait>(Vec<E::Column>);
|
||||||
|
|
||||||
impl<E: EntityTrait> ModelKey<E> for UnitPk<E> {
|
impl<E: EntityTrait> ModelKey<E> for UnitPk<E> {
|
||||||
@ -1025,6 +1039,13 @@ impl<E: EntityTrait> ModelKey<E> for UnitPk<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<E: EntityTrait> ModelKey<E> for PairPk<E> {
|
||||||
|
type Type = (Value, Value);
|
||||||
|
fn get(&self, model: &E::Model) -> Self::Type {
|
||||||
|
(model.get(self.0), model.get(self.1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E: EntityTrait> ModelKey<E> for TuplePk<E> {
|
impl<E: EntityTrait> ModelKey<E> for TuplePk<E> {
|
||||||
type Type = Vec<Value>;
|
type Type = Vec<Value>;
|
||||||
fn get(&self, model: &E::Model) -> Self::Type {
|
fn get(&self, model: &E::Model) -> Self::Type {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ActiveEnum, ColumnTrait, ColumnType, DbBackend, EntityTrait, Iterable, PrimaryKeyToColumn,
|
ActiveEnum, ColumnTrait, ColumnType, DbBackend, EntityTrait, Iterable, PrimaryKeyArity,
|
||||||
PrimaryKeyTrait, RelationTrait, Schema,
|
PrimaryKeyToColumn, PrimaryKeyTrait, RelationTrait, Schema,
|
||||||
};
|
};
|
||||||
use sea_query::{
|
use sea_query::{
|
||||||
extension::postgres::{Type, TypeCreateStatement},
|
extension::postgres::{Type, TypeCreateStatement},
|
||||||
@ -172,7 +172,7 @@ where
|
|||||||
stmt.col(&mut column_def);
|
stmt.col(&mut column_def);
|
||||||
}
|
}
|
||||||
|
|
||||||
if E::PrimaryKey::iter().count() > 1 {
|
if <<E::PrimaryKey as PrimaryKeyTrait>::ValueType as PrimaryKeyArity>::ARITY > 1 {
|
||||||
let mut idx_pk = Index::create();
|
let mut idx_pk = Index::create();
|
||||||
for primary_key in E::PrimaryKey::iter() {
|
for primary_key in E::PrimaryKey::iter() {
|
||||||
idx_pk.col(primary_key);
|
idx_pk.col(primary_key);
|
||||||
@ -228,7 +228,7 @@ where
|
|||||||
if E::PrimaryKey::auto_increment() {
|
if E::PrimaryKey::auto_increment() {
|
||||||
column_def.auto_increment();
|
column_def.auto_increment();
|
||||||
}
|
}
|
||||||
if E::PrimaryKey::iter().count() == 1 {
|
if <<E::PrimaryKey as PrimaryKeyTrait>::ValueType as PrimaryKeyArity>::ARITY == 1 {
|
||||||
column_def.primary_key();
|
column_def.primary_key();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user