44//! transformations, stat transforms, and post-query operations.
55
66use crate :: plot:: {
7- AestheticValue , DefaultAestheticValue , Layer , ParameterValue , Scale , Schema , SqlTypeNames ,
8- StatResult ,
7+ AestheticValue , DefaultAestheticValue , Layer , ParameterValue , Scale , Schema , StatResult ,
98} ;
9+ use crate :: reader:: SqlDialect ;
1010use crate :: { naming, DataFrame , GgsqlError , Result } ;
1111use polars:: prelude:: DataType ;
1212use std:: collections:: { HashMap , HashSet } ;
@@ -150,6 +150,17 @@ pub fn apply_remappings_post_query(df: DataFrame, layer: &Layer) -> Result<DataF
150150 }
151151 }
152152
153+ // Drop any remaining __ggsql_stat_* columns that weren't consumed by remappings.
154+ let stat_cols: Vec < String > = df
155+ . get_column_names ( )
156+ . into_iter ( )
157+ . filter ( |name| naming:: is_stat_column ( name) )
158+ . map ( |name| name. to_string ( ) )
159+ . collect ( ) ;
160+ if !stat_cols. is_empty ( ) {
161+ df = df. drop_many ( stat_cols) ;
162+ }
163+
153164 Ok ( df)
154165}
155166
@@ -183,14 +194,14 @@ pub fn literal_to_series(name: &str, lit: &ParameterValue, len: usize) -> polars
183194/// * `layer` - The layer configuration
184195/// * `schema` - The layer's schema (used for column dtype lookup)
185196/// * `scales` - All resolved scales
186- /// * `type_names ` - SQL type names for the database backend
197+ /// * `dialect ` - SQL dialect for the database backend
187198pub fn apply_pre_stat_transform (
188199 query : & str ,
189200 layer : & Layer ,
190201 full_schema : & Schema ,
191202 aesthetic_schema : & Schema ,
192203 scales : & [ Scale ] ,
193- type_names : & SqlTypeNames ,
204+ dialect : & dyn SqlDialect ,
194205) -> String {
195206 let mut transform_exprs: Vec < ( String , String ) > = vec ! [ ] ;
196207 let mut transformed_columns: HashSet < String > = HashSet :: new ( ) ;
@@ -226,7 +237,7 @@ pub fn apply_pre_stat_transform(
226237 // Get pre-stat SQL transformation from scale type (if applicable)
227238 // Each scale type's pre_stat_transform_sql() returns None if not applicable
228239 if let Some ( sql) =
229- scale_type. pre_stat_transform_sql ( & aes_col_name, & col_dtype, scale, type_names )
240+ scale_type. pre_stat_transform_sql ( & aes_col_name, & col_dtype, scale, dialect )
230241 {
231242 transformed_columns. insert ( aes_col_name. clone ( ) ) ;
232243 transform_exprs. push ( ( aes_col_name, sql) ) ;
@@ -336,7 +347,7 @@ pub fn build_layer_base_query(
336347/// * `base_query` - The base query from build_layer_base_query
337348/// * `schema` - The layer's schema (with min/max from base_query)
338349/// * `scales` - All resolved scales
339- /// * `type_names ` - SQL type names for the database backend
350+ /// * `dialect ` - SQL dialect for the database backend
340351/// * `execute_query` - Function to execute queries (needed for some stat transforms)
341352///
342353/// # Returns
@@ -347,7 +358,7 @@ pub fn apply_layer_transforms<F>(
347358 base_query : & str ,
348359 schema : & Schema ,
349360 scales : & [ Scale ] ,
350- type_names : & SqlTypeNames ,
361+ dialect : & dyn SqlDialect ,
351362 execute_query : & F ,
352363) -> Result < String >
353364where
@@ -387,7 +398,7 @@ where
387398 schema,
388399 & aesthetic_schema,
389400 scales,
390- type_names ,
401+ dialect ,
391402 ) ;
392403
393404 // Build group_by columns from partition_by
@@ -416,6 +427,7 @@ where
416427 & group_by,
417428 & layer. parameters ,
418429 execute_query,
430+ dialect,
419431 ) ?;
420432
421433 // Apply literal default remappings from geom defaults (e.g., y2 => 0.0 for bar baseline).
@@ -518,12 +530,6 @@ where
518530 if stat_rename_exprs. is_empty ( ) {
519531 transformed_query
520532 } else {
521- let stat_col_names: Vec < String > = stat_columns
522- . iter ( )
523- . map ( |s| naming:: stat_column ( s) )
524- . collect ( ) ;
525- let exclude_clause = format ! ( "EXCLUDE ({})" , stat_col_names. join( ", " ) ) ;
526-
527533 // If the transformed query uses CTEs (WITH ... SELECT ...),
528534 // we can't wrap it in a subquery because Polars SQL doesn't
529535 // support CTEs inside subqueries. Instead, split into CTE
@@ -536,16 +542,14 @@ where
536542 . and_then ( super :: cte:: split_with_query)
537543 {
538544 format ! (
539- "{}, __ggsql_stat__ AS ({}) SELECT * {} , {} FROM __ggsql_stat__" ,
545+ "{}, __ggsql_stat__ AS ({}) SELECT *, {} FROM __ggsql_stat__" ,
540546 cte_prefix,
541547 trailing_select,
542- exclude_clause,
543548 stat_rename_exprs. join( ", " )
544549 )
545550 } else {
546551 format ! (
547- "SELECT * {}, {} FROM ({}) AS __ggsql_stat__" ,
548- exclude_clause,
552+ "SELECT *, {} FROM ({}) AS __ggsql_stat__" ,
549553 stat_rename_exprs. join( ", " ) ,
550554 transformed_query
551555 )
0 commit comments