From 790d5bc9922d515f04b83182b1767a4eaa37cdb7 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 23 Jan 2003 05:10:41 +0000 Subject: [PATCH] Change CREATE TABLE AS / SELECT INTO to create the new table with OIDs, for backwards compatibility with pre-7.3 behavior. Per discussion on pgsql-general and pgsql-hackers. --- src/backend/executor/execMain.c | 131 ++++++++++++++++--------------- src/backend/executor/execUtils.c | 24 ++++-- src/include/nodes/execnodes.h | 4 +- 3 files changed, 89 insertions(+), 70 deletions(-) diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 04aed372c0..e1178cd6a6 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -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); + /* + * 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...) - */ + 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 diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 63eede2280..90bd8adf1a 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -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; + } } /* diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 2aa672b65e..98c6f1ddfb 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -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 */