I thought SearchSysCacheCopyAttNum is expensive. Relation->rd_att is enough for checking attnotnull.
What do you think of the following refactoring of set_attnotnull? static void set_attnotnull(List **wqueue, Relation rel, AttrNumber attnum, LOCKMODE lockmode) { Oid reloid = RelationGetRelid(rel); HeapTuple tuple; Form_pg_attribute attForm; Form_pg_attribute attr; TupleDesc tupleDesc; CheckAlterTableIsSafe(rel); tupleDesc = RelationGetDescr(rel); attr = TupleDescAttr(tupleDesc, attnum - 1); if (attr->attisdropped) return; if (!attr->attnotnull) { Relation attr_rel; attr_rel = table_open(AttributeRelationId, RowExclusiveLock); tuple = SearchSysCacheCopyAttNum(reloid, attnum); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for attribute %d of relation %u", attnum, reloid); attForm = (Form_pg_attribute) GETSTRUCT(tuple); attForm->attnotnull = true; CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple); if (wqueue && !NotNullImpliedByRelConstraints(rel, attForm)) { AlteredTableInfo *tab; tab = ATGetQueueEntry(wqueue, rel); tab->verify_new_notnull = true; } CommandCounterIncrement(); heap_freetuple(tuple); table_close(attr_rel, RowExclusiveLock); } }