Skip to content

Commit d0ec2dd

Browse files
committed
Fix not-null constraint test
When a partitioned table has a primary key, trying to find the corresponding not-null constraint for that column would come up empty, causing code that's trying to check said not-null constraint to crash. Fix by only running the check when the not-null constraint exists. Reported-by: Alexander Lakhin <exclusion@gmail.com> Discussion: https://postgr.es/m/d57b4a69-7394-3146-5976-9a1ef27e7972@gmail.com
1 parent e09d763 commit d0ec2dd

File tree

3 files changed

+41
-7
lines changed

3 files changed

+41
-7
lines changed

src/backend/commands/tablecmds.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15746,21 +15746,23 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel)
1574615746
attributeName)));
1574715747

1574815748
/*
15749-
* Check child doesn't discard NOT NULL property. (Other
15750-
* constraints are checked elsewhere.) However, if the constraint
15751-
* is NO INHERIT in the parent, this is allowed.
15749+
* If the parent has a not-null constraint that's not NO INHERIT,
15750+
* make sure the child has one too.
15751+
*
15752+
* Other constraints are checked elsewhere.
1575215753
*/
1575315754
if (attribute->attnotnull && !childatt->attnotnull)
1575415755
{
1575515756
HeapTuple contup;
1575615757

1575715758
contup = findNotNullConstraintAttnum(RelationGetRelid(parent_rel),
1575815759
attribute->attnum);
15759-
if (!((Form_pg_constraint) GETSTRUCT(contup))->connoinherit)
15760+
if (HeapTupleIsValid(contup) &&
15761+
!((Form_pg_constraint) GETSTRUCT(contup))->connoinherit)
1576015762
ereport(ERROR,
15761-
(errcode(ERRCODE_DATATYPE_MISMATCH),
15762-
errmsg("column \"%s\" in child table must be marked NOT NULL",
15763-
attributeName)));
15763+
errcode(ERRCODE_DATATYPE_MISMATCH),
15764+
errmsg("column \"%s\" in child table must be marked NOT NULL",
15765+
attributeName));
1576415766
}
1576515767

1576615768
/*
@@ -15981,10 +15983,20 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
1598115983
systable_endscan(child_scan);
1598215984

1598315985
if (!found)
15986+
{
15987+
if (parent_con->contype == CONSTRAINT_NOTNULL)
15988+
ereport(ERROR,
15989+
errcode(ERRCODE_DATATYPE_MISMATCH),
15990+
errmsg("column \"%s\" in child table must be marked NOT NULL",
15991+
get_attname(parent_relid,
15992+
extractNotNullColumn(parent_tuple),
15993+
false)));
15994+
1598415995
ereport(ERROR,
1598515996
(errcode(ERRCODE_DATATYPE_MISMATCH),
1598615997
errmsg("child table is missing constraint \"%s\"",
1598715998
NameStr(parent_con->conname))));
15999+
}
1598816000
}
1598916001

1599016002
systable_endscan(parent_scan);

src/test/regress/expected/constraints.out

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,17 @@ Inherits: cnn_grandchild,
10061006
ALTER TABLE cnn_parent DROP CONSTRAINT cnn_parent_pkey;
10071007
ERROR: constraint "cnn_parent_pkey" of relation "cnn_parent" does not exist
10081008
-- keeps these tables around, for pg_upgrade testing
1009+
-- ensure columns in partitions are marked not-null
1010+
create table cnn2_parted(a int primary key) partition by list (a);
1011+
create table cnn2_part1(a int);
1012+
alter table cnn2_parted attach partition cnn2_part1 for values in (1);
1013+
ERROR: primary key column "a" is not marked NOT NULL
1014+
drop table cnn2_parted, cnn2_part1;
1015+
create table cnn2_parted(a int not null) partition by list (a);
1016+
create table cnn2_part1(a int primary key);
1017+
alter table cnn2_parted attach partition cnn2_part1 for values in (1);
1018+
ERROR: column "a" in child table must be marked NOT NULL
1019+
drop table cnn2_parted, cnn2_part1;
10091020
-- Comments
10101021
-- Setup a low-level role to enforce non-superuser checks.
10111022
CREATE ROLE regress_constraint_comments;

src/test/regress/sql/constraints.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,17 @@ ALTER TABLE cnn_parent ADD PRIMARY KEY USING INDEX b_uq;
657657
ALTER TABLE cnn_parent DROP CONSTRAINT cnn_parent_pkey;
658658
-- keeps these tables around, for pg_upgrade testing
659659

660+
-- ensure columns in partitions are marked not-null
661+
create table cnn2_parted(a int primary key) partition by list (a);
662+
create table cnn2_part1(a int);
663+
alter table cnn2_parted attach partition cnn2_part1 for values in (1);
664+
drop table cnn2_parted, cnn2_part1;
665+
666+
create table cnn2_parted(a int not null) partition by list (a);
667+
create table cnn2_part1(a int primary key);
668+
alter table cnn2_parted attach partition cnn2_part1 for values in (1);
669+
drop table cnn2_parted, cnn2_part1;
670+
660671

661672
-- Comments
662673
-- Setup a low-level role to enforce non-superuser checks.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy