aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-06-16 18:42:24 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-06-16 18:42:24 +0000
commit06e10abc0bb4297a0754313b4f158bdd5622ca24 (patch)
tree6d413dfdfab3fea4a6d96b07b7fdb8ba81498860 /src/backend/executor
parentb49ce32da1975b2fdab26e463b7189b95e770809 (diff)
downloadpostgresql-06e10abc0bb4297a0754313b4f158bdd5622ca24.tar.gz
postgresql-06e10abc0bb4297a0754313b4f158bdd5622ca24.zip
Fix problems with cached tuple descriptors disappearing while still in use
by creating a reference-count mechanism, similar to what we did a long time ago for catcache entries. The back branches have an ugly solution involving lots of extra copies, but this way is more efficient. Reference counting is only applied to tupdescs that are actually in caches --- there seems no need to use it for tupdescs that are generated in the executor, since they'll go away during plan shutdown by virtue of being in the per-query memory context. Neil Conway and Tom Lane
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.