Skip to content

Commit d9ffc27

Browse files
committed
Prevent setting a column as identity if its not-null constraint is invalid
We don't allow null values to appear in identity-generated columns in other ways, so we shouldn't let unvalidated not-null constraints do it either. Oversight in commit a379061. Author: jian he <jian.universality@gmail.com> Backpatch-through: 18 Discussion: https://postgr.es/m/CACJufxGQM_+vZoYJMaRoZfNyV=L2jxosjv_0TLAScbuLJXWRfQ@mail.gmail.com
1 parent 6c3b1df commit d9ffc27

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

src/backend/commands/tablecmds.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8279,6 +8279,31 @@ ATExecAddIdentity(Relation rel, const char *colName,
82798279
errmsg("column \"%s\" of relation \"%s\" must be declared NOT NULL before identity can be added",
82808280
colName, RelationGetRelationName(rel))));
82818281

8282+
/*
8283+
* On the other hand, if a not-null constraint exists, then verify that
8284+
* it's compatible.
8285+
*/
8286+
if (attTup->attnotnull)
8287+
{
8288+
HeapTuple contup;
8289+
Form_pg_constraint conForm;
8290+
8291+
contup = findNotNullConstraintAttnum(RelationGetRelid(rel),
8292+
attnum);
8293+
if (!HeapTupleIsValid(contup))
8294+
elog(ERROR, "cache lookup failed for not-null constraint on column \"%s\" of relation \"%s\"",
8295+
colName, RelationGetRelationName(rel));
8296+
8297+
conForm = (Form_pg_constraint) GETSTRUCT(contup);
8298+
if (!conForm->convalidated)
8299+
ereport(ERROR,
8300+
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8301+
errmsg("incompatible NOT VALID constraint \"%s\" on relation \"%s\"",
8302+
NameStr(conForm->conname), RelationGetRelationName(rel)),
8303+
errhint("You might need to validate it using %s.",
8304+
"ALTER TABLE ... VALIDATE CONSTRAINT"));
8305+
}
8306+
82828307
if (attTup->attidentity)
82838308
ereport(ERROR,
82848309
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),

src/test/regress/expected/constraints.out

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,10 @@ ALTER TABLE notnull_tbl1 ADD PRIMARY KEY (a);
14041404
ERROR: cannot create primary key on column "a"
14051405
DETAIL: The constraint "nn" on column "a" of table "notnull_tbl1", marked NOT VALID, is incompatible with a primary key.
14061406
HINT: You might need to validate it using ALTER TABLE ... VALIDATE CONSTRAINT.
1407+
-- cannot set column as generated-as-identity if it has an invalid not-null
1408+
ALTER TABLE notnull_tbl1 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
1409+
ERROR: incompatible NOT VALID constraint "nn" on relation "notnull_tbl1"
1410+
HINT: You might need to validate it using ALTER TABLE ... VALIDATE CONSTRAINT.
14071411
-- ALTER column SET NOT NULL validates an invalid constraint (but this fails
14081412
-- because of rows with null values)
14091413
ALTER TABLE notnull_tbl1 ALTER a SET NOT NULL;

src/test/regress/sql/constraints.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,9 @@ ALTER TABLE notnull_tbl1 ADD CONSTRAINT nn NOT NULL a;
832832
-- cannot add primary key on a column with an invalid not-null
833833
ALTER TABLE notnull_tbl1 ADD PRIMARY KEY (a);
834834

835+
-- cannot set column as generated-as-identity if it has an invalid not-null
836+
ALTER TABLE notnull_tbl1 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
837+
835838
-- ALTER column SET NOT NULL validates an invalid constraint (but this fails
836839
-- because of rows with null values)
837840
ALTER TABLE notnull_tbl1 ALTER a SET NOT NULL;

0 commit comments

Comments
 (0)