I was trying to take Postgresql's EXCLUDE example a little further, by adding a PREDICATE.
In one case it works like I expect it. In another case...not so
First example, with a predicate on "cage". Works just fine :
=> CREATE TABLE zoo( cage INTEGER, animal TEXT, EXCLUDE USING GIST (cage WITH =, animal WITH <>) WHERE (cage = 1) ); CREATE TABLE => INSERT INTO zoo VALUES (1, 'zebra'); INSERT 0 1 => INSERT INTO zoo VALUES (2, 'lion'); INSERT 0 1 => INSERT INTO zoo VALUES (1, 'lion'); ERROR: conflicting key value violates exclusion constraint "zoo_cage_animal_excl" DETAIL: Key (cage, animal)=(1, lion) conflicts with existing key (cage, animal)=(1, zebra). So far, so good. (1, lion) conflicts indeed with (1, zebra).
Second example, with a predicate on "animal". Unexpected result :
=> CREATE TABLE zoo( cage INTEGER, animal TEXT, EXCLUDE USING GIST (cage WITH =, animal WITH <>) WHERE (animal = 'lion') ); CREATE TABLE => INSERT INTO zoo VALUES (1, 'zebra'); INSERT 0 1 => INSERT INTO zoo VALUES (2, 'lion'); INSERT 0 1 => INSERT INTO zoo VALUES (2, 'zebra'); INSERT 0 1 Why doesn't this last statement raise a conflicting error ?
WHERE (animal = 'lion') builds a partial GIST index. The last row ((2, zebra)) should conflict with the existing row (2, lion) (same cage, different animal : 2 = 2, zebra <> lion).
So how come that PostgreSQL allows this row (2, zebra) to be inserted ?