* update its catalog status and we're done.
*/
if (AdjustNotNullInheritance1(RelationGetRelid(rel), colnum,
- cdef->inhcount))
+ cdef->inhcount, cdef->is_no_inherit))
continue;
/*
if (old->attnum == attnum)
{
+ /*
+ * If we get a constraint from the parent, having a local NO
+ * INHERIT one doesn't work.
+ */
+ if (constr->is_no_inherit)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("cannot define not-null constraint on column \"%s\" with NO INHERIT",
+ strVal(linitial(constr->keys))),
+ errdetail("The column has an inherited not-null constraint.")));
+
inhcount++;
old_notnulls = foreach_delete_current(old_notnulls, lc2);
}
* 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;
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;
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;
extern HeapTuple findNotNullConstraintAttnum(Oid relid, AttrNumber attnum);
extern HeapTuple findNotNullConstraint(Oid relid, const char *colname);
extern AttrNumber extractNotNullColumn(HeapTuple constrTup);
-extern bool AdjustNotNullInheritance1(Oid relid, AttrNumber attnum, int count);
+extern bool AdjustNotNullInheritance1(Oid relid, AttrNumber attnum, int count,
+ bool is_no_inherit);
extern void AdjustNotNullInheritance(Oid relid, Bitmapset *columns, int count);
extern List *RelationGetNotNullConstraints(Oid relid, bool cooked);
Inherits: pp1,
cc1
+-- cannot create table with inconsistent NO INHERIT constraint
+create table cc3 (a2 int not null no inherit) inherits (cc1);
+NOTICE: moving and merging column "a2" with inherited definition
+DETAIL: User-specified column moved to the position of the inherited column.
+ERROR: cannot define not-null constraint on column "a2" with NO INHERIT
+DETAIL: The column has an inherited not-null constraint.
+-- change NO INHERIT status of inherited constraint: no dice, it's inherited
+alter table cc2 add not null a2 no inherit;
+ERROR: cannot change NO INHERIT status of inherited NOT NULL constraint "nn" on relation "cc2"
-- remove constraint from cc2: no dice, it's inherited
alter table cc2 alter column a2 drop not null;
ERROR: cannot drop inherited constraint "nn" of relation "cc2"
\d+ cc1
\d+ cc2
+-- cannot create table with inconsistent NO INHERIT constraint
+create table cc3 (a2 int not null no inherit) inherits (cc1);
+
+-- change NO INHERIT status of inherited constraint: no dice, it's inherited
+alter table cc2 add not null a2 no inherit;
+
-- remove constraint from cc2: no dice, it's inherited
alter table cc2 alter column a2 drop not null;