pass-numaggs-from-planner.patch
text/x-patch
Filename: pass-numaggs-from-planner.patch
Type: text/x-patch
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/executor/execExpr.c | 13 | 1 |
| src/backend/executor/nodeAgg.c | 25 | 44 |
| src/backend/nodes/copyfuncs.c | 2 | 0 |
| src/backend/nodes/outfuncs.c | 2 | 0 |
| src/backend/nodes/readfuncs.c | 2 | 0 |
| src/backend/optimizer/plan/createplan.c | 9 | 2 |
| src/include/nodes/execnodes.h | 4 | 5 |
| src/include/nodes/plannodes.h | 3 | 0 |
| src/include/optimizer/planmain.h | 1 | 1 |
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 2a4dea2b052..6a03fa730e5 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -785,11 +785,23 @@ ExecInitExprRec(Expr *node, ExprState *state,
scratch.d.aggref.astate = astate;
astate->aggno = aggref->aggno;
+ /*
+ * Remember this Aggref as the representative for the
+ * aggregate. ExecInitAgg needs a representative for
+ * initializing the states, and it can also be accessed
+ * by the user-defined functions by AggGetAggref().
+ */
if (state->parent && IsA(state->parent, AggState))
{
AggState *aggstate = (AggState *) state->parent;
+ AggStatePerAgg peragg;
+
+ if (aggref->aggno >= aggstate->numaggs)
+ elog(ERROR, "invalid aggno %d", aggref->aggno);
+ peragg = &aggstate->peragg[aggref->aggno];
- aggstate->aggs = lappend(aggstate->aggs, aggref);
+ if (peragg->aggref == NULL)
+ peragg->aggref = aggref;
}
else
{
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 7585689b94d..1949729a494 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -3236,13 +3236,11 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
Plan *outerPlan;
ExprContext *econtext;
TupleDesc scanDesc;
- int max_aggno;
- int max_transno;
- int numaggrefs;
int numaggs;
int numtrans;
int phase;
int phaseidx;
+ int aggno;
ListCell *l;
Bitmapset *all_grouped_cols = NULL;
int numGroupingSets = 1;
@@ -3264,7 +3262,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
aggstate->ss.ps.state = estate;
aggstate->ss.ps.ExecProcNode = ExecAgg;
- aggstate->aggs = NIL;
aggstate->numaggs = 0;
aggstate->numtrans = 0;
aggstate->aggstrategy = node->aggstrategy;
@@ -3401,6 +3398,17 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
aggstate->ss.ps.outeropsfixed = false;
}
+ /* Initialize the per-agg and per-trans arrays before calling ExecInitExpr() */
+ numaggs = node->numAggs;
+ peraggs = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
+ aggstate->peragg = peraggs;
+ aggstate->numaggs = numaggs;
+
+ numtrans = node->numTrans;
+ pertransstates = (AggStatePerTrans) palloc0(sizeof(AggStatePerTransData) * numtrans);
+ aggstate->pertrans = pertransstates;
+ aggstate->numtrans = numtrans;
+
/*
* Initialize result type, slot and projection.
*/
@@ -3423,22 +3431,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
aggstate->ss.ps.qual =
ExecInitQual(node->plan.qual, (PlanState *) aggstate);
- /*
- * We should now have found all Aggrefs in the targetlist and quals.
- */
- numaggrefs = list_length(aggstate->aggs);
- max_aggno = -1;
- max_transno = -1;
- foreach(l, aggstate->aggs)
- {
- Aggref *aggref = (Aggref *) lfirst(l);
-
- max_aggno = Max(max_aggno, aggref->aggno);
- max_transno = Max(max_transno, aggref->aggtransno);
- }
- numaggs = max_aggno + 1;
- numtrans = max_transno + 1;
-
/*
* For each phase, prepare grouping set data and fmgr lookup data for
* compare functions. Accumulate all_grouped_cols in passing.
@@ -3607,13 +3599,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
- peraggs = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
- pertransstates = (AggStatePerTrans) palloc0(sizeof(AggStatePerTransData) * numtrans);
-
- aggstate->peragg = peraggs;
- aggstate->pertrans = pertransstates;
-
-
aggstate->all_pergroups =
(AggStatePerGroup *) palloc0(sizeof(AggStatePerGroup)
* (numGroupingSets + numHashes));
@@ -3699,11 +3684,11 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
* Perform lookups of aggregate function info, and initialize the
* unchanging fields of the per-agg and per-trans data.
*/
- foreach(l, aggstate->aggs)
+ for (aggno = 0; aggno < numaggs; aggno++)
{
- Aggref *aggref = lfirst(l);
- AggStatePerAgg peragg;
+ AggStatePerAgg peragg = &peraggs[aggno];
AggStatePerTrans pertrans;
+ Aggref *aggref;
Oid inputTypes[FUNC_MAX_ARGS];
int numArguments;
int numDirectArgs;
@@ -3717,18 +3702,18 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
Expr *finalfnexpr;
Oid aggtranstype;
+ if (peragg->aggref == NULL)
+ {
+ elog(ERROR, "aggregate %d of %d was not found in expression initialization",
+ aggno, numaggs);
+ }
+ aggref = peragg->aggref;
+
/* Planner should have assigned aggregate to correct level */
Assert(aggref->agglevelsup == 0);
/* ... and the split mode should match */
Assert(aggref->aggsplit == aggstate->aggsplit);
- peragg = &peraggs[aggref->aggno];
-
- /* Check if we initialized the state for this aggregate already. */
- if (peragg->aggref != NULL)
- continue;
-
- peragg->aggref = aggref;
peragg->transno = aggref->aggtransno;
/* Fetch the pg_aggregate row */
@@ -3934,13 +3919,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
ReleaseSysCache(aggTuple);
}
- /*
- * Update aggstate->numaggs to be the number of unique aggregates found.
- * Also set numstates to the number of unique transition states found.
- */
- aggstate->numaggs = numaggs;
- aggstate->numtrans = numtrans;
-
/*
* Last, check whether any more aggregates got added onto the node while
* we processed the expressions for the aggregate arguments (including not
@@ -3951,10 +3929,13 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
* need to work hard on a helpful error message; but we defend against it
* here anyway, just to be sure.)
*/
+ /* FIXME: need another way to sanity check this now. Not hard. Or just remove this */
+#if 0
if (numaggrefs != list_length(aggstate->aggs))
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("aggregate function calls cannot be nested")));
+#endif
/*
* Build expressions doing all the transition work at once. We build a
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index d15866de89f..812735576f2 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -1024,6 +1024,8 @@ _copyAgg(const Agg *from)
COPY_BITMAPSET_FIELD(aggParams);
COPY_NODE_FIELD(groupingSets);
COPY_NODE_FIELD(chain);
+ COPY_SCALAR_FIELD(numAggs);
+ COPY_SCALAR_FIELD(numTrans);
return newnode;
}
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 3c740b805f3..e3c168531f9 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -785,6 +785,8 @@ _outAgg(StringInfo str, const Agg *node)
WRITE_BITMAPSET_FIELD(aggParams);
WRITE_NODE_FIELD(groupingSets);
WRITE_NODE_FIELD(chain);
+ WRITE_INT_FIELD(numAggs);
+ WRITE_INT_FIELD(numTrans);
}
static void
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 169d5581b91..43533e13daa 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -2235,6 +2235,8 @@ _readAgg(void)
READ_BITMAPSET_FIELD(aggParams);
READ_NODE_FIELD(groupingSets);
READ_NODE_FIELD(chain);
+ READ_INT_FIELD(numAggs);
+ READ_INT_FIELD(numTrans);
READ_DONE();
}
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 94280a730c4..b5e88acf055 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -1657,7 +1657,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
NIL,
NIL,
best_path->path.rows,
- 0,
+ 0, 0, 0,
subplan);
}
else
@@ -2139,6 +2139,7 @@ create_agg_plan(PlannerInfo *root, AggPath *best_path)
NIL,
best_path->numGroups,
best_path->transitionSpace,
+ list_length(root->agginfos), list_length(root->aggtransinfos),
subplan);
copy_generic_path_info(&plan->plan, (Path *) best_path);
@@ -2301,6 +2302,8 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
NIL,
rollup->numGroups,
best_path->transitionSpace,
+ list_length(root->agginfos),
+ list_length(root->aggtransinfos),
sort_plan);
/*
@@ -2340,6 +2343,8 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
chain,
rollup->numGroups,
best_path->transitionSpace,
+ list_length(root->agginfos),
+ list_length(root->aggtransinfos),
subplan);
/* Copy cost data from Path to Plan */
@@ -6350,7 +6355,7 @@ make_agg(List *tlist, List *qual,
AggStrategy aggstrategy, AggSplit aggsplit,
int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
List *groupingSets, List *chain, double dNumGroups,
- Size transitionSpace, Plan *lefttree)
+ Size transitionSpace, int numAggs, int numTrans, Plan *lefttree)
{
Agg *node = makeNode(Agg);
Plan *plan = &node->plan;
@@ -6370,6 +6375,8 @@ make_agg(List *tlist, List *qual,
node->aggParams = NULL; /* SS_finalize_plan() will fill this */
node->groupingSets = groupingSets;
node->chain = chain;
+ node->numAggs = numAggs;
+ node->numTrans = numTrans;
plan->qual = qual;
plan->targetlist = tlist;
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index fc5698cff20..ce47d7869dc 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -2140,7 +2140,6 @@ typedef struct AggStatePerHashData *AggStatePerHash;
typedef struct AggState
{
ScanState ss; /* its first field is NodeTag */
- List *aggs; /* all Aggref nodes in targetlist & quals */
int numaggs; /* length of list (could be zero!) */
int numtrans; /* number of pertrans items */
AggStrategy aggstrategy; /* strategy mode */
@@ -2153,15 +2152,15 @@ typedef struct AggState
ExprContext *hashcontext; /* econtexts for long-lived data (hashtable) */
ExprContext **aggcontexts; /* econtexts for long-lived data (per GS) */
ExprContext *tmpcontext; /* econtext for input expressions */
-#define FIELDNO_AGGSTATE_CURAGGCONTEXT 14
+#define FIELDNO_AGGSTATE_CURAGGCONTEXT 13
ExprContext *curaggcontext; /* currently active aggcontext */
AggStatePerAgg curperagg; /* currently active aggregate, if any */
-#define FIELDNO_AGGSTATE_CURPERTRANS 16
+#define FIELDNO_AGGSTATE_CURPERTRANS 15
AggStatePerTrans curpertrans; /* currently active trans state, if any */
bool input_done; /* indicates end of input */
bool agg_done; /* indicates completion of Agg scan */
int projected_set; /* The last projected grouping set */
-#define FIELDNO_AGGSTATE_CURRENT_SET 20
+#define FIELDNO_AGGSTATE_CURRENT_SET 19
int current_set; /* The current grouping set being evaluated */
Bitmapset *grouped_cols; /* grouped cols in current projection */
List *all_grouped_cols; /* list of all grouped cols in DESC order */
@@ -2207,7 +2206,7 @@ typedef struct AggState
* per-group pointers */
/* support for evaluation of agg input expressions: */
-#define FIELDNO_AGGSTATE_ALL_PERGROUPS 53
+#define FIELDNO_AGGSTATE_ALL_PERGROUPS 52
AggStatePerGroup *all_pergroups; /* array of first ->pergroups, than
* ->hash_pergroup */
ProjectionInfo *combinedproj; /* projection machinery */
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 7e6b10f86b9..f60f301a2b1 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -828,6 +828,9 @@ typedef struct Agg
/* Note: planner provides numGroups & aggParams only in HASHED/MIXED case */
List *groupingSets; /* grouping sets to use */
List *chain; /* chained Agg/Sort nodes */
+
+ int numAggs;
+ int numTrans;
} Agg;
/* ----------------
diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h
index f3cefe67b8d..d64f7c1344b 100644
--- a/src/include/optimizer/planmain.h
+++ b/src/include/optimizer/planmain.h
@@ -55,7 +55,7 @@ extern Agg *make_agg(List *tlist, List *qual,
AggStrategy aggstrategy, AggSplit aggsplit,
int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
List *groupingSets, List *chain, double dNumGroups,
- Size transitionSpace, Plan *lefttree);
+ Size transitionSpace, int numAggs, int numTrans, Plan *lefttree);
extern Limit *make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount,
LimitOption limitOption, int uniqNumCols,
AttrNumber *uniqColIdx, Oid *uniqOperators,