Re: NOT ENFORCED constraint feature
Peter Eisentraut <peter@eisentraut.org>
From: Peter Eisentraut <peter@eisentraut.org>
To: Álvaro Herrera <alvherre@alvh.no-ip.org>, Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Cc: Isaac Morland <isaac.morland@gmail.com>, Amul Sul <sulamul@gmail.com>,
jian he <jian.universality@gmail.com>,
PostgreSQL-development <pgsql-hackers@postgresql.org>,
Joel Jacobson <joel@compiler.org>,
Suraj Kharage <suraj.kharage@enterprisedb.com>
Date: 2025-02-12T14:45:36Z
Lists: pgsql-hackers
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Add support for NOT ENFORCED in foreign key constraints
- eec0040c4bcd 18.0 landed
-
Expand test a bit
- 5d5f415816a6 18.0 landed
-
refactor: Pass relation OID instead of Relation to createForeignKeyCheckTriggers()
- ef7a5af77d44 18.0 landed
-
refactor: Split ATExecAlterConstraintInternal()
- 639238b978fe 18.0 landed
-
refactor: Move some code that updates pg_constraint to a separate function
- a3280e2a494f 18.0 landed
-
Move RemoveInheritedConstraint() call slightly earlier
- dabccf45139a 18.0 landed
-
refactor: Split tryAttachPartitionForeignKey()
- 1d26c2d2c4b8 18.0 landed
-
refactor: re-add ATExecAlterChildConstr()
- 64224a834ce4 18.0 landed
-
Add ATAlterConstraint struct for ALTER .. CONSTRAINT
- 80d7f990496b 18.0 landed
-
refactor: split ATExecAlterConstrRecurse()
- 7a947ed25b54 18.0 landed
-
Add support for NOT ENFORCED in CHECK constraints
- ca87c415e2fc 18.0 landed
On 12.02.25 12:13, Álvaro Herrera wrote: > On 2025-Feb-12, Ashutosh Bapat wrote: > >> I have been asking a different question: What's the use of >> not-enforced constraints if we don't allow VALID, NOT ENFORCED state >> for them? > > That's a question for the SQL standards committee. They may serve > schema documentation purposes, for example. > https://www.postgresql.eu/events/pgconfeu2024/schedule/session/5677-exploring-postgres-databases-with-graphs/ > >> OTOH, consider an application which "knows" that the constraint is >> valid for the data (either because of checks at application level, or >> because the data was replicated from some other system where the >> cosntraints were applied). It's a natural ask to use the constraints >> for, say optimization, but don't take unnecessary overhead of >> validating them. VALID, NOT ENFORCED state helps in such a scenario. >> Of course an application can misuse it (just like stable marking on a >> function), but well ... they will be penalised for their misuse. > > I disagree that we should see a VALID NOT ENFORCED constraint as one > that can be used for query optimization purposes. This is only going to > bring users pain, because it's far too easy to misuse and they will get > wrong query results, possibly without knowing for who knows how long. I've been digging into the ISO archives for some more background on the intended meaning of this feature. Result: "NOT ENFORCED" just means "off" or "disabled", "could contain anything". You can use this to do data loads, or schema surgery, or things like that. Or just if you want it for documentation. This idea that a not-enforced constraint should contain valid data anyway is not supported by anything I could find written down. I've heard that in discussions, but those could have been speculations. (I still think that could be a feature, but it's clearly not this one, at least not in its default state.) So considering that, I think a three-state system makes more sense. Something like: 1) NOT ENFORCED -- no data is checked 2) NOT VALID -- existing data is unchecked, new data is checked 3) ENFORCED -- all data is checked Transitions: (1) - [ ALTER TABLE ... ALTER CONSTRAINT ... NOT VALID ] -> (2) (1) - [ ALTER TABLE ... ALTER CONSTRAINT ... ENFORCED ] -> (3) (2) - [ ALTER TABLE ... VALIDATE CONSTRAINT ... ] -> (3) (2|3) - [ ALTER TABLE ... ALTER CONSTRAINT ... NOT ENFORCED ] -> (1) (3) - [ ALTER TABLE ... ALTER CONSTRAINT ... NOT VALID ] -> (2)