%type  <str>   Typename SimpleTypename Numeric opt_float DiscardStmt
 %type  <str>   Character character opt_varying opt_charset enum_val_list
 %type  <str>   opt_timezone opt_interval table_ref fetch_direction
-%type  <str>   ConstDatetime AlterDomainStmt AlterSeqStmt 
+%type  <str>   ConstDatetime AlterDomainStmt AlterSeqStmt table_func_column
 %type  <str>   SelectStmt into_clause OptTemp ConstraintAttributeSpec
 %type  <str>   opt_table opt_all sort_clause sortby_list ConstraintAttr
 %type  <str>   sortby qualified_name_list name_list ColId_or_Sconst
 %type  <str>   RemoveOperStmt RenameStmt all_Op opt_trusted opt_lancompiler
 %type  <str>   VariableSetStmt var_value zone_value VariableShowStmt
 %type  <str>   VariableResetStmt AlterTableStmt from_list overlay_list
-%type  <str>   relation_name OptTableSpace LockStmt opt_lock 
+%type  <str>   relation_name OptTableSpace LockStmt opt_lock table_func_column_list
 %type  <str>   CreateUserStmt AlterUserStmt CreateSeqStmt SeqOptList
 %type  <str>   SeqOptElem TriggerForSpec TriggerForOpt TriggerForType
 %type  <str>   DropTrigStmt TriggerOneEvent TriggerEvents RuleActionStmt
 fetch_count:   IntConst        {
                                        if ($1[1] == '$')
                                        {
-                                               /* a variable here has to be replaced on the client side, thus we have to use '?' here */
+                                               /* a variable here has to be replaced on the client side, thus we have to use '$0' here */
                                                $$ = make_str("$0");
                                                free($1);
                                        }
 CreateFunctionStmt:    CREATE opt_or_replace FUNCTION func_name func_args
                                        RETURNS func_return createfunc_opt_list opt_definition
                        { $$ = cat_str(8, make_str("create"), $2, make_str("function"), $4, $5, make_str("returns"), $7, $8); }
+               | CREATE opt_or_replace FUNCTION func_name func_args
+                                       RETURNS TABLE '(' table_func_column_list ')' createfunc_opt_list opt_definition
+                       { $$ = cat_str(9, make_str("create"), $2, make_str("function"), $4, $5, make_str("returns table ("), $9, make_str(")"), $11, $12); }
                | CREATE opt_or_replace FUNCTION func_name func_args
                                        createfunc_opt_list opt_definition
                        { $$ = cat_str(6, make_str("create"), $2, make_str("function"), $4, $5, $6, $7); }
                | /*EMPTY*/     { $$ = EMPTY; }
                ;
 
+table_func_column:      param_name func_type   { $$ = cat2_str($1, $2); }
+                       ;
+
+table_func_column_list:
+                       table_func_column                               { $$ = $1; }
+                       | table_func_column_list ',' table_func_column  { $$ = cat_str(3, $1, make_str(","), $3); }
+                       ; 
+
 AlterFunctionStmt:
                ALTER FUNCTION function_with_argtypes alterfunc_opt_list opt_restrict
                        { $$ = cat_str(4, make_str("alter function"), $3, $4, $5); }
                        { $$ = cat2_str($1, make_str("()"));    }
                | func_name '(' expr_list ')'
                        { $$ = cat_str(4, $1, make_str("("), $3, make_str(")"));        }
+               | func_name '(' VARIADIC a_expr ')'
+                       { $$ = cat_str(4, $1, make_str("( variadic "), $4, make_str(")"));      }
+               | func_name '(' expr_list ',' VARIADIC a_expr ')'
+                       { $$ = cat_str(6, $1, make_str("("), $3, make_str(", variadic "), $6, make_str(")"));   }
                | func_name '(' ALL expr_list ')'
                        { $$ = cat_str(4, $1, make_str("( all"), $4, make_str(")"));    }
                | func_name '(' DISTINCT expr_list ')'