@@ -37,7 +37,7 @@ use crate::logical_plan::{
37
37
use crate :: optimizer:: utils:: exprlist_to_columns;
38
38
use crate :: prelude:: JoinType ;
39
39
use crate :: scalar:: ScalarValue ;
40
- use crate :: sql:: utils:: { make_decimal_type, normalize_ident} ;
40
+ use crate :: sql:: utils:: { make_decimal_type, normalize_ident, resolve_columns } ;
41
41
use crate :: {
42
42
error:: { DataFusionError , Result } ,
43
43
physical_plan:: aggregates,
@@ -1144,30 +1144,45 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
1144
1144
group_by_exprs : Vec < Expr > ,
1145
1145
aggr_exprs : Vec < Expr > ,
1146
1146
) -> Result < ( LogicalPlan , Vec < Expr > , Option < Expr > ) > {
1147
+ // create the aggregate plan
1148
+ let plan = LogicalPlanBuilder :: from ( input. clone ( ) )
1149
+ . aggregate ( group_by_exprs. clone ( ) , aggr_exprs. clone ( ) ) ?
1150
+ . build ( ) ?;
1151
+
1152
+ // in this next section of code we are re-writing the projection to refer to columns
1153
+ // output by the aggregate plan. For example, if the projection contains the expression
1154
+ // `SUM(a)` then we replace that with a reference to a column `#SUM(a)` produced by
1155
+ // the aggregate plan.
1156
+
1157
+ // combine the original grouping and aggregate expressions into one list (note that
1158
+ // we do not add the "having" expression since that is not part of the projection)
1147
1159
let aggr_projection_exprs = group_by_exprs
1148
1160
. iter ( )
1149
1161
. chain ( aggr_exprs. iter ( ) )
1150
1162
. cloned ( )
1151
1163
. collect :: < Vec < Expr > > ( ) ;
1152
1164
1153
- let plan = LogicalPlanBuilder :: from ( input. clone ( ) )
1154
- . aggregate ( group_by_exprs, aggr_exprs) ?
1155
- . build ( ) ?;
1165
+ // now attempt to resolve columns and replace with fully-qualified columns
1166
+ let aggr_projection_exprs = aggr_projection_exprs
1167
+ . iter ( )
1168
+ . map ( |expr| resolve_columns ( expr, & input) )
1169
+ . collect :: < Result < Vec < Expr > > > ( ) ?;
1156
1170
1157
- // After aggregation, these are all of the columns that will be
1158
- // available to next phases of planning.
1171
+ // next we replace any expressions that are not a column with a column referencing
1172
+ // an output column from the aggregate schema
1159
1173
let column_exprs_post_aggr = aggr_projection_exprs
1160
1174
. iter ( )
1161
1175
. map ( |expr| expr_as_column_expr ( expr, & input) )
1162
1176
. collect :: < Result < Vec < Expr > > > ( ) ?;
1163
1177
1164
- // Rewrite the SELECT expression to use the columns produced by the
1165
- // aggregation.
1178
+ // next we re-write the projection
1166
1179
let select_exprs_post_aggr = select_exprs
1167
1180
. iter ( )
1168
1181
. map ( |expr| rebase_expr ( expr, & aggr_projection_exprs, & input) )
1169
1182
. collect :: < Result < Vec < Expr > > > ( ) ?;
1170
1183
1184
+ // finally, we have some validation that the re-written projection can be resolved
1185
+ // from the aggregate output columns
1171
1186
check_columns_satisfy_exprs (
1172
1187
& column_exprs_post_aggr,
1173
1188
& select_exprs_post_aggr,
0 commit comments