diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execJunk.c | 6 | ||||
-rw-r--r-- | src/backend/executor/execMain.c | 10 | ||||
-rw-r--r-- | src/backend/executor/execQual.c | 249 | ||||
-rw-r--r-- | src/backend/executor/execTuples.c | 34 | ||||
-rw-r--r-- | src/backend/executor/execUtils.c | 16 | ||||
-rw-r--r-- | src/backend/executor/nodeBitmapHeapscan.c | 4 | ||||
-rw-r--r-- | src/backend/executor/nodeFunctionscan.c | 4 | ||||
-rw-r--r-- | src/backend/executor/nodeHashjoin.c | 5 | ||||
-rw-r--r-- | src/backend/executor/nodeIndexscan.c | 4 | ||||
-rw-r--r-- | src/backend/executor/nodeMergejoin.c | 5 | ||||
-rw-r--r-- | src/backend/executor/nodeSeqscan.c | 4 | ||||
-rw-r--r-- | src/backend/executor/nodeSubplan.c | 6 | ||||
-rw-r--r-- | src/backend/executor/nodeSubqueryscan.c | 10 | ||||
-rw-r--r-- | src/backend/executor/nodeTidscan.c | 4 |
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. |