Let us have the following things in PostgreSQL:
CREATE TYPE struct AS (x INT, y INT);
CREATE TABLE tbl (a INT, b struct);
CREATE FUNCTION find_tbl_entry(clear BOOL) RETURNS tbl AS $$
DECLARE k tbl;
BEGIN
IF clear THEN
k.b := NULL;
END IF;
RETURN k;
END;
$$ LANGUAGE plpgsql;
That is, we have a function returning a value of the composite type tbl, which in turn has an attribute b of composite type struct as one of its attributes. (The original problem is more interesting - a translating function returning a row with some attributes translated accordingly; the problem boils down to the presented code, though.)
SELECT find_tbl_entry(FALSE) results in (,(,)), i.e., NULL as the value of a and an empty struct (pair of NULL and NULL) as the value of b, which is somewhat expected.
Now, even SELECT find_tbl_entry(TRUE) results in (,(,)), i.e., even if the b attribute is explicitly set to NULL, the result is not NULL, but it is still the empty struct.
What can I do for the function find_tbl_entry to return NULL in the b attribute?
EDIT: As it turns out, the strange thing is the assignment k.b := NULL. When extending the function:
k.b := NULL;
RAISE NOTICE '%', k.b IS DISTINCT FROM NULL;
it emits "NOTICE: t". Thus, it seems assigning NULL to a composite value actually assigns a composite having all attributes NULL. Which is quite strange, considering the fact that NULL values are distinguishable from (NULL,NULL) when stored in a table (UPDATE tbl SET b = NULL results in b IS NOT DISTINCT FROM NULL holding for each row; on the other hand, UPDATE tbl SET b = (NULL,NULL) is false for that test).