postgres.git / summary / log / commit / refs

commit    5812be7b63cfaf09d982a401ca8f72d150c0f721
Author:   Michael Paquier <michael@paquier.xyz>
Date:     Mon Dec 17 01:36:34 2018 +0000
First released in: 12.0, 9.4.21, 9.5.16, 9.6.12, 10.7, 11.2

    Make constraint rename issue relcache invalidation on target relation
    
    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 | 7 +++++++ src/test/regress/expected/alter_table.out | 22 ++++++++++++++++++++++ src/test/regress/sql/alter_table.sql | 14 ++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 515e1a7f3df..6ff3d46fb29 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -2486,8 +2486,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 address; } diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index 6f459dfadf2..de56f69e16f 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -342,6 +342,28 @@ ALTER TABLE IF EXISTS constraint_not_exist RENAME CONSTRAINT con3 TO con3foo; -- NOTICE: relation "constraint_not_exist" does not exist, skipping 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); diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql index 358081b3c9b..96b95e013ae 100644 --- a/src/test/regress/sql/alter_table.sql +++ b/src/test/regress/sql/alter_table.sql @@ -251,6 +251,20 @@ DROP TABLE constraint_rename_test; ALTER TABLE IF EXISTS constraint_not_exist RENAME CONSTRAINT con3 TO con3foo; -- ok 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); [parent: 35efdd7fb81d]