8000 Fix possible crash in ALTER TABLE ... REPLICA IDENTITY USING INDEX. · prmdeveloper/postgres@8eed31f · GitHub
[go: up one dir, main page]

Skip to content

Commit 8eed31f

Browse files
committed
Fix possible crash in ALTER TABLE ... REPLICA IDENTITY USING INDEX.
Careless coding added by commit 07cacba could result in a crash or a bizarre error message if someone tried to select an index on the OID column as the replica identity index for a table. Back-patch to 9.4 where the feature was introduced. Discussion: CAKJS1f8TQYgTRDyF1_u9PVCKWRWz+DkieH=U7954HeHVPJKaKg@mail.gmail.com David Rowley
1 parent 0479ecc commit 8eed31f

File tree

3 files changed

+27
-6
lines changed

3 files changed

+27
-6
lines changed

src/backend/commands/tablecmds.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10569,10 +10569,20 @@ ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode
1056910569
int16 attno = indexRel->rd_index->indkey.values[key];
1057010570
Form_pg_attribute attr;
1057110571

10572-
/* Of the system columns, only oid is indexable. */
10573-
if (attno <= 0 && attno != ObjectIdAttributeNumber)
10574-
elog(ERROR, "internal column %u in unique index \"%s\"",
10575-
attno, RelationGetRelationName(indexRel));
10572+
/* Allow OID column to be indexed; it's certainly not nullable */
10573+
if (attno == ObjectIdAttributeNumber)
10574+
continue;
10575+
10576+
/*
10577+
* Reject any other system columns. (Going forward, we'll disallow
10578+
* indexes containing such columns in the first place, but they might
10579+
* exist in older branches.)
10580+
*/
10581+
if (attno <= 0)
10582+
ereport(ERROR,
10583+
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
10584+
errmsg("index \"%s\" cannot be used as replica identity because column %d is a system column",
10585+
RelationGetRelationName(indexRel), attno)));
1057610586

1057710587
attr = rel->rd_att->attrs[attno - 1];
1057810588
if (!attr->attnotnull)

src/test/regress/expected/replica_identity.out

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ CREATE TABLE test_replica_identity (
55
nonkey text,
66
CONSTRAINT test_replica_identity_unique_defer UNIQUE (keya, keyb) DEFERRABLE,
77
CONSTRAINT test_replica_identity_unique_nondefer UNIQUE (keya, keyb)
8-
);
8+
) WITH OIDS;
99
CREATE TABLE test_replica_identity_othertable (id serial primary key);
1010
CREATE INDEX test_replica_identity_keyab ON test_replica_identity (keya, keyb);
1111
CREATE UNIQUE INDEX test_replica_identity_keyab_key ON test_replica_identity (keya, keyb);
12+
CREATE UNIQUE INDEX test_replica_identity_oid_idx ON test_replica_identity (oid);
1213
CREATE UNIQUE INDEX test_replica_identity_nonkey ON test_replica_identity (keya, nonkey);
1314
CREATE INDEX test_replica_identity_hash ON test_replica_identity USING hash (nonkey);
1415
CREATE UNIQUE INDEX test_replica_identity_expr ON test_replica_identity (keya, keyb, (3));
@@ -87,12 +88,15 @@ Indexes:
8788
"test_replica_identity_expr" UNIQUE, btree (keya, keyb, (3))
8889
"test_replica_identity_keyab_key" UNIQUE, btree (keya, keyb)
8990
"test_replica_identity_nonkey" UNIQUE, btree (keya, nonkey)
91+
"test_replica_identity_oid_idx" UNIQUE, btree (oid)
9092
"test_replica_identity_partial" UNIQUE, btree (keya, keyb) WHERE keyb <> '3'::text
9193
"test_replica_identity_unique_defer" UNIQUE CONSTRAINT, btree (keya, keyb) DEFERRABLE
9294
"test_replica_identity_unique_nondefer" UNIQUE CONSTRAINT, btree (keya, keyb)
9395
"test_replica_identity_hash" hash (nonkey)
9496
"test_replica_identity_keyab" btree (keya, keyb)
9597

98+
-- succeed, oid unique index
99+
ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_oid_idx;
96100
-- succeed, nondeferrable unique constraint over nonullable cols
97101
ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_unique_nondefer;
98102
-- succeed unique index over nonnullable cols
@@ -117,6 +121,7 @@ Indexes:
117121
"test_replica_identity_expr" UNIQUE, btree (keya, keyb, (3))
118122
"test_replica_identity_keyab_key" UNIQUE, btree (keya, keyb) REPLICA IDENTITY
119123
"test_replica_identity_nonkey" UNIQUE, btree (keya, nonkey)
124+
"test_replica_identity_oid_idx" UNIQUE, btree (oid)
120125
"test_replica_identity_partial" UNIQUE, btree (keya, keyb) WHERE keyb <> '3'::text
121126
"test_replica_identity_unique_defer" UNIQUE CONSTRAINT, btree (keya, keyb) DEFERRABLE
122127
"test_replica_identity_unique_nondefer" UNIQUE CONSTRAINT, btree (keya, keyb)
@@ -165,12 +170,14 @@ Indexes:
165170
"test_replica_identity_expr" UNIQUE, btree (keya, keyb, (3))
166171
"test_replica_identity_keyab_key" UNIQUE, btree (keya, keyb)
167172
"test_replica_identity_nonkey" UNIQUE, btree (keya, nonkey)
173+
"test_replica_identity_oid_idx" UNIQUE, btree (oid)
168174
"test_replica_identity_partial" UNIQUE, btree (keya, keyb) WHERE keyb <> '3'::text
169175
"test_replica_identity_unique_defer" UNIQUE CONSTRAINT, btree (keya, keyb) DEFERRABLE
170176
"test_replica_identity_unique_nondefer" UNIQUE CONSTRAINT, btree (keya, keyb)
171177
"test_replica_identity_hash" hash (nonkey)
172178
"test_replica_identity_keyab" btree (keya, keyb)
173179
Replica Identity: FULL
180+
Has OIDs: yes
174181

175182
ALTER TABLE test_replica_identity REPLICA IDENTITY NOTHING;
176183
SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass;

src/test/regress/sql/replica_identity.sql

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ CREATE TABLE test_replica_identity (
55
nonkey text,
66
CONSTRAINT test_replica_identity_unique_defer UNIQUE (keya, keyb) DEFERRABLE,
77
CONSTRAINT test_replica_identity_unique_nondefer UNIQUE (keya, keyb)
8-
);
8+
) WITH OIDS;
99

1010
CREATE TABLE test_replica_identity_othertable (id serial primary key);
1111

1212
CREATE INDEX test_replica_identity_keyab ON test_replica_identity (keya, keyb);
1313
CREATE UNIQUE INDEX test_replica_identity_keyab_key ON test_replica_identity (keya, keyb);
14+
CREATE UNIQUE INDEX test_replica_identity_oid_idx ON test_replica_identity (oid);
1415
CREATE UNIQUE INDEX test_replica_identity_nonkey ON test_replica_identity (keya, nonkey);
1516
CREATE INDEX test_replica_identity_hash ON test_replica_identity USING hash (nonkey);
1617
CREATE UNIQUE INDEX test_replica_identity_expr ON test_replica_identity (keya, keyb, (3));
@@ -52,6 +53,9 @@ ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_iden
5253
SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass;
5354
\d test_replica_identity
5455

56+
-- succeed, oid unique index
57+
ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_oid_idx;
58+
5559
-- succeed, nondeferrable unique constraint over nonullable cols
5660
ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_unique_nondefer;
5761

0 commit comments

Comments
 (0)
0