1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-27 07:42:10 +03:00

Further fixes for CREATE TABLE LIKE: cope with self-referential FKs.

Commit 502898192 was too careless about the order of execution of the
additional ALTER TABLE operations generated by expandTableLikeClause.
It just stuck them all at the end, which seems okay for most purposes.
But it falls down in the case where LIKE is importing a primary key
or unique index and the outer CREATE TABLE includes a FOREIGN KEY
constraint that needs to depend on that index.  Weird as that is,
it used to work, so we ought to keep it working.

To fix, make parse_utilcmd.c insert LIKE clauses between index-creation
and FK-creation commands in the transformed list of commands, and change
utility.c so that the commands generated by expandTableLikeClause are
executed immediately not at the end.  One could imagine scenarios where
this wouldn't work either; but currently expandTableLikeClause only
makes column default expressions, CHECK constraints, and indexes, and
this ordering seems fine for those.

Per bug #16730 from Sofoklis Papasofokli.  Like the previous patch,
back-patch to all supported branches.

Discussion: https://postgr.es/m/16730-b902f7e6e0276b30@postgresql.org
This commit is contained in:
Tom Lane
2020-11-19 15:03:17 -05:00
parent afaccbba78
commit 97390fe8a6
4 changed files with 56 additions and 20 deletions

View File

@@ -1138,17 +1138,22 @@ ProcessUtilitySlow(ParseState *pstate,
case T_CreateForeignTableStmt:
{
List *stmts;
ListCell *l;
RangeVar *table_rv = NULL;
/* Run parse analysis ... */
stmts = transformCreateStmt((CreateStmt *) parsetree,
queryString);
/* ... and do it */
foreach(l, stmts)
/*
* ... and do it. We can't use foreach() because we may
* modify the list midway through, so pick off the
* elements one at a time, the hard way.
*/
while (stmts != NIL)
{
Node *stmt = (Node *) lfirst(l);
Node *stmt = (Node *) linitial(stmts);
stmts = list_delete_first(stmts);
if (IsA(stmt, CreateStmt))
{
@@ -1214,8 +1219,8 @@ ProcessUtilitySlow(ParseState *pstate,
/*
* Do delayed processing of LIKE options. This
* will result in additional sub-statements for us
* to process. We can just tack those onto the
* to-do list.
* to process. Those should get done before any
* remaining actions, so prepend them to "stmts".
*/
TableLikeClause *like = (TableLikeClause *) stmt;
List *morestmts;
@@ -1223,14 +1228,7 @@ ProcessUtilitySlow(ParseState *pstate,
Assert(table_rv != NULL);
morestmts = expandTableLikeClause(table_rv, like);
stmts = list_concat(stmts, morestmts);
/*
* We don't need a CCI now, besides which the "l"
* list pointer is now possibly invalid, so just
* skip the CCI test below.
*/
continue;
stmts = list_concat(morestmts, stmts);
}
else
{
@@ -1258,7 +1256,7 @@ ProcessUtilitySlow(ParseState *pstate,
}
/* Need CCI between commands */
if (lnext(stmts, l) != NULL)
if (stmts != NIL)
CommandCounterIncrement();
}