1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-24 00:23:06 +03:00

Disallow changing NO INHERIT status of a not-null constraint

It makes no sense to add a NO INHERIT not-null constraint to a child
table that already has one in that column inherited from its parent.
Disallow that, and add tests for the relevant cases.

Per complaint from Kyotaro Horiguchi.  I also used part of his proposed
patch.

Co-authored-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Co-authored-by: Álvaro Herrera <alvherre@alvh.no-ip.org>
Discussion: https://postgr.es/m/20230828.161658.1184657435220765047.horikyota.ntt@gmail.com
This commit is contained in:
Alvaro Herrera
2023-08-29 19:19:24 +02:00
parent 952db4979f
commit 9b581c5341
5 changed files with 47 additions and 6 deletions

View File

@@ -669,7 +669,8 @@ extractNotNullColumn(HeapTuple constrTup)
* If no not-null constraint is found for the column, return false.
*/
bool
AdjustNotNullInheritance1(Oid relid, AttrNumber attnum, int count)
AdjustNotNullInheritance1(Oid relid, AttrNumber attnum, int count,
bool is_no_inherit)
{
HeapTuple tup;
@@ -681,6 +682,19 @@ AdjustNotNullInheritance1(Oid relid, AttrNumber attnum, int count)
pg_constraint = table_open(ConstraintRelationId, RowExclusiveLock);
conform = (Form_pg_constraint) GETSTRUCT(tup);
/*
* Don't let the NO INHERIT status change (but don't complain
* unnecessarily.) In the future it might be useful to let an
* inheritable constraint replace a non-inheritable one, but we'd need
* to recurse to children to get it added there.
*/
if (is_no_inherit != conform->connoinherit)
ereport(ERROR,
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("cannot change NO INHERIT status of inherited NOT NULL constraint \"%s\" on relation \"%s\"",
NameStr(conform->conname), get_rel_name(relid)));
if (count > 0)
conform->coninhcount += count;
@@ -691,9 +705,9 @@ AdjustNotNullInheritance1(Oid relid, AttrNumber attnum, int count)
get_rel_name(relid));
/*
* If the constraints are no longer inherited, mark them local. It's
* arguable that we should drop them instead, but it's hard to see
* that being better. The user can drop it manually later.
* If the constraint is no longer inherited, mark it local. It's
* arguable that we should drop it instead, but it's hard to see that
* being better. The user can drop it manually later.
*/
if (conform->coninhcount == 0)
conform->conislocal = true;