]> granicus.if.org Git - postgresql/commitdiff
Make constraint rename issue relcache invalidation on target relation
authorMichael Paquier <michael@paquier.xyz>
Mon, 17 Dec 2018 01:37:24 +0000 (10:37 +0900)
committerMichael Paquier <michael@paquier.xyz>
Mon, 17 Dec 2018 01:37:24 +0000 (10:37 +0900)
When a constraint gets renamed, it may have associated with it a target
relation (for example domain constraints don't have one).  Not
invalidating the target relation cache when issuing the renaming can
result in issues with subsequent commands that refer to the old
constraint name using the relation cache, causing various failures.  One
pattern spotted was using CREATE TABLE LIKE after a constraint
renaming.

Reported-by: Stuart <sfbarbee@gmail.com>
Author: Amit Langote
Reviewed-by: Michael Paquier
Discussion: https://postgr.es/m/2047094.V130LYfLq4@station53.ousa.org

src/backend/commands/tablecmds.c
src/test/regress/expected/alter_table.out
src/test/regress/sql/alter_table.sql

index 6bbd906c0b71e3b94be268006d5580072b7d104b..8c2f650a88a977f0f136c81e8e2762f0e9d9f96c 100644 (file)
@@ -2428,8 +2428,15 @@ rename_constraint_internal(Oid myrelid,
        ReleaseSysCache(tuple);
 
        if (targetrelation)
+       {
                relation_close(targetrelation, NoLock); /* close rel but keep lock */
 
+               /*
+                * Invalidate relcache so as others can see the new constraint name.
+                */
+               CacheInvalidateRelcache(targetrelation);
+       }
+
        return constraintOid;
 }
 
index b9f9cf58e09c9d7f8f48fa8fd07d7ca72f7e5925..bd63075139c7dddf57facffb5a9374e434323199 100644 (file)
@@ -340,6 +340,28 @@ DROP TABLE constraint_rename_test2;
 DROP TABLE constraint_rename_test;
 ALTER TABLE IF EXISTS constraint_rename_test ADD CONSTRAINT con4 UNIQUE (a);
 NOTICE:  relation "constraint_rename_test" does not exist, skipping
+-- renaming constraints with cache reset of target relation
+CREATE TABLE constraint_rename_cache (a int,
+  CONSTRAINT chk_a CHECK (a > 0),
+  PRIMARY KEY (a));
+ALTER TABLE constraint_rename_cache
+  RENAME CONSTRAINT chk_a TO chk_a_new;
+ALTER TABLE constraint_rename_cache
+  RENAME CONSTRAINT constraint_rename_cache_pkey TO chk_a_gt_zero;
+CREATE TABLE like_constraint_rename_cache
+  (LIKE constraint_rename_cache INCLUDING ALL);
+\d like_constraint_rename_cache
+Table "public.like_constraint_rename_cache"
+ Column |  Type   | Modifiers 
+--------+---------+-----------
+ a      | integer | not null
+Indexes:
+    "like_constraint_rename_cache_pkey" PRIMARY KEY, btree (a)
+Check constraints:
+    "chk_a_new" CHECK (a > 0)
+
+DROP TABLE constraint_rename_cache;
+DROP TABLE like_constraint_rename_cache;
 -- FOREIGN KEY CONSTRAINT adding TEST
 CREATE TABLE tmp2 (a int primary key);
 CREATE TABLE tmp3 (a int, b int);
index 7e29b4855c2fdf9153c875e10f62be6ed56fd927..4ccba34409e47a15c36902c8252a47e5043a6dfa 100644 (file)
@@ -250,6 +250,20 @@ DROP TABLE constraint_rename_test2;
 DROP TABLE constraint_rename_test;
 ALTER TABLE IF EXISTS constraint_rename_test ADD CONSTRAINT con4 UNIQUE (a);
 
+-- renaming constraints with cache reset of target relation
+CREATE TABLE constraint_rename_cache (a int,
+  CONSTRAINT chk_a CHECK (a > 0),
+  PRIMARY KEY (a));
+ALTER TABLE constraint_rename_cache
+  RENAME CONSTRAINT chk_a TO chk_a_new;
+ALTER TABLE constraint_rename_cache
+  RENAME CONSTRAINT constraint_rename_cache_pkey TO chk_a_gt_zero;
+CREATE TABLE like_constraint_rename_cache
+  (LIKE constraint_rename_cache INCLUDING ALL);
+\d like_constraint_rename_cache
+DROP TABLE constraint_rename_cache;
+DROP TABLE like_constraint_rename_cache;
+
 -- FOREIGN KEY CONSTRAINT adding TEST
 
 CREATE TABLE tmp2 (a int primary key);