Dear PostgreSQL Hackers, I would like to propose adding support for NOT NULL constraints on individual fields within composite types, with enforcement *only at rest* when the composite type is used as a table column. This approach addresses several key challenges while aligning with PostgreSQL’s existing behavior for NOT NULL constraints. Rationale
1. *Consistency with Existing NOT NULL Behavior*: - NOT NULL constraints for table columns are already enforced *only during INSERT or UPDATE* operations. This proposal extends the same principle to composite types, ensuring constraints are checked at the same points in the data lifecycle. - This avoids runtime inconsistencies, as queries (e.g., joins) and in-memory operations in procedural languages (e.g., plpgsql) are not expected to revalidate NOT NULL constraints. 2. *Avoids Fundamental SQL Conflicts*: - SQL semantics, particularly in outer joins, allow for NULL values in query results. Enforcing NOT NULL constraints outside of the “at rest” context would lead to contradictions, as demonstrated <https://www.postgresql.org/message-id/20534.1481817136%40sss.pgh.pa.us> by Tom Lane with domains in a previous discussion. - By limiting enforcement to storage, this proposal avoids the conflict while preserving the utility of NOT NULL for data integrity. 3. *Improved Usability for Composite Types*: - Composite types are often used to model structured data. Allowing field-level NOT NULL constraints enhances their expressiveness, enabling developers to enforce more robust data models directly within PostgreSQL. - This improvement benefits schema design by embedding field constraints directly in the composite type definition, reducing reliance on table-level CHECK constraints or application-level validations. Scope of Enforcement - *At Rest*: - Constraints are enforced during INSERT and UPDATE operations when a composite type is used as a column in a table. - *Out of Scope*: - Constraints are *not enforced* during query execution, in procedural language variables, or for composite types passed as function parameters, to avoid runtime performance and semantic conflicts. Why This is a Good Compromise This proposal strikes a balance between utility and feasibility: - It avoids the known pitfalls of universally enforcing NOT NULL constraints for composite types while still enabling field-level integrity checks during storage operations. - It aligns with PostgreSQL’s existing constraint enforcement model, ensuring intuitive behavior for users already familiar with how NOT NULL works for table columns. Next Steps If there is interest, I would be happy to explore the technical implications further and submit a draft patch for discussion. Feedback on potential implementation challenges or edge cases is very welcome. Thank you for considering this proposal! Best regards, Alec Larson