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.
This commit is contained in:
Tom Lane 2003-01-23 05:10:41 +00:00
parent 742403bdad
commit 790d5bc992
3 changed files with 89 additions and 70 deletions

View File

@ -26,7 +26,7 @@
* *
* *
* IDENTIFICATION * 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; PlanState *planstate;
List *rangeTable; List *rangeTable;
Relation intoRelationDesc; Relation intoRelationDesc;
bool do_select_into;
TupleDesc tupType; TupleDesc tupType;
/* /*
@ -529,6 +530,26 @@ InitPlan(QueryDesc *queryDesc)
estate->es_result_relation_info = NULL; 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 * 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; intoRelationDesc = (Relation) NULL;
if (operation == CMD_SELECT) if (do_select_into)
{ {
if (!parseTree->isPortal) char *intoName;
{ Oid namespaceId;
/* AclResult aclresult;
* a select into table --- need to create the "into" table Oid intoRelationId;
*/ TupleDesc tupdesc;
if (parseTree->into != NULL)
{
char *intoName;
Oid namespaceId;
AclResult aclresult;
Oid intoRelationId;
TupleDesc tupdesc;
/* /*
* find namespace to create in, check permissions * find namespace to create in, check permissions
*/ */
intoName = parseTree->into->relname; intoName = parseTree->into->relname;
namespaceId = RangeVarGetCreationNamespace(parseTree->into); namespaceId = RangeVarGetCreationNamespace(parseTree->into);
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
ACL_CREATE); ACL_CREATE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, aclcheck_error(aclresult, get_namespace_name(namespaceId));
get_namespace_name(namespaceId));
/* /*
* have to copy tupType to get rid of constraints * have to copy tupType to get rid of constraints
*/ */
tupdesc = CreateTupleDescCopy(tupType); tupdesc = CreateTupleDescCopy(tupType);
/* intoRelationId = heap_create_with_catalog(intoName,
* Formerly we forced the output table to have OIDs, but namespaceId,
* as of 7.3 it will not have OIDs, because it's too late tupdesc,
* here to change the tupdescs of the already-initialized RELKIND_RELATION,
* plan tree. (Perhaps we could recurse and change them false,
* all, but it's not really worth the trouble IMHO...) ONCOMMIT_NOOP,
*/ allowSystemTableMods);
intoRelationId = FreeTupleDesc(tupdesc);
heap_create_with_catalog(intoName,
namespaceId,
tupdesc,
RELKIND_RELATION,
false,
ONCOMMIT_NOOP,
allowSystemTableMods);
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 * If necessary, create a TOAST table for the into
* relation's catalog tuples will be visible to heap_open. * relation. Note that AlterTableCreateToastTable ends
*/ * with CommandCounterIncrement(), so that the TOAST table
CommandCounterIncrement(); * will be visible for insertion.
*/
AlterTableCreateToastTable(intoRelationId, true);
/* /*
* If necessary, create a TOAST table for the into * And open the constructed table for writing.
* relation. Note that AlterTableCreateToastTable ends */
* with CommandCounterIncrement(), so that the TOAST table intoRelationDesc = heap_open(intoRelationId, AccessExclusiveLock);
* will be visible for insertion.
*/
AlterTableCreateToastTable(intoRelationId, true);
intoRelationDesc = heap_open(intoRelationId,
AccessExclusiveLock);
}
}
} }
estate->es_into_relation_descriptor = intoRelationDesc; estate->es_into_relation_descriptor = intoRelationDesc;
@ -1964,6 +1970,7 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
palloc0(estate->es_topPlan->nParamExec * sizeof(ParamExecData)); palloc0(estate->es_topPlan->nParamExec * sizeof(ParamExecData));
epqstate->es_rowMark = estate->es_rowMark; epqstate->es_rowMark = estate->es_rowMark;
epqstate->es_instrument = estate->es_instrument; epqstate->es_instrument = estate->es_instrument;
epqstate->es_force_oids = estate->es_force_oids;
epqstate->es_topPlan = estate->es_topPlan; epqstate->es_topPlan = estate->es_topPlan;
/* /*
* Each epqstate must have its own es_evTupleNull state, but * Each epqstate must have its own es_evTupleNull state, but

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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_rowMark = NIL;
estate->es_instrument = false; estate->es_instrument = false;
estate->es_force_oids = false;
estate->es_exprcontexts = NIL; estate->es_exprcontexts = NIL;
@ -424,7 +425,6 @@ ExecAssignResultTypeFromOuterPlan(PlanState *planstate)
void void
ExecAssignResultTypeFromTL(PlanState *planstate) ExecAssignResultTypeFromTL(PlanState *planstate)
{ {
ResultRelInfo *ri;
bool hasoid = false; bool hasoid = false;
TupleDesc tupDesc; TupleDesc tupDesc;
@ -444,14 +444,24 @@ ExecAssignResultTypeFromTL(PlanState *planstate)
* have to make the decision on a per-relation basis as we initialize * 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 * each of the child plans of the topmost Append plan. So, this is
* ugly but it works, for now ... * 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 (planstate->state->es_force_oids)
if (ri != NULL) hasoid = true;
else
{ {
Relation rel = ri->ri_RelationDesc; ResultRelInfo *ri = planstate->state->es_result_relation_info;
if (rel != NULL) if (ri != NULL)
hasoid = rel->rd_rel->relhasoids; {
Relation rel = ri->ri_RelationDesc;
if (rel != NULL)
hasoid = rel->rd_rel->relhasoids;
}
} }
/* /*

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 */ List *es_rowMark; /* not good place, but there is no other */
bool es_instrument; /* true requests runtime instrumentation */ 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 */ List *es_exprcontexts; /* List of ExprContexts within EState */