I would like to define a composite type whose fields are NOT NULL; while at the same time, allow the value itself to be NULL in a table column. My first attempt was to define a DOMAIN on the composite type with a CHECK constraint that ensured the fields are NOT NULL; unfortunately this prevents NULL itself from being INSERTed into the table:
BEGIN;
CREATE TYPE foo AS (x int, y int);
CREATE DOMAIN non_null_foo AS foo CHECK((VALUE).x IS NOT NULL AND (VALUE).y IS NOT NULL);
CREATE TABLE bar(y non_null_foo);
INSERT INTO bar VALUES (NULL);
ROLLBACK;
errors: ERROR: value for domain non_null_foo violates check constraint "non_null_foo_check".
My second attempt was to allow NULL for VALUE in the DOMAIN, but this also does not work since it now allows a value where all fields are NULL:
BEGIN;
CREATE TYPE foo AS (x int, y int);
CREATE DOMAIN non_null_foo AS foo CHECK(VALUE IS NULL OR ((VALUE).x IS NOT NULL AND (VALUE).y IS NOT NULL));
CREATE TABLE bar(y non_null_foo);
INSERT INTO bar VALUES ((NULL, NULL)); --succeeds
INSERT INTO bar VALUES ((1, NULL)); --fails
ROLLBACK;
It's as if Postgresql is unable to distinguish between NULL and a value where all the fields are NULL. Is there something I'm missing?