summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorHeikki Linnakangas2020-11-24 08:45:00 +0000
committerHeikki Linnakangas2020-11-24 08:45:00 +0000
commit0a2bc5d61e713e3fe72438f020eea5fcc90b0f0b (patch)
tree8f630f828fa6bbfb5984f037118211cd68d8a50e /src/include
parente522024bd8dd28a0f13dcccfd39170698f45c939 (diff)
Move per-agg and per-trans duplicate finding to the planner.
This has the advantage that the cost estimates for aggregates can count the number of calls to transition and final functions correctly. Bump catalog version, because views can contain Aggrefs. Reviewed-by: Andres Freund Discussion: https://www.postgresql.org/message-id/b2e3536b-1dbc-8303-c97e-89cb0b4a9a48%40iki.fi
Diffstat (limited to 'src/include')
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/executor/execExpr.h3
-rw-r--r--src/include/nodes/execnodes.h11
-rw-r--r--src/include/nodes/nodes.h3
-rw-r--r--src/include/nodes/pathnodes.h80
-rw-r--r--src/include/nodes/primnodes.h8
-rw-r--r--src/include/optimizer/clauses.h2
-rw-r--r--src/include/optimizer/prep.h8
-rw-r--r--src/include/utils/selfuncs.h2
9 files changed, 96 insertions, 23 deletions
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 1276ff8bdac..087efddff9b 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202011231
+#define CATALOG_VERSION_NO 202011241
#endif
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
index b792de1bc95..abb489e2062 100644
--- a/src/include/executor/execExpr.h
+++ b/src/include/executor/execExpr.h
@@ -564,8 +564,7 @@ typedef struct ExprEvalStep
/* for EEOP_AGGREF */
struct
{
- /* out-of-line state, modified by nodeAgg.c */
- AggrefExprState *astate;
+ int aggno;
} aggref;
/* for EEOP_GROUPING_FUNC */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index f6824bf2e1b..61ba4c36662 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -747,17 +747,6 @@ typedef tuplehash_iterator TupleHashIterator;
*/
/* ----------------
- * AggrefExprState node
- * ----------------
- */
-typedef struct AggrefExprState
-{
- NodeTag type;
- Aggref *aggref; /* expression plan node */
- int aggno; /* ID number for agg within its plan node */
-} AggrefExprState;
-
-/* ----------------
* WindowFuncExprState node
* ----------------
*/
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 7ddd8c011bf..3684f87a883 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -206,10 +206,9 @@ typedef enum NodeTag
* Most Expr-based plan nodes do not have a corresponding expression state
* node, they're fully handled within execExpr* - but sometimes the state
* needs to be shared with other parts of the executor, as for example
- * with AggrefExprState, which nodeAgg.c has to modify.
+ * with SubPlanState, which nodeSubplan.c has to modify.
*/
T_ExprState,
- T_AggrefExprState,
T_WindowFuncExprState,
T_SetExprState,
T_SubPlanState,
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index 8f62d617028..abe6f570e32 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -55,10 +55,6 @@ typedef struct QualCost
*/
typedef struct AggClauseCosts
{
- int numAggs; /* total number of aggregate functions */
- int numOrderedAggs; /* number w/ DISTINCT/ORDER BY/WITHIN GROUP */
- bool hasNonPartial; /* does any agg not support partial mode? */
- bool hasNonSerial; /* is any partial agg non-serializable? */
QualCost transCost; /* total per-input-row execution costs */
QualCost finalCost; /* total per-aggregated-row costs */
Size transitionSpace; /* space for pass-by-ref transition data */
@@ -348,6 +344,15 @@ struct PlannerInfo
bool hasAlternativeSubPlans; /* true if we've made any of those */
bool hasRecursion; /* true if planning a recursive WITH item */
+ /*
+ * Information about aggregates. Filled by preprocess_aggrefs().
+ */
+ List *agginfos; /* AggInfo structs */
+ List *aggtransinfos; /* AggTransInfo structs */
+ int numOrderedAggs; /* number w/ DISTINCT/ORDER BY/WITHIN GROUP */
+ bool hasNonPartialAggs; /* does any agg not support partial mode? */
+ bool hasNonSerialAggs; /* is any partial agg non-serializable? */
+
/* These fields are used only when hasRecursion is true: */
int wt_param_id; /* PARAM_EXEC ID for the work table */
struct Path *non_recursive_path; /* a path for non-recursive term */
@@ -2549,4 +2554,71 @@ typedef struct JoinCostWorkspace
double inner_rows_total;
} JoinCostWorkspace;
+/*
+ * AggInfo holds information about an aggregate that needs to be computed.
+ * Multiple Aggrefs in a query can refer to the same AggInfo by having the
+ * same 'aggno' value, so that the aggregate is computed only once.
+ */
+typedef struct AggInfo
+{
+ /*
+ * Link to an Aggref expr this state value is for.
+ *
+ * There can be multiple identical Aggref's sharing the same per-agg. This
+ * points to the first one of them.
+ */
+ Aggref *representative_aggref;
+
+ int transno;
+
+ /*
+ * "shareable" is false if this agg cannot share state values with other
+ * aggregates because the final function is read-write.
+ */
+ bool shareable;
+
+ /* Oid of the final function or InvalidOid */
+ Oid finalfn_oid;
+
+} AggInfo;
+
+/*
+ * AggTransInfo holds information about transition state that is used by one
+ * or more aggregates in the query. Multiple aggregates can share the same
+ * transition state, if they have the same inputs and the same transition
+ * function. Aggrefs that share the same transition info have the same
+ * 'aggtransno' value.
+ */
+typedef struct AggTransInfo
+{
+ List *args;
+ Expr *aggfilter;
+
+ /* Oid of the state transition function */
+ Oid transfn_oid;
+
+ /* Oid of the serialization function or InvalidOid */
+ Oid serialfn_oid;
+
+ /* Oid of the deserialization function or InvalidOid */
+ Oid deserialfn_oid;
+
+ /* Oid of the combine function or InvalidOid */
+ Oid combinefn_oid;
+
+ /* Oid of state value's datatype */
+ Oid aggtranstype;
+ int32 aggtranstypmod;
+ int transtypeLen;
+ bool transtypeByVal;
+ int32 aggtransspace;
+
+ /*
+ * initial value from pg_aggregate entry
+ */
+ Datum initValue;
+ bool initValueIsNull;
+
+} AggTransInfo;
+
#endif /* PATHNODES_H */
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 5b190bb99bd..cdbe781c734 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -305,6 +305,12 @@ typedef struct Param
* a crosscheck that the Aggrefs match the plan; but note that when aggsplit
* indicates a non-final mode, aggtype reflects the transition data type
* not the SQL-level output type of the aggregate.
+ *
+ * aggno and aggtransno are -1 in the parse stage, and are set in planning.
+ * Aggregates with the same 'aggno' represent the same aggregate expression,
+ * and can share the result. Aggregates with same 'transno' but different
+ * 'aggno' can share the same transition state, only the final function needs
+ * to be called separately.
*/
typedef struct Aggref
{
@@ -326,6 +332,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 */
+ int aggno; /* unique ID within the Agg node */
+ int aggtransno; /* unique ID of transition state in the Agg */
int location; /* token location, or -1 if unknown */
} Aggref;
diff --git a/src/include/optimizer/clauses.h b/src/include/optimizer/clauses.h
index 2584ffc72fc..68855d0cee7 100644
--- a/src/include/optimizer/clauses.h
+++ b/src/include/optimizer/clauses.h
@@ -24,8 +24,6 @@ typedef struct
} WindowFuncLists;
extern bool contain_agg_clause(Node *clause);
-extern void get_agg_clause_costs(PlannerInfo *root, Node *clause,
- AggSplit aggsplit, AggClauseCosts *costs);
extern bool contain_window_function(Node *clause);
extern WindowFuncLists *find_window_functions(Node *clause, Index maxWinRef);
diff --git a/src/include/optimizer/prep.h b/src/include/optimizer/prep.h
index 19c92302b03..0abe6bec00e 100644
--- a/src/include/optimizer/prep.h
+++ b/src/include/optimizer/prep.h
@@ -39,8 +39,16 @@ extern List *preprocess_targetlist(PlannerInfo *root);
extern PlanRowMark *get_plan_rowmark(List *rowmarks, Index rtindex);
/*
+ * prototypes for prepagg.c
+ */
+extern void get_agg_clause_costs(PlannerInfo *root, AggSplit aggsplit,
+ AggClauseCosts *agg_costs);
+extern void preprocess_aggrefs(PlannerInfo *root, Node *clause);
+
+/*
* prototypes for prepunion.c
*/
extern RelOptInfo *plan_set_operations(PlannerInfo *root);
+
#endif /* PREP_H */
diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h
index 7ac4a063915..3a2cfb7efa6 100644
--- a/src/include/utils/selfuncs.h
+++ b/src/include/utils/selfuncs.h
@@ -200,7 +200,7 @@ extern void estimate_hash_bucket_stats(PlannerInfo *root,
Node *hashkey, double nbuckets,
Selectivity *mcv_freq,
Selectivity *bucketsize_frac);
-extern double estimate_hashagg_tablesize(Path *path,
+extern double estimate_hashagg_tablesize(PlannerInfo *root, Path *path,
const AggClauseCosts *agg_costs,
double dNumGroups);