aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeAgg.c
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2000-04-12 17:17:23 +0000
committerBruce Momjian <bruce@momjian.us>2000-04-12 17:17:23 +0000
commit52f77df613cea1803ce86321c37229626d9f213c (patch)
treebd9ac9f667f295cb65f4c448a5bb5a062d656b27 /src/backend/executor/nodeAgg.c
parentdb4518729d85da83eafdacbcebaeb12618517595 (diff)
downloadpostgresql-52f77df613cea1803ce86321c37229626d9f213c.tar.gz
postgresql-52f77df613cea1803ce86321c37229626d9f213c.zip
Ye-old pgindent run. Same 4-space tabs.
Diffstat (limited to 'src/backend/executor/nodeAgg.c')
-rw-r--r--src/backend/executor/nodeAgg.c261
1 files changed, 137 insertions, 124 deletions
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 961440cc66d..e2db06f84d1 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -15,7 +15,7 @@
* value1 = finalfunc(value1, value2)
*
* If initcond1 is NULL then the first non-NULL input_value is
- * assigned directly to value1. sfunc1 isn't applied until value1
+ * assigned directly to value1. sfunc1 isn't applied until value1
* is non-NULL.
*
* sfunc1 is never applied when the current tuple's input_value is NULL.
@@ -24,7 +24,7 @@
* (usenulls was formerly used for COUNT(*), but is no longer needed for
* that purpose; as of 10/1999 the support for usenulls is dead code.
* I have not removed it because it seems like a potentially useful
- * feature for user-defined aggregates. We'd just need to add a
+ * feature for user-defined aggregates. We'd just need to add a
* flag column to pg_aggregate and a parameter to CREATE AGGREGATE...)
*
*
@@ -32,7 +32,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.62 2000/01/26 05:56:22 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.63 2000/04/12 17:15:09 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -56,6 +56,7 @@
*/
typedef struct AggStatePerAggData
{
+
/*
* These values are set up during ExecInitAgg() and do not change
* thereafter:
@@ -68,6 +69,7 @@ typedef struct AggStatePerAggData
Oid xfn1_oid;
Oid xfn2_oid;
Oid finalfn_oid;
+
/*
* fmgr lookup data for transfer functions --- only valid when
* corresponding oid is not InvalidOid
@@ -75,18 +77,21 @@ typedef struct AggStatePerAggData
FmgrInfo xfn1;
FmgrInfo xfn2;
FmgrInfo finalfn;
+
/*
- * Type of input data and Oid of sort operator to use for it;
- * only set/used when aggregate has DISTINCT flag. (These are not
- * used directly by nodeAgg, but must be passed to the Tuplesort object.)
+ * Type of input data and Oid of sort operator to use for it; only
+ * set/used when aggregate has DISTINCT flag. (These are not used
+ * directly by nodeAgg, but must be passed to the Tuplesort object.)
*/
Oid inputType;
Oid sortOperator;
+
/*
- * fmgr lookup data for input type's equality operator --- only set/used
- * when aggregate has DISTINCT flag.
+ * fmgr lookup data for input type's equality operator --- only
+ * set/used when aggregate has DISTINCT flag.
*/
FmgrInfo equalfn;
+
/*
* initial values from pg_aggregate entry
*/
@@ -94,6 +99,7 @@ typedef struct AggStatePerAggData
Datum initValue2; /* for transtype2 */
bool initValue1IsNull,
initValue2IsNull;
+
/*
* We need the len and byval info for the agg's input and transition
* data types in order to know how to copy/delete values.
@@ -106,14 +112,14 @@ typedef struct AggStatePerAggData
transtype2ByVal;
/*
- * These values are working state that is initialized at the start
- * of an input tuple group and updated for each input tuple.
+ * These values are working state that is initialized at the start of
+ * an input tuple group and updated for each input tuple.
*
* For a simple (non DISTINCT) aggregate, we just feed the input values
- * straight to the transition functions. If it's DISTINCT, we pass the
- * input values into a Tuplesort object; then at completion of the input
- * tuple group, we scan the sorted values, eliminate duplicates, and run
- * the transition functions on the rest.
+ * straight to the transition functions. If it's DISTINCT, we pass
+ * the input values into a Tuplesort object; then at completion of the
+ * input tuple group, we scan the sorted values, eliminate duplicates,
+ * and run the transition functions on the rest.
*/
Tuplesortstate *sortstate; /* sort object, if a DISTINCT agg */
@@ -123,20 +129,22 @@ typedef struct AggStatePerAggData
bool value1IsNull,
value2IsNull;
bool noInitValue; /* true if value1 not set yet */
+
/*
- * Note: right now, noInitValue always has the same value as value1IsNull.
- * But we should keep them separate because once the fmgr interface is
- * fixed, we'll need to distinguish a null returned by transfn1 from
- * a null we haven't yet replaced with an input value.
+ * Note: right now, noInitValue always has the same value as
+ * value1IsNull. But we should keep them separate because once the
+ * fmgr interface is fixed, we'll need to distinguish a null returned
+ * by transfn1 from a null we haven't yet replaced with an input
+ * value.
*/
} AggStatePerAggData;
-static void initialize_aggregate (AggStatePerAgg peraggstate);
-static void advance_transition_functions (AggStatePerAgg peraggstate,
- Datum newVal, bool isNull);
-static void finalize_aggregate (AggStatePerAgg peraggstate,
- Datum *resultVal, bool *resultIsNull);
+static void initialize_aggregate(AggStatePerAgg peraggstate);
+static void advance_transition_functions(AggStatePerAgg peraggstate,
+ Datum newVal, bool isNull);
+static void finalize_aggregate(AggStatePerAgg peraggstate,
+ Datum *resultVal, bool *resultIsNull);
static Datum copyDatum(Datum val, int typLen, bool typByVal);
@@ -144,17 +152,19 @@ static Datum copyDatum(Datum val, int typLen, bool typByVal);
* Initialize one aggregate for a new set of input values.
*/
static void
-initialize_aggregate (AggStatePerAgg peraggstate)
+initialize_aggregate(AggStatePerAgg peraggstate)
{
- Aggref *aggref = peraggstate->aggref;
+ Aggref *aggref = peraggstate->aggref;
/*
* Start a fresh sort operation for each DISTINCT aggregate.
*/
if (aggref->aggdistinct)
{
- /* In case of rescan, maybe there could be an uncompleted
- * sort operation? Clean it up if so.
+
+ /*
+ * In case of rescan, maybe there could be an uncompleted sort
+ * operation? Clean it up if so.
*/
if (peraggstate->sortstate)
tuplesort_end(peraggstate->sortstate);
@@ -169,8 +179,8 @@ initialize_aggregate (AggStatePerAgg peraggstate)
* (Re)set value1 and value2 to their initial values.
*/
if (OidIsValid(peraggstate->xfn1_oid) &&
- ! peraggstate->initValue1IsNull)
- peraggstate->value1 = copyDatum(peraggstate->initValue1,
+ !peraggstate->initValue1IsNull)
+ peraggstate->value1 = copyDatum(peraggstate->initValue1,
peraggstate->transtype1Len,
peraggstate->transtype1ByVal);
else
@@ -178,8 +188,8 @@ initialize_aggregate (AggStatePerAgg peraggstate)
peraggstate->value1IsNull = peraggstate->initValue1IsNull;
if (OidIsValid(peraggstate->xfn2_oid) &&
- ! peraggstate->initValue2IsNull)
- peraggstate->value2 = copyDatum(peraggstate->initValue2,
+ !peraggstate->initValue2IsNull)
+ peraggstate->value2 = copyDatum(peraggstate->initValue2,
peraggstate->transtype2Len,
peraggstate->transtype2ByVal);
else
@@ -205,8 +215,8 @@ initialize_aggregate (AggStatePerAgg peraggstate)
* out before reaching here.
*/
static void
-advance_transition_functions (AggStatePerAgg peraggstate,
- Datum newVal, bool isNull)
+advance_transition_functions(AggStatePerAgg peraggstate,
+ Datum newVal, bool isNull)
{
Datum args[2];
@@ -214,6 +224,7 @@ advance_transition_functions (AggStatePerAgg peraggstate,
{
if (peraggstate->noInitValue)
{
+
/*
* value1 has not been initialized. This is the first non-NULL
* input value. We use it as the initial value for value1.
@@ -238,7 +249,7 @@ advance_transition_functions (AggStatePerAgg peraggstate,
newVal = (Datum) fmgr_c(&peraggstate->xfn1,
(FmgrValues *) args,
&isNull);
- if (! peraggstate->transtype1ByVal)
+ if (!peraggstate->transtype1ByVal)
pfree(peraggstate->value1);
peraggstate->value1 = newVal;
}
@@ -252,7 +263,7 @@ advance_transition_functions (AggStatePerAgg peraggstate,
newVal = (Datum) fmgr_c(&peraggstate->xfn2,
(FmgrValues *) args,
&isNull);
- if (! peraggstate->transtype2ByVal)
+ if (!peraggstate->transtype2ByVal)
pfree(peraggstate->value2);
peraggstate->value2 = newVal;
}
@@ -262,17 +273,18 @@ advance_transition_functions (AggStatePerAgg peraggstate,
* Compute the final value of one aggregate.
*/
static void
-finalize_aggregate (AggStatePerAgg peraggstate,
- Datum *resultVal, bool *resultIsNull)
+finalize_aggregate(AggStatePerAgg peraggstate,
+ Datum *resultVal, bool *resultIsNull)
{
Aggref *aggref = peraggstate->aggref;
char *args[2];
/*
* If it's a DISTINCT aggregate, all we've done so far is to stuff the
- * input values into the sort object. Complete the sort, then run
- * the transition functions on the non-duplicate values. Note that
- * DISTINCT always suppresses nulls, per SQL spec, regardless of usenulls.
+ * input values into the sort object. Complete the sort, then run the
+ * transition functions on the non-duplicate values. Note that
+ * DISTINCT always suppresses nulls, per SQL spec, regardless of
+ * usenulls.
*/
if (aggref->aggdistinct)
{
@@ -289,41 +301,41 @@ finalize_aggregate (AggStatePerAgg peraggstate,
continue;
if (haveOldVal)
{
- Datum equal;
+ Datum equal;
equal = (Datum) (*fmgr_faddr(&peraggstate->equalfn)) (oldVal,
- newVal);
+ newVal);
if (DatumGetInt32(equal) != 0)
{
- if (! peraggstate->inputtypeByVal)
+ if (!peraggstate->inputtypeByVal)
pfree(DatumGetPointer(newVal));
continue;
}
}
advance_transition_functions(peraggstate, newVal, false);
- if (haveOldVal && ! peraggstate->inputtypeByVal)
+ if (haveOldVal && !peraggstate->inputtypeByVal)
pfree(DatumGetPointer(oldVal));
oldVal = newVal;
haveOldVal = true;
}
- if (haveOldVal && ! peraggstate->inputtypeByVal)
+ if (haveOldVal && !peraggstate->inputtypeByVal)
pfree(DatumGetPointer(oldVal));
tuplesort_end(peraggstate->sortstate);
peraggstate->sortstate = NULL;
}
/*
- * Now apply the agg's finalfn, or substitute the appropriate transition
- * value if there is no finalfn.
+ * Now apply the agg's finalfn, or substitute the appropriate
+ * transition value if there is no finalfn.
*
- * XXX For now, only apply finalfn if we got at least one
- * non-null input value. This prevents zero divide in AVG().
- * If we had cleaner handling of null inputs/results in functions,
- * we could probably take out this hack and define the result
- * for no inputs as whatever finalfn returns for null input.
+ * XXX For now, only apply finalfn if we got at least one non-null input
+ * value. This prevents zero divide in AVG(). If we had cleaner
+ * handling of null inputs/results in functions, we could probably
+ * take out this hack and define the result for no inputs as whatever
+ * finalfn returns for null input.
*/
if (OidIsValid(peraggstate->finalfn_oid) &&
- ! peraggstate->noInitValue)
+ !peraggstate->noInitValue)
{
if (peraggstate->finalfn.fn_nargs > 1)
{
@@ -361,17 +373,17 @@ finalize_aggregate (AggStatePerAgg peraggstate,
elog(ERROR, "ExecAgg: no valid transition functions??");
/*
- * Release any per-group working storage, unless we're passing
- * it back as the result of the aggregate.
+ * Release any per-group working storage, unless we're passing it back
+ * as the result of the aggregate.
*/
if (OidIsValid(peraggstate->xfn1_oid) &&
- ! peraggstate->value1IsNull &&
- ! peraggstate->transtype1ByVal)
+ !peraggstate->value1IsNull &&
+ !peraggstate->transtype1ByVal)
pfree(peraggstate->value1);
-
+
if (OidIsValid(peraggstate->xfn2_oid) &&
- ! peraggstate->value2IsNull &&
- ! peraggstate->transtype2ByVal)
+ !peraggstate->value2IsNull &&
+ !peraggstate->transtype2ByVal)
pfree(peraggstate->value2);
}
@@ -383,8 +395,8 @@ finalize_aggregate (AggStatePerAgg peraggstate,
* the appropriate attribute for each aggregate function use (Aggref
* node) appearing in the targetlist or qual of the node. The number
* of tuples to aggregate over depends on whether a GROUP BY clause is
- * present. We can produce an aggregate result row per group, or just
- * one for the whole query. The value of each aggregate is stored in
+ * present. We can produce an aggregate result row per group, or just
+ * one for the whole query. The value of each aggregate is stored in
* the expression context to be used when ExecProject evaluates the
* result tuple.
*
@@ -403,7 +415,7 @@ ExecAgg(Agg *node)
ProjectionInfo *projInfo;
Datum *aggvalues;
bool *aggnulls;
- AggStatePerAgg peragg;
+ AggStatePerAgg peragg;
TupleTableSlot *resultSlot;
HeapTuple inputTuple;
int aggno;
@@ -437,7 +449,7 @@ ExecAgg(Agg *node)
*/
for (aggno = 0; aggno < aggstate->numaggs; aggno++)
{
- AggStatePerAgg peraggstate = &peragg[aggno];
+ AggStatePerAgg peraggstate = &peragg[aggno];
initialize_aggregate(peraggstate);
}
@@ -459,9 +471,9 @@ ExecAgg(Agg *node)
for (aggno = 0; aggno < aggstate->numaggs; aggno++)
{
- AggStatePerAgg peraggstate = &peragg[aggno];
- Aggref *aggref = peraggstate->aggref;
- Datum newVal;
+ AggStatePerAgg peraggstate = &peragg[aggno];
+ Aggref *aggref = peraggstate->aggref;
+ Datum newVal;
newVal = ExecEvalExpr(aggref->target, econtext,
&isNull, &isDone);
@@ -479,37 +491,37 @@ ExecAgg(Agg *node)
/*
* Keep a copy of the first input tuple for the projection.
- * (We only need one since only the GROUP BY columns in it
- * can be referenced, and these will be the same for all
- * tuples aggregated over.)
+ * (We only need one since only the GROUP BY columns in it can
+ * be referenced, and these will be the same for all tuples
+ * aggregated over.)
*/
if (!inputTuple)
inputTuple = heap_copytuple(outerslot->val);
}
/*
- * Done scanning input tuple group.
- * Finalize each aggregate calculation.
+ * Done scanning input tuple group. Finalize each aggregate
+ * calculation.
*/
for (aggno = 0; aggno < aggstate->numaggs; aggno++)
{
- AggStatePerAgg peraggstate = &peragg[aggno];
+ AggStatePerAgg peraggstate = &peragg[aggno];
finalize_aggregate(peraggstate,
- & aggvalues[aggno], & aggnulls[aggno]);
+ &aggvalues[aggno], &aggnulls[aggno]);
}
/*
* If the outerPlan is a Group node, we will reach here after each
* group. We are not done unless the Group node is done (a little
- * ugliness here while we reach into the Group's state to find out).
- * Furthermore, when grouping we return nothing at all unless we
- * had some input tuple(s). By the nature of Group, there are
- * no empty groups, so if we get here with no input the whole scan
- * is empty.
+ * ugliness here while we reach into the Group's state to find
+ * out). Furthermore, when grouping we return nothing at all
+ * unless we had some input tuple(s). By the nature of Group,
+ * there are no empty groups, so if we get here with no input the
+ * whole scan is empty.
*
- * If the outerPlan isn't a Group, we are done when we get here,
- * and we will emit a (single) tuple even if there were no input
+ * If the outerPlan isn't a Group, we are done when we get here, and
+ * we will emit a (single) tuple even if there were no input
* tuples.
*/
if (IsA(outerPlan, Group))
@@ -523,17 +535,18 @@ ExecAgg(Agg *node)
else
{
aggstate->agg_done = true;
+
/*
- * If inputtuple==NULL (ie, the outerPlan didn't return anything),
- * create a dummy all-nulls input tuple for use by execProject.
- * 99.44% of the time this is a waste of cycles, because
- * ordinarily the projected output tuple's targetlist cannot
- * contain any direct (non-aggregated) references to input
- * columns, so the dummy tuple will not be referenced. However
- * there are special cases where this isn't so --- in particular
- * an UPDATE involving an aggregate will have a targetlist
- * reference to ctid. We need to return a null for ctid in that
- * situation, not coredump.
+ * If inputtuple==NULL (ie, the outerPlan didn't return
+ * anything), create a dummy all-nulls input tuple for use by
+ * execProject. 99.44% of the time this is a waste of cycles,
+ * because ordinarily the projected output tuple's targetlist
+ * cannot contain any direct (non-aggregated) references to
+ * input columns, so the dummy tuple will not be referenced.
+ * However there are special cases where this isn't so --- in
+ * particular an UPDATE involving an aggregate will have a
+ * targetlist reference to ctid. We need to return a null for
+ * ctid in that situation, not coredump.
*
* The values returned for the aggregates will be the initial
* values of the transition functions.
@@ -550,7 +563,7 @@ ExecAgg(Agg *node)
/* watch out for null input tuples, though... */
if (tupType && tupValue)
{
- null_array = (char *) palloc(sizeof(char)*tupType->natts);
+ null_array = (char *) palloc(sizeof(char) * tupType->natts);
for (attnum = 0; attnum < tupType->natts; attnum++)
null_array[attnum] = 'n';
inputTuple = heap_formtuple(tupType, tupValue, null_array);
@@ -571,17 +584,17 @@ ExecAgg(Agg *node)
/*
* Form a projection tuple using the aggregate results and the
- * representative input tuple. Store it in the result tuple slot.
+ * representative input tuple. Store it in the result tuple slot.
*/
resultSlot = ExecProject(projInfo, &isDone);
/*
- * If the completed tuple does not match the qualifications,
- * it is ignored and we loop back to try to process another group.
+ * If the completed tuple does not match the qualifications, it is
+ * ignored and we loop back to try to process another group.
* Otherwise, return the tuple.
*/
}
- while (! ExecQual(node->plan.qual, econtext, false));
+ while (!ExecQual(node->plan.qual, econtext, false));
return resultSlot;
}
@@ -596,13 +609,13 @@ ExecAgg(Agg *node)
bool
ExecInitAgg(Agg *node, EState *estate, Plan *parent)
{
- AggState *aggstate;
- AggStatePerAgg peragg;
- Plan *outerPlan;
- ExprContext *econtext;
- int numaggs,
- aggno;
- List *alist;
+ AggState *aggstate;
+ AggStatePerAgg peragg;
+ Plan *outerPlan;
+ ExprContext *econtext;
+ int numaggs,
+ aggno;
+ List *alist;
/*
* assign the node's execution state
@@ -620,21 +633,23 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
* find aggregates in targetlist and quals
*
* Note: pull_agg_clauses also checks that no aggs contain other agg
- * calls in their arguments. This would make no sense under SQL semantics
- * anyway (and it's forbidden by the spec). Because that is true, we
- * don't need to worry about evaluating the aggs in any particular order.
+ * calls in their arguments. This would make no sense under SQL
+ * semantics anyway (and it's forbidden by the spec). Because that is
+ * true, we don't need to worry about evaluating the aggs in any
+ * particular order.
*/
aggstate->aggs = nconc(pull_agg_clause((Node *) node->plan.targetlist),
pull_agg_clause((Node *) node->plan.qual));
aggstate->numaggs = numaggs = length(aggstate->aggs);
if (numaggs <= 0)
{
+
/*
- * This used to be treated as an error, but we can't do that anymore
- * because constant-expression simplification could optimize away
- * all of the Aggrefs in the targetlist and qual. So, just make a
- * debug note, and force numaggs positive so that palloc()s below
- * don't choke.
+ * This used to be treated as an error, but we can't do that
+ * anymore because constant-expression simplification could
+ * optimize away all of the Aggrefs in the targetlist and qual.
+ * So, just make a debug note, and force numaggs positive so that
+ * palloc()s below don't choke.
*/
elog(DEBUG, "ExecInitAgg: could not find any aggregate functions");
numaggs = 1;
@@ -655,8 +670,8 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
ExecInitResultTupleSlot(estate, &aggstate->csstate.cstate);
/*
- * Set up aggregate-result storage in the expr context,
- * and also allocate my private per-agg working storage
+ * Set up aggregate-result storage in the expr context, and also
+ * allocate my private per-agg working storage
*/
econtext = aggstate->csstate.cstate.cs_ExprContext;
econtext->ecxt_aggvalues = (Datum *) palloc(sizeof(Datum) * numaggs);
@@ -693,15 +708,15 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
aggno = -1;
foreach(alist, aggstate->aggs)
{
- Aggref *aggref = (Aggref *) lfirst(alist);
- AggStatePerAgg peraggstate = &peragg[++aggno];
- char *aggname = aggref->aggname;
- HeapTuple aggTuple;
+ Aggref *aggref = (Aggref *) lfirst(alist);
+ AggStatePerAgg peraggstate = &peragg[++aggno];
+ char *aggname = aggref->aggname;
+ HeapTuple aggTuple;
Form_pg_aggregate aggform;
- Type typeInfo;
- Oid xfn1_oid,
- xfn2_oid,
- finalfn_oid;
+ Type typeInfo;
+ Oid xfn1_oid,
+ xfn2_oid,
+ finalfn_oid;
/* Mark Aggref node with its associated index in the result array */
aggref->aggno = aggno;
@@ -762,9 +777,7 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
}
if (OidIsValid(finalfn_oid))
- {
fmgr_info(finalfn_oid, &peraggstate->finalfn);
- }
if (aggref->aggdistinct)
{
@@ -848,7 +861,7 @@ copyDatum(Datum val, int typLen, bool typByVal)
return val;
else
{
- char *newVal;
+ char *newVal;
if (typLen == -1) /* variable length type? */
typLen = VARSIZE((struct varlena *) DatumGetPointer(val));