Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b021e9a

Browse files
committed
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...
1 parent 60f3e6b commit b021e9a

File tree

1 file changed

+35
-16
lines changed

1 file changed

+35
-16
lines changed

src/backend/executor/nodeAgg.c

+35-16
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* SQL aggregates. (Do not expect POSTQUEL semantics.) -- ay 2/95
1212
*
1313
* IDENTIFICATION
14-
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.57 1999/10/08 03:49:55 tgl Exp $
14+
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.58 1999/10/30 01:18:16 tgl Exp $
1515
*
1616
*-------------------------------------------------------------------------
1717
*/
@@ -408,24 +408,43 @@ ExecAgg(Agg *node)
408408
return NULL;
409409
}
410410
else
411+
{
411412
aggstate->agg_done = true;
413+
/*
414+
* If inputtuple==NULL (ie, the outerPlan didn't return anything),
415+
* create a dummy all-nulls input tuple for use by execProject.
416+
* 99.44% of the time this is a waste of cycles, because
417+
* ordinarily the projected output tuple's targetlist cannot
418+
* contain any direct (non-aggregated) references to input
419+
* columns, so the dummy tuple will not be referenced. However
420+
* there are special cases where this isn't so --- in particular
421+
* an UPDATE involving an aggregate will have a targetlist
422+
* reference to ctid. We need to return a null for ctid in that
423+
* situation, not coredump.
424+
*
425+
* The values returned for the aggregates will be the initial
426+
* values of the transition functions.
427+
*/
428+
if (inputTuple == NULL)
429+
{
430+
TupleDesc tupType;
431+
Datum *tupValue;
432+
char *null_array;
433+
AttrNumber attnum;
434+
435+
tupType = aggstate->csstate.css_ScanTupleSlot->ttc_tupleDescriptor;
436+
tupValue = projInfo->pi_tupValue;
437+
null_array = (char *) palloc(sizeof(char) * tupType->natts);
438+
for (attnum = 0; attnum < tupType->natts; attnum++)
439+
null_array[attnum] = 'n';
440+
inputTuple = heap_formtuple(tupType, tupValue, null_array);
441+
pfree(null_array);
442+
}
443+
}
412444

413445
/*
414-
* We used to create a dummy all-nulls input tuple here if
415-
* inputTuple == NULL (ie, the outerPlan didn't return anything).
416-
* However, now that we don't return a bogus tuple in Group mode,
417-
* we can only get here with inputTuple == NULL in non-Group mode.
418-
* So, if the parser has done its job right, the projected output
419-
* tuple's targetList must not contain any direct references to
420-
* input columns, and so it's a waste of time to create an
421-
* all-nulls input tuple. We just let the tuple slot get set
422-
* to NULL instead. The values returned for the aggregates will
423-
* be the initial values of the transition functions.
424-
*/
425-
426-
/*
427-
* Store the representative input tuple (or NULL, if none)
428-
* in the tuple table slot reserved for it.
446+
* Store the representative input tuple in the tuple table slot
447+
* reserved for it.
429448
*/
430449
ExecStoreTuple(inputTuple,
431450
aggstate->csstate.css_ScanTupleSlot,

0 commit comments

Comments
 (0)