@@ -217,6 +217,25 @@ async fn run_examples(ctx: &SessionContext) -> Result<()> {
217217 +--------+
218218 " ) ;
219219
220+ // Example 7: PIVOT on a quoted mixed-case column
221+ // Reuses the parsed column expression so quoted identifiers keep their case.
222+ let results = run_example (
223+ ctx,
224+ "Example 7: PIVOT with quoted mixed-case column" ,
225+ r#"SELECT * FROM point_stats
226+ PIVOT (MAX(max_value) FOR "pointNumber" IN ('16951' AS p16951, '16952' AS p16952)) AS p
227+ ORDER BY ts"# ,
228+ )
229+ . await ?;
230+ assert_snapshot ! ( results, @r"
231+ +----------------------+-------+--------+--------+
232+ | ts | port | p16951 | p16952 |
233+ +----------------------+-------+--------+--------+
234+ | 2024-09-01T10:00:00Z | 2411 | 10 | 20 |
235+ | 2024-09-01T10:01:00Z | 2411 | 30 | 40 |
236+ +----------------------+-------+--------+--------+
237+ " ) ;
238+
220239 Ok ( ( ) )
221240}
222241
@@ -288,6 +307,31 @@ fn register_sample_data(ctx: &SessionContext) -> Result<()> {
288307 ] ) ?,
289308 ) ?;
290309
310+ // point_stats: grouped data with a quoted mixed-case pivot column.
311+ ctx. register_batch (
312+ "point_stats" ,
313+ RecordBatch :: try_from_iter ( vec ! [
314+ (
315+ "ts" ,
316+ Arc :: new( StringArray :: from( vec![
317+ "2024-09-01T10:00:00Z" ,
318+ "2024-09-01T10:00:00Z" ,
319+ "2024-09-01T10:01:00Z" ,
320+ "2024-09-01T10:01:00Z" ,
321+ ] ) ) as ArrayRef ,
322+ ) ,
323+ (
324+ "pointNumber" ,
325+ Arc :: new( StringArray :: from( vec![ "16951" , "16952" , "16951" , "16952" ] ) ) ,
326+ ) ,
327+ (
328+ "port" ,
329+ Arc :: new( StringArray :: from( vec![ "2411" , "2411" , "2411" , "2411" ] ) ) ,
330+ ) ,
331+ ( "max_value" , Arc :: new( Int64Array :: from( vec![ 10 , 20 , 30 , 40 ] ) ) ) ,
332+ ] ) ?,
333+ ) ?;
334+
291335 Ok ( ( ) )
292336}
293337
@@ -415,11 +459,12 @@ fn plan_pivot(
415459 . collect ( ) ;
416460
417461 let group_by_cols: Vec < Expr > = schema
418- . fields ( )
419462 . iter ( )
420- . map ( |f| f. name ( ) . as_str ( ) )
421- . filter ( |name| * name != pivot_col_name. as_str ( ) && !agg_input_cols. contains ( name) )
422- . map ( col)
463+ . filter ( |( _, field) | {
464+ let name = field. name ( ) ;
465+ name != pivot_col_name. as_str ( ) && !agg_input_cols. contains ( & name. as_str ( ) )
466+ } )
467+ . map ( Expr :: from)
423468 . collect ( ) ;
424469
425470 // Build CASE expressions for each (aggregate, pivot_value) pair
@@ -434,7 +479,7 @@ fn plan_pivot(
434479
435480 for ( value_alias, pivot_value) in & pivot_values {
436481 // CASE pivot_col WHEN pivot_value THEN agg_input END
437- let case_expr = case ( col ( & pivot_col_name ) )
482+ let case_expr = case ( pivot_col . clone ( ) )
438483 . when ( pivot_value. clone ( ) , agg_input. clone ( ) )
439484 . end ( ) ?;
440485
0 commit comments