Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4784208

Browse files
danolivoCommitfest Bot
authored and
Commitfest Bot
committed
Add prosupport helpers to aggregate functions.
Following the spirit of ed1a88d, add a prosupport call for aggregates. Here, we introduce a new support function node type to allow support functions to be called for aggregate functions. This code introduces only min/max trivial optimisation in the core. However, a user can design alternative support functions on their own.
1 parent 898c131 commit 4784208

File tree

7 files changed

+352
-47
lines changed

7 files changed

+352
-47
lines changed

src/backend/optimizer/plan/planagg.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "catalog/pg_type.h"
3434
#include "nodes/makefuncs.h"
3535
#include "nodes/nodeFuncs.h"
36+
#include "nodes/supportnodes.h"
3637
#include "optimizer/cost.h"
3738
#include "optimizer/optimizer.h"
3839
#include "optimizer/pathnode.h"
@@ -43,6 +44,7 @@
4344
#include "parser/parse_clause.h"
4445
#include "parser/parsetree.h"
4546
#include "rewrite/rewriteManip.h"
47+
#include "utils/fmgrprotos.h"
4648
#include "utils/lsyscache.h"
4749
#include "utils/syscache.h"
4850

@@ -512,3 +514,77 @@ fetch_agg_sort_op(Oid aggfnoid)
512514

513515
return aggsortop;
514516
}
517+
518+
Datum
519+
minmax_support(PG_FUNCTION_ARGS)
520+
{
521+
Node *rawreq = (Node *) PG_GETARG_POINTER(0);
522+
Oid aggsortop;
523+
524+
if (IsA(rawreq, SupportRequestAggregate))
525+
{
526+
SupportRequestAggregate *req = (SupportRequestAggregate *) rawreq;
527+
Aggref *aggref = req->aggref;
528+
529+
if (list_length(aggref->args) != 1 || aggref->aggfilter != NULL)
530+
PG_RETURN_POINTER(NULL);
531+
532+
aggsortop = fetch_agg_sort_op(aggref->aggfnoid);
533+
if (!OidIsValid(aggsortop))
534+
PG_RETURN_POINTER(NULL); /* not a MIN/MAX aggregate */
535+
536+
if (aggref->aggorder != NIL)
537+
{
538+
SortGroupClause *orderClause;
539+
TargetEntry *curTarget;
540+
541+
curTarget = (TargetEntry *) linitial(aggref->args);
542+
543+
/*
544+
* If the order clause is the same column as the one we're
545+
* aggregating, we can still use the index: It is undefined which
546+
* value is MIN() or MAX(), as well as which value is first or
547+
* last when sorted. So, we can still use the index IFF the
548+
* aggregated expression equals the expression used in the
549+
* ordering operation.
550+
*/
551+
552+
/*
553+
* We only accept a single argument to min/max aggregates,
554+
* orderings that have more clauses won't provide correct results.
555+
*/
556+
Assert(list_length(aggref->aggorder) == 1);
557+
558+
orderClause = castNode(SortGroupClause, linitial(aggref->aggorder));
559+
560+
if (orderClause->tleSortGroupRef != curTarget->ressortgroupref)
561+
elog(ERROR, "Aggregate order clause isn't found in target list");
562+
563+
if (orderClause->sortop != aggsortop)
564+
{
565+
List *btclasses;
566+
ListCell *lc;
567+
568+
btclasses = get_op_btree_interpretation(orderClause->sortop);
569+
570+
foreach(lc, btclasses)
571+
{
572+
OpBtreeInterpretation *interpretation;
573+
574+
interpretation = (OpBtreeInterpretation *) lfirst(lc);
575+
if (op_in_opfamily(aggsortop, interpretation->opfamily_id))
576+
{
577+
aggref->aggorder = NIL;
578+
break;
579+
}
580+
}
581+
582+
list_free_deep(btclasses);
583+
}
584+
else
585+
aggref->aggorder = NIL;
586+
}
587+
}
588+
589+
PG_RETURN_POINTER(NULL);
590+
}

src/backend/optimizer/prep/prepagg.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "catalog/pg_type.h"
4040
#include "nodes/nodeFuncs.h"
4141
#include "nodes/pathnodes.h"
42+
#include "nodes/supportnodes.h"
4243
#include "optimizer/cost.h"
4344
#include "optimizer/optimizer.h"
4445
#include "optimizer/plancat.h"
@@ -64,6 +65,25 @@ static int find_compatible_trans(PlannerInfo *root, Aggref *newagg,
6465
List *transnos);
6566
static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
6667

68+
static void
69+
optimize_aggregates(Aggref *aggref)
70+
{
71+
SupportRequestAggregate req;
72+
Oid prosupport;
73+
74+
prosupport = get_func_support(aggref->aggfnoid);
75+
76+
/* Check if there's a support function for the aggregate */
77+
if (!OidIsValid(prosupport))
78+
return;
79+
80+
81+
req.type = T_SupportRequestAggregate;
82+
req.aggref = aggref;
83+
/* call the support function */
84+
(void) OidFunctionCall1(prosupport, PointerGetDatum(&req));
85+
}
86+
6787
/* -----------------
6888
* Resolve the transition type of all Aggrefs, and determine which Aggrefs
6989
* can share aggregate or transition state.
@@ -215,6 +235,12 @@ preprocess_aggref(Aggref *aggref, PlannerInfo *root)
215235

216236
ReleaseSysCache(aggTuple);
217237

238+
/*
239+
* See if any modifications can be made to each aggregate to allow
240+
* planner to process it in more effective way.
241+
*/
242+
optimize_aggregates(aggref);
243+
218244
/*
219245
* 1. See if this is identical to another aggregate function call that
220246
* we've seen already.

src/include/catalog/pg_proc.dat

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6914,155 +6914,159 @@
69146914
proname => 'sum', prokind => 'a', proisstrict => 'f', prorettype => 'numeric',
69156915
proargtypes => 'numeric', prosrc => 'aggregate_dummy' },
69166916

6917-
{ oid => '2115', descr => 'maximum value of all bigint input values',
6917+
{ oid => '2775', descr => 'planner support for min and max aggregates',
6918+
proname => 'minmax_support', prorettype => 'internal',
6919+
proargtypes => 'internal', prosrc => 'minmax_support' },
6920+
{ oid => '2115', prosupport => 'minmax_support',
6921+
descr => 'maximum value of all bigint input values',
69186922
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'int8',
69196923
proargtypes => 'int8', prosrc => 'aggregate_dummy' },
6920-
{ oid => '2116', descr => 'maximum value of all integer input values',
6924+
{ oid => '2116', prosupport => 'minmax_support', descr => 'maximum value of all integer input values',
69216925
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'int4',
69226926
proargtypes => 'int4', prosrc => 'aggregate_dummy' },
6923-
{ oid => '2117', descr => 'maximum value of all smallint input values',
6927+
{ oid => '2117', prosupport => 'minmax_support', descr => 'maximum value of all smallint input values',
69246928
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'int2',
69256929
proargtypes => 'int2', prosrc => 'aggregate_dummy' },
6926-
{ oid => '2118', descr => 'maximum value of all oid input values',
6930+
{ oid => '2118', prosupport => 'minmax_support', descr => 'maximum value of all oid input values',
69276931
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'oid',
69286932
proargtypes => 'oid', prosrc => 'aggregate_dummy' },
6929-
{ oid => '2119', descr => 'maximum value of all float4 input values',
6933+
{ oid => '2119', prosupport => 'minmax_support', descr => 'maximum value of all float4 input values',
69306934
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'float4',
69316935
proargtypes => 'float4', prosrc => 'aggregate_dummy' },
6932-
{ oid => '2120', descr => 'maximum value of all float8 input values',
6936+
{ oid => '2120', prosupport => 'minmax_support', descr => 'maximum value of all float8 input values',
69336937
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'float8',
69346938
proargtypes => 'float8', prosrc => 'aggregate_dummy' },
6935-
{ oid => '2122', descr => 'maximum value of all date input values',
6939+
{ oid => '2122', prosupport => 'minmax_support', descr => 'maximum value of all date input values',
69366940
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'date',
69376941
proargtypes => 'date', prosrc => 'aggregate_dummy' },
6938-
{ oid => '2123', descr => 'maximum value of all time input values',
6942+
{ oid => '2123', prosupport => 'minmax_support', descr => 'maximum value of all time input values',
69396943
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'time',
69406944
proargtypes => 'time', prosrc => 'aggregate_dummy' },
6941-
{ oid => '2124',
6945+
{ oid => '2124', prosupport => 'minmax_support',
69426946
descr => 'maximum value of all time with time zone input values',
69436947
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'timetz',
69446948
proargtypes => 'timetz', prosrc => 'aggregate_dummy' },
6945-
{ oid => '2125', descr => 'maximum value of all money input values',
6949+
{ oid => '2125', prosupport => 'minmax_support', descr => 'maximum value of all money input values',
69466950
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'money',
69476951
proargtypes => 'money', prosrc => 'aggregate_dummy' },
6948-
{ oid => '2126', descr => 'maximum value of all timestamp input values',
6952+
{ oid => '2126', prosupport => 'minmax_support', descr => 'maximum value of all timestamp input values',
69496953
proname => 'max', prokind => 'a', proisstrict => 'f',
69506954
prorettype => 'timestamp', proargtypes => 'timestamp',
69516955
prosrc => 'aggregate_dummy' },
6952-
{ oid => '2127',
6956+
{ oid => '2127', prosupport => 'minmax_support',
69536957
descr => 'maximum value of all timestamp with time zone input values',
69546958
proname => 'max', prokind => 'a', proisstrict => 'f',
69556959
prorettype => 'timestamptz', proargtypes => 'timestamptz',
69566960
prosrc => 'aggregate_dummy' },
6957-
{ oid => '2128', descr => 'maximum value of all interval input values',
6961+
{ oid => '2128', prosupport => 'minmax_support', descr => 'maximum value of all interval input values',
69586962
proname => 'max', prokind => 'a', proisstrict => 'f',
69596963
prorettype => 'interval', proargtypes => 'interval',
69606964
prosrc => 'aggregate_dummy' },
6961-
{ oid => '2129', descr => 'maximum value of all text input values',
6965+
{ oid => '2129', prosupport => 'minmax_support', descr => 'maximum value of all text input values',
69626966
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'text',
69636967
proargtypes => 'text', prosrc => 'aggregate_dummy' },
69646968
{ oid => '2130', descr => 'maximum value of all numeric input values',
69656969
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'numeric',
69666970
proargtypes => 'numeric', prosrc => 'aggregate_dummy' },
6967-
{ oid => '2050', descr => 'maximum value of all anyarray input values',
6971+
{ oid => '2050', prosupport => 'minmax_support', descr => 'maximum value of all anyarray input values',
69686972
proname => 'max', prokind => 'a', proisstrict => 'f',
69696973
prorettype => 'anyarray', proargtypes => 'anyarray',
69706974
prosrc => 'aggregate_dummy' },
6971-
{ oid => '8595', descr => 'maximum value of all record input values',
6975+
{ oid => '8595', prosupport => 'minmax_support', descr => 'maximum value of all record input values',
69726976
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'record',
69736977
proargtypes => 'record', prosrc => 'aggregate_dummy' },
6974-
{ oid => '2244', descr => 'maximum value of all bpchar input values',
6978+
{ oid => '2244', prosupport => 'minmax_support', descr => 'maximum value of all bpchar input values',
69756979
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'bpchar',
69766980
proargtypes => 'bpchar', prosrc => 'aggregate_dummy' },
6977-
{ oid => '2797', descr => 'maximum value of all tid input values',
6981+
{ oid => '2797', prosupport => 'minmax_support', descr => 'maximum value of all tid input values',
69786982
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'tid',
69796983
proargtypes => 'tid', prosrc => 'aggregate_dummy' },
6980-
{ oid => '3564', descr => 'maximum value of all inet input values',
6984+
{ oid => '3564', prosupport => 'minmax_support', descr => 'maximum value of all inet input values',
69816985
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'inet',
69826986
proargtypes => 'inet', prosrc => 'aggregate_dummy' },
6983-
{ oid => '4189', descr => 'maximum value of all pg_lsn input values',
6987+
{ oid => '4189', prosupport => 'minmax_support', descr => 'maximum value of all pg_lsn input values',
69846988
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'pg_lsn',
69856989
proargtypes => 'pg_lsn', prosrc => 'aggregate_dummy' },
6986-
{ oid => '5099', descr => 'maximum value of all xid8 input values',
6990+
{ oid => '5099', prosupport => 'minmax_support', descr => 'maximum value of all xid8 input values',
69876991
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'xid8',
69886992
proargtypes => 'xid8', prosrc => 'aggregate_dummy' },
6989-
{ oid => '8922', descr => 'maximum value of all bytea input values',
6993+
{ oid => '8922', prosupport => 'minmax_support', descr => 'maximum value of all bytea input values',
69906994
proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'bytea',
69916995
proargtypes => 'bytea', prosrc => 'aggregate_dummy' },
69926996

6993-
{ oid => '2131', descr => 'minimum value of all bigint input values',
6997+
{ oid => '2131', prosupport => 'minmax_support', descr => 'minimum value of all bigint input values',
69946998
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'int8',
69956999
proargtypes => 'int8', prosrc => 'aggregate_dummy' },
6996-
{ oid => '2132', descr => 'minimum value of all integer input values',
7000+
{ oid => '2132', prosupport => 'minmax_support', descr => 'minimum value of all integer input values',
69977001
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'int4',
69987002
proargtypes => 'int4', prosrc => 'aggregate_dummy' },
6999-
{ oid => '2133', descr => 'minimum value of all smallint input values',
7003+
{ oid => '2133', prosupport => 'minmax_support', descr => 'minimum value of all smallint input values',
70007004
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'int2',
70017005
proargtypes => 'int2', prosrc => 'aggregate_dummy' },
7002-
{ oid => '2134', descr => 'minimum value of all oid input values',
7006+
{ oid => '2134', prosupport => 'minmax_support', descr => 'minimum value of all oid input values',
70037007
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'oid',
70047008
proargtypes => 'oid', prosrc => 'aggregate_dummy' },
7005-
{ oid => '2135', descr => 'minimum value of all float4 input values',
7009+
{ oid => '2135', prosupport => 'minmax_support', descr => 'minimum value of all float4 input values',
70067010
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'float4',
70077011
proargtypes => 'float4', prosrc => 'aggregate_dummy' },
7008-
{ oid => '2136', descr => 'minimum value of all float8 input values',
7012+
{ oid => '2136', prosupport => 'minmax_support', descr => 'minimum value of all float8 input values',
70097013
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'float8',
70107014
proargtypes => 'float8', prosrc => 'aggregate_dummy' },
7011-
{ oid => '2138', descr => 'minimum value of all date input values',
7015+
{ oid => '2138', prosupport => 'minmax_support', descr => 'minimum value of all date input values',
70127016
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'date',
70137017
proargtypes => 'date', prosrc => 'aggregate_dummy' },
7014-
{ oid => '2139', descr => 'minimum value of all time input values',
7018+
{ oid => '2139', prosupport => 'minmax_support', descr => 'minimum value of all time input values',
70157019
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'time',
70167020
proargtypes => 'time', prosrc => 'aggregate_dummy' },
7017-
{ oid => '2140',
7021+
{ oid => '2140', prosupport => 'minmax_support',
70187022
descr => 'minimum value of all time with time zone input values',
70197023
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'timetz',
70207024
proargtypes => 'timetz', prosrc => 'aggregate_dummy' },
7021-
{ oid => '2141', descr => 'minimum value of all money input values',
7025+
{ oid => '2141', prosupport => 'minmax_support', descr => 'minimum value of all money input values',
70227026
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'money',
70237027
proargtypes => 'money', prosrc => 'aggregate_dummy' },
7024-
{ oid => '2142', descr => 'minimum value of all timestamp input values',
7028+
{ oid => '2142', prosupport => 'minmax_support', descr => 'minimum value of all timestamp input values',
70257029
proname => 'min', prokind => 'a', proisstrict => 'f',
70267030
prorettype => 'timestamp', proargtypes => 'timestamp',
70277031
prosrc => 'aggregate_dummy' },
7028-
{ oid => '2143',
7032+
{ oid => '2143', prosupport => 'minmax_support',
70297033
descr => 'minimum value of all timestamp with time zone input values',
70307034
proname => 'min', prokind => 'a', proisstrict => 'f',
70317035
prorettype => 'timestamptz', proargtypes => 'timestamptz',
70327036
prosrc => 'aggregate_dummy' },
7033-
{ oid => '2144', descr => 'minimum value of all interval input values',
7037+
{ oid => '2144', prosupport => 'minmax_support', descr => 'minimum value of all interval input values',
70347038
proname => 'min', prokind => 'a', proisstrict => 'f',
70357039
prorettype => 'interval', proargtypes => 'interval',
70367040
prosrc => 'aggregate_dummy' },
7037-
{ oid => '2145', descr => 'minimum value of all text values',
7041+
{ oid => '2145', prosupport => 'minmax_support', descr => 'minimum value of all text values',
70387042
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'text',
70397043
proargtypes => 'text', prosrc => 'aggregate_dummy' },
70407044
{ oid => '2146', descr => 'minimum value of all numeric input values',
70417045
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'numeric',
70427046
proargtypes => 'numeric', prosrc => 'aggregate_dummy' },
7043-
{ oid => '2051', descr => 'minimum value of all anyarray input values',
7047+
{ oid => '2051', prosupport => 'minmax_support', descr => 'minimum value of all anyarray input values',
70447048
proname => 'min', prokind => 'a', proisstrict => 'f',
70457049
prorettype => 'anyarray', proargtypes => 'anyarray',
70467050
prosrc => 'aggregate_dummy' },
7047-
{ oid => '8596', descr => 'minimum value of all record input values',
7051+
{ oid => '8596', prosupport => 'minmax_support', descr => 'minimum value of all record input values',
70487052
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'record',
70497053
proargtypes => 'record', prosrc => 'aggregate_dummy' },
7050-
{ oid => '2245', descr => 'minimum value of all bpchar input values',
7054+
{ oid => '2245', prosupport => 'minmax_support', descr => 'minimum value of all bpchar input values',
70517055
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'bpchar',
70527056
proargtypes => 'bpchar', prosrc => 'aggregate_dummy' },
7053-
{ oid => '2798', descr => 'minimum value of all tid input values',
7057+
{ oid => '2798', prosupport => 'minmax_support', descr => 'minimum value of all tid input values',
70547058
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'tid',
70557059
proargtypes => 'tid', prosrc => 'aggregate_dummy' },
7056-
{ oid => '3565', descr => 'minimum value of all inet input values',
7060+
{ oid => '3565', prosupport => 'minmax_support', descr => 'minimum value of all inet input values',
70577061
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'inet',
70587062
proargtypes => 'inet', prosrc => 'aggregate_dummy' },
7059-
{ oid => '4190', descr => 'minimum value of all pg_lsn input values',
7063+
{ oid => '4190', prosupport => 'minmax_support', descr => 'minimum value of all pg_lsn input values',
70607064
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'pg_lsn',
70617065
proargtypes => 'pg_lsn', prosrc => 'aggregate_dummy' },
7062-
{ oid => '5100', descr => 'minimum value of all xid8 input values',
7066+
{ oid => '5100', prosupport => 'minmax_support', descr => 'minimum value of all xid8 input values',
70637067
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'xid8',
70647068
proargtypes => 'xid8', prosrc => 'aggregate_dummy' },
7065-
{ oid => '8923', descr => 'minimum value of all bytea input values',
7069+
{ oid => '8923', prosupport => 'minmax_support', descr => 'minimum value of all bytea input values',
70667070
proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'bytea',
70677071
proargtypes => 'bytea', prosrc => 'aggregate_dummy' },
70687072

src/include/nodes/supportnodes.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,4 +390,11 @@ typedef struct SupportRequestModifyInPlace
390390
int paramid; /* ID of Param(s) representing variable */
391391
} SupportRequestModifyInPlace;
392392

393+
typedef struct SupportRequestAggregate
394+
{
395+
NodeTag type;
396+
397+
Aggref *aggref;
398+
} SupportRequestAggregate;
399+
393400
#endif /* SUPPORTNODES_H */

0 commit comments

Comments
 (0)