diff options
author | Peter Eisentraut <peter@eisentraut.org> | 2020-03-13 11:28:11 +0100 |
---|---|---|
committer | Peter Eisentraut <peter@eisentraut.org> | 2020-03-13 13:03:28 +0100 |
commit | 02530da73f0438f7c2073267de6fe2be84f592d7 (patch) | |
tree | 130fb38a8950d5b18d1fca04fa020534d0f5e86a /src/backend | |
parent | 05e0aff58446203d01dfc16717866df769e4e25e (diff) |
Preserve replica identity index across ALTER TABLE rewrite
If an index was explicitly set as replica identity index, this setting
was lost when a table was rewritten by ALTER TABLE. Because this
setting is part of pg_index but actually controlled by ALTER
TABLE (not part of CREATE INDEX, say), we have to do some extra work
to restore it.
Based-on-patch-by: Quan Zongliang <quanzongliang@gmail.com>
Reviewed-by: Euler Taveira <euler.taveira@2ndquadrant.com>
Discussion: https://www.postgresql.org/message-id/flat/c70fcab2-4866-0d9f-1d01-e75e189db342@gmail.com
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/commands/tablecmds.c | 42 | ||||
-rw-r--r-- | src/backend/utils/cache/lsyscache.c | 25 |
2 files changed, 67 insertions, 0 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 1a005760d86..e99e16efbc0 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -173,6 +173,7 @@ typedef struct AlteredTableInfo List *changedConstraintDefs; /* string definitions of same */ List *changedIndexOids; /* OIDs of indexes to rebuild */ List *changedIndexDefs; /* string definitions of same */ + char *replicaIdentityIndex; /* index to reset as REPLICA IDENTITY */ } AlteredTableInfo; /* Struct describing one new constraint to check in Phase 3 scan */ @@ -9421,6 +9422,22 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, } /* + * Subroutine for ATExecAlterColumnType: remember that a replica identity + * needs to be reset. + */ +static void +RememberReplicaIdentityForRebuilding(Oid indoid, AlteredTableInfo *tab) +{ + if (!get_index_isreplident(indoid)) + return; + + if (tab->replicaIdentityIndex) + elog(ERROR, "relation %u has multiple indexes marked as replica identity", tab->relid); + + tab->replicaIdentityIndex = get_rel_name(indoid); +} + +/* * Subroutine for ATExecAlterColumnType: remember that a constraint needs * to be rebuilt (which we might already know). */ @@ -9439,6 +9456,7 @@ RememberConstraintForRebuilding(Oid conoid, AlteredTableInfo *tab, { /* OK, capture the constraint's existing definition string */ char *defstring = pg_get_constraintdef_command(conoid); + Oid indoid; /* * Put NORMAL dependencies at the front of the list and AUTO @@ -9462,6 +9480,10 @@ RememberConstraintForRebuilding(Oid conoid, AlteredTableInfo *tab, tab->changedConstraintDefs = lappend(tab->changedConstraintDefs, defstring); } + + indoid = get_constraint_index(conoid); + if (OidIsValid(indoid)) + RememberReplicaIdentityForRebuilding(indoid, tab); } } @@ -9505,6 +9527,8 @@ RememberIndexForRebuilding(Oid indoid, AlteredTableInfo *tab) indoid); tab->changedIndexDefs = lappend(tab->changedIndexDefs, defstring); + + RememberReplicaIdentityForRebuilding(indoid, tab); } } } @@ -9698,6 +9722,24 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode) } /* + * Queue up command to restore replica identity index marking + */ + if (tab->replicaIdentityIndex) + { + AlterTableCmd *cmd = makeNode(AlterTableCmd); + ReplicaIdentityStmt *subcmd = makeNode(ReplicaIdentityStmt); + + subcmd->identity_type = REPLICA_IDENTITY_INDEX; + subcmd->name = tab->replicaIdentityIndex; + cmd->subtype = AT_ReplicaIdentity; + cmd->def = (Node *) subcmd; + + /* do it after indexes and constraints */ + tab->subcmds[AT_PASS_OLD_CONSTR] = + lappend(tab->subcmds[AT_PASS_OLD_CONSTR], cmd); + } + + /* * Now we can drop the existing constraints and indexes --- constraints * first, since some of them might depend on the indexes. In fact, we * have to delete FOREIGN KEY constraints before UNIQUE constraints, but diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 88415e6892d..db62daf77ec 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -3138,3 +3138,28 @@ get_range_collation(Oid rangeOid) else return InvalidOid; } + +/* ---------- PG_INDEX CACHE ---------- */ + +/* + * get_index_isreplident + * + * Given the index OID, return pg_index.indisreplident. + */ +bool +get_index_isreplident(Oid index_oid) +{ + HeapTuple tuple; + Form_pg_index rd_index; + bool result; + + tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid)); + if (!HeapTupleIsValid(tuple)) + return false; + + rd_index = (Form_pg_index) GETSTRUCT(tuple); + result = rd_index->indisreplident; + ReleaseSysCache(tuple); + + return result; +} |