@@ -283,22 +283,16 @@ pub fn parse_aggregate_param(
283283 if func. is_empty ( ) {
284284 return Err ( format ! ( "'{}': aggregate function is empty" , entry) ) ;
285285 }
286- let agg = parse_agg_name ( func) . ok_or_else ( || {
287- format ! (
288- "'{}': {}" ,
289- entry,
290- diagnose_invalid_function_name( func)
291- )
292- } ) ?;
286+ let agg = parse_agg_name ( func)
287+ . ok_or_else ( || format ! ( "'{}': {}" , entry, diagnose_invalid_function_name( func) ) ) ?;
293288 // Append to existing list for this aesthetic, or create one.
294289 if let Some ( ( _, fns) ) = spec. targets . iter_mut ( ) . find ( |( a, _) | a == aes) {
295290 fns. push ( agg) ;
296291 } else {
297292 spec. targets . push ( ( aes. to_string ( ) , vec ! [ agg] ) ) ;
298293 }
299294 } else {
300- let agg = parse_agg_name ( entry)
301- . ok_or_else ( || diagnose_invalid_function_name ( entry) ) ?;
295+ let agg = parse_agg_name ( entry) . ok_or_else ( || diagnose_invalid_function_name ( entry) ) ?;
302296 if spec. default_lower . is_none ( ) {
303297 spec. default_lower = Some ( agg) ;
304298 } else if spec. default_upper . is_none ( ) {
@@ -613,8 +607,7 @@ pub fn apply(
613607 None | Some ( ParameterValue :: Null ) => return Ok ( StatResult :: Identity ) ,
614608 Some ( v) => v,
615609 } ;
616- let spec = parse_aggregate_param ( raw)
617- . map_err ( GgsqlError :: ValidationError ) ?;
610+ let spec = parse_aggregate_param ( raw) . map_err ( GgsqlError :: ValidationError ) ?;
618611 let spec = match spec {
619612 Some ( s) => s,
620613 None => return Ok ( StatResult :: Identity ) ,
@@ -654,7 +647,8 @@ pub fn apply(
654647 let mut kept_cols: Vec < String > = Vec :: new ( ) ;
655648 let mut dropped: Vec < String > = Vec :: new ( ) ;
656649
657- let mut entries: Vec < ( & String , & crate :: AestheticValue ) > = aesthetics. aesthetics . iter ( ) . collect ( ) ;
650+ let mut entries: Vec < ( & String , & crate :: AestheticValue ) > =
651+ aesthetics. aesthetics . iter ( ) . collect ( ) ;
658652 entries. sort_by ( |a, b| a. 0 . cmp ( b. 0 ) ) ;
659653
660654 for ( aes, value) in entries {
@@ -682,7 +676,9 @@ pub fn apply(
682676 }
683677 } else {
684678 let default = if is_upper_half ( aes) {
685- spec. default_upper . clone ( ) . or_else ( || spec. default_lower . clone ( ) )
679+ spec. default_upper
680+ . clone ( )
681+ . or_else ( || spec. default_lower . clone ( ) )
686682 } else {
687683 spec. default_lower . clone ( )
688684 } ;
@@ -934,7 +930,12 @@ mod tests {
934930 }
935931
936932 fn arr ( items : & [ & str ] ) -> ParameterValue {
937- ParameterValue :: Array ( items. iter ( ) . map ( |s| ArrayElement :: String ( s. to_string ( ) ) ) . collect ( ) )
933+ ParameterValue :: Array (
934+ items
935+ . iter ( )
936+ . map ( |s| ArrayElement :: String ( s. to_string ( ) ) )
937+ . collect ( ) ,
938+ )
938939 }
939940
940941 // ---------- parser tests ----------
@@ -957,7 +958,9 @@ mod tests {
957958
958959 #[ test]
959960 fn parses_two_defaults_in_order ( ) {
960- let s = parse_aggregate_param ( & arr ( & [ "min" , "max" ] ) ) . unwrap ( ) . unwrap ( ) ;
961+ let s = parse_aggregate_param ( & arr ( & [ "min" , "max" ] ) )
962+ . unwrap ( )
963+ . unwrap ( ) ;
961964 assert_eq ! ( s. default_lower. as_ref( ) . map( |a| a. offset) , Some ( "min" ) ) ;
962965 assert_eq ! ( s. default_upper. as_ref( ) . map( |a| a. offset) , Some ( "max" ) ) ;
963966 }
@@ -982,12 +985,17 @@ mod tests {
982985 . unwrap ( ) ;
983986 assert_eq ! ( s. default_lower. as_ref( ) . map( |a| a. offset) , Some ( "mean" ) ) ;
984987 assert_eq ! ( target_funcs( & s, "y" ) . map( |fs| fs[ 0 ] . offset) , Some ( "max" ) ) ;
985- assert_eq ! ( target_funcs( & s, "color" ) . map( |fs| fs[ 0 ] . offset) , Some ( "median" ) ) ;
988+ assert_eq ! (
989+ target_funcs( & s, "color" ) . map( |fs| fs[ 0 ] . offset) ,
990+ Some ( "median" )
991+ ) ;
986992 }
987993
988994 #[ test]
989995 fn duplicate_target_explodes_into_a_list ( ) {
990- let s = parse_aggregate_param ( & arr ( & [ "y:min" , "y:max" ] ) ) . unwrap ( ) . unwrap ( ) ;
996+ let s = parse_aggregate_param ( & arr ( & [ "y:min" , "y:max" ] ) )
997+ . unwrap ( )
998+ . unwrap ( ) ;
991999 let fns = target_funcs ( & s, "y" ) . unwrap ( ) ;
9921000 assert_eq ! ( fns. len( ) , 2 ) ;
9931001 assert_eq ! ( fns[ 0 ] . offset, "min" ) ;
@@ -1044,7 +1052,9 @@ mod tests {
10441052 . unwrap ( ) ;
10451053 assert_eq ! ( s. explosion_labels( ) , None ) ;
10461054
1047- let s = parse_aggregate_param ( & arr ( & [ "mean" , "color:median" ] ) ) . unwrap ( ) . unwrap ( ) ;
1055+ let s = parse_aggregate_param ( & arr ( & [ "mean" , "color:median" ] ) )
1056+ . unwrap ( )
1057+ . unwrap ( ) ;
10481058 assert_eq ! ( s. explosion_labels( ) , None ) ;
10491059 }
10501060
@@ -1090,11 +1100,23 @@ mod tests {
10901100 . unwrap ( ) ;
10911101 assert_eq ! ( s. default_lower. as_ref( ) . unwrap( ) . offset, "mean" ) ;
10921102 assert_eq ! (
1093- s. default_lower. as_ref( ) . unwrap( ) . band. as_ref( ) . unwrap( ) . expansion,
1103+ s. default_lower
1104+ . as_ref( )
1105+ . unwrap( )
1106+ . band
1107+ . as_ref( )
1108+ . unwrap( )
1109+ . expansion,
10941110 "sdev"
10951111 ) ;
10961112 assert_eq ! (
1097- s. default_lower. as_ref( ) . unwrap( ) . band. as_ref( ) . unwrap( ) . sign,
1113+ s. default_lower
1114+ . as_ref( )
1115+ . unwrap( )
1116+ . band
1117+ . as_ref( )
1118+ . unwrap( )
1119+ . sign,
10981120 '-'
10991121 ) ;
11001122 assert_eq ! ( s. default_upper. as_ref( ) . unwrap( ) . offset, "mean" ) ;
@@ -1108,16 +1130,31 @@ mod tests {
11081130 let schema: Schema = vec ! [ ] ;
11091131 let p: HashMap < String , ParameterValue > = HashMap :: new ( ) ;
11101132 let ctx = cartesian_ctx ( ) ;
1111- let result = apply ( "SELECT * FROM t" , & schema, & aes, & [ ] , & p, & InlineQuantileDialect , & ctx)
1112- . unwrap ( ) ;
1133+ let result = apply (
1134+ "SELECT * FROM t" ,
1135+ & schema,
1136+ & aes,
1137+ & [ ] ,
1138+ & p,
1139+ & InlineQuantileDialect ,
1140+ & ctx,
1141+ )
1142+ . unwrap ( ) ;
11131143 assert_eq ! ( result, StatResult :: Identity ) ;
11141144 }
11151145
11161146 #[ test]
11171147 fn returns_identity_when_param_null ( ) {
11181148 let aes = Mappings :: new ( ) ;
11191149 let schema: Schema = vec ! [ ] ;
1120- let result = run ( ParameterValue :: Null , & aes, & schema, & [ ] , & InlineQuantileDialect ) . unwrap ( ) ;
1150+ let result = run (
1151+ ParameterValue :: Null ,
1152+ & aes,
1153+ & schema,
1154+ & [ ] ,
1155+ & InlineQuantileDialect ,
1156+ )
1157+ . unwrap ( ) ;
11211158 assert_eq ! ( result, StatResult :: Identity ) ;
11221159 }
11231160
@@ -1126,10 +1163,7 @@ mod tests {
11261163 let mut aes = Mappings :: new ( ) ;
11271164 aes. insert ( "pos1" , col ( "__ggsql_aes_pos1__" ) ) ;
11281165 aes. insert ( "pos2" , col ( "__ggsql_aes_pos2__" ) ) ;
1129- let schema = schema_for ( & [
1130- ( "__ggsql_aes_pos1__" , false ) ,
1131- ( "__ggsql_aes_pos2__" , false ) ,
1132- ] ) ;
1166+ let schema = schema_for ( & [ ( "__ggsql_aes_pos1__" , false ) , ( "__ggsql_aes_pos2__" , false ) ] ) ;
11331167 let result = run (
11341168 ParameterValue :: String ( "mean" . to_string ( ) ) ,
11351169 & aes,
@@ -1173,15 +1207,29 @@ mod tests {
11731207 ( "__ggsql_aes_pos1end__" , false ) ,
11741208 ( "__ggsql_aes_pos2end__" , false ) ,
11751209 ] ) ;
1176- let result = run ( arr ( & [ "min" , "max" ] ) , & aes, & schema, & [ ] , & InlineQuantileDialect )
1177- . unwrap ( ) ;
1210+ let result = run (
1211+ arr ( & [ "min" , "max" ] ) ,
1212+ & aes,
1213+ & schema,
1214+ & [ ] ,
1215+ & InlineQuantileDialect ,
1216+ )
1217+ . unwrap ( ) ;
11781218 match result {
11791219 StatResult :: Transformed { query, .. } => {
11801220 // pos1, pos2 use MIN; pos1end, pos2end use MAX.
11811221 assert ! ( query. contains( "MIN(\" __ggsql_aes_pos1__\" )" ) , "{}" , query) ;
11821222 assert ! ( query. contains( "MIN(\" __ggsql_aes_pos2__\" )" ) , "{}" , query) ;
1183- assert ! ( query. contains( "MAX(\" __ggsql_aes_pos1end__\" )" ) , "{}" , query) ;
1184- assert ! ( query. contains( "MAX(\" __ggsql_aes_pos2end__\" )" ) , "{}" , query) ;
1223+ assert ! (
1224+ query. contains( "MAX(\" __ggsql_aes_pos1end__\" )" ) ,
1225+ "{}" ,
1226+ query
1227+ ) ;
1228+ assert ! (
1229+ query. contains( "MAX(\" __ggsql_aes_pos2end__\" )" ) ,
1230+ "{}" ,
1231+ query
1232+ ) ;
11851233 assert ! ( !query. contains( "MIN(\" __ggsql_aes_pos1end__\" )" ) ) ;
11861234 assert ! ( !query. contains( "MAX(\" __ggsql_aes_pos1__\" )" ) ) ;
11871235 }
@@ -1213,10 +1261,7 @@ mod tests {
12131261 assert ! ( query. contains( "STDDEV_POP(\" __ggsql_aes_pos2max__\" )" ) ) ;
12141262 assert ! ( query. contains( "AVG(\" __ggsql_aes_pos2min__\" )" ) ) ;
12151263 // upper default (mean+sdev) goes to pos2max → '+' between AVG and STDDEV
1216- let pos2max_section = query
1217- . split ( "__ggsql_aes_pos2max__\" )" )
1218- . next ( )
1219- . unwrap_or ( "" ) ;
1264+ let pos2max_section = query. split ( "__ggsql_aes_pos2max__\" )" ) . next ( ) . unwrap_or ( "" ) ;
12201265 assert ! ( pos2max_section. contains( '+' ) || query. contains( "+ STDDEV_POP" ) ) ;
12211266 }
12221267 _ => panic ! ( "expected Transformed" ) ,
@@ -1228,10 +1273,7 @@ mod tests {
12281273 let mut aes = Mappings :: new ( ) ;
12291274 aes. insert ( "pos1" , col ( "__ggsql_aes_pos1__" ) ) ;
12301275 aes. insert ( "pos2" , col ( "__ggsql_aes_pos2__" ) ) ;
1231- let schema = schema_for ( & [
1232- ( "__ggsql_aes_pos1__" , false ) ,
1233- ( "__ggsql_aes_pos2__" , false ) ,
1234- ] ) ;
1276+ let schema = schema_for ( & [ ( "__ggsql_aes_pos1__" , false ) , ( "__ggsql_aes_pos2__" , false ) ] ) ;
12351277 let result = run (
12361278 arr ( & [ "mean" , "y:max" ] ) ,
12371279 & aes,
@@ -1270,7 +1312,11 @@ mod tests {
12701312 )
12711313 . unwrap ( ) ;
12721314 match result {
1273- StatResult :: Transformed { query, stat_columns, .. } => {
1315+ StatResult :: Transformed {
1316+ query,
1317+ stat_columns,
1318+ ..
1319+ } => {
12741320 assert ! ( query. contains( "QUANTILE_CONT(\" __ggsql_aes_size__\" , 0.5)" ) ) ;
12751321 assert ! ( stat_columns. contains( & "size" . to_string( ) ) ) ;
12761322 }
@@ -1300,7 +1346,11 @@ mod tests {
13001346 )
13011347 . unwrap ( ) ;
13021348 match result {
1303- StatResult :: Transformed { query, stat_columns, .. } => {
1349+ StatResult :: Transformed {
1350+ query,
1351+ stat_columns,
1352+ ..
1353+ } => {
13041354 assert ! ( query. contains( "MAX(\" __ggsql_aes_fill__\" )" ) , "{}" , query) ;
13051355 assert ! ( query. contains( "AVG(\" __ggsql_aes_pos1__\" )" ) ) ;
13061356 assert ! ( stat_columns. contains( & "fill" . to_string( ) ) ) ;
@@ -1316,12 +1366,15 @@ mod tests {
13161366 let mut aes = Mappings :: new ( ) ;
13171367 aes. insert ( "pos1" , col ( "__ggsql_aes_pos1__" ) ) ;
13181368 aes. insert ( "pos2" , col ( "__ggsql_aes_pos2__" ) ) ;
1319- let schema = schema_for ( & [
1320- ( "__ggsql_aes_pos1__" , false ) ,
1321- ( "__ggsql_aes_pos2__" , false ) ,
1322- ] ) ;
1323- let result = run ( arr ( & [ "y:min" , "y:max" ] ) , & aes, & schema, & [ ] , & InlineQuantileDialect )
1324- . unwrap ( ) ;
1369+ let schema = schema_for ( & [ ( "__ggsql_aes_pos1__" , false ) , ( "__ggsql_aes_pos2__" , false ) ] ) ;
1370+ let result = run (
1371+ arr ( & [ "y:min" , "y:max" ] ) ,
1372+ & aes,
1373+ & schema,
1374+ & [ ] ,
1375+ & InlineQuantileDialect ,
1376+ )
1377+ . unwrap ( ) ;
13251378 match result {
13261379 StatResult :: Transformed {
13271380 query,
@@ -1375,11 +1428,21 @@ mod tests {
13751428 assert ! ( query. contains( "MIN(\" __ggsql_aes_pos2__\" )" ) , "{}" , query) ;
13761429 assert ! ( query. contains( "MAX(\" __ggsql_aes_pos2__\" )" ) ) ;
13771430 // color (alias → fill) is recycled → QUANTILE_CONT(.5) appears in BOTH branches
1378- let median_count = query. matches ( "QUANTILE_CONT(\" __ggsql_aes_fill__\" , 0.5)" ) . count ( ) ;
1379- assert_eq ! ( median_count, 2 , "color median should appear once per branch: {}" , query) ;
1431+ let median_count = query
1432+ . matches ( "QUANTILE_CONT(\" __ggsql_aes_fill__\" , 0.5)" )
1433+ . count ( ) ;
1434+ assert_eq ! (
1435+ median_count, 2 ,
1436+ "color median should appear once per branch: {}" ,
1437+ query
1438+ ) ;
13801439 // size has no target → uses default 'mean' → AVG appears in both branches
13811440 let avg_size = query. matches ( "AVG(\" __ggsql_aes_size__\" )" ) . count ( ) ;
1382- assert_eq ! ( avg_size, 2 , "size mean should appear once per branch: {}" , query) ;
1441+ assert_eq ! (
1442+ avg_size, 2 ,
1443+ "size mean should appear once per branch: {}" ,
1444+ query
1445+ ) ;
13831446 // pos1 (no target) → mean → AVG appears in both branches
13841447 let avg_pos1 = query. matches ( "AVG(\" __ggsql_aes_pos1__\" )" ) . count ( ) ;
13851448 assert_eq ! ( avg_pos1, 2 ) ;
@@ -1416,7 +1479,11 @@ mod tests {
14161479 )
14171480 . unwrap ( ) ;
14181481 match result {
1419- StatResult :: Transformed { query, stat_columns, .. } => {
1482+ StatResult :: Transformed {
1483+ query,
1484+ stat_columns,
1485+ ..
1486+ } => {
14201487 assert ! ( query. contains( "UNION ALL" ) ) ;
14211488 // pos2max always uses mean+sdev (upper default) — a `+` between AVG and STDDEV
14221489 let upper_branch_marker = "AVG(\" __ggsql_aes_pos2max__\" ) + STDDEV_POP" ;
@@ -1456,7 +1523,11 @@ mod tests {
14561523 stat_columns,
14571524 ..
14581525 } => {
1459- assert ! ( query. contains( "GROUP BY \" __ggsql_aes_color__\" " ) , "{}" , query) ;
1526+ assert ! (
1527+ query. contains( "GROUP BY \" __ggsql_aes_color__\" " ) ,
1528+ "{}" ,
1529+ query
1530+ ) ;
14601531 assert ! ( !stat_columns. contains( & "color" . to_string( ) ) ) ;
14611532 assert ! ( query. contains( "AVG(\" __ggsql_aes_pos1__\" )" ) ) ;
14621533 assert ! ( query. contains( "AVG(\" __ggsql_aes_pos2__\" )" ) ) ;
@@ -1474,10 +1545,7 @@ mod tests {
14741545 "fill" ,
14751546 AestheticValue :: Literal ( ParameterValue :: String ( "steelblue" . to_string ( ) ) ) ,
14761547 ) ;
1477- let schema = schema_for ( & [
1478- ( "__ggsql_aes_pos1__" , false ) ,
1479- ( "__ggsql_aes_pos2__" , false ) ,
1480- ] ) ;
1548+ let schema = schema_for ( & [ ( "__ggsql_aes_pos1__" , false ) , ( "__ggsql_aes_pos2__" , false ) ] ) ;
14811549 let result = run (
14821550 ParameterValue :: String ( "mean" . to_string ( ) ) ,
14831551 & aes,
@@ -1501,10 +1569,7 @@ mod tests {
15011569 let mut aes = Mappings :: new ( ) ;
15021570 aes. insert ( "pos1" , col ( "__ggsql_aes_pos1__" ) ) ;
15031571 aes. insert ( "pos2" , col ( "__ggsql_aes_pos2__" ) ) ;
1504- let schema = schema_for ( & [
1505- ( "__ggsql_aes_pos1__" , false ) ,
1506- ( "__ggsql_aes_pos2__" , false ) ,
1507- ] ) ;
1572+ let schema = schema_for ( & [ ( "__ggsql_aes_pos1__" , false ) , ( "__ggsql_aes_pos2__" , false ) ] ) ;
15081573 // Only `y` targeted, no default → x is dropped.
15091574 let result = run (
15101575 ParameterValue :: String ( "y:mean" . to_string ( ) ) ,
@@ -1579,10 +1644,7 @@ mod tests {
15791644 let mut aes = Mappings :: new ( ) ;
15801645 aes. insert ( "pos1" , col ( "__ggsql_aes_pos1__" ) ) ;
15811646 aes. insert ( "pos2" , col ( "__ggsql_aes_pos2__" ) ) ;
1582- let schema = schema_for ( & [
1583- ( "__ggsql_aes_pos1__" , false ) ,
1584- ( "__ggsql_aes_pos2__" , false ) ,
1585- ] ) ;
1647+ let schema = schema_for ( & [ ( "__ggsql_aes_pos1__" , false ) , ( "__ggsql_aes_pos2__" , false ) ] ) ;
15861648 let err = run (
15871649 ParameterValue :: String ( "size:mean" . to_string ( ) ) ,
15881650 & aes,
0 commit comments