Thread: BUG #1847: Error in some kind of UNION query.

BUG #1847: Error in some kind of UNION query.

From
"THIBAULT Jean-Jacques"
Date:
The following bug has been logged online:

Bug reference:      1847
Logged by:          THIBAULT Jean-Jacques
Email address:      jjt4@wanadoo.fr
PostgreSQL version: 8.0.3
Operating system:   Linux (Mandrake)
Description:        Error in some kind of UNION query.
Details:

this query work :
select null UNION 1;

this query doesn't work :
select null UNION null UNION 1;

ERROR:  UNION types text and integer cannot be matched

I use Hibernate API, that generates this kind of query in "one table for
each concret class" mapping strategy. I allways have real value in a union
member that justify this kind of query.

Thank-you.

Jean-Jacques THIBAULT (France)

Re: BUG #1847: Error in some kind of UNION query.

From
Michael Fuhr
Date:
On Thu, Aug 25, 2005 at 09:53:26AM +0100, THIBAULT Jean-Jacques wrote:
>
> this query work :
> select null UNION 1;

Please show the *exact* query.  The above produces a syntax error:

test=> select null UNION 1;
ERROR:  syntax error at or near "1" at character 19
LINE 1: select null UNION 1;
                          ^

I suspect this is the actual query:

test=> select null UNION select 1;
 ?column?
----------
        1

(2 rows)

> this query doesn't work :
> select null UNION null UNION 1;
>
> ERROR:  UNION types text and integer cannot be matched

Again, the query as written causes a syntax error.  This is probably
the actual query:

test=> select null UNION select null UNION select 1;
ERROR:  UNION types text and integer cannot be matched

To understand what's happening, see "UNION, CASE, and ARRAY Type
Resolution" in the "Type Conversion" chapter of the documentation:

http://www.postgresql.org/docs/8.0/static/typeconv-union-case.html

--
Michael Fuhr

Re: BUG #1847: Error in some kind of UNION query.

From
Andreas Pflug
Date:
THIBAULT Jean-Jacques wrote:
> The following bug has been logged online:
>
> Bug reference:      1847
> Logged by:          THIBAULT Jean-Jacques
> Email address:      jjt4@wanadoo.fr
> PostgreSQL version: 8.0.3
> Operating system:   Linux (Mandrake)
> Description:        Error in some kind of UNION query.
> Details:
>
> this query work :
> select null UNION 1;
>
> this query doesn't work :
> select null UNION null UNION 1;
>
> ERROR:  UNION types text and integer cannot be matched

You probably mean
SELECT NULL
UNION
SELECT NULL
UNION
SELECT 1

Proper casting will help, insuring the correct type can be determined
from the first SELECT. Changing the order to have SELECT 1 does the job too.

Regards,
Andreas

Re: BUG #1847: Error in some kind of UNION query.

From
Tom Lane
Date:
Andreas Pflug <pgadmin@pse-consulting.de> writes:
> You probably mean
> SELECT NULL
> UNION
> SELECT NULL
> UNION
> SELECT 1

This has come up a couple of times before.  It'd probably be possible to
resolve the type across all the union'd selects at once, using the same
rules as we do for CASE.  The thing that bothers me is that I think
doing so would violate the SQL spec.  The spec defines UNION as a
two-at-a-time operation; it is perfectly clear that the above must mean
    (SELECT NULL UNION SELECT NULL) UNION SELECT 1
and in turn that means that a CASE-like approach would cause the "SELECT
1" to change the semantics of the other parenthesized operation.  Which
is surely wrong.

For UNION ALL this might not matter a lot, because the end result
datatype would be the same anyway.  But for UNION it matters a whole
lot, because the assigned datatype determines what "equality" means
and therefore which rows are going to be eliminated as duplicates.
Here is an example:

regression=# (select '1.0' union select '1');
 ?column?
----------
 1
 1.0
(2 rows)

By default, the literals are resolved as type TEXT, and so they are
considered different.  But try this:

regression=# select '1.0' union (select '1' union select 1.0);
 ?column?
----------
      1.0
(1 row)

The unquoted 1.0 is numeric, and so that choice propagates to the
untyped literals, and we end up with just one row because 1 == 1.0.
This example proves that the parenthesization of a nest of UNIONs
does make a difference.

So the short answer is: I don't think we can change this without
breaking spec.  Better put some explicit casts on your nulls, eg

SELECT NULL::INTEGER UNION SELECT NULL::INTEGER UNION SELECT 1

(BTW, I'm fairly sure that "SELECT NULL" is illegal per the spec,
anyway.  You'd have to CAST it to some specific type to be valid SQL.)

            regards, tom lane