Thanks to visit codestin.com
Credit goes to github.com

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 <[email protected]> Discussion: http://postgr.es/m/[email protected]
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)