diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2020-08-21 15:00:43 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2020-08-21 15:00:43 -0400 |
commit | d9253df12e4c06a54e515136b115538c56eace56 (patch) | |
tree | 8b570180ccc6613864519802daca7acfc8b6cefe /src/backend/tcop/utility.c | |
parent | 3248633579e9ed1c718afa70bb93d499fe85d40c (diff) | |
download | postgresql-d9253df12e4c06a54e515136b115538c56eace56.tar.gz postgresql-d9253df12e4c06a54e515136b115538c56eace56.zip |
Fix handling of CREATE TABLE LIKE with inheritance.
If a CREATE TABLE command uses both LIKE and traditional inheritance,
Vars in CHECK constraints and expression indexes that are absorbed
from a LIKE parent table tended to get mis-numbered, resulting in
wrong answers and/or bizarre error messages (though probably not any
actual crashes, thanks to validation occurring in the executor).
In v12 and up, the same could happen to Vars in GENERATED expressions,
even in cases with no LIKE clause but multiple traditional-inheritance
parents.
The cause of the problem for LIKE is that parse_utilcmd.c supposed
it could renumber such Vars correctly during transformCreateStmt(),
which it cannot since we have not yet accounted for columns added via
inheritance. Fix that by postponing processing of LIKE INCLUDING
CONSTRAINTS, DEFAULTS, GENERATED, INDEXES till after we've performed
DefineRelation().
The error with GENERATED and multiple inheritance is a simple oversight
in MergeAttributes(); it knows it has to renumber Vars in inherited
CHECK constraints, but forgot to apply the same processing to inherited
GENERATED expressions (a/k/a defaults).
Per bug #16272 from Tom Gottfried. The non-GENERATED variants of the
issue are ancient, presumably dating right back to the addition of
CREATE TABLE LIKE; hence back-patch to all supported branches.
Discussion: https://postgr.es/m/16272-6e32da020e9a9381@postgresql.org
Diffstat (limited to 'src/backend/tcop/utility.c')
-rw-r--r-- | src/backend/tcop/utility.c | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 05ec7f3ac61..4992c22bbbf 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1055,6 +1055,28 @@ ProcessUtilitySlow(ParseState *pstate, secondaryObject, stmt); } + else if (IsA(stmt, TableLikeClause)) + { + /* + * 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. + */ + TableLikeClause *like = (TableLikeClause *) stmt; + RangeVar *rv = ((CreateStmt *) parsetree)->relation; + List *morestmts; + + morestmts = expandTableLikeClause(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; + } else { /* @@ -1303,6 +1325,7 @@ ProcessUtilitySlow(ParseState *pstate, IndexStmt *stmt = (IndexStmt *) parsetree; Oid relid; LOCKMODE lockmode; + bool is_alter_table; if (stmt->concurrent) PreventInTransactionBlock(isTopLevel, @@ -1364,6 +1387,17 @@ ProcessUtilitySlow(ParseState *pstate, list_free(inheritors); } + /* + * If the IndexStmt is already transformed, it must have + * come from generateClonedIndexStmt, which in current + * usage means it came from expandTableLikeClause rather + * than from original parse analysis. And that means we + * must treat it like ALTER TABLE ADD INDEX, not CREATE. + * (This is a bit grotty, but currently it doesn't seem + * worth adding a separate bool field for the purpose.) + */ + is_alter_table = stmt->transformed; + /* Run parse analysis ... */ stmt = transformIndexStmt(relid, stmt, queryString); @@ -1375,7 +1409,7 @@ ProcessUtilitySlow(ParseState *pstate, InvalidOid, /* no predefined OID */ InvalidOid, /* no parent index */ InvalidOid, /* no parent constraint */ - false, /* is_alter_table */ + is_alter_table, true, /* check_rights */ true, /* check_not_in_use */ false, /* skip_build */ |