@@ -127,7 +127,7 @@ pub fn get_node_properties_mod(proto_file: &ProtoFile) -> proc_macro2::TokenStre
127127 }
128128 }
129129
130- pub fn get_node_properties( node: & NodeEnum ) -> Vec <TokenProperty > {
130+ pub fn get_node_properties( node: & NodeEnum , parent : Option < & NodeEnum > ) -> Vec <TokenProperty > {
131131 let mut tokens: Vec <TokenProperty > = Vec :: new( ) ;
132132
133133 match node {
@@ -515,6 +515,56 @@ fn custom_handlers(node: &Node) -> TokenStream {
515515 tokens. push( TokenProperty :: from( Token :: As ) ) ;
516516 }
517517 } ,
518+ "List" => quote ! {
519+ if parent. is_some( ) {
520+ // if parent is `DefineStmt`, we need to check whether an ORDER BY needs to be added
521+ if let NodeEnum :: DefineStmt ( define_stmt) = parent. unwrap( ) {
522+ // there *seems* to be an integer node in the last position of the DefineStmt args that
523+ // defines whether the list contains an order by statement
524+ let integer = define_stmt. args. last( )
525+ . and_then( |node| node. node. as_ref( ) )
526+ . and_then( |node| if let NodeEnum :: Integer ( n) = node { Some ( n. ival) } else { None } ) ;
527+ if integer. is_none( ) {
528+ panic!( "DefineStmt of type ObjectAggregate has no integer node in last position of args" ) ;
529+ }
530+ // if the integer is 1, then there is an order by statement
531+ // we add it to the `List` node because that seems to make most sense based off the grammar definition
532+ // ref: https://github.com/postgres/postgres/blob/REL_15_STABLE/src/backend/parser/gram.y#L8355
533+ // ```
534+ // aggr_args:
535+ // | '(' aggr_args_list ORDER BY aggr_args_list ')'
536+ // ```
537+ if integer. unwrap( ) == 1 {
538+ tokens. push( TokenProperty :: from( Token :: Order ) ) ;
539+ tokens. push( TokenProperty :: from( Token :: By ) ) ;
540+ }
541+ }
542+ }
543+ } ,
544+ "DefineStmt" => quote ! {
545+ tokens. push( TokenProperty :: from( Token :: Create ) ) ;
546+ if n. replace {
547+ tokens. push( TokenProperty :: from( Token :: Or ) ) ;
548+ tokens. push( TokenProperty :: from( Token :: Replace ) ) ;
549+ }
550+ match n. kind( ) {
551+ protobuf:: ObjectType :: ObjectAggregate => {
552+ tokens. push( TokenProperty :: from( Token :: Aggregate ) ) ;
553+
554+ // n.args is always an array with two nodes
555+ assert_eq!( n. args. len( ) , 2 , "DefineStmt of type ObjectAggregate does not have exactly 2 args" ) ;
556+ // the first is either a List or a Node { node: None }
557+
558+ if let Some ( node) = & n. args. first( ) {
559+ if node. node. is_none( ) {
560+ // if first element is a Node { node: None }, then it's "*"
561+ tokens. push( TokenProperty :: from( Token :: Ascii42 ) ) ;
562+ } }
563+ // if its a list, we handle it in the handler for `List`
564+ } ,
565+ _ => panic!( "Unknown DefineStmt {:#?}" , n. kind( ) ) ,
566+ }
567+ } ,
518568 "CreateSchemaStmt" => quote ! {
519569 tokens. push( TokenProperty :: from( Token :: Create ) ) ;
520570 tokens. push( TokenProperty :: from( Token :: Schema ) ) ;
0 commit comments