While fooling with Gen_fmgrtab.pl for a nearby patch [1], I noticed that fmgrtab.c had a lot of entries pointing at aggregate_dummy, which seemed rather useless. So I experimented with removing them.
It turns out that nodeWindowAgg.c is carelessly expecting them to be there, because it does fmgr_info_cxt() on the target window function even if it will never call it because it's a plain aggregate. But that's pretty trivial to fix, just need to relocate that call. With that, we don't actually need aggregate_dummy() to exist at all, because it's never referenced. Having "aggregate_dummy" as the prosrc value for an aggregate function is now just a random convention; any other string would do as well. (We could save a few bytes in pg_proc by choosing a shorter string, but probably it's better to stick to the existing convention.) Anyway, this saves about 3KB in fmgrtab.o, without any downside that I can see. If someone accidentally called an aggregate as a normal function, they'd now get a different error message, namely "internal function "aggregate_dummy" is not in internal lookup table" instead of "aggregate function NNN called as normal function". That doesn't really seem like a problem. The attached patch is a delta over the one in [1]. regards, tom lane [1] https://www.postgresql.org/message-id/472274.1604258384%40sss.pgh.pa.us
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index 0cf1da6ebb..7664bb6285 100644 --- a/src/backend/catalog/pg_aggregate.c +++ b/src/backend/catalog/pg_aggregate.c @@ -620,7 +620,7 @@ AggregateCreate(const char *aggName, GetUserId(), /* proowner */ INTERNALlanguageId, /* languageObjectId */ InvalidOid, /* no validator */ - "aggregate_dummy", /* placeholder proc */ + "aggregate_dummy", /* placeholder (no such proc) */ NULL, /* probin */ PROKIND_AGGREGATE, false, /* security invoker (currently not diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 75e5bbf209..d87677d659 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -4935,24 +4935,6 @@ AggRegisterCallback(FunctionCallInfo fcinfo, } -/* - * aggregate_dummy - dummy execution routine for aggregate functions - * - * This function is listed as the implementation (prosrc field) of pg_proc - * entries for aggregate functions. Its only purpose is to throw an error - * if someone mistakenly executes such a function in the normal way. - * - * Perhaps someday we could assign real meaning to the prosrc field of - * an aggregate? - */ -Datum -aggregate_dummy(PG_FUNCTION_ARGS) -{ - elog(ERROR, "aggregate function %u called as normal function", - fcinfo->flinfo->fn_oid); - return (Datum) 0; /* keep compiler quiet */ -} - /* ---------------------------------------------------------------- * Parallel Query Support * ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index 4cc7da268d..de58df3d3f 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -2446,11 +2446,6 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags) perfuncstate->wfuncstate = wfuncstate; perfuncstate->wfunc = wfunc; perfuncstate->numArguments = list_length(wfuncstate->args); - - fmgr_info_cxt(wfunc->winfnoid, &perfuncstate->flinfo, - econtext->ecxt_per_query_memory); - fmgr_info_set_expr((Node *) wfunc, &perfuncstate->flinfo); - perfuncstate->winCollation = wfunc->inputcollid; get_typlenbyval(wfunc->wintype, @@ -2479,6 +2474,11 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags) winobj->argstates = wfuncstate->args; winobj->localmem = NULL; perfuncstate->winobj = winobj; + + /* It's a real window function, so set up to call it. */ + fmgr_info_cxt(wfunc->winfnoid, &perfuncstate->flinfo, + econtext->ecxt_per_query_memory); + fmgr_info_set_expr((Node *) wfunc, &perfuncstate->flinfo); } } diff --git a/src/backend/utils/Gen_fmgrtab.pl b/src/backend/utils/Gen_fmgrtab.pl index 1edd5195d7..34e27950e7 100644 --- a/src/backend/utils/Gen_fmgrtab.pl +++ b/src/backend/utils/Gen_fmgrtab.pl @@ -75,6 +75,7 @@ foreach my $row (@{ $catalog_data{pg_proc} }) oid => $bki_values{oid}, name => $bki_values{proname}, lang => $bki_values{prolang}, + kind => $bki_values{prokind}, strict => $bki_values{proisstrict}, retset => $bki_values{proretset}, nargs => $bki_values{pronargs}, @@ -195,8 +196,10 @@ foreach my $s (sort { $a->{oid} <=> $b->{oid} } @fmgr) $sqlname .= "_" . $s->{args} if ($proname_counts{ $s->{name} } > 1); $sqlname =~ tr/ /_/; print $ofh "#define F_" . uc $sqlname . " $s->{oid}\n"; - # We want only one extern per internal-language function - if ($s->{lang} eq 'internal' && !$seenit{ $s->{prosrc} }) + # We want only one extern per internal-language, non-aggregate function + if ( $s->{lang} eq 'internal' + && $s->{kind} ne 'a' + && !$seenit{ $s->{prosrc} }) { $seenit{ $s->{prosrc} } = 1; print $pfh "extern Datum $s->{prosrc}(PG_FUNCTION_ARGS);\n"; @@ -214,6 +217,8 @@ my $fmgr_count = 0; foreach my $s (sort { $a->{oid} <=> $b->{oid} } @fmgr) { next if $s->{lang} ne 'internal'; + # We do not need entries for aggregate functions + next if $s->{kind} eq 'a'; print $tfh ",\n" if ($fmgr_count > 0); print $tfh