Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit15cbbf8

Browse files
committed
Preserve replica identity index across ALTER TABLE rewrite
If an index was explicitly set as replica identity index, this settingwas lost when a table was rewritten by ALTER TABLE. Because thissetting is part of pg_index but actually controlled by ALTERTABLE (not part of CREATE INDEX, say), we have to do some extra workto 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
1 parenta493f93 commit15cbbf8

File tree

5 files changed

+135
-0
lines changed

5 files changed

+135
-0
lines changed

‎src/backend/commands/tablecmds.c‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ typedef struct AlteredTableInfo
175175
List*changedConstraintDefs;/* string definitions of same */
176176
List*changedIndexOids;/* OIDs of indexes to rebuild */
177177
List*changedIndexDefs;/* string definitions of same */
178+
char*replicaIdentityIndex;/* index to reset as REPLICA IDENTITY */
178179
}AlteredTableInfo;
179180

180181
/* Struct describing one new constraint to check in Phase 3 scan */
@@ -10314,6 +10315,22 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
1031410315
returnaddress;
1031510316
}
1031610317

10318+
/*
10319+
* Subroutine for ATExecAlterColumnType: remember that a replica identity
10320+
* needs to be reset.
10321+
*/
10322+
staticvoid
10323+
RememberReplicaIdentityForRebuilding(Oidindoid,AlteredTableInfo*tab)
10324+
{
10325+
if (!get_index_isreplident(indoid))
10326+
return;
10327+
10328+
if (tab->replicaIdentityIndex)
10329+
elog(ERROR,"relation %u has multiple indexes marked as replica identity",tab->relid);
10330+
10331+
tab->replicaIdentityIndex=get_rel_name(indoid);
10332+
}
10333+
1031710334
/*
1031810335
* Subroutine for ATExecAlterColumnType: remember that a constraint needs
1031910336
* to be rebuilt (which we might already know).
@@ -10332,11 +10349,16 @@ RememberConstraintForRebuilding(Oid conoid, AlteredTableInfo *tab)
1033210349
{
1033310350
/* OK, capture the constraint's existing definition string */
1033410351
char*defstring=pg_get_constraintdef_command(conoid);
10352+
Oidindoid;
1033510353

1033610354
tab->changedConstraintOids=lappend_oid(tab->changedConstraintOids,
1033710355
conoid);
1033810356
tab->changedConstraintDefs=lappend(tab->changedConstraintDefs,
1033910357
defstring);
10358+
10359+
indoid=get_constraint_index(conoid);
10360+
if (OidIsValid(indoid))
10361+
RememberReplicaIdentityForRebuilding(indoid,tab);
1034010362
}
1034110363
}
1034210364

@@ -10379,6 +10401,8 @@ RememberIndexForRebuilding(Oid indoid, AlteredTableInfo *tab)
1037910401
indoid);
1038010402
tab->changedIndexDefs=lappend(tab->changedIndexDefs,
1038110403
defstring);
10404+
10405+
RememberReplicaIdentityForRebuilding(indoid,tab);
1038210406
}
1038310407
}
1038410408
}
@@ -10593,6 +10617,24 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
1059310617
add_exact_object_address(&obj,objects);
1059410618
}
1059510619

10620+
/*
10621+
* Queue up command to restore replica identity index marking
10622+
*/
10623+
if (tab->replicaIdentityIndex)
10624+
{
10625+
AlterTableCmd*cmd=makeNode(AlterTableCmd);
10626+
ReplicaIdentityStmt*subcmd=makeNode(ReplicaIdentityStmt);
10627+
10628+
subcmd->identity_type=REPLICA_IDENTITY_INDEX;
10629+
subcmd->name=tab->replicaIdentityIndex;
10630+
cmd->subtype=AT_ReplicaIdentity;
10631+
cmd->def= (Node*)subcmd;
10632+
10633+
/* do it after indexes and constraints */
10634+
tab->subcmds[AT_PASS_OLD_CONSTR]=
10635+
lappend(tab->subcmds[AT_PASS_OLD_CONSTR],cmd);
10636+
}
10637+
1059610638
/*
1059710639
* It should be okay to use DROP_RESTRICT here, since nothing else should
1059810640
* be depending on these objects.

‎src/backend/utils/cache/lsyscache.c‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3156,3 +3156,28 @@ get_range_collation(Oid rangeOid)
31563156
else
31573157
returnInvalidOid;
31583158
}
3159+
3160+
/*---------- PG_INDEX CACHE ---------- */
3161+
3162+
/*
3163+
* get_index_isreplident
3164+
*
3165+
*Given the index OID, return pg_index.indisreplident.
3166+
*/
3167+
bool
3168+
get_index_isreplident(Oidindex_oid)
3169+
{
3170+
HeapTupletuple;
3171+
Form_pg_indexrd_index;
3172+
boolresult;
3173+
3174+
tuple=SearchSysCache1(INDEXRELID,ObjectIdGetDatum(index_oid));
3175+
if (!HeapTupleIsValid(tuple))
3176+
return false;
3177+
3178+
rd_index= (Form_pg_index)GETSTRUCT(tuple);
3179+
result=rd_index->indisreplident;
3180+
ReleaseSysCache(tuple);
3181+
3182+
returnresult;
3183+
}

‎src/include/utils/lsyscache.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ extern char *get_namespace_name(Oid nspid);
178178
externchar*get_namespace_name_or_temp(Oidnspid);
179179
externOidget_range_subtype(OidrangeOid);
180180
externOidget_range_collation(OidrangeOid);
181+
externboolget_index_isreplident(Oidindex_oid);
181182

182183
#definetype_is_array(typid) (get_element_type(typid) != InvalidOid)
183184
/* type_is_array_domain accepts both plain arrays and domains over arrays */

‎src/test/regress/expected/replica_identity.out‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,5 +186,51 @@ SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass;
186186
n
187187
(1 row)
188188

189+
---
190+
-- Test that ALTER TABLE rewrite preserves nondefault replica identity
191+
---
192+
-- constraint variant
193+
CREATE TABLE test_replica_identity2 (id int UNIQUE NOT NULL);
194+
ALTER TABLE test_replica_identity2 REPLICA IDENTITY USING INDEX test_replica_identity2_id_key;
195+
\d test_replica_identity2
196+
Table "public.test_replica_identity2"
197+
Column | Type | Collation | Nullable | Default
198+
--------+---------+-----------+----------+---------
199+
id | integer | | not null |
200+
Indexes:
201+
"test_replica_identity2_id_key" UNIQUE CONSTRAINT, btree (id) REPLICA IDENTITY
202+
203+
ALTER TABLE test_replica_identity2 ALTER COLUMN id TYPE bigint;
204+
\d test_replica_identity2
205+
Table "public.test_replica_identity2"
206+
Column | Type | Collation | Nullable | Default
207+
--------+--------+-----------+----------+---------
208+
id | bigint | | not null |
209+
Indexes:
210+
"test_replica_identity2_id_key" UNIQUE CONSTRAINT, btree (id) REPLICA IDENTITY
211+
212+
-- straight index variant
213+
CREATE TABLE test_replica_identity3 (id int NOT NULL);
214+
CREATE UNIQUE INDEX test_replica_identity3_id_key ON test_replica_identity3 (id);
215+
ALTER TABLE test_replica_identity3 REPLICA IDENTITY USING INDEX test_replica_identity3_id_key;
216+
\d test_replica_identity3
217+
Table "public.test_replica_identity3"
218+
Column | Type | Collation | Nullable | Default
219+
--------+---------+-----------+----------+---------
220+
id | integer | | not null |
221+
Indexes:
222+
"test_replica_identity3_id_key" UNIQUE, btree (id) REPLICA IDENTITY
223+
224+
ALTER TABLE test_replica_identity3 ALTER COLUMN id TYPE bigint;
225+
\d test_replica_identity3
226+
Table "public.test_replica_identity3"
227+
Column | Type | Collation | Nullable | Default
228+
--------+--------+-----------+----------+---------
229+
id | bigint | | not null |
230+
Indexes:
231+
"test_replica_identity3_id_key" UNIQUE, btree (id) REPLICA IDENTITY
232+
189233
DROP TABLE test_replica_identity;
234+
DROP TABLE test_replica_identity2;
235+
DROP TABLE test_replica_identity3;
190236
DROP TABLE test_replica_identity_othertable;

‎src/test/regress/sql/replica_identity.sql‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,26 @@ SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass;
7979
ALTERTABLE test_replica_identity REPLICA IDENTITY NOTHING;
8080
SELECT relreplidentFROM pg_classWHEREoid='test_replica_identity'::regclass;
8181

82+
---
83+
-- Test that ALTER TABLE rewrite preserves nondefault replica identity
84+
---
85+
86+
-- constraint variant
87+
CREATETABLEtest_replica_identity2 (idint UNIQUENOT NULL);
88+
ALTERTABLE test_replica_identity2 REPLICA IDENTITY USING INDEX test_replica_identity2_id_key;
89+
\d test_replica_identity2
90+
ALTERTABLE test_replica_identity2 ALTER COLUMN id TYPEbigint;
91+
\d test_replica_identity2
92+
93+
-- straight index variant
94+
CREATETABLEtest_replica_identity3 (idintNOT NULL);
95+
CREATEUNIQUE INDEXtest_replica_identity3_id_keyON test_replica_identity3 (id);
96+
ALTERTABLE test_replica_identity3 REPLICA IDENTITY USING INDEX test_replica_identity3_id_key;
97+
\d test_replica_identity3
98+
ALTERTABLE test_replica_identity3 ALTER COLUMN id TYPEbigint;
99+
\d test_replica_identity3
100+
82101
DROPTABLE test_replica_identity;
102+
DROPTABLE test_replica_identity2;
103+
DROPTABLE test_replica_identity3;
83104
DROPTABLE test_replica_identity_othertable;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp