Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c370910

Browse files
committed
Fix propagating attnotnull in multiple inheritance
In one of the many strange corner cases of multiple inheritance being used, commit b0e96f3 missed a CommandCounterIncrement() call after updating the attnotnull flag during ALTER TABLE ADD COLUMN, which caused a catalog tuple to be update attempted twice in the same command, giving rise to a "tuple already updated by self" error. Add the missing call to solve that, and a test case that reproduces the scenario. As a (perhaps surprising) secondary effect, this CCI addition triggers another behavior change: when a primary key is added to a parent partitioned table and the column in an existing partition does not have a not-null constraint, we no longer error out. This will probably be a welcome change by some users, and I think it's unlikely that anybody will miss the old behavior. Reported-by: Alexander Lakhin <exclusion@gmail.com> Discussion: http://postgr.es/m/045dec3f-9b3d-aa44-0c99-85f6992306c7@gmail.com
1 parent 6ff21c0 commit c370910

File tree

5 files changed

+35
-1
lines changed

5 files changed

+35
-1
lines changed

src/backend/commands/tablecmds.c

+4
Original file line numberDiff line numberDiff line change
@@ -7757,6 +7757,10 @@ set_attnotnull(List **wqueue, Relation rel, AttrNumber attnum, bool recurse,
77577757
List *children;
77587758
ListCell *lc;
77597759

7760+
/* Make above update visible, for multiple inheritance cases */
7761+
if (retval)
7762+
CommandCounterIncrement();
7763+
77607764
children = find_inheritance_children(RelationGetRelid(rel), lockmode);
77617765
foreach(lc, children)
77627766
{

src/test/regress/expected/constraints.out

+9-1
Original file line numberDiff line numberDiff line change
@@ -1010,13 +1010,21 @@ ERROR: constraint "cnn_parent_pkey" of relation "cnn_parent" does not exist
10101010
create table cnn2_parted(a int primary key) partition by list (a);
10111011
create table cnn2_part1(a int);
10121012
alter table cnn2_parted attach partition cnn2_part1 for values in (1);
1013-
ERROR: primary key column "a" is not marked NOT NULL
1013+
insert into cnn2_part1 values (null);
1014+
ERROR: null value in column "a" of relation "cnn2_part1" violates not-null constraint
1015+
DETAIL: Failing row contains (null).
10141016
drop table cnn2_parted, cnn2_part1;
10151017
create table cnn2_parted(a int not null) partition by list (a);
10161018
create table cnn2_part1(a int primary key);
10171019
alter table cnn2_parted attach partition cnn2_part1 for values in (1);
10181020
ERROR: column "a" in child table must be marked NOT NULL
10191021
drop table cnn2_parted, cnn2_part1;
1022+
create table cnn2_parted(a int) partition by list (a);
1023+
create table cnn_part1 partition of cnn2_parted for values in (1, null);
1024+
insert into cnn_part1 values (null);
1025+
alter table cnn2_parted add primary key (a);
1026+
ERROR: column "a" of relation "cnn_part1" contains null values
1027+
drop table cnn2_parted;
10201028
-- columns in regular and LIKE inheritance should be marked not-nullable
10211029
-- for primary keys, even if those are deferred
10221030
CREATE TABLE notnull_tbl4 (a INTEGER PRIMARY KEY INITIALLY DEFERRED);

src/test/regress/expected/inherit.out

+8
Original file line numberDiff line numberDiff line change
@@ -2177,6 +2177,14 @@ Child tables: cc1,
21772177

21782178
alter table pp1 add primary key (f1);
21792179
-- Leave these tables around, for pg_upgrade testing
2180+
-- Test a not-null addition that must walk down the hierarchy
2181+
CREATE TABLE inh_parent ();
2182+
CREATE TABLE inh_child (i int) INHERITS (inh_parent);
2183+
CREATE TABLE inh_grandchild () INHERITS (inh_parent, inh_child);
2184+
ALTER TABLE inh_parent ADD COLUMN i int NOT NULL;
2185+
NOTICE: merging definition of column "i" for child "inh_child"
2186+
NOTICE: merging definition of column "i" for child "inh_grandchild"
2187+
drop table inh_parent, inh_child, inh_grandchild;
21802188
-- Test the same constraint name for different columns in different parents
21812189
create table inh_parent1(a int constraint nn not null);
21822190
create table inh_parent2(b int constraint nn not null);

src/test/regress/sql/constraints.sql

+7
Original file line numberDiff line numberDiff line change
@@ -661,13 +661,20 @@ ALTER TABLE cnn_parent DROP CONSTRAINT cnn_parent_pkey;
661661
create table cnn2_parted(a int primary key) partition by list (a);
662662
create table cnn2_part1(a int);
663663
alter table cnn2_parted attach partition cnn2_part1 for values in (1);
664+
insert into cnn2_part1 values (null);
664665
drop table cnn2_parted, cnn2_part1;
665666

666667
create table cnn2_parted(a int not null) partition by list (a);
667668
create table cnn2_part1(a int primary key);
668669
alter table cnn2_parted attach partition cnn2_part1 for values in (1);
669670
drop table cnn2_parted, cnn2_part1;
670671

672+
create table cnn2_parted(a int) partition by list (a);
673+
create table cnn_part1 partition of cnn2_parted for values in (1, null);
674+
insert into cnn_part1 values (null);
675+
alter table cnn2_parted add primary key (a);
676+
drop table cnn2_parted;
677+
671678
-- columns in regular and LIKE inheritance should be marked not-nullable
672679
-- for primary keys, even if those are deferred
673680
CREATE TABLE notnull_tbl4 (a INTEGER PRIMARY KEY INITIALLY DEFERRED);

src/test/regress/sql/inherit.sql

+7
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,13 @@ alter table pp1 alter column f1 drop not null;
804804
alter table pp1 add primary key (f1);
805805
-- Leave these tables around, for pg_upgrade testing
806806

807+
-- Test a not-null addition that must walk down the hierarchy
808+
CREATE TABLE inh_parent ();
809+
CREATE TABLE inh_child (i int) INHERITS (inh_parent);
810+
CREATE TABLE inh_grandchild () INHERITS (inh_parent, inh_child);
811+
ALTER TABLE inh_parent ADD COLUMN i int NOT NULL;
812+
drop table inh_parent, inh_child, inh_grandchild;
813+
807814
-- Test the same constraint name for different columns in different parents
808815
create table inh_parent1(a int constraint nn not null);
809816
create table inh_parent2(b int constraint nn not null);

0 commit comments

Comments
 (0)