@@ -6,10 +6,11 @@ use partiql_ast::ast;
66use partiql_ast:: ast:: {
77 Assignment , Bag , Between , BinOp , BinOpKind , Call , CallAgg , CallArg , CallArgNamed ,
88 CaseSensitivity , CreateIndex , CreateTable , Ddl , DdlOp , Delete , Dml , DmlOp , DropIndex ,
9- DropTable , FromClause , FromLet , FromLetKind , GroupByExpr , Insert , InsertValue , Item , Join ,
10- JoinKind , JoinSpec , Like , List , Lit , NodeId , OnConflict , OrderByExpr , Path , PathStep ,
11- ProjectExpr , Projection , ProjectionKind , Query , QuerySet , Remove , SearchedCase , Select , Set ,
12- SetExpr , SetQuantifier , Sexp , SimpleCase , Struct , SymbolPrimitive , UniOp , UniOpKind , VarRef ,
9+ DropTable , FromClause , FromLet , FromLetKind , GroupByExpr , GroupKey , GroupingStrategy , Insert ,
10+ InsertValue , Item , Join , JoinKind , JoinSpec , Like , List , Lit , NodeId , OnConflict , OrderByExpr ,
11+ Path , PathStep , ProjectExpr , Projection , ProjectionKind , Query , QuerySet , Remove , SearchedCase ,
12+ Select , Set , SetExpr , SetQuantifier , Sexp , SimpleCase , Struct , SymbolPrimitive , UniOp ,
13+ UniOpKind , VarRef ,
1314} ;
1415use partiql_ast:: visit:: { Visit , Visitor } ;
1516use partiql_logical as logical;
@@ -1087,17 +1088,71 @@ impl<'ast> Visitor<'ast> for AstToLogical {
10871088 }
10881089
10891090 fn exit_having_clause ( & mut self , _having_clause : & ' ast ast:: HavingClause ) {
1090- let _env = self . exit_env ( ) ;
1091- todo ! ( "having clause" ) ;
1091+ let mut env = self . exit_env ( ) ;
1092+ assert_eq ! ( env. len( ) , 1 ) ;
1093+
1094+ let having = BindingsOp :: Having ( logical:: Having {
1095+ expr : env. pop ( ) . unwrap ( ) ,
1096+ } ) ;
1097+ let id = self . plan . add_operator ( having) ;
1098+
1099+ self . current_clauses_mut ( ) . having_clause . replace ( id) ;
10921100 }
10931101
10941102 fn enter_group_by_expr ( & mut self , _group_by_expr : & ' ast GroupByExpr ) {
1103+ self . enter_benv ( ) ;
10951104 self . enter_env ( ) ;
10961105 }
10971106
10981107 fn exit_group_by_expr ( & mut self , _group_by_expr : & ' ast GroupByExpr ) {
1099- let _env = self . exit_env ( ) ;
1100- todo ! ( "group by clause" ) ;
1108+ let benv = self . exit_benv ( ) ;
1109+ assert_eq ! ( benv. len( ) , 0 ) ; // TODO sub-query
1110+ let env = self . exit_env ( ) ;
1111+
1112+ let group_as_alias = _group_by_expr
1113+ . group_as_alias
1114+ . as_ref ( )
1115+ . map ( |SymbolPrimitive { value, case : _ } | value. clone ( ) ) ;
1116+
1117+ let strategy = match _group_by_expr. strategy {
1118+ GroupingStrategy :: GroupFull => logical:: GroupingStrategy :: GroupFull ,
1119+ GroupingStrategy :: GroupPartial => logical:: GroupingStrategy :: GroupPartial ,
1120+ } ;
1121+ let mut exprs = HashMap :: with_capacity ( env. len ( ) / 2 ) ;
1122+ let mut iter = env. into_iter ( ) ;
1123+ while let Some ( value) = iter. next ( ) {
1124+ let alias = iter. next ( ) . unwrap ( ) ;
1125+ let alias = match alias {
1126+ ValueExpr :: Lit ( lit) => match * lit {
1127+ Value :: String ( s) => ( * s) . clone ( ) ,
1128+ _ => panic ! ( "unexpected literal" ) ,
1129+ } ,
1130+ _ => panic ! ( "unexpected alias type" ) ,
1131+ } ;
1132+ exprs. insert ( alias, value) ;
1133+ }
1134+ let group_by: BindingsOp = BindingsOp :: GroupBy ( logical:: GroupBy {
1135+ strategy,
1136+ exprs,
1137+ group_as_alias,
1138+ } ) ;
1139+
1140+ let id = self . plan . add_operator ( group_by) ;
1141+ self . current_clauses_mut ( ) . group_by_clause . replace ( id) ;
1142+ }
1143+
1144+ fn exit_group_key ( & mut self , _group_key : & ' ast GroupKey ) {
1145+ let as_key: & name_resolver:: Symbol = self
1146+ . key_registry
1147+ . aliases
1148+ . get ( self . current_node ( ) )
1149+ . expect ( "alias" ) ;
1150+ // TODO intern strings
1151+ let as_key = match as_key {
1152+ name_resolver:: Symbol :: Known ( sym) => sym. value . clone ( ) ,
1153+ name_resolver:: Symbol :: Unknown ( id) => format ! ( "_{id}" ) ,
1154+ } ;
1155+ self . push_value ( as_key. into ( ) ) ;
11011156 }
11021157
11031158 fn enter_order_by_expr ( & mut self , _order_by_expr : & ' ast OrderByExpr ) {
0 commit comments