Hi, I think it's probably not relevant, but it confused me for a moment that RelationBuildTupleDesc() might set constr->has_generated_stored to true, but then throw away the constraint at the end, because nothing matches the /* * Set up constraint/default info */ if (has_not_null || ndef > 0 || attrmiss || relation->rd_rel->relchecks) test, i.e. there are no defaults.
A quick assert confirms we do indeed pfree() constr in cases where has_generated_stored == true. I suspect that's just an intermediate catalog, however, e.g. when DefineRelation() does heap_create_with_catalog(); CommandCounterIncrement(); relation_open(); AddRelationNewConstraints(). It does still strike me as not great that we can get a different relcache entry, even if transient, depending on whether there are other reasons to create a TupleConstr. Say a NOT NULL column. I'm inclined to think we should just also check has_generated_stored in the if quoted above? Greetings, Andres Freund