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
* $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

View 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;
}
}
/*

View 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 */