Why does Type Resolution fail when using SELECT DISTINCT instead of SELECT on PostgreSQL?
-
07-03-2021 - |
Question
Here is a minimal reproduction:
SELECT 1
UNION ALL
SELECT DISTINCT NULL
Fails with:
UNION types numeric and text cannot be matched
According to the PostgreSQL documentation on Type Resolution for UNION, CASE, and Related Constructs and the following chapter on SELECT Output Columns, the type of null
should be derived from the preceding select.
In fact it works, if I remove the DISTINCT
:
SELECT 1
UNION ALL
SELECT NULL
Why does the DISTINCT
modifier interfere with type resolution?
Solution
Without the DISTINCT
, the type of the second part of the UNION ALL
is unknown
:
SELECT pg_typeof(NULL);
pg_typeof
-----------
unknown
(1 row)
This gets resolved to integer
.
If there is a DISTINCT
, PostgreSQL has to resolve the type of NULL
earlier on: to eliminate duplicates, it has to know which equality operator to use. Lacking other information, it chooses text
as the preferred type of the string category.
Then you get the error because integer
and text
cannot be reconciled.
The documentation describes the type choice for the equality operator as follows:
If any input arguments are
unknown
, check the type categories accepted at those argument positions by the remaining candidates. At each position, select thestring
category if any candidate accepts that category. (This bias towards string is appropriate since an unknown-type literal looks like a string.)