@@ -7,8 +7,8 @@ use sea_orm::prelude::{Expr, Json};
77use sea_orm:: sea_query:: Query ;
88use sea_orm:: { sqlx:: types:: chrono:: Utc , EntityTrait } ;
99use sea_orm:: {
10- ActiveModelTrait , ColumnTrait , DbBackend , DbErr , DeleteResult , EntityOrSelect , ModelTrait ,
11- QueryFilter , QueryOrder , QuerySelect , QueryTrait , RuntimeErr , TransactionTrait ,
10+ ActiveModelTrait , ColumnTrait , Condition , DbBackend , DbErr , DeleteResult , EntityOrSelect ,
11+ ModelTrait , QueryFilter , QueryOrder , QuerySelect , QueryTrait , RuntimeErr , TransactionTrait ,
1212} ;
1313use serde_json:: json;
1414
@@ -18,8 +18,10 @@ use super::interface::{
1818} ;
1919
2020impl BackendManager {
21- fn get_description_from_attr_ids ( & self , attr_ids : Vec < AttrId > ) -> String {
22- let mut attr_ids = attr_ids;
21+ /// The description is to concat `attr_ids` using commas
22+ /// Note that `attr_ids` should be sorted before concatenation
23+ /// e.g. [1, 2, 3] -> "1,2,3"
24+ fn get_description_from_attr_ids ( & self , mut attr_ids : Vec < AttrId > ) -> String {
2325 attr_ids. sort ( ) ;
2426 attr_ids
2527 . iter ( )
@@ -399,9 +401,6 @@ impl CostModelStorageLayer for BackendManager {
399401 epoch_id : Option < EpochId > ,
400402 ) -> StorageResult < Option < Json > > {
401403 let attr_num = attr_ids. len ( ) as i32 ;
402- // The description is to concat `attr_ids` using commas
403- // Note that `attr_ids` should be sorted before concatenation
404- // e.g. [1, 2, 3] -> "1,2,3"
405404 attr_ids. sort ( ) ;
406405 let description = self . get_description_from_attr_ids ( attr_ids) ;
407406
@@ -429,6 +428,37 @@ impl CostModelStorageLayer for BackendManager {
429428 }
430429 }
431430
431+ async fn get_stats_for_attr_indices_based (
432+ & self ,
433+ table_id : TableId ,
434+ attr_base_indices : Vec < i32 > ,
435+ stat_type : StatType ,
436+ epoch_id : Option < EpochId > ,
437+ ) -> StorageResult < Option < Json > > {
438+ // Get the attribute ids based on table id and attribute base indices
439+ let mut condition = Condition :: any ( ) ;
440+ for attr_base_index in & attr_base_indices {
441+ condition = condition. add ( attribute:: Column :: BaseAttributeNumber . eq ( * attr_base_index) ) ;
442+ }
443+ let attr_ids = Attribute :: find ( )
444+ . filter ( attribute:: Column :: TableId . eq ( table_id) )
445+ . filter ( condition)
446+ . all ( & self . db )
447+ . await ?
448+ . iter ( )
449+ . map ( |attr| attr. id )
450+ . collect :: < Vec < _ > > ( ) ;
451+
452+ if attr_ids. len ( ) != attr_base_indices. len ( ) {
453+ return Err ( BackendError :: BackendError ( format ! (
454+ "Not all attributes found for table_id {} and base indices {:?}" ,
455+ table_id, attr_base_indices
456+ ) ) ) ;
457+ }
458+
459+ self . get_stats_for_attr ( attr_ids, stat_type, epoch_id) . await
460+ }
461+
432462 /// TODO: documentation
433463 async fn get_cost_analysis (
434464 & self ,
@@ -1212,4 +1242,42 @@ mod tests {
12121242
12131243 remove_db_file ( DATABASE_FILE ) ;
12141244 }
1245+
1246+ #[ tokio:: test]
1247+ async fn test_get_stats_for_attr_indices_based ( ) {
1248+ const DATABASE_FILE : & str = "test_get_stats_for_attr_indices_based.db" ;
1249+ let database_url = copy_init_db ( DATABASE_FILE ) . await ;
1250+ let mut binding = super :: BackendManager :: new ( Some ( & database_url) ) . await ;
1251+ let backend_manager = binding. as_mut ( ) . unwrap ( ) ;
1252+ let epoch_id = 1 ;
1253+ let table_id = 1 ;
1254+ let attr_base_indices = vec ! [ 0 , 1 ] ;
1255+ let stat_type = StatType :: Cardinality ;
1256+
1257+ // Statistics exist in the database
1258+ let res = backend_manager
1259+ . get_stats_for_attr_indices_based ( table_id, attr_base_indices. clone ( ) , stat_type, None )
1260+ . await
1261+ . unwrap ( )
1262+ . unwrap ( ) ;
1263+ let cardinality = res. as_i64 ( ) . unwrap ( ) ;
1264+ assert_eq ! ( cardinality, 0 ) ;
1265+
1266+ // Statistics do not exist in the database
1267+ let attr_base_indices = vec ! [ 1 ] ;
1268+ let res = backend_manager
1269+ . get_stats_for_attr_indices_based ( table_id, attr_base_indices. clone ( ) , stat_type, None )
1270+ . await
1271+ . unwrap ( ) ;
1272+ assert ! ( res. is_none( ) ) ;
1273+
1274+ // Attribute base indices not valid.
1275+ let attr_base_indices = vec ! [ 1 , 2 ] ;
1276+ let res = backend_manager
1277+ . get_stats_for_attr_indices_based ( table_id, attr_base_indices. clone ( ) , stat_type, None )
1278+ . await ;
1279+ assert ! ( res. is_err( ) ) ;
1280+
1281+ remove_db_file ( DATABASE_FILE ) ;
1282+ }
12151283}
0 commit comments