From 89ae829386d62a2c9cb5b8f9c827fa805f39d327 Mon Sep 17 00:00:00 2001 From: jian he Date: Mon, 7 Apr 2025 20:40:15 +0800 Subject: [PATCH v8 3/3] not null not valid miscellous fix --- src/backend/access/common/tupdesc.c | 10 ++++++++-- src/backend/commands/tablecmds.c | 15 ++++++++++++++- src/backend/optimizer/util/plancat.c | 1 + src/backend/utils/cache/relcache.c | 2 +- src/test/regress/expected/constraints.out | 2 ++ src/test/regress/sql/constraints.sql | 3 +++ 6 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index 5831788cbff..8e4dcd412fa 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -22,6 +22,7 @@ #include "access/htup_details.h" #include "access/toast_compression.h" #include "access/tupdesc_details.h" +#include "catalog/catalog.h" #include "catalog/pg_collation.h" #include "catalog/pg_type.h" #include "common/hashfn.h" @@ -74,8 +75,13 @@ populate_compact_attribute_internal(Form_pg_attribute src, dst->atthasmissing = src->atthasmissing; dst->attisdropped = src->attisdropped; dst->attgenerated = (src->attgenerated != '\0'); - dst->attnullability = !src->attnotnull ? ATTNULLABLE_UNRESTRICTED : - ATTNULLABLE_UNKNOWN; + + if (IsCatalogRelationOid(src->attrelid)) + dst->attnullability = !src->attnotnull ? ATTNULLABLE_UNRESTRICTED : + ATTNULLABLE_VALID; + else + dst->attnullability = !src->attnotnull ? ATTNULLABLE_UNRESTRICTED : + ATTNULLABLE_UNKNOWN; switch (src->attalign) { diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 91905533da7..6be6609a747 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -6224,7 +6224,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap) { CompactAttribute *attr = TupleDescCompactAttr(newTupDesc, i); - if (attr->attnullability != ATTNULLABLE_UNRESTRICTED && + if (attr->attnullability == ATTNULLABLE_VALID && !attr->attisdropped) { Form_pg_attribute wholeatt = TupleDescAttr(newTupDesc, i); @@ -7832,6 +7832,7 @@ set_attnotnull(List **wqueue, Relation rel, AttrNumber attnum, bool is_valid, bool queue_validation) { Form_pg_attribute attr; + CompactAttribute *thisatt; Assert(!queue_validation || wqueue); @@ -7857,6 +7858,9 @@ set_attnotnull(List **wqueue, Relation rel, AttrNumber attnum, elog(ERROR, "cache lookup failed for attribute %d of relation %u", attnum, RelationGetRelid(rel)); + thisatt = TupleDescCompactAttr(RelationGetDescr(rel), attnum - 1); + thisatt->attnullability = ATTNULLABLE_VALID; + attr = (Form_pg_attribute) GETSTRUCT(tuple); attr->attnotnull = true; @@ -7880,6 +7884,15 @@ set_attnotnull(List **wqueue, Relation rel, AttrNumber attnum, table_close(attr_rel, RowExclusiveLock); heap_freetuple(tuple); } + else + { + thisatt = TupleDescCompactAttr(RelationGetDescr(rel), attnum - 1); + + if(is_valid) + thisatt->attnullability = ATTNULLABLE_VALID; + else + thisatt->attnullability = ATTNULLABLE_INVALID; + } } /* diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 881747e71d4..316b51b724f 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -176,6 +176,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, for (int i = 0; i < relation->rd_att->natts; i++) { CompactAttribute *attr = TupleDescCompactAttr(relation->rd_att, i); + Assert(attr->attnullability != ATTNULLABLE_UNKNOWN); if (attr->attnullability == ATTNULLABLE_VALID) { diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 4128cfa8314..483f19711f0 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -704,7 +704,7 @@ RelationBuildTupleDesc(Relation relation) * CompactAttribute array. In catalog relations however, any not-null * constraint is necessarily valid. */ - for (int i = 0; i < relation->rd_rel->relnatts - 1; i++) + for (int i = 0; i < relation->rd_rel->relnatts; i++) { CompactAttribute *attr; diff --git a/src/test/regress/expected/constraints.out b/src/test/regress/expected/constraints.out index d8547a9bc81..1346134e23c 100644 --- a/src/test/regress/expected/constraints.out +++ b/src/test/regress/expected/constraints.out @@ -1441,6 +1441,8 @@ EXECUTE get_nnconstraint_info('{notnull_tbl1_child2}'); notnull_tbl1_child2 | notnull_tbl1_child2_a_not_null | f | t | 1 (1 row) +--table rewrite won't validate invalid constraint +ALTER TABLE notnull_tbl1 ADD column d float8 default random(); -- VALIDATE CONSTRAINT scans the table ALTER TABLE notnull_tbl1 VALIDATE CONSTRAINT nn; -- error, nulls exist ERROR: column "a" of relation "notnull_tbl1" contains null values diff --git a/src/test/regress/sql/constraints.sql b/src/test/regress/sql/constraints.sql index 8f199c7ba34..0f2fe3e6e2d 100644 --- a/src/test/regress/sql/constraints.sql +++ b/src/test/regress/sql/constraints.sql @@ -849,6 +849,9 @@ ALTER TABLE notnull_tbl1_child2 ADD NOT NULL a NOT VALID; ALTER TABLE notnull_tbl1_child2 INHERIT notnull_tbl1; EXECUTE get_nnconstraint_info('{notnull_tbl1_child2}'); +--table rewrite won't validate invalid constraint +ALTER TABLE notnull_tbl1 ADD column d float8 default random(); + -- VALIDATE CONSTRAINT scans the table ALTER TABLE notnull_tbl1 VALIDATE CONSTRAINT nn; -- error, nulls exist UPDATE notnull_tbl1 SET a = 100 WHERE b = 1; -- 2.34.1