1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-07 00:36:50 +03:00

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
This commit is contained in:
Peter Eisentraut
2020-03-13 11:28:11 +01:00
parent 630590d6ff
commit c9ef507e82
5 changed files with 133 additions and 0 deletions

View File

@ -174,6 +174,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 */
@ -11138,6 +11139,22 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
return address;
}
/*
* 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).
@ -11156,11 +11173,16 @@ RememberConstraintForRebuilding(Oid conoid, AlteredTableInfo *tab)
{
/* OK, capture the constraint's existing definition string */
char *defstring = pg_get_constraintdef_command(conoid);
Oid indoid;
tab->changedConstraintOids = lappend_oid(tab->changedConstraintOids,
conoid);
tab->changedConstraintDefs = lappend(tab->changedConstraintDefs,
defstring);
indoid = get_constraint_index(conoid);
if (OidIsValid(indoid))
RememberReplicaIdentityForRebuilding(indoid, tab);
}
}
@ -11203,6 +11225,8 @@ RememberIndexForRebuilding(Oid indoid, AlteredTableInfo *tab)
indoid);
tab->changedIndexDefs = lappend(tab->changedIndexDefs,
defstring);
RememberReplicaIdentityForRebuilding(indoid, tab);
}
}
}
@ -11311,6 +11335,24 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
add_exact_object_address(&obj, objects);
}
/*
* 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);
}
/*
* It should be okay to use DROP_RESTRICT here, since nothing else should
* be depending on these objects.

View File

@ -3228,6 +3228,29 @@ get_index_column_opclass(Oid index_oid, int attno)
return opclass;
}
/*
* 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;
}
/*
* get_index_isvalid
*