@ -6,6 +6,10 @@ use sqlx::FromRow;
pub trait TableName {
const TABLE_NAME : & ' static str ;
}
pub trait NameTableName {
const NAME_TABLE_NAME : & ' static str ;
const NAME_TABLE_FK_NAME : & ' static str ;
}
macro_rules! impl_table_name {
( $ty :ident , $tname :literal ) = > {
impl TableName for $ty {
@ -13,6 +17,14 @@ macro_rules! impl_table_name {
}
} ;
}
macro_rules! impl_name_table_name {
( $ty :ident , $tname :literal , $fk_name :literal ) = > {
impl NameTableName for $ty {
const NAME_TABLE_NAME : & ' static str = $tname ;
const NAME_TABLE_FK_NAME : & ' static str = $fk_name ;
}
} ;
}
#[ derive(FromRow, Serialize, Deserialize, Debug, ormx::Table) ]
#[ ormx(table = " supported_languages " , id = id, insertable, deletable) ]
@ -23,59 +35,174 @@ pub struct Language {
pub short_name : String ,
}
#[ derive(FromRow, Serialize, Deserialize, Debug, ormx::Table) ]
#[ ormx(table = " leagues " , id = id, insertable, deletable) ]
macro_rules! impl_localized_get {
( $struct :ident , $func :ident ) = > {
impl $struct {
pub async fn get ( pool : & sqlx ::PgPool , id : i32 , lang : crate ::SupportedLanguage ) -> Result < Option < Self > , sqlx ::Error > {
let query = const_format ::formatcp ! ( r #"
SELECT
{ 0 } . * ,
{ 1 } ( { 0 } . id , $ 2 ) AS name
FROM { 0 }
WHERE { 0 } . id = $ 1 ; " #,
stringify! ( < $struct as TableName > ::TABLE_NAME ) ,
stringify! ( $func ) ,
) ;
sqlx ::query_as ::< _ , $struct > ( & query )
. bind ( id )
. bind ( lang )
. fetch_optional ( pool )
. await
}
}
} ;
}
macro_rules! impl_localized_get_by_many {
( $struct :ident , $by :ident ) = > {
impl $struct {
#[ rename::rename_fn(prepend= " by_ " ) ]
pub async fn $by ( pool : & sqlx ::PgPool , by : i32 , lang : crate ::SupportedLanguage ) -> Result < Vec < Self > , sqlx ::Error > {
let query = format! ( r #"
SELECT
{ 0 } . * ,
- - if available , use the localized name ,
- - if not , choose the default name ( in English , CA )
- - if not , see if there is any name attached ( there should be at least some language selected )
COALESCE (
localized_name . name ,
default_name . name ,
any_name . name
) AS name
FROM { 0 }
- - search for the proper , localized name
LEFT JOIN { 1 } localized_name
ON localized_name . { 2 } = { 0 } . id
AND localized_name . language = $ 2
- - also look for the name in the default language ( English , CA )
LEFT JOIN { 1 } default_name
ON default_name . { 2 } = { 0 } . id
AND default_name . language = 1
- - also look for ANY matching name in ANY locale
LEFT JOIN { 1 } any_name
ON any_name . { 2 } = { 0 } . id
WHERE { 0 } . { 3 } = $ 1 ; " #,
< $struct as TableName > ::TABLE_NAME ,
< $struct as NameTableName > ::NAME_TABLE_NAME ,
< $struct as NameTableName > ::NAME_TABLE_FK_NAME ,
stringify! ( $by ) ,
) ;
sqlx ::query_as ::< _ , $struct > ( & query )
. bind ( by )
. bind ( lang )
. fetch_all ( pool )
. await
}
}
} ;
}
macro_rules! impl_localized_all {
( $struct :ident ) = > {
impl $struct {
pub async fn all ( pool : & sqlx ::PgPool , lang : crate ::SupportedLanguage ) -> Result < Vec < Self > , sqlx ::Error > {
let query = format! ( r #"
SELECT
{ 0 } . * ,
- - if available , use the localized name ,
- - if not , choose the default name ( in English , CA )
- - if not , see if there is any name attached ( there should be at least some language selected )
COALESCE (
localized_name . name ,
default_name . name ,
any_name . name
) AS name
FROM { 0 }
- - search for the proper , localized name
LEFT JOIN { 1 } localized_name
ON localized_name . { 2 } = { 0 } . id
AND localized_name . language = $ 1
- - also look for the name in the default language ( English , CA )
LEFT JOIN { 1 } default_name
ON default_name . { 2 } = { 0 } . id
AND default_name . language = 1
- - also look for ANY matching name in ANY locale
LEFT JOIN { 1 } any_name
ON any_name . { 2 } = { 0 } . id ; " #,
< $struct as TableName > ::TABLE_NAME ,
< $struct as NameTableName > ::NAME_TABLE_NAME ,
< $struct as NameTableName > ::NAME_TABLE_FK_NAME ,
) ;
sqlx ::query_as ::< _ , $struct > ( & query )
. bind ( lang )
. fetch_all ( pool )
. await
}
}
} ;
}
#[ derive(FromRow, Serialize, Deserialize, Debug, NameTableName) ]
#[ table_names(table_name = " leagues " , name_func = " league_name " , name_table_name = " league_names " , name_table_name_fk = " league " ) ]
pub struct League {
#[ ormx(default) ]
//#[ormx(default)]
pub id : i32 ,
pub name : String ,
pub name : Option< String> ,
}
//impl_localized_get!(League, league_name);
impl_localized_all ! ( League ) ;
/*
#[ derive(FromRow, Serialize, Deserialize, Debug, ormx::Patch) ]
#[ ormx(table_name = " leagues " , table = League, id = " id " ) ]
pub struct NewLeague {
pub name : String ,
pub name : String ,
}
* /
#[ derive(FromRow, Serialize, Deserialize, Debug, ormx::Table) ]
#[ ormx(table = " divisions " , id = id, insertable, deletable) ]
#[ derive(FromRow, Serialize, Deserialize, Debug )]
//#[ormx(table = "divisions", id = id, insertable, deletable)]
pub struct Division {
#[ ormx(default) ]
//#[ormx(default)]
pub id : i32 ,
pub name : String ,
#[ ormx(get_many(i32)) ]
//#[ormx(get_many(i32))]
pub league : i32 ,
pub name : Option < String > ,
}
impl_localized_get ! ( Division , division_name ) ;
impl_localized_get_by_many ! ( Division , league ) ;
impl_localized_all ! ( Division ) ;
#[ derive(FromRow, Serialize, Deserialize, Debug, ormx::Patch) ]
#[ ormx(table_name = " divisions " , table = Division, id = " id " ) ]
#[ derive(FromRow, Serialize, Deserialize, Debug )]
//#[ormx(table_name = "divisions", table = Division, id = "id")]
pub struct NewDivision {
pub name : String ,
pub league : i32 ,
}
#[ derive(FromRow, Serialize, Deserialize, Debug, ormx::Table) ]
#[ ormx(table = " teams " , id = id, insertable, deletable) ]
#[ derive(FromRow, Serialize, Deserialize, Debug )]
//#[ormx(table = "teams", id = id, insertable, deletable)]
pub struct Team {
#[ ormx(default) ]
//#[ormx(default)]
pub id : i32 ,
pub name : String ,
pub division : i32 ,
pub image : Option < String > ,
pub name : Option < String > ,
}
impl_localized_get ! ( Team , team_name ) ;
/*
#[ derive(FromRow, Serialize, Deserialize, Debug, ormx::Patch) ]
#[ ormx(table_name = " teams " , table = Team, id = " id " ) ]
pub struct NewTeam {
pub name : String ,
pub division : i32 ,
}
* /
#[ derive(FromRow, Serialize, Deserialize, Debug, ormx::Table) ]
#[ ormx(table = " players " , id = id, insertable, deletable) ]
pub struct Player {
#[ ormx(default) ]
//#[ormx(default)]
pub id : i32 ,
pub name : String ,
pub first_names : String ,
pub last_name : String ,
pub weight_kg : Option < i32 > ,
pub height_cm : Option < i32 > ,
}
@ -95,7 +222,8 @@ impl Player {
#[ derive(FromRow, Deserialize, Serialize, Debug, ormx::Patch) ]
#[ ormx(table_name = " players " , table = Player, id = " id " ) ]
pub struct NewPlayer {
pub name : String ,
pub first_names : String ,
pub last_name : String ,
pub weight_kg : Option < i32 > ,
pub height_cm : Option < i32 > ,
}
@ -130,17 +258,19 @@ pub struct GamePlayer {
pub game : i32 ,
}
#[ derive(FromRow, Deserialize, Serialize, Debug , ormx::Table )]
#[ ormx(table = " games " , id = id, insertable, deletable) ]
#[ derive(FromRow, Deserialize, Serialize, Debug )]
//#[ormx(table = "games", id = id, insertable, deletable)]
pub struct Game {
#[ ormx(default) ]
//#[ormx(default)]
pub id : i32 ,
#[ ormx(get_many(i32)) ]
//#[ormx(get_many(i32))]
pub division : i32 ,
pub name : String ,
pub team_home : i32 ,
pub team_away : i32 ,
pub name : Option < String > ,
}
impl_localized_get ! ( Game , game_name ) ;
impl_localized_get_by_many ! ( Game , division ) ;
#[ derive(FromRow, Deserialize, Serialize, Debug, ormx::Table) ]
#[ ormx(table = " periods " , id = id, insertable, deletable) ]
@ -154,10 +284,14 @@ pub struct Period {
impl_table_name ! ( GamePlayer , "game_players" ) ;
impl_table_name ! ( Player , "players" ) ;
impl_table_name ! ( League , "leagues" ) ;
//impl_name_table_name!(League, "league_names", "league");
impl_table_name ! ( Division , "divisions" ) ;
impl_name_table_name ! ( Division , "division_names" , "division" ) ;
impl_table_name ! ( Team , "teams" ) ;
impl_name_table_name ! ( Team , "team_names" , "team" ) ;
impl_table_name ! ( Shot , "shots" ) ;
impl_table_name ! ( Game , "games" ) ;
impl_name_table_name ! ( Game , "game_names" , "game" ) ;
impl_table_name ! ( Period , "periods" ) ;
impl_table_name ! ( Language , "supported_languages" ) ;
@ -197,7 +331,7 @@ mod tests {
let player = Player ::from_name_case_insensitive ( & pool , "tait-hoyem" . to_string ( ) ) . await ;
assert! ( player . is_some ( ) ) ;
let player = player . unwrap ( ) ;
assert_eq! ( player . name, "Tait Hoyem ") ;
assert_eq! ( player . first_ names , "Tait ") ;
} )
}