Change CREATE TABLE AS / SELECT INTO to create the new table with OIDs,
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 23 Jan 2003 05:10:41 +0000 (05:10 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 23 Jan 2003 05:10:41 +0000 (05:10 +0000)
for backwards compatibility with pre-7.3 behavior.  Per discussion on
pgsql-general and pgsql-hackers.

src/backend/executor/execMain.c
src/backend/executor/execUtils.c
src/include/nodes/execnodes.h

index 04aed372c004e856aae44576f1373d33e080b65f..e1178cd6a69cfa33703ee32302e0c76047cab23b 100644 (file)
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.198 2003/01/12 18:19:37 petere Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.199 2003/01/23 05:10:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -450,6 +450,7 @@ InitPlan(QueryDesc *queryDesc)
        PlanState  *planstate;
        List       *rangeTable;
        Relation        intoRelationDesc;
+       bool            do_select_into;
        TupleDesc       tupType;
 
        /*
@@ -529,6 +530,26 @@ InitPlan(QueryDesc *queryDesc)
                estate->es_result_relation_info = NULL;
        }
 
+       /*
+        * Detect whether we're doing SELECT INTO.  If so, set the force_oids
+        * flag appropriately so that the plan tree will be initialized with
+        * the correct tuple descriptors.
+        */
+       do_select_into = false;
+
+       if (operation == CMD_SELECT &&
+               !parseTree->isPortal &&
+               parseTree->into != NULL)
+       {
+               do_select_into = true;
+               /*
+                * For now, always create OIDs in SELECT INTO; this is for backwards
+                * compatibility with pre-7.3 behavior.  Eventually we might want
+                * to allow the user to choose.
+                */
+               estate->es_force_oids = true;
+       }
+
        /*
         * Have to lock relations selected for update
         */
@@ -687,79 +708,64 @@ InitPlan(QueryDesc *queryDesc)
        }
 
        /*
-        * initialize the "into" relation
+        * If doing SELECT INTO, initialize the "into" relation.  We must wait
+        * till now so we have the "clean" result tuple type to create the
+        * new table from.
         */
        intoRelationDesc = (Relation) NULL;
 
-       if (operation == CMD_SELECT)
+       if (do_select_into)
        {
-               if (!parseTree->isPortal)
-               {
-                       /*
-                        * a select into table --- need to create the "into" table
-                        */
-                       if (parseTree->into != NULL)
-                       {
-                               char       *intoName;
-                               Oid                     namespaceId;
-                               AclResult       aclresult;
-                               Oid                     intoRelationId;
-                               TupleDesc       tupdesc;
+               char       *intoName;
+               Oid                     namespaceId;
+               AclResult       aclresult;
+               Oid                     intoRelationId;
+               TupleDesc       tupdesc;
 
-                               /*
-                                * find namespace to create in, check permissions
-                                */
-                               intoName = parseTree->into->relname;
-                               namespaceId = RangeVarGetCreationNamespace(parseTree->into);
+               /*
+                * find namespace to create in, check permissions
+                */
+               intoName = parseTree->into->relname;
+               namespaceId = RangeVarGetCreationNamespace(parseTree->into);
 
-                               aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
-                                                                                                 ACL_CREATE);
-                               if (aclresult != ACLCHECK_OK)
-                                       aclcheck_error(aclresult,
-                                                                  get_namespace_name(namespaceId));
+               aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
+                                                                                 ACL_CREATE);
+               if (aclresult != ACLCHECK_OK)
+                       aclcheck_error(aclresult, get_namespace_name(namespaceId));
 
-                               /*
-                                * have to copy tupType to get rid of constraints
-                                */
-                               tupdesc = CreateTupleDescCopy(tupType);
-
-                               /*
-                                * Formerly we forced the output table to have OIDs, but
-                                * as of 7.3 it will not have OIDs, because it's too late
-                                * here to change the tupdescs of the already-initialized
-                                * plan tree.  (Perhaps we could recurse and change them
-                                * all, but it's not really worth the trouble IMHO...)
-                                */
+               /*
+                * have to copy tupType to get rid of constraints
+                */
+               tupdesc = CreateTupleDescCopy(tupType);
 
-                               intoRelationId =
-                                       heap_create_with_catalog(intoName,
-                                                                                        namespaceId,
-                                                                                        tupdesc,
-                                                                                        RELKIND_RELATION,
-                                                                                        false,
-                                                                                        ONCOMMIT_NOOP,
-                                                                                        allowSystemTableMods);
+               intoRelationId = heap_create_with_catalog(intoName,
+                                                                                                 namespaceId,
+                                                                                                 tupdesc,
+                                                                                                 RELKIND_RELATION,
+                                                                                                 false,
+                                                                                                 ONCOMMIT_NOOP,
+                                                                                                 allowSystemTableMods);
 
-                               FreeTupleDesc(tupdesc);
+               FreeTupleDesc(tupdesc);
 
-                               /*
-                                * Advance command counter so that the newly-created
-                                * relation's catalog tuples will be visible to heap_open.
-                                */
-                               CommandCounterIncrement();
+               /*
+                * Advance command counter so that the newly-created
+                * relation's catalog tuples will be visible to heap_open.
+                */
+               CommandCounterIncrement();
 
-                               /*
-                                * If necessary, create a TOAST table for the into
-                                * relation. Note that AlterTableCreateToastTable ends
-                                * with CommandCounterIncrement(), so that the TOAST table
-                                * will be visible for insertion.
-                                */
-                               AlterTableCreateToastTable(intoRelationId, true);
+               /*
+                * If necessary, create a TOAST table for the into
+                * relation. Note that AlterTableCreateToastTable ends
+                * with CommandCounterIncrement(), so that the TOAST table
+                * will be visible for insertion.
+                */
+               AlterTableCreateToastTable(intoRelationId, true);
 
-                               intoRelationDesc = heap_open(intoRelationId,
-                                                                                        AccessExclusiveLock);
-                       }
-               }
+               /*
+                * And open the constructed table for writing.
+                */
+               intoRelationDesc = heap_open(intoRelationId, AccessExclusiveLock);
        }
 
        estate->es_into_relation_descriptor = intoRelationDesc;
@@ -1964,6 +1970,7 @@ 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_topPlan = estate->es_topPlan;
        /*
         * Each epqstate must have its own es_evTupleNull state, but
index 63eede2280234d613b4cbb1ef595fd4c65e17dea..90bd8adf1ae13beef3fb1230e223979127473bae 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.95 2003/01/12 04:03:34 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.96 2003/01/23 05:10:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -199,6 +199,7 @@ CreateExecutorState(void)
        estate->es_rowMark = NIL;
 
        estate->es_instrument = false;
+       estate->es_force_oids = false;
 
        estate->es_exprcontexts = NIL;
 
@@ -424,7 +425,6 @@ ExecAssignResultTypeFromOuterPlan(PlanState *planstate)
 void
 ExecAssignResultTypeFromTL(PlanState *planstate)
 {
-       ResultRelInfo *ri;
        bool            hasoid = false;
        TupleDesc       tupDesc;
 
@@ -444,14 +444,24 @@ ExecAssignResultTypeFromTL(PlanState *planstate)
         * 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().
         */
-       ri = planstate->state->es_result_relation_info;
-       if (ri != NULL)
+       if (planstate->state->es_force_oids)
+               hasoid = true;
+       else
        {
-               Relation        rel = ri->ri_RelationDesc;
+               ResultRelInfo *ri = planstate->state->es_result_relation_info;
 
-               if (rel != NULL)
-                       hasoid = rel->rd_rel->relhasoids;
+               if (ri != NULL)
+               {
+                       Relation        rel = ri->ri_RelationDesc;
+
+                       if (rel != NULL)
+                               hasoid = rel->rd_rel->relhasoids;
+               }
        }
 
        /*
index 2aa672b65ea345f22ce67ecac7afecb292945b85..98c6f1ddfbd0b3f013da586e70f5485b12ed7e8b 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: execnodes.h,v 1.91 2003/01/12 04:03:34 tgl Exp $
+ * $Id: execnodes.h,v 1.92 2003/01/23 05:10:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -311,6 +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 */
 
        List       *es_exprcontexts; /* List of ExprContexts within EState */