*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
}
/*
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
*
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;
/*
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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);
/* ----------------------------------------------------------------
{
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;
}
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];
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;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
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;
}
/*
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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++)
{
* 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 $
*
*-------------------------------------------------------------------------
*/
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,
* 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 $
*
*-------------------------------------------------------------------------
*/
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 */