diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 9286734..afc56a1 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -2480,11 +2480,13 @@ JumbleExpr(pgssJumbleState *jstate, Node *node) Aggref *expr = (Aggref *) node; APP_JUMB(expr->aggfnoid); + APP_JUMB(expr->aggformat); JumbleExpr(jstate, (Node *) expr->aggdirectargs); JumbleExpr(jstate, (Node *) expr->args); JumbleExpr(jstate, (Node *) expr->aggorder); JumbleExpr(jstate, (Node *) expr->aggdistinct); JumbleExpr(jstate, (Node *) expr->aggfilter); + JumbleExpr(jstate, (Node *) expr->aggformatopts); } break; case T_GroupingFunc: @@ -2500,8 +2502,10 @@ JumbleExpr(pgssJumbleState *jstate, Node *node) APP_JUMB(expr->winfnoid); APP_JUMB(expr->winref); + APP_JUMB(expr->winformat); JumbleExpr(jstate, (Node *) expr->args); JumbleExpr(jstate, (Node *) expr->aggfilter); + JumbleExpr(jstate, (Node *) expr->winformatopts); } break; case T_ArrayRef: @@ -2519,7 +2523,9 @@ JumbleExpr(pgssJumbleState *jstate, Node *node) FuncExpr *expr = (FuncExpr *) node; APP_JUMB(expr->funcid); + APP_JUMB(expr->funcformat2); JumbleExpr(jstate, (Node *) expr->args); + JumbleExpr(jstate, (Node *) expr->funcformatopts); } break; case T_NamedArgExpr: diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index f84da80..f215f3a 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -1378,6 +1378,8 @@ _copyAggref(const Aggref *from) COPY_SCALAR_FIELD(aggkind); COPY_SCALAR_FIELD(agglevelsup); COPY_SCALAR_FIELD(aggsplit); + COPY_SCALAR_FIELD(aggformat); + COPY_NODE_FIELD(aggformatopts); COPY_LOCATION_FIELD(location); return newnode; @@ -1417,6 +1419,8 @@ _copyWindowFunc(const WindowFunc *from) COPY_SCALAR_FIELD(winref); COPY_SCALAR_FIELD(winstar); COPY_SCALAR_FIELD(winagg); + COPY_SCALAR_FIELD(winformat); + COPY_NODE_FIELD(winformatopts); COPY_LOCATION_FIELD(location); return newnode; @@ -1458,6 +1462,8 @@ _copyFuncExpr(const FuncExpr *from) COPY_SCALAR_FIELD(funccollid); COPY_SCALAR_FIELD(inputcollid); COPY_NODE_FIELD(args); + COPY_SCALAR_FIELD(funcformat2); + COPY_NODE_FIELD(funcformatopts); COPY_LOCATION_FIELD(location); return newnode; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index ee8d925..7c28151 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -226,6 +226,8 @@ _equalAggref(const Aggref *a, const Aggref *b) COMPARE_SCALAR_FIELD(aggkind); COMPARE_SCALAR_FIELD(agglevelsup); COMPARE_SCALAR_FIELD(aggsplit); + COMPARE_SCALAR_FIELD(aggformat); + COMPARE_NODE_FIELD(aggformatopts); COMPARE_LOCATION_FIELD(location); return true; @@ -258,6 +260,8 @@ _equalWindowFunc(const WindowFunc *a, const WindowFunc *b) COMPARE_SCALAR_FIELD(winref); COMPARE_SCALAR_FIELD(winstar); COMPARE_SCALAR_FIELD(winagg); + COMPARE_SCALAR_FIELD(winformat); + COMPARE_NODE_FIELD(winformatopts); COMPARE_LOCATION_FIELD(location); return true; @@ -289,6 +293,8 @@ _equalFuncExpr(const FuncExpr *a, const FuncExpr *b) COMPARE_SCALAR_FIELD(funccollid); COMPARE_SCALAR_FIELD(inputcollid); COMPARE_NODE_FIELD(args); + COMPARE_SCALAR_FIELD(funcformat2); + COMPARE_NODE_FIELD(funcformatopts); COMPARE_LOCATION_FIELD(location); return true; diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index fd80891..52fdcbb 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -1153,6 +1153,8 @@ _outAggref(StringInfo str, const Aggref *node) WRITE_CHAR_FIELD(aggkind); WRITE_UINT_FIELD(agglevelsup); WRITE_ENUM_FIELD(aggsplit, AggSplit); + WRITE_ENUM_FIELD(aggformat, FuncFormat); + WRITE_NODE_FIELD(aggformatopts); WRITE_LOCATION_FIELD(location); } @@ -1182,6 +1184,8 @@ _outWindowFunc(StringInfo str, const WindowFunc *node) WRITE_UINT_FIELD(winref); WRITE_BOOL_FIELD(winstar); WRITE_BOOL_FIELD(winagg); + WRITE_ENUM_FIELD(winformat, FuncFormat); + WRITE_NODE_FIELD(winformatopts); WRITE_LOCATION_FIELD(location); } @@ -1213,6 +1217,8 @@ _outFuncExpr(StringInfo str, const FuncExpr *node) WRITE_OID_FIELD(funccollid); WRITE_OID_FIELD(inputcollid); WRITE_NODE_FIELD(args); + WRITE_ENUM_FIELD(funcformat2, FuncFormat); + WRITE_NODE_FIELD(funcformatopts); WRITE_LOCATION_FIELD(location); } diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 068db35..745d3f3 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -600,6 +600,8 @@ _readAggref(void) READ_CHAR_FIELD(aggkind); READ_UINT_FIELD(agglevelsup); READ_ENUM_FIELD(aggsplit, AggSplit); + READ_ENUM_FIELD(aggformat, FuncFormat); + READ_NODE_FIELD(aggformatopts); READ_LOCATION_FIELD(location); READ_DONE(); @@ -639,6 +641,8 @@ _readWindowFunc(void) READ_UINT_FIELD(winref); READ_BOOL_FIELD(winstar); READ_BOOL_FIELD(winagg); + READ_ENUM_FIELD(winformat, FuncFormat); + READ_NODE_FIELD(winformatopts); READ_LOCATION_FIELD(location); READ_DONE(); @@ -680,6 +684,8 @@ _readFuncExpr(void) READ_OID_FIELD(funccollid); READ_OID_FIELD(inputcollid); READ_NODE_FIELD(args); + READ_ENUM_FIELD(funcformat2, FuncFormat); + READ_NODE_FIELD(funcformatopts); READ_LOCATION_FIELD(location); READ_DONE(); diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index a9a09af..bee71b7 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -2655,6 +2655,8 @@ eval_const_expressions_mutator(Node *node, newexpr->winref = expr->winref; newexpr->winstar = expr->winstar; newexpr->winagg = expr->winagg; + newexpr->winformat = expr->winformat; + newexpr->winformatopts = copyObject(expr->winformatopts); newexpr->location = expr->location; return (Node *) newexpr; @@ -2701,6 +2703,8 @@ eval_const_expressions_mutator(Node *node, newexpr->funccollid = expr->funccollid; newexpr->inputcollid = expr->inputcollid; newexpr->args = args; + newexpr->funcformat2 = expr->funcformat2; + newexpr->funcformatopts = copyObject(expr->funcformatopts); newexpr->location = expr->location; return (Node *) newexpr; } diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 096aa82..be46c00 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -8937,6 +8937,16 @@ get_oper_expr(OpExpr *expr, deparse_context *context) appendStringInfoChar(buf, ')'); } +static void +get_func_opts(FuncFormat aggformat, Node *aggformatopts, deparse_context *context) +{ + switch (aggformat) + { + default: + break; + } +} + /* * get_func_expr - Parse back a FuncExpr node */ @@ -8951,6 +8961,7 @@ get_func_expr(FuncExpr *expr, deparse_context *context, List *argnames; bool use_variadic; ListCell *l; + const char *funcname; /* * If the function call came from an implicit coercion, then just show the @@ -9005,12 +9016,19 @@ get_func_expr(FuncExpr *expr, deparse_context *context, nargs++; } - appendStringInfo(buf, "%s(", - generate_function_name(funcoid, nargs, - argnames, argtypes, - expr->funcvariadic, - &use_variadic, - context->special_exprkind)); + switch (expr->funcformat2) + { + default: + funcname = generate_function_name(funcoid, nargs, + argnames, argtypes, + expr->funcvariadic, + &use_variadic, + context->special_exprkind); + break; + } + + appendStringInfo(buf, "%s(", funcname); + nargs = 0; foreach(l, expr->args) { @@ -9020,6 +9038,9 @@ get_func_expr(FuncExpr *expr, deparse_context *context, appendStringInfoString(buf, "VARIADIC "); get_rule_expr((Node *) lfirst(l), context, true); } + + get_func_opts(expr->funcformat2, expr->funcformatopts, context); + appendStringInfoChar(buf, ')'); } @@ -9118,6 +9139,8 @@ get_agg_expr(Aggref *aggref, deparse_context *context, } } + get_func_opts(aggref->aggformat, aggref->aggformatopts, context); + if (aggref->aggfilter != NULL) { appendStringInfoString(buf, ") FILTER (WHERE "); @@ -9184,6 +9207,8 @@ get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context) else get_rule_expr((Node *) wfunc->args, context, true); + get_func_opts(wfunc->winformat, wfunc->winformatopts, context); + if (wfunc->aggfilter != NULL) { appendStringInfoString(buf, ") FILTER (WHERE "); diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 41330b2..641500e 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -249,6 +249,11 @@ typedef struct Param int location; /* token location, or -1 if unknown */ } Param; +typedef enum FuncFormat +{ + FUNCFMT_REGULAR = 0, +} FuncFormat; + /* * Aggref * @@ -308,6 +313,8 @@ typedef struct Aggref char aggkind; /* aggregate kind (see pg_aggregate.h) */ Index agglevelsup; /* > 0 if agg belongs to outer query */ AggSplit aggsplit; /* expected agg-splitting mode of parent Agg */ + FuncFormat aggformat; /* how to display this aggregate */ + Node *aggformatopts; /* display options, if any */ int location; /* token location, or -1 if unknown */ } Aggref; @@ -361,6 +368,8 @@ typedef struct WindowFunc Index winref; /* index of associated WindowClause */ bool winstar; /* true if argument list was really '*' */ bool winagg; /* is function a simple aggregate? */ + FuncFormat winformat; /* how to display this window function */ + Node *winformatopts; /* display options, if any */ int location; /* token location, or -1 if unknown */ } WindowFunc; @@ -456,6 +465,8 @@ typedef struct FuncExpr Oid funccollid; /* OID of collation of result */ Oid inputcollid; /* OID of collation that function should use */ List *args; /* arguments to the function */ + FuncFormat funcformat2; /* how to display this function call */ + Node *funcformatopts; /* display options, if any */ int location; /* token location, or -1 if unknown */ } FuncExpr;