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 ?