1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-02 09:02:37 +03:00

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
This commit is contained in:
Tom Lane
2006-06-16 18:42:24 +00:00
parent b49ce32da1
commit 06e10abc0b
36 changed files with 581 additions and 246 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;
}
@ -826,6 +836,61 @@ ShutdownFuncExpr(Datum arg)
fcache->shutdown_reg = false;
}
/*
* 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.
*/
@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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)
{

View File

@ -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));
}

View File

@ -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);

View File

@ -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.

View File

@ -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.