1 CREATE TABLE test_replica_identity (
6 CONSTRAINT test_replica_identity_unique_defer UNIQUE (keya, keyb) DEFERRABLE,
7 CONSTRAINT test_replica_identity_unique_nondefer UNIQUE (keya, keyb)
9 CREATE TABLE test_replica_identity_othertable (id serial primary key);
10 CREATE TABLE test_replica_identity_t3 (id serial constraint pk primary key deferrable);
11 CREATE INDEX test_replica_identity_keyab ON test_replica_identity (keya, keyb);
12 CREATE UNIQUE INDEX test_replica_identity_keyab_key ON test_replica_identity (keya, keyb);
13 CREATE UNIQUE INDEX test_replica_identity_nonkey ON test_replica_identity (keya, nonkey);
14 CREATE INDEX test_replica_identity_hash ON test_replica_identity USING hash (nonkey);
15 CREATE UNIQUE INDEX test_replica_identity_expr ON test_replica_identity (keya, keyb, (3));
16 CREATE UNIQUE INDEX test_replica_identity_partial ON test_replica_identity (keya, keyb) WHERE keyb != '3';
17 -- default is 'd'/DEFAULT for user created tables
18 SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass;
24 -- but 'none' for system tables
25 SELECT relreplident FROM pg_class WHERE oid = 'pg_class'::regclass;
31 SELECT relreplident FROM pg_class WHERE oid = 'pg_constraint'::regclass;
38 -- Make sure we detect ineligible indexes
41 ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_keyab;
42 ERROR: cannot use non-unique index "test_replica_identity_keyab" as replica identity
43 -- fail, not a candidate key, nullable column
44 ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_nonkey;
45 ERROR: index "test_replica_identity_nonkey" cannot be used as replica identity because column "nonkey" is nullable
46 -- fail, hash indexes cannot do uniqueness
47 ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_hash;
48 ERROR: cannot use non-unique index "test_replica_identity_hash" as replica identity
49 -- fail, expression index
50 ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_expr;
51 ERROR: cannot use expression index "test_replica_identity_expr" as replica identity
52 -- fail, partial index
53 ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_partial;
54 ERROR: cannot use partial index "test_replica_identity_partial" as replica identity
55 -- fail, not our index
56 ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_othertable_pkey;
57 ERROR: "test_replica_identity_othertable_pkey" is not an index for table "test_replica_identity"
59 ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_unique_defer;
60 ERROR: cannot use non-immediate index "test_replica_identity_unique_defer" as replica identity
62 ALTER TABLE test_replica_identity_t3 REPLICA IDENTITY USING INDEX pk;
63 ERROR: cannot use non-immediate index "pk" as replica identity
64 SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass;
71 -- Make sure index cases succeed
73 -- succeed, primary key
74 ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_pkey;
75 SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass;
81 \d test_replica_identity
82 Table "public.test_replica_identity"
83 Column | Type | Collation | Nullable | Default
84 --------+---------+-----------+----------+---------------------------------------------------
85 id | integer | | not null | nextval('test_replica_identity_id_seq'::regclass)
86 keya | text | | not null |
87 keyb | text | | not null |
90 "test_replica_identity_pkey" PRIMARY KEY, btree (id) REPLICA IDENTITY
91 "test_replica_identity_expr" UNIQUE, btree (keya, keyb, (3))
92 "test_replica_identity_hash" hash (nonkey)
93 "test_replica_identity_keyab" btree (keya, keyb)
94 "test_replica_identity_keyab_key" UNIQUE, btree (keya, keyb)
95 "test_replica_identity_nonkey" UNIQUE, btree (keya, nonkey)
96 "test_replica_identity_partial" UNIQUE, btree (keya, keyb) WHERE keyb <> '3'::text
97 "test_replica_identity_unique_defer" UNIQUE CONSTRAINT, btree (keya, keyb) DEFERRABLE
98 "test_replica_identity_unique_nondefer" UNIQUE CONSTRAINT, btree (keya, keyb)
100 -- succeed, nondeferrable unique constraint over nonnullable cols
101 ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_unique_nondefer;
102 -- succeed unique index over nonnullable cols
103 ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_keyab_key;
104 ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_keyab_key;
105 SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass;
111 \d test_replica_identity
112 Table "public.test_replica_identity"
113 Column | Type | Collation | Nullable | Default
114 --------+---------+-----------+----------+---------------------------------------------------
115 id | integer | | not null | nextval('test_replica_identity_id_seq'::regclass)
116 keya | text | | not null |
117 keyb | text | | not null |
120 "test_replica_identity_pkey" PRIMARY KEY, btree (id)
121 "test_replica_identity_expr" UNIQUE, btree (keya, keyb, (3))
122 "test_replica_identity_hash" hash (nonkey)
123 "test_replica_identity_keyab" btree (keya, keyb)
124 "test_replica_identity_keyab_key" UNIQUE, btree (keya, keyb) REPLICA IDENTITY
125 "test_replica_identity_nonkey" UNIQUE, btree (keya, nonkey)
126 "test_replica_identity_partial" UNIQUE, btree (keya, keyb) WHERE keyb <> '3'::text
127 "test_replica_identity_unique_defer" UNIQUE CONSTRAINT, btree (keya, keyb) DEFERRABLE
128 "test_replica_identity_unique_nondefer" UNIQUE CONSTRAINT, btree (keya, keyb)
130 SELECT count(*) FROM pg_index WHERE indrelid = 'test_replica_identity'::regclass AND indisreplident;
137 -- Make sure non index cases work
139 ALTER TABLE test_replica_identity REPLICA IDENTITY DEFAULT;
140 SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass;
146 SELECT count(*) FROM pg_index WHERE indrelid = 'test_replica_identity'::regclass AND indisreplident;
152 ALTER TABLE test_replica_identity REPLICA IDENTITY FULL;
153 SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass;
159 \d+ test_replica_identity
160 Table "public.test_replica_identity"
161 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
162 --------+---------+-----------+----------+---------------------------------------------------+----------+--------------+-------------
163 id | integer | | not null | nextval('test_replica_identity_id_seq'::regclass) | plain | |
164 keya | text | | not null | | extended | |
165 keyb | text | | not null | | extended | |
166 nonkey | text | | | | extended | |
168 "test_replica_identity_pkey" PRIMARY KEY, btree (id)
169 "test_replica_identity_expr" UNIQUE, btree (keya, keyb, (3))
170 "test_replica_identity_hash" hash (nonkey)
171 "test_replica_identity_keyab" btree (keya, keyb)
172 "test_replica_identity_keyab_key" UNIQUE, btree (keya, keyb)
173 "test_replica_identity_nonkey" UNIQUE, btree (keya, nonkey)
174 "test_replica_identity_partial" UNIQUE, btree (keya, keyb) WHERE keyb <> '3'::text
175 "test_replica_identity_unique_defer" UNIQUE CONSTRAINT, btree (keya, keyb) DEFERRABLE
176 "test_replica_identity_unique_nondefer" UNIQUE CONSTRAINT, btree (keya, keyb)
177 Not-null constraints:
178 "test_replica_identity_id_not_null" NOT NULL "id"
179 "test_replica_identity_keya_not_null" NOT NULL "keya"
180 "test_replica_identity_keyb_not_null" NOT NULL "keyb"
181 Replica Identity: FULL
183 ALTER TABLE test_replica_identity REPLICA IDENTITY NOTHING;
184 SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass;
191 -- Test that ALTER TABLE rewrite preserves nondefault replica identity
193 -- constraint variant
194 CREATE TABLE test_replica_identity2 (id int UNIQUE NOT NULL);
195 ALTER TABLE test_replica_identity2 REPLICA IDENTITY USING INDEX test_replica_identity2_id_key;
196 \d test_replica_identity2
197 Table "public.test_replica_identity2"
198 Column | Type | Collation | Nullable | Default
199 --------+---------+-----------+----------+---------
200 id | integer | | not null |
202 "test_replica_identity2_id_key" UNIQUE CONSTRAINT, btree (id) REPLICA IDENTITY
204 ALTER TABLE test_replica_identity2 ALTER COLUMN id TYPE bigint;
205 \d test_replica_identity2
206 Table "public.test_replica_identity2"
207 Column | Type | Collation | Nullable | Default
208 --------+--------+-----------+----------+---------
209 id | bigint | | not null |
211 "test_replica_identity2_id_key" UNIQUE CONSTRAINT, btree (id) REPLICA IDENTITY
213 -- straight index variant
214 CREATE TABLE test_replica_identity3 (id int NOT NULL);
215 CREATE UNIQUE INDEX test_replica_identity3_id_key ON test_replica_identity3 (id);
216 ALTER TABLE test_replica_identity3 REPLICA IDENTITY USING INDEX test_replica_identity3_id_key;
217 \d test_replica_identity3
218 Table "public.test_replica_identity3"
219 Column | Type | Collation | Nullable | Default
220 --------+---------+-----------+----------+---------
221 id | integer | | not null |
223 "test_replica_identity3_id_key" UNIQUE, btree (id) REPLICA IDENTITY
225 ALTER TABLE test_replica_identity3 ALTER COLUMN id TYPE bigint;
226 \d test_replica_identity3
227 Table "public.test_replica_identity3"
228 Column | Type | Collation | Nullable | Default
229 --------+--------+-----------+----------+---------
230 id | bigint | | not null |
232 "test_replica_identity3_id_key" UNIQUE, btree (id) REPLICA IDENTITY
234 -- ALTER TABLE DROP NOT NULL is not allowed for columns part of an index
235 -- used as replica identity.
236 ALTER TABLE test_replica_identity3 ALTER COLUMN id DROP NOT NULL;
237 ERROR: column "id" is in index used as replica identity
238 -- but it's OK when the identity is FULL
239 ALTER TABLE test_replica_identity3 REPLICA IDENTITY FULL;
240 ALTER TABLE test_replica_identity3 ALTER COLUMN id DROP NOT NULL;
242 -- Test that replica identity can be set on an index that's not yet valid.
243 -- (This matches the way pg_dump will try to dump a partitioned table.)
245 CREATE TABLE test_replica_identity4(id integer NOT NULL) PARTITION BY LIST (id);
246 CREATE TABLE test_replica_identity4_1(id integer NOT NULL);
247 ALTER TABLE ONLY test_replica_identity4
248 ATTACH PARTITION test_replica_identity4_1 FOR VALUES IN (1);
249 ALTER TABLE ONLY test_replica_identity4
250 ADD CONSTRAINT test_replica_identity4_pkey PRIMARY KEY (id);
251 ALTER TABLE ONLY test_replica_identity4
252 REPLICA IDENTITY USING INDEX test_replica_identity4_pkey;
253 ALTER TABLE ONLY test_replica_identity4_1
254 ADD CONSTRAINT test_replica_identity4_1_pkey PRIMARY KEY (id);
255 \d+ test_replica_identity4
256 Partitioned table "public.test_replica_identity4"
257 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
258 --------+---------+-----------+----------+---------+---------+--------------+-------------
259 id | integer | | not null | | plain | |
260 Partition key: LIST (id)
262 "test_replica_identity4_pkey" PRIMARY KEY, btree (id) INVALID REPLICA IDENTITY
263 Not-null constraints:
264 "test_replica_identity4_id_not_null" NOT NULL "id"
265 Partitions: test_replica_identity4_1 FOR VALUES IN (1)
267 ALTER INDEX test_replica_identity4_pkey
268 ATTACH PARTITION test_replica_identity4_1_pkey;
269 \d+ test_replica_identity4
270 Partitioned table "public.test_replica_identity4"
271 Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
272 --------+---------+-----------+----------+---------+---------+--------------+-------------
273 id | integer | | not null | | plain | |
274 Partition key: LIST (id)
276 "test_replica_identity4_pkey" PRIMARY KEY, btree (id) REPLICA IDENTITY
277 Not-null constraints:
278 "test_replica_identity4_id_not_null" NOT NULL "id"
279 Partitions: test_replica_identity4_1 FOR VALUES IN (1)
281 -- Dropping the primary key is not allowed if that would leave the replica
282 -- identity as nullable
283 CREATE TABLE test_replica_identity5 (a int not null, b int, c int,
285 CREATE UNIQUE INDEX test_replica_identity5_a_b_key ON test_replica_identity5 (a, b);
286 ALTER TABLE test_replica_identity5 REPLICA IDENTITY USING INDEX test_replica_identity5_a_b_key;
287 ALTER TABLE test_replica_identity5 DROP CONSTRAINT test_replica_identity5_pkey;
288 ALTER TABLE test_replica_identity5 ALTER b SET NOT NULL;
289 ALTER TABLE test_replica_identity5 DROP CONSTRAINT test_replica_identity5_pkey;
290 ERROR: constraint "test_replica_identity5_pkey" of relation "test_replica_identity5" does not exist
291 ALTER TABLE test_replica_identity5 ALTER b DROP NOT NULL;
292 ERROR: column "b" is in index used as replica identity
293 DROP TABLE test_replica_identity;
294 DROP TABLE test_replica_identity2;
295 DROP TABLE test_replica_identity3;
296 DROP TABLE test_replica_identity4;
297 DROP TABLE test_replica_identity5;
298 DROP TABLE test_replica_identity_othertable;
299 DROP TABLE test_replica_identity_t3;