@@ -332,6 +332,8 @@ impl SqlToMirConverter {
332332 . transpose ( ) ?,
333333 limit,
334334 make_topk,
335+ // TODO: we should have access to the output cols even if this is a compound query
336+ None ,
335337 ) ?
336338 . last ( )
337339 . unwrap ( ) ;
@@ -1305,6 +1307,7 @@ impl SqlToMirConverter {
13051307 order : & Option < Vec < ( Expr , OrderType ) > > ,
13061308 limit : usize ,
13071309 is_topk : bool ,
1310+ outputs : Option < & Vec < OutputColumn > > ,
13081311 ) -> ReadySetResult < Vec < NodeIndex > > {
13091312 if !self . config . allow_topk && is_topk {
13101313 unsupported ! ( "TopK is not supported" ) ;
@@ -1314,37 +1317,78 @@ impl SqlToMirConverter {
13141317
13151318 // Gather a list of expressions we need to evaluate before the paginate node
13161319 let mut exprs_to_project = vec ! [ ] ;
1317- let order = order. as_ref ( ) . map ( |oc| {
1318- oc. iter ( )
1319- . map ( |( expr, ot) | {
1320- (
1321- match expr {
1322- Expr :: Column ( col) => Column :: from ( col) ,
1323- expr => {
1324- let col = Column :: named (
1325- // FIXME(REA-2168+2502): Use correct dialect.
1326- expr. display ( readyset_sql:: Dialect :: MySQL ) . to_string ( ) ,
1327- ) ;
1328- if self
1329- . mir_graph
1330- . column_id_for_column ( parent, & col)
1331- . err ( )
1320+
1321+ let order = order
1322+ . clone ( )
1323+ . unwrap_or_default ( )
1324+ . iter ( )
1325+ . map ( |( expr, ot) | {
1326+ let col = match expr {
1327+ Expr :: Column ( col) => {
1328+ let col = Column :: from ( col) ;
1329+ match self . mir_graph . column_id_for_column ( parent, & col) {
1330+ Ok ( _) => Ok ( col) ,
1331+ Err ( ReadySetError :: NonExistentColumn { .. } ) => {
1332+ // we couldn't find this column in the parent, this means
1333+ // that either:
1334+ // 1. the col is referencing an alias
1335+ // 2. the col is referencing a col that doesn't even exist
1336+ // We pass the list of output cols to check their aliases,
1337+ // if we couldn't find the outputs then mark the column
1338+ // as non-existent
1339+ let outputs =
1340+ outputs. ok_or_else ( || ReadySetError :: NonExistentColumn {
1341+ column : col. name . to_string ( ) ,
1342+ node : self . mir_graph [ parent]
1343+ . name ( )
1344+ . display_unquoted ( )
1345+ . to_string ( ) ,
1346+ } ) ?;
1347+ let resolved_expr = outputs
13321348 . iter ( )
1333- . any ( |err| {
1334- matches ! ( err, ReadySetError :: NonExistentColumn { .. } )
1349+ . find_map ( |o| {
1350+ if * o. name ( ) == * col. name {
1351+ Some ( o. clone ( ) . into_expr ( ) )
1352+ } else {
1353+ None
1354+ }
13351355 } )
1336- {
1337- // Only project the expression if we haven't already
1338- exprs_to_project. push ( expr. clone ( ) ) ;
1339- }
1340- col
1356+ . ok_or_else ( || ReadySetError :: NonExistentColumn {
1357+ column : col. name . to_string ( ) ,
1358+ node : self . mir_graph [ parent]
1359+ . name ( )
1360+ . display_unquoted ( )
1361+ . to_string ( ) ,
1362+ } ) ?;
1363+
1364+ exprs_to_project. push ( ( resolved_expr, Some ( col. name . clone ( ) ) ) ) ;
1365+ Ok ( col)
13411366 }
1342- } ,
1343- * ot,
1344- )
1345- } )
1346- . collect ( )
1347- } ) ;
1367+ Err ( e) => Err ( e) ,
1368+ }
1369+ }
1370+ expr => {
1371+ let col = Column :: named (
1372+ // FIXME(REA-2168+2502): Use correct dialect.
1373+ expr. display ( readyset_sql:: Dialect :: MySQL ) . to_string ( ) ,
1374+ ) ;
1375+ if self
1376+ . mir_graph
1377+ . column_id_for_column ( parent, & col)
1378+ . err ( )
1379+ . iter ( )
1380+ . any ( |err| matches ! ( err, ReadySetError :: NonExistentColumn { .. } ) )
1381+ {
1382+ // Only project the expression if we haven't already
1383+ exprs_to_project. push ( ( expr. clone ( ) , None ) ) ;
1384+ }
1385+ Ok ( col)
1386+ }
1387+ } ?;
1388+
1389+ Ok ( ( col, * ot) )
1390+ } )
1391+ . collect :: < ReadySetResult < Vec < _ > > > ( ) ?;
13481392
13491393 let mut nodes = vec ! [ ] ;
13501394
@@ -1358,12 +1402,13 @@ impl SqlToMirConverter {
13581402 parent_columns
13591403 . into_iter ( )
13601404 . map ( ProjectExpr :: Column )
1361- . chain ( exprs_to_project. into_iter ( ) . map ( |expr| {
1405+ . chain ( exprs_to_project. into_iter ( ) . map ( |( expr, name ) | {
13621406 // FIXME(ENG-2502): Use correct dialect.
1363- let alias = expr
1364- . display ( readyset_sql:: Dialect :: MySQL )
1365- . to_string ( )
1366- . into ( ) ;
1407+ let alias = name. unwrap_or_else ( || {
1408+ expr. display ( readyset_sql:: Dialect :: MySQL )
1409+ . to_string ( )
1410+ . into ( )
1411+ } ) ;
13671412 ProjectExpr :: Expr { alias, expr }
13681413 } ) )
13691414 . collect ( ) ,
@@ -2367,7 +2412,7 @@ impl SqlToMirConverter {
23672412 let make_topk = offset. is_none ( ) ;
23682413 // view key will have the offset parameter if it exists. We must filter it out
23692414 // of the group by, because the column originates at this node
2370- let group_by = view_key
2415+ let mut group_by: Vec < Column > = view_key
23712416 . columns
23722417 . iter ( )
23732418 . filter_map ( |( col, _) | {
@@ -2379,6 +2424,14 @@ impl SqlToMirConverter {
23792424 } )
23802425 . collect ( ) ;
23812426
2427+ group_by. extend ( query_graph. group_by . iter ( ) . filter_map ( |expr| {
2428+ if let Expr :: Column ( col) = expr {
2429+ Some ( Column :: from ( col. clone ( ) ) )
2430+ } else {
2431+ None
2432+ }
2433+ } ) ) ;
2434+
23822435 // Order by expression projections and either a topk or paginate node
23832436 let paginate_nodes = self . make_paginate_node (
23842437 query_name,
@@ -2393,6 +2446,7 @@ impl SqlToMirConverter {
23932446 order,
23942447 * limit,
23952448 make_topk,
2449+ Some ( & query_graph. columns ) ,
23962450 ) ?;
23972451 func_nodes. extend ( paginate_nodes. clone ( ) ) ;
23982452 final_node = * paginate_nodes. last ( ) . unwrap ( ) ;
0 commit comments