diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index a340477c47..4f36602aa0 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.227 2004/01/14 23:01:54 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.228 2004/01/22 02:23:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -591,7 +591,8 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly) if (operation == CMD_SELECT && parseTree->into != NULL) { do_select_into = true; - estate->es_force_oids = parseTree->intoHasOids; + estate->es_select_into = true; + estate->es_into_oids = parseTree->intoHasOids; } /* @@ -897,6 +898,63 @@ initResultRelInfo(ResultRelInfo *resultRelInfo, ExecOpenIndices(resultRelInfo); } +/* + * ExecContextForcesOids + * + * This is pretty grotty: when doing INSERT, UPDATE, or SELECT INTO, + * we need to ensure that result tuples have space for an OID iff they are + * going to be stored into a relation that has OIDs. In other contexts + * we are free to choose whether to leave space for OIDs in result tuples + * (we generally don't want to, but we do if a physical-tlist optimization + * is possible). This routine checks the plan context and returns TRUE if the + * choice is forced, FALSE if the choice is not forced. In the TRUE case, + * *hasoids is set to the required value. + * + * One reason this is ugly is that all plan nodes in the plan tree will emit + * tuples with space for an OID, though we really only need the topmost node + * to do so. However, node types like Sort don't project new tuples but just + * return their inputs, and in those cases the requirement propagates down + * to the input node. Eventually we might make this code smart enough to + * recognize how far down the requirement really goes, but for now we just + * make all plan nodes do the same thing if the top level forces the choice. + * + * We assume that estate->es_result_relation_info is already set up to + * describe the target relation. Note that in an UPDATE that spans an + * inheritance tree, some of the target relations may have OIDs and some not. + * We have to make the decisions on a per-relation basis as we initialize + * each of the child plans of the topmost Append plan. + * + * SELECT INTO is even uglier, because we don't have the INTO relation's + * descriptor available when this code runs; we have to look aside at a + * flag set by InitPlan(). + */ +bool +ExecContextForcesOids(PlanState *planstate, bool *hasoids) +{ + if (planstate->state->es_select_into) + { + *hasoids = planstate->state->es_into_oids; + return true; + } + else + { + ResultRelInfo *ri = planstate->state->es_result_relation_info; + + if (ri != NULL) + { + Relation rel = ri->ri_RelationDesc; + + if (rel != NULL) + { + *hasoids = rel->rd_rel->relhasoids; + return true; + } + } + } + + return false; +} + /* ---------------------------------------------------------------- * ExecEndPlan * @@ -2058,7 +2116,8 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq) palloc0(estate->es_topPlan->nParamExec * sizeof(ParamExecData)); epqstate->es_rowMark = estate->es_rowMark; epqstate->es_instrument = estate->es_instrument; - epqstate->es_force_oids = estate->es_force_oids; + epqstate->es_select_into = estate->es_select_into; + epqstate->es_into_oids = estate->es_into_oids; epqstate->es_topPlan = estate->es_topPlan; /* diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c index 39b879310e..2508a9f2b1 100644 --- a/src/backend/executor/execScan.c +++ b/src/backend/executor/execScan.c @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execScan.c,v 1.29 2003/11/29 19:51:48 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execScan.c,v 1.30 2004/01/22 02:23:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,7 +23,7 @@ #include "utils/memutils.h" -static bool tlist_matches_tupdesc(List *tlist, Index varno, TupleDesc tupdesc); +static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc); /* ---------------------------------------------------------------- @@ -180,7 +180,8 @@ ExecAssignScanProjectionInfo(ScanState *node) { Scan *scan = (Scan *) node->ps.plan; - if (tlist_matches_tupdesc(scan->plan.targetlist, + if (tlist_matches_tupdesc(&node->ps, + scan->plan.targetlist, scan->scanrelid, node->ss_ScanTupleSlot->ttc_tupleDescriptor)) node->ps.ps_ProjInfo = NULL; @@ -189,11 +190,13 @@ ExecAssignScanProjectionInfo(ScanState *node) } static bool -tlist_matches_tupdesc(List *tlist, Index varno, TupleDesc tupdesc) +tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc) { int numattrs = tupdesc->natts; int attrno; + bool hasoid; + /* Check the tlist attributes */ for (attrno = 1; attrno <= numattrs; attrno++) { Form_pg_attribute att_tup = tupdesc->attrs[attrno - 1]; @@ -219,5 +222,13 @@ tlist_matches_tupdesc(List *tlist, Index varno, TupleDesc tupdesc) if (tlist) return false; /* tlist too long */ + /* + * If the plan context requires a particular hasoid setting, then + * that has to match, too. + */ + if (ExecContextForcesOids(ps, &hasoid) && + hasoid != tupdesc->tdhasoid) + return false; + return true; } diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index cb11f4fc36..b89f401597 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.108 2003/12/18 20:21:37 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.109 2004/01/22 02:23:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -201,7 +201,8 @@ CreateExecutorState(void) estate->es_rowMark = NIL; estate->es_instrument = false; - estate->es_force_oids = false; + estate->es_select_into = false; + estate->es_into_oids = false; estate->es_exprcontexts = NIL; @@ -446,43 +447,17 @@ ExecAssignResultTypeFromOuterPlan(PlanState *planstate) void ExecAssignResultTypeFromTL(PlanState *planstate) { - bool hasoid = false; + bool hasoid; TupleDesc tupDesc; - /* - * This is pretty grotty: we need to ensure that result tuples have - * space for an OID iff they are going to be stored into a relation - * that has OIDs. We assume that estate->es_result_relation_info is - * already set up to describe the target relation. One reason this is - * ugly is that all plan nodes in the plan tree will emit tuples with - * space for an OID, though we really only need the topmost plan to do - * so. - * - * It would be better to have InitPlan adjust the topmost plan node's - * output descriptor after plan tree initialization. However, that - * doesn't quite work because in an UPDATE that spans an inheritance - * tree, some of the target relations may have OIDs and some not. We - * have to make the decision on a per-relation basis as we initialize - * each of the child plans of the topmost Append plan. So, this is - * ugly but it works, for now ... - * - * SELECT INTO is also pretty grotty, because we don't yet have the INTO - * relation's descriptor at this point; we have to look aside at a - * flag set by InitPlan(). - */ - if (planstate->state->es_force_oids) - hasoid = true; + if (ExecContextForcesOids(planstate, &hasoid)) + { + /* context forces OID choice; hasoid is now set correctly */ + } else { - ResultRelInfo *ri = planstate->state->es_result_relation_info; - - if (ri != NULL) - { - Relation rel = ri->ri_RelationDesc; - - if (rel != NULL) - hasoid = rel->rd_rel->relhasoids; - } + /* given free choice, don't leave space for OIDs in result tuples */ + hasoid = false; } /* diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index 32e2c3ea55..c0d74c4778 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeAppend.c,v 1.55 2003/11/29 19:51:48 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeAppend.c,v 1.56 2004/01/22 02:23:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -208,7 +208,7 @@ ExecInitAppend(Append *node, EState *estate) * call ExecInitNode on each of the plans to be executed and save the * results into the array "appendplans". Note we *must* set * estate->es_result_relation_info correctly while we initialize each - * sub-plan; ExecAssignResultTypeFromTL depends on that! + * sub-plan; ExecContextForcesOids depends on that! */ for (i = appendstate->as_firstplan; i <= appendstate->as_lastplan; i++) { diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 050894708c..39e07da8af 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.105 2004/01/14 23:01:55 tgl Exp $ + * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.106 2004/01/22 02:23:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -93,6 +93,7 @@ extern void ExecutorEnd(QueryDesc *queryDesc); extern void ExecutorRewind(QueryDesc *queryDesc); extern void ExecCheckRTPerms(List *rangeTable); extern void ExecEndPlan(PlanState *planstate, EState *estate); +extern bool ExecContextForcesOids(PlanState *planstate, bool *hasoids); extern void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate); extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti, diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 21d32dec85..50db072f41 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.110 2004/01/06 04:31:01 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.111 2004/01/22 02:23:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -311,9 +311,8 @@ typedef struct EState List *es_rowMark; /* not good place, but there is no other */ bool es_instrument; /* true requests runtime instrumentation */ - bool es_force_oids; /* true forces result tuples to have - * (space for) OIDs --- used for SELECT - * INTO */ + bool es_select_into; /* true if doing SELECT INTO */ + bool es_into_oids; /* true to generate OIDs in SELECT INTO */ List *es_exprcontexts; /* List of ExprContexts within EState */