aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2023-09-01 19:49:20 +0200
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2023-09-01 19:49:20 +0200
commitd0ec2ddbe088f6da35444fad688a62eae4fbd840 (patch)
tree188c43938b4bef294032086a6029ffa4841d52d6
parente09d763e25dccc40695bc824ddda9abea791d66f (diff)
downloadpostgresql-d0ec2ddbe088f6da35444fad688a62eae4fbd840.tar.gz
postgresql-d0ec2ddbe088f6da35444fad688a62eae4fbd840.zip
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
-rw-r--r--src/backend/commands/tablecmds.c26
-rw-r--r--src/test/regress/expected/constraints.out11
-rw-r--r--src/test/regress/sql/constraints.sql11
3 files changed, 41 insertions, 7 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 03397746724..47c556669f3 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -15746,9 +15746,10 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel)
attributeName)));
/*
- * Check child doesn't discard NOT NULL property. (Other
- * constraints are checked elsewhere.) However, if the constraint
- * is NO INHERIT in the parent, this is allowed.
+ * If the parent has a not-null constraint that's not NO INHERIT,
+ * make sure the child has one too.
+ *
+ * Other constraints are checked elsewhere.
*/
if (attribute->attnotnull && !childatt->attnotnull)
{
@@ -15756,11 +15757,12 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel)
contup = findNotNullConstraintAttnum(RelationGetRelid(parent_rel),
attribute->attnum);
- if (!((Form_pg_constraint) GETSTRUCT(contup))->connoinherit)
+ if (HeapTupleIsValid(contup) &&
+ !((Form_pg_constraint) GETSTRUCT(contup))->connoinherit)
ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("column \"%s\" in child table must be marked NOT NULL",
- attributeName)));
+ errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("column \"%s\" in child table must be marked NOT NULL",
+ attributeName));
}
/*
@@ -15981,10 +15983,20 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
systable_endscan(child_scan);
if (!found)
+ {
+ if (parent_con->contype == CONSTRAINT_NOTNULL)
+ ereport(ERROR,
+ errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("column \"%s\" in child table must be marked NOT NULL",
+ get_attname(parent_relid,
+ extractNotNullColumn(parent_tuple),
+ false)));
+
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("child table is missing constraint \"%s\"",
NameStr(parent_con->conname))));
+ }
}
systable_endscan(parent_scan);
diff --git a/src/test/regress/expected/constraints.out b/src/test/regress/expected/constraints.out
index b7de50ad6a6..5b068477bf8 100644
--- a/src/test/regress/expected/constraints.out
+++ b/src/test/regress/expected/constraints.out
@@ -1006,6 +1006,17 @@ Inherits: cnn_grandchild,
ALTER TABLE cnn_parent DROP CONSTRAINT cnn_parent_pkey;
ERROR: constraint "cnn_parent_pkey" of relation "cnn_parent" does not exist
-- keeps these tables around, for pg_upgrade testing
+-- ensure columns in partitions are marked not-null
+create table cnn2_parted(a int primary key) partition by list (a);
+create table cnn2_part1(a int);
+alter table cnn2_parted attach partition cnn2_part1 for values in (1);
+ERROR: primary key column "a" is not marked NOT NULL
+drop table cnn2_parted, cnn2_part1;
+create table cnn2_parted(a int not null) partition by list (a);
+create table cnn2_part1(a int primary key);
+alter table cnn2_parted attach partition cnn2_part1 for values in (1);
+ERROR: column "a" in child table must be marked NOT NULL
+drop table cnn2_parted, cnn2_part1;
-- Comments
-- Setup a low-level role to enforce non-superuser checks.
CREATE ROLE regress_constraint_comments;
diff --git a/src/test/regress/sql/constraints.sql b/src/test/regress/sql/constraints.sql
index 782699a4377..a7d96e98f58 100644
--- a/src/test/regress/sql/constraints.sql
+++ b/src/test/regress/sql/constraints.sql
@@ -657,6 +657,17 @@ ALTER TABLE cnn_parent ADD PRIMARY KEY USING INDEX b_uq;
ALTER TABLE cnn_parent DROP CONSTRAINT cnn_parent_pkey;
-- keeps these tables around, for pg_upgrade testing
+-- ensure columns in partitions are marked not-null
+create table cnn2_parted(a int primary key) partition by list (a);
+create table cnn2_part1(a int);
+alter table cnn2_parted attach partition cnn2_part1 for values in (1);
+drop table cnn2_parted, cnn2_part1;
+
+create table cnn2_parted(a int not null) partition by list (a);
+create table cnn2_part1(a int primary key);
+alter table cnn2_parted attach partition cnn2_part1 for values in (1);
+drop table cnn2_parted, cnn2_part1;
+
-- Comments
-- Setup a low-level role to enforce non-superuser checks.