aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execJunk.c6
-rw-r--r--src/backend/executor/execMain.c10
-rw-r--r--src/backend/executor/execQual.c249
-rw-r--r--src/backend/executor/execTuples.c34
-rw-r--r--src/backend/executor/execUtils.c16
-rw-r--r--src/backend/executor/nodeBitmapHeapscan.c4
-rw-r--r--src/backend/executor/nodeFunctionscan.c4
-rw-r--r--src/backend/executor/nodeHashjoin.c5
-rw-r--r--src/backend/executor/nodeIndexscan.c4
-rw-r--r--src/backend/executor/nodeMergejoin.c5
-rw-r--r--src/backend/executor/nodeSeqscan.c4
-rw-r--r--src/backend/executor/nodeSubplan.c6
-rw-r--r--src/backend/executor/nodeSubqueryscan.c10
-rw-r--r--src/backend/executor/nodeTidscan.c4
14 files changed, 207 insertions, 154 deletions
diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c
index 787a569b8f8..459e5db7aaa 100644
--- a/src/backend/executor/execJunk.c
+++ b/src/backend/executor/execJunk.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execJunk.c,v 1.52 2006/03/05 15:58:25 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execJunk.c,v 1.53 2006/06/16 18:42:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -79,7 +79,7 @@ ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot)
* Use the given slot, or make a new slot if we weren't given one.
*/
if (slot)
- ExecSetSlotDescriptor(slot, cleanTupType, false);
+ ExecSetSlotDescriptor(slot, cleanTupType);
else
slot = MakeSingleTupleTableSlot(cleanTupType);
@@ -150,7 +150,7 @@ ExecInitJunkFilterConversion(List *targetList,
* Use the given slot, or make a new slot if we weren't given one.
*/
if (slot)
- ExecSetSlotDescriptor(slot, cleanTupType, false);
+ ExecSetSlotDescriptor(slot, cleanTupType);
else
slot = MakeSingleTupleTableSlot(cleanTupType);
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index e8e0c8bd56d..b39e7a587b1 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -26,7 +26,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.270 2006/04/30 18:30:38 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.271 2006/06/16 18:42:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1445,9 +1445,7 @@ ExecInsert(TupleTableSlot *slot,
TupleTableSlot *newslot = estate->es_trig_tuple_slot;
if (newslot->tts_tupleDescriptor != slot->tts_tupleDescriptor)
- ExecSetSlotDescriptor(newslot,
- slot->tts_tupleDescriptor,
- false);
+ ExecSetSlotDescriptor(newslot, slot->tts_tupleDescriptor);
ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
slot = newslot;
tuple = newtuple;
@@ -1654,9 +1652,7 @@ ExecUpdate(TupleTableSlot *slot,
TupleTableSlot *newslot = estate->es_trig_tuple_slot;
if (newslot->tts_tupleDescriptor != slot->tts_tupleDescriptor)
- ExecSetSlotDescriptor(newslot,
- slot->tts_tupleDescriptor,
- false);
+ ExecSetSlotDescriptor(newslot, slot->tts_tupleDescriptor);
ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
slot = newslot;
tuple = newtuple;
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 41ea452df58..30ba2de5b43 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.190 2006/04/22 01:25:58 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.191 2006/06/16 18:42:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -71,6 +71,10 @@ static Datum ExecEvalConst(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
+static void ShutdownFuncExpr(Datum arg);
+static TupleDesc get_cached_rowtype(Oid type_id, int32 typmod,
+ TupleDesc *cache_field, ExprContext *econtext);
+static void ShutdownTupleDescRef(Datum arg);
static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo,
List *argList, ExprContext *econtext);
static Datum ExecMakeFunctionResultNoSets(FuncExprState *fcache,
@@ -715,6 +719,9 @@ GetAttributeByNum(HeapTupleHeader tuple,
attrno,
tupDesc,
isNull);
+
+ ReleaseTupleDesc(tupDesc);
+
return result;
}
@@ -773,6 +780,9 @@ GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
attrno,
tupDesc,
isNull);
+
+ ReleaseTupleDesc(tupDesc);
+
return result;
}
@@ -827,6 +837,61 @@ ShutdownFuncExpr(Datum arg)
}
/*
+ * get_cached_rowtype: utility function to lookup a rowtype tupdesc
+ *
+ * type_id, typmod: identity of the rowtype
+ * cache_field: where to cache the TupleDesc pointer in expression state node
+ * (field must be initialized to NULL)
+ * econtext: expression context we are executing in
+ *
+ * NOTE: because the shutdown callback will be called during plan rescan,
+ * must be prepared to re-do this during any node execution; cannot call
+ * just once during expression initialization
+ */
+static TupleDesc
+get_cached_rowtype(Oid type_id, int32 typmod,
+ TupleDesc *cache_field, ExprContext *econtext)
+{
+ TupleDesc tupDesc = *cache_field;
+
+ /* Do lookup if no cached value or if requested type changed */
+ if (tupDesc == NULL ||
+ type_id != tupDesc->tdtypeid ||
+ typmod != tupDesc->tdtypmod)
+ {
+ tupDesc = lookup_rowtype_tupdesc(type_id, typmod);
+
+ if (*cache_field)
+ {
+ /* Release old tupdesc; but callback is already registered */
+ ReleaseTupleDesc(*cache_field);
+ }
+ else
+ {
+ /* Need to register shutdown callback to release tupdesc */
+ RegisterExprContextCallback(econtext,
+ ShutdownTupleDescRef,
+ PointerGetDatum(cache_field));
+ }
+ *cache_field = tupDesc;
+ }
+ return tupDesc;
+}
+
+/*
+ * Callback function to release a tupdesc refcount at expression tree shutdown
+ */
+static void
+ShutdownTupleDescRef(Datum arg)
+{
+ TupleDesc *cache_field = (TupleDesc *) DatumGetPointer(arg);
+
+ if (*cache_field)
+ ReleaseTupleDesc(*cache_field);
+ *cache_field = NULL;
+}
+
+/*
* Evaluate arguments for a function.
*/
static ExprDoneCond
@@ -1351,9 +1416,8 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
HeapTupleHeader td;
td = DatumGetHeapTupleHeader(result);
- tupdesc = lookup_rowtype_tupdesc(HeapTupleHeaderGetTypeId(td),
+ tupdesc = lookup_rowtype_tupdesc_copy(HeapTupleHeaderGetTypeId(td),
HeapTupleHeaderGetTypMod(td));
- tupdesc = CreateTupleDescCopy(tupdesc);
}
else
{
@@ -1919,17 +1983,18 @@ ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
+ ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) cstate->xprstate.expr;
HeapTuple result;
Datum tupDatum;
HeapTupleHeader tuple;
HeapTupleData tmptup;
- AttrNumber *attrMap = cstate->attrMap;
- Datum *invalues = cstate->invalues;
- bool *inisnull = cstate->inisnull;
- Datum *outvalues = cstate->outvalues;
- bool *outisnull = cstate->outisnull;
+ AttrNumber *attrMap;
+ Datum *invalues;
+ bool *inisnull;
+ Datum *outvalues;
+ bool *outisnull;
int i;
- int outnatts = cstate->outdesc->natts;
+ int outnatts;
tupDatum = ExecEvalExpr(cstate->arg, econtext, isNull, isDone);
@@ -1939,9 +2004,82 @@ ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
tuple = DatumGetHeapTupleHeader(tupDatum);
+ /* Lookup tupdescs if first time through or after rescan */
+ if (cstate->indesc == NULL)
+ get_cached_rowtype(exprType((Node *) convert->arg), -1,
+ &cstate->indesc, econtext);
+ if (cstate->outdesc == NULL)
+ get_cached_rowtype(convert->resulttype, -1,
+ &cstate->outdesc, econtext);
+
Assert(HeapTupleHeaderGetTypeId(tuple) == cstate->indesc->tdtypeid);
Assert(HeapTupleHeaderGetTypMod(tuple) == cstate->indesc->tdtypmod);
+ /* if first time through, initialize */
+ if (cstate->attrMap == NULL)
+ {
+ MemoryContext old_cxt;
+ int n;
+
+ /* allocate state in long-lived memory context */
+ old_cxt = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
+
+ /* prepare map from old to new attribute numbers */
+ n = cstate->outdesc->natts;
+ cstate->attrMap = (AttrNumber *) palloc0(n * sizeof(AttrNumber));
+ for (i = 0; i < n; i++)
+ {
+ Form_pg_attribute att = cstate->outdesc->attrs[i];
+ char *attname;
+ Oid atttypid;
+ int32 atttypmod;
+ int j;
+
+ if (att->attisdropped)
+ continue; /* attrMap[i] is already 0 */
+ attname = NameStr(att->attname);
+ atttypid = att->atttypid;
+ atttypmod = att->atttypmod;
+ for (j = 0; j < cstate->indesc->natts; j++)
+ {
+ att = cstate->indesc->attrs[j];
+ if (att->attisdropped)
+ continue;
+ if (strcmp(attname, NameStr(att->attname)) == 0)
+ {
+ /* Found it, check type */
+ if (atttypid != att->atttypid || atttypmod != att->atttypmod)
+ elog(ERROR, "attribute \"%s\" of type %s does not match corresponding attribute of type %s",
+ attname,
+ format_type_be(cstate->indesc->tdtypeid),
+ format_type_be(cstate->outdesc->tdtypeid));
+ cstate->attrMap[i] = (AttrNumber) (j + 1);
+ break;
+ }
+ }
+ if (cstate->attrMap[i] == 0)
+ elog(ERROR, "attribute \"%s\" of type %s does not exist",
+ attname,
+ format_type_be(cstate->indesc->tdtypeid));
+ }
+ /* preallocate workspace for Datum arrays */
+ n = cstate->indesc->natts + 1; /* +1 for NULL */
+ cstate->invalues = (Datum *) palloc(n * sizeof(Datum));
+ cstate->inisnull = (bool *) palloc(n * sizeof(bool));
+ n = cstate->outdesc->natts;
+ cstate->outvalues = (Datum *) palloc(n * sizeof(Datum));
+ cstate->outisnull = (bool *) palloc(n * sizeof(bool));
+
+ MemoryContextSwitchTo(old_cxt);
+ }
+
+ attrMap = cstate->attrMap;
+ invalues = cstate->invalues;
+ inisnull = cstate->inisnull;
+ outvalues = cstate->outvalues;
+ outisnull = cstate->outisnull;
+ outnatts = cstate->outdesc->natts;
+
/*
* heap_deform_tuple needs a HeapTuple not a bare HeapTupleHeader.
*/
@@ -2797,22 +2935,8 @@ ExecEvalFieldSelect(FieldSelectState *fstate,
tupTypmod = HeapTupleHeaderGetTypMod(tuple);
/* Lookup tupdesc if first time through or if type changes */
- tupDesc = fstate->argdesc;
- if (tupDesc == NULL ||
- tupType != tupDesc->tdtypeid ||
- tupTypmod != tupDesc->tdtypmod)
- {
- MemoryContext oldcontext;
-
- tupDesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
- /* Copy the tupdesc into query storage for safety */
- oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
- tupDesc = CreateTupleDescCopy(tupDesc);
- if (fstate->argdesc)
- FreeTupleDesc(fstate->argdesc);
- fstate->argdesc = tupDesc;
- MemoryContextSwitchTo(oldcontext);
- }
+ tupDesc = get_cached_rowtype(tupType, tupTypmod,
+ &fstate->argdesc, econtext);
/*
* heap_getattr needs a HeapTuple not a bare HeapTupleHeader. We set all
@@ -2859,22 +2983,9 @@ ExecEvalFieldStore(FieldStoreState *fstate,
if (isDone && *isDone == ExprEndResult)
return tupDatum;
- /* Lookup tupdesc if first time through or if type changes */
- tupDesc = fstate->argdesc;
- if (tupDesc == NULL ||
- fstore->resulttype != tupDesc->tdtypeid)
- {
- MemoryContext oldcontext;
-
- tupDesc = lookup_rowtype_tupdesc(fstore->resulttype, -1);
- /* Copy the tupdesc into query storage for safety */
- oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
- tupDesc = CreateTupleDescCopy(tupDesc);
- if (fstate->argdesc)
- FreeTupleDesc(fstate->argdesc);
- fstate->argdesc = tupDesc;
- MemoryContextSwitchTo(oldcontext);
- }
+ /* Lookup tupdesc if first time through or after rescan */
+ tupDesc = get_cached_rowtype(fstore->resulttype, -1,
+ &fstate->argdesc, econtext);
/* Allocate workspace */
values = (Datum *) palloc(tupDesc->natts * sizeof(Datum));
@@ -3247,61 +3358,9 @@ ExecInitExpr(Expr *node, PlanState *parent)
{
ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
ConvertRowtypeExprState *cstate = makeNode(ConvertRowtypeExprState);
- int i;
- int n;
cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalConvertRowtype;
cstate->arg = ExecInitExpr(convert->arg, parent);
- /* save copies of needed tuple descriptors */
- cstate->indesc = lookup_rowtype_tupdesc(exprType((Node *) convert->arg), -1);
- cstate->indesc = CreateTupleDescCopy(cstate->indesc);
- cstate->outdesc = lookup_rowtype_tupdesc(convert->resulttype, -1);
- cstate->outdesc = CreateTupleDescCopy(cstate->outdesc);
- /* prepare map from old to new attribute numbers */
- n = cstate->outdesc->natts;
- cstate->attrMap = (AttrNumber *) palloc0(n * sizeof(AttrNumber));
- for (i = 0; i < n; i++)
- {
- Form_pg_attribute att = cstate->outdesc->attrs[i];
- char *attname;
- Oid atttypid;
- int32 atttypmod;
- int j;
-
- if (att->attisdropped)
- continue; /* attrMap[i] is already 0 */
- attname = NameStr(att->attname);
- atttypid = att->atttypid;
- atttypmod = att->atttypmod;
- for (j = 0; j < cstate->indesc->natts; j++)
- {
- att = cstate->indesc->attrs[j];
- if (att->attisdropped)
- continue;
- if (strcmp(attname, NameStr(att->attname)) == 0)
- {
- /* Found it, check type */
- if (atttypid != att->atttypid || atttypmod != att->atttypmod)
- elog(ERROR, "attribute \"%s\" of type %s does not match corresponding attribute of type %s",
- attname,
- format_type_be(cstate->indesc->tdtypeid),
- format_type_be(cstate->outdesc->tdtypeid));
- cstate->attrMap[i] = (AttrNumber) (j + 1);
- break;
- }
- }
- if (cstate->attrMap[i] == 0)
- elog(ERROR, "attribute \"%s\" of type %s does not exist",
- attname,
- format_type_be(cstate->indesc->tdtypeid));
- }
- /* preallocate workspace for Datum arrays */
- n = cstate->indesc->natts + 1; /* +1 for NULL */
- cstate->invalues = (Datum *) palloc(n * sizeof(Datum));
- cstate->inisnull = (bool *) palloc(n * sizeof(bool));
- n = cstate->outdesc->natts;
- cstate->outvalues = (Datum *) palloc(n * sizeof(Datum));
- cstate->outisnull = (bool *) palloc(n * sizeof(bool));
state = (ExprState *) cstate;
}
break;
@@ -3372,12 +3431,12 @@ ExecInitExpr(Expr *node, PlanState *parent)
/* generic record, use runtime type assignment */
rstate->tupdesc = ExecTypeFromExprList(rowexpr->args);
BlessTupleDesc(rstate->tupdesc);
+ /* we won't need to redo this at runtime */
}
else
{
/* it's been cast to a named type, use that */
- rstate->tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
- rstate->tupdesc = CreateTupleDescCopy(rstate->tupdesc);
+ rstate->tupdesc = lookup_rowtype_tupdesc_copy(rowexpr->row_typeid, -1);
}
/* Set up evaluation, skipping any deleted columns */
Assert(list_length(rowexpr->args) <= rstate->tupdesc->natts);
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 81f589fd44b..971822525f0 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.93 2006/04/04 19:35:34 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.94 2006/06/16 18:42:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -143,7 +143,6 @@ ExecCreateTupleTable(int tableSize)
slot->type = T_TupleTableSlot;
slot->tts_isempty = true;
slot->tts_shouldFree = false;
- slot->tts_shouldFreeDesc = false;
slot->tts_tuple = NULL;
slot->tts_tupleDescriptor = NULL;
slot->tts_mcxt = CurrentMemoryContext;
@@ -189,8 +188,8 @@ ExecDropTupleTable(TupleTable table, /* tuple table */
TupleTableSlot *slot = &(table->array[i]);
ExecClearTuple(slot);
- if (slot->tts_shouldFreeDesc)
- FreeTupleDesc(slot->tts_tupleDescriptor);
+ if (slot->tts_tupleDescriptor)
+ ReleaseTupleDesc(slot->tts_tupleDescriptor);
if (slot->tts_values)
pfree(slot->tts_values);
if (slot->tts_isnull)
@@ -210,7 +209,7 @@ ExecDropTupleTable(TupleTable table, /* tuple table */
* This is a convenience routine for operations that need a
* standalone TupleTableSlot not gotten from the main executor
* tuple table. It makes a single slot and initializes it as
- * though by ExecSetSlotDescriptor(slot, tupdesc, false).
+ * though by ExecSetSlotDescriptor(slot, tupdesc).
* --------------------------------
*/
TupleTableSlot *
@@ -221,7 +220,6 @@ MakeSingleTupleTableSlot(TupleDesc tupdesc)
/* This should match ExecCreateTupleTable() */
slot->tts_isempty = true;
slot->tts_shouldFree = false;
- slot->tts_shouldFreeDesc = false;
slot->tts_tuple = NULL;
slot->tts_tupleDescriptor = NULL;
slot->tts_mcxt = CurrentMemoryContext;
@@ -230,7 +228,7 @@ MakeSingleTupleTableSlot(TupleDesc tupdesc)
slot->tts_values = NULL;
slot->tts_isnull = NULL;
- ExecSetSlotDescriptor(slot, tupdesc, false);
+ ExecSetSlotDescriptor(slot, tupdesc);
return slot;
}
@@ -250,8 +248,8 @@ ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Assert(slot != NULL);
ExecClearTuple(slot);
- if (slot->tts_shouldFreeDesc)
- FreeTupleDesc(slot->tts_tupleDescriptor);
+ if (slot->tts_tupleDescriptor)
+ ReleaseTupleDesc(slot->tts_tupleDescriptor);
if (slot->tts_values)
pfree(slot->tts_values);
if (slot->tts_isnull)
@@ -309,13 +307,15 @@ ExecAllocTableSlot(TupleTable table)
* ExecSetSlotDescriptor
*
* This function is used to set the tuple descriptor associated
- * with the slot's tuple.
+ * with the slot's tuple. The passed descriptor must have lifespan
+ * at least equal to the slot's. If it is a reference-counted descriptor
+ * then the reference count is incremented for as long as the slot holds
+ * a reference.
* --------------------------------
*/
void
ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
- TupleDesc tupdesc, /* new tuple descriptor */
- bool shouldFree) /* is desc owned by slot? */
+ TupleDesc tupdesc) /* new tuple descriptor */
{
/* For safety, make sure slot is empty before changing it */
ExecClearTuple(slot);
@@ -324,8 +324,8 @@ ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
* Release any old descriptor. Also release old Datum/isnull arrays if
* present (we don't bother to check if they could be re-used).
*/
- if (slot->tts_shouldFreeDesc)
- FreeTupleDesc(slot->tts_tupleDescriptor);
+ if (slot->tts_tupleDescriptor)
+ ReleaseTupleDesc(slot->tts_tupleDescriptor);
if (slot->tts_values)
pfree(slot->tts_values);
@@ -333,10 +333,10 @@ ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
pfree(slot->tts_isnull);
/*
- * Set up the new descriptor
+ * Install the new descriptor; if it's refcounted, bump its refcount.
*/
slot->tts_tupleDescriptor = tupdesc;
- slot->tts_shouldFreeDesc = shouldFree;
+ PinTupleDesc(tupdesc);
/*
* Allocate Datum/isnull arrays of the appropriate size. These must have
@@ -740,7 +740,7 @@ ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
{
TupleTableSlot *slot = ExecInitExtraTupleSlot(estate);
- ExecSetSlotDescriptor(slot, tupType, false);
+ ExecSetSlotDescriptor(slot, tupType);
return ExecStoreAllNullTuple(slot);
}
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index d1a294f9bb8..c30c8f2badf 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.134 2006/04/30 18:30:38 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.135 2006/06/16 18:42:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -427,12 +427,11 @@ ExecAssignExprContext(EState *estate, PlanState *planstate)
* ----------------
*/
void
-ExecAssignResultType(PlanState *planstate,
- TupleDesc tupDesc, bool shouldFree)
+ExecAssignResultType(PlanState *planstate, TupleDesc tupDesc)
{
TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
- ExecSetSlotDescriptor(slot, tupDesc, shouldFree);
+ ExecSetSlotDescriptor(slot, tupDesc);
}
/* ----------------
@@ -461,7 +460,7 @@ ExecAssignResultTypeFromTL(PlanState *planstate)
* to set up planstate->targetlist ...
*/
tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
- ExecAssignResultType(planstate, tupDesc, true);
+ ExecAssignResultType(planstate, tupDesc);
}
/* ----------------
@@ -659,12 +658,11 @@ ExecGetScanType(ScanState *scanstate)
* ----------------
*/
void
-ExecAssignScanType(ScanState *scanstate,
- TupleDesc tupDesc, bool shouldFree)
+ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
{
TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
- ExecSetSlotDescriptor(slot, tupDesc, shouldFree);
+ ExecSetSlotDescriptor(slot, tupDesc);
}
/* ----------------
@@ -680,7 +678,7 @@ ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
outerPlan = outerPlanState(scanstate);
tupDesc = ExecGetResultType(outerPlan);
- ExecAssignScanType(scanstate, tupDesc, false);
+ ExecAssignScanType(scanstate, tupDesc);
}
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 5ecded32ed9..6f8a7a66558 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -21,7 +21,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapHeapscan.c,v 1.11 2006/05/23 15:21:52 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapHeapscan.c,v 1.12 2006/06/16 18:42:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -538,7 +538,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
/*
* get the scan type from the relation descriptor.
*/
- ExecAssignScanType(&scanstate->ss, RelationGetDescr(currentRelation), false);
+ ExecAssignScanType(&scanstate->ss, RelationGetDescr(currentRelation));
/*
* Initialize result tuple type and projection info.
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 494ac209a92..0c77e821690 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.38 2006/03/16 00:31:54 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.39 2006/06/16 18:42:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -220,7 +220,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
BlessTupleDesc(tupdesc);
scanstate->tupdesc = tupdesc;
- ExecAssignScanType(&scanstate->ss, tupdesc, false);
+ ExecAssignScanType(&scanstate->ss, tupdesc);
/*
* Other node-specific setup
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index 0aabe49e932..097343fd88c 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.81 2006/03/05 15:58:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.82 2006/06/16 18:42:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -436,8 +436,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
ExecAssignProjectionInfo(&hjstate->js.ps);
ExecSetSlotDescriptor(hjstate->hj_OuterTupleSlot,
- ExecGetResultType(outerPlanState(hjstate)),
- false);
+ ExecGetResultType(outerPlanState(hjstate)));
/*
* initialize hash-specific info
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 41b4dea980c..433151a8a76 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.113 2006/05/23 15:21:52 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.114 2006/06/16 18:42:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -516,7 +516,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
/*
* get the scan type from the relation descriptor.
*/
- ExecAssignScanType(&indexstate->ss, RelationGetDescr(currentRelation), false);
+ ExecAssignScanType(&indexstate->ss, RelationGetDescr(currentRelation));
/*
* Open the index relation.
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index 0c59e11be60..dbf056e25ef 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.79 2006/03/17 19:38:12 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.80 2006/06/16 18:42:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1552,8 +1552,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate);
ExecSetSlotDescriptor(mergestate->mj_MarkedTupleSlot,
- ExecGetResultType(innerPlanState(mergestate)),
- false);
+ ExecGetResultType(innerPlanState(mergestate)));
switch (node->join.jointype)
{
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index ce42ffbd6b7..c6e61d04d93 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeSeqscan.c,v 1.58 2006/03/05 15:58:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeSeqscan.c,v 1.59 2006/06/16 18:42:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -159,7 +159,7 @@ InitScanRelation(SeqScanState *node, EState *estate)
node->ss_currentRelation = currentRelation;
node->ss_currentScanDesc = currentScanDesc;
- ExecAssignScanType(node, RelationGetDescr(currentRelation), false);
+ ExecAssignScanType(node, RelationGetDescr(currentRelation));
}
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 181f86ed03e..c6663c7eac2 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.74 2006/03/05 15:58:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.75 2006/06/16 18:42:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -865,14 +865,14 @@ ExecInitSubPlan(SubPlanState *node, EState *estate, int eflags)
*/
tupDesc = ExecTypeFromTL(leftptlist, false);
slot = ExecAllocTableSlot(tupTable);
- ExecSetSlotDescriptor(slot, tupDesc, true);
+ ExecSetSlotDescriptor(slot, tupDesc);
node->projLeft = ExecBuildProjectionInfo(lefttlist,
NULL,
slot);
tupDesc = ExecTypeFromTL(rightptlist, false);
slot = ExecAllocTableSlot(tupTable);
- ExecSetSlotDescriptor(slot, tupDesc, true);
+ ExecSetSlotDescriptor(slot, tupDesc);
node->projRight = ExecBuildProjectionInfo(righttlist,
node->innerecontext,
slot);
diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c
index 02b072893a5..e16bf7fe3c5 100644
--- a/src/backend/executor/nodeSubqueryscan.c
+++ b/src/backend/executor/nodeSubqueryscan.c
@@ -12,7 +12,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.29 2006/03/05 15:58:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.30 2006/06/16 18:42:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -202,11 +202,13 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
subquerystate->ss.ps.ps_TupFromTlist = false;
/*
- * Initialize scan tuple type (needed by ExecAssignScanProjectionInfo)
+ * Initialize scan tuple type (needed by ExecAssignScanProjectionInfo).
+ * Because the subplan is in its own memory context, we need to copy its
+ * result tuple type not just link to it; else the tupdesc will disappear
+ * too soon during shutdown.
*/
ExecAssignScanType(&subquerystate->ss,
- ExecGetResultType(subquerystate->subplan),
- false);
+ CreateTupleDescCopy(ExecGetResultType(subquerystate->subplan)));
/*
* Initialize result tuple type and projection info.
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index 75862f08ac4..78fd702e70c 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeTidscan.c,v 1.48 2006/03/05 15:58:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeTidscan.c,v 1.49 2006/06/16 18:42:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -524,7 +524,7 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
/*
* get the scan type from the relation descriptor.
*/
- ExecAssignScanType(&tidstate->ss, RelationGetDescr(currentRelation), false);
+ ExecAssignScanType(&tidstate->ss, RelationGetDescr(currentRelation));
/*
* Initialize result tuple type and projection info.