Put back code in nodeAgg to generate a dummy all-nulls input tuple
before calling execProject, when the outerPlan has returned zero tuples. I took this out under the mistaken impression that the input tuple couldn't be referenced by execProject if we weren't in GROUP BY mode. But it can, if we're in an UPDATE or DELETE...
This commit is contained in:
parent
60f3e6b3a5
commit
b021e9a130
|
@ -11,7 +11,7 @@
|
||||||
* SQL aggregates. (Do not expect POSTQUEL semantics.) -- ay 2/95
|
* SQL aggregates. (Do not expect POSTQUEL semantics.) -- ay 2/95
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.57 1999/10/08 03:49:55 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.58 1999/10/30 01:18:16 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -408,24 +408,43 @@ ExecAgg(Agg *node)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
aggstate->agg_done = true;
|
aggstate->agg_done = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We used to create a dummy all-nulls input tuple here if
|
* If inputtuple==NULL (ie, the outerPlan didn't return anything),
|
||||||
* inputTuple == NULL (ie, the outerPlan didn't return anything).
|
* create a dummy all-nulls input tuple for use by execProject.
|
||||||
* However, now that we don't return a bogus tuple in Group mode,
|
* 99.44% of the time this is a waste of cycles, because
|
||||||
* we can only get here with inputTuple == NULL in non-Group mode.
|
* ordinarily the projected output tuple's targetlist cannot
|
||||||
* So, if the parser has done its job right, the projected output
|
* contain any direct (non-aggregated) references to input
|
||||||
* tuple's targetList must not contain any direct references to
|
* columns, so the dummy tuple will not be referenced. However
|
||||||
* input columns, and so it's a waste of time to create an
|
* there are special cases where this isn't so --- in particular
|
||||||
* all-nulls input tuple. We just let the tuple slot get set
|
* an UPDATE involving an aggregate will have a targetlist
|
||||||
* to NULL instead. The values returned for the aggregates will
|
* reference to ctid. We need to return a null for ctid in that
|
||||||
* be the initial values of the transition functions.
|
* situation, not coredump.
|
||||||
|
*
|
||||||
|
* The values returned for the aggregates will be the initial
|
||||||
|
* values of the transition functions.
|
||||||
*/
|
*/
|
||||||
|
if (inputTuple == NULL)
|
||||||
|
{
|
||||||
|
TupleDesc tupType;
|
||||||
|
Datum *tupValue;
|
||||||
|
char *null_array;
|
||||||
|
AttrNumber attnum;
|
||||||
|
|
||||||
|
tupType = aggstate->csstate.css_ScanTupleSlot->ttc_tupleDescriptor;
|
||||||
|
tupValue = projInfo->pi_tupValue;
|
||||||
|
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);
|
||||||
|
pfree(null_array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Store the representative input tuple (or NULL, if none)
|
* Store the representative input tuple in the tuple table slot
|
||||||
* in the tuple table slot reserved for it.
|
* reserved for it.
|
||||||
*/
|
*/
|
||||||
ExecStoreTuple(inputTuple,
|
ExecStoreTuple(inputTuple,
|
||||||
aggstate->csstate.css_ScanTupleSlot,
|
aggstate->csstate.css_ScanTupleSlot,
|
||||||
|
|
Loading…
Reference in New Issue