diff options
author | Bruce Momjian <bruce@momjian.us> | 2000-04-12 17:17:23 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2000-04-12 17:17:23 +0000 |
commit | 52f77df613cea1803ce86321c37229626d9f213c (patch) | |
tree | bd9ac9f667f295cb65f4c448a5bb5a062d656b27 /src/backend/executor/nodeAgg.c | |
parent | db4518729d85da83eafdacbcebaeb12618517595 (diff) | |
download | postgresql-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.c | 261 |
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)); |