--
-- UNION (also INTERSECT, EXCEPT)
--
-- Simple UNION constructs
SELECT 1 AS two UNION SELECT 2;
 two 
-----
   1
   2
(2 rows)

SELECT 1 AS one UNION SELECT 1;
 one 
-----
   1
(1 row)

SELECT 1 AS two UNION ALL SELECT 2;
 two 
-----
   1
   2
(2 rows)

SELECT 1 AS two UNION ALL SELECT 1;
 two 
-----
   1
   1
(2 rows)

SELECT 1 AS three UNION SELECT 2 UNION SELECT 3;
 three 
-------
     1
     2
     3
(3 rows)

SELECT 1 AS two UNION SELECT 2 UNION SELECT 2;
 two 
-----
   1
   2
(2 rows)

SELECT 1 AS three UNION SELECT 2 UNION ALL SELECT 2;
 three 
-------
     1
     2
     2
(3 rows)

SELECT 1.1 AS two UNION SELECT 2.2;
 two 
-----
 1.1
 2.2
(2 rows)

-- Mixed types
SELECT 1.1 AS two UNION SELECT 2;
 two 
-----
 1.1
   2
(2 rows)

SELECT 1 AS two UNION SELECT 2.2;
 two 
-----
   1
 2.2
(2 rows)

SELECT 1 AS one UNION SELECT 1.0::float8;
 one 
-----
   1
(1 row)

SELECT 1.1 AS two UNION ALL SELECT 2;
 two 
-----
 1.1
   2
(2 rows)

SELECT 1.0::float8 AS two UNION ALL SELECT 1;
 two 
-----
   1
   1
(2 rows)

SELECT 1.1 AS three UNION SELECT 2 UNION SELECT 3;
 three 
-------
   1.1
     2
     3
(3 rows)

SELECT 1.1::float8 AS two UNION SELECT 2 UNION SELECT 2.0::float8 ORDER BY 1;
 two 
-----
 1.1
   2
(2 rows)

SELECT 1.1 AS three UNION SELECT 2 UNION ALL SELECT 2;
 three 
-------
   1.1
     2
     2
(3 rows)

SELECT 1.1 AS two UNION (SELECT 2 UNION ALL SELECT 2);
 two 
-----
 1.1
   2
(2 rows)

--
-- Try testing from tables...
--
SELECT f1 AS five FROM FLOAT8_TBL
UNION
SELECT f1 FROM FLOAT8_TBL
ORDER BY 1;
         five          
-----------------------
 -1.2345678901234e+200
               -1004.3
                -34.84
 -1.2345678901234e-200
                     0
(5 rows)

SELECT f1 AS ten FROM FLOAT8_TBL
UNION ALL
SELECT f1 FROM FLOAT8_TBL;
          ten          
-----------------------
                     0
                -34.84
               -1004.3
 -1.2345678901234e+200
 -1.2345678901234e-200
                     0
                -34.84
               -1004.3
 -1.2345678901234e+200
 -1.2345678901234e-200
(10 rows)

SELECT f1 AS nine FROM FLOAT8_TBL
UNION
SELECT f1 FROM INT4_TBL
ORDER BY 1;
         nine          
-----------------------
 -1.2345678901234e+200
           -2147483647
               -123456
               -1004.3
                -34.84
 -1.2345678901234e-200
                     0
                123456
            2147483647
(9 rows)

SELECT f1 AS ten FROM FLOAT8_TBL
UNION ALL
SELECT f1 FROM INT4_TBL;
          ten          
-----------------------
                     0
                -34.84
               -1004.3
 -1.2345678901234e+200
 -1.2345678901234e-200
                     0
                123456
               -123456
            2147483647
           -2147483647
(10 rows)

SELECT f1 AS five FROM FLOAT8_TBL
  WHERE f1 BETWEEN -1e6 AND 1e6
UNION
SELECT f1 FROM INT4_TBL
  WHERE f1 BETWEEN 0 AND 1000000;
         five          
-----------------------
               -1004.3
                -34.84
 -1.2345678901234e-200
                     0
                123456
(5 rows)

SELECT CAST(f1 AS char(4)) AS three FROM VARCHAR_TBL
UNION
SELECT f1 FROM CHAR_TBL
ORDER BY 1;
 three 
-------
 a   
 ab  
 abcd
(3 rows)

SELECT f1 AS three FROM VARCHAR_TBL
UNION
SELECT CAST(f1 AS varchar) FROM CHAR_TBL
ORDER BY 1;
 three 
-------
 a
 ab
 abcd
(3 rows)

SELECT f1 AS eight FROM VARCHAR_TBL
UNION ALL
SELECT f1 FROM CHAR_TBL;
 eight 
-------
 a
 ab
 abcd
 abcd
 a
 ab
 abcd
 abcd
(8 rows)

SELECT f1 AS five FROM TEXT_TBL
UNION
SELECT f1 FROM VARCHAR_TBL
UNION
SELECT TRIM(TRAILING FROM f1) FROM CHAR_TBL
ORDER BY 1;
       five        
-------------------
 a
 ab
 abcd
 doh!
 hi de ho neighbor
(5 rows)

--
-- INTERSECT and EXCEPT
--
SELECT q2 FROM int8_tbl INTERSECT SELECT q1 FROM int8_tbl;
        q2        
------------------
 4567890123456789
              123
(2 rows)

SELECT q2 FROM int8_tbl INTERSECT ALL SELECT q1 FROM int8_tbl;
        q2        
------------------
 4567890123456789
 4567890123456789
              123
(3 rows)

SELECT q2 FROM int8_tbl EXCEPT SELECT q1 FROM int8_tbl ORDER BY 1;
        q2         
-------------------
 -4567890123456789
               456
(2 rows)

SELECT q2 FROM int8_tbl EXCEPT ALL SELECT q1 FROM int8_tbl ORDER BY 1;
        q2         
-------------------
 -4567890123456789
               456
(2 rows)

SELECT q2 FROM int8_tbl EXCEPT ALL SELECT DISTINCT q1 FROM int8_tbl ORDER BY 1;
        q2         
-------------------
 -4567890123456789
               456
  4567890123456789
(3 rows)

SELECT q1 FROM int8_tbl EXCEPT SELECT q2 FROM int8_tbl;
 q1 
----
(0 rows)

SELECT q1 FROM int8_tbl EXCEPT ALL SELECT q2 FROM int8_tbl;
        q1        
------------------
 4567890123456789
              123
(2 rows)

SELECT q1 FROM int8_tbl EXCEPT ALL SELECT DISTINCT q2 FROM int8_tbl;
        q1        
------------------
 4567890123456789
 4567890123456789
              123
(3 rows)

--
-- Mixed types
--
SELECT f1 FROM float8_tbl INTERSECT SELECT f1 FROM int4_tbl;
 f1 
----
  0
(1 row)

SELECT f1 FROM float8_tbl EXCEPT SELECT f1 FROM int4_tbl ORDER BY 1;
          f1           
-----------------------
 -1.2345678901234e+200
               -1004.3
                -34.84
 -1.2345678901234e-200
(4 rows)

--
-- Operator precedence and (((((extra))))) parentheses
--
SELECT q1 FROM int8_tbl INTERSECT SELECT q2 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl;
        q1         
-------------------
  4567890123456789
               123
               456
  4567890123456789
               123
  4567890123456789
 -4567890123456789
(7 rows)

SELECT q1 FROM int8_tbl INTERSECT (((SELECT q2 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl)));
        q1        
------------------
 4567890123456789
              123
(2 rows)

(((SELECT q1 FROM int8_tbl INTERSECT SELECT q2 FROM int8_tbl))) UNION ALL SELECT q2 FROM int8_tbl;
        q1         
-------------------
  4567890123456789
               123
               456
  4567890123456789
               123
  4567890123456789
 -4567890123456789
(7 rows)

SELECT q1 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl EXCEPT SELECT q1 FROM int8_tbl ORDER BY 1;
        q1         
-------------------
 -4567890123456789
               456
(2 rows)

SELECT q1 FROM int8_tbl UNION ALL (((SELECT q2 FROM int8_tbl EXCEPT SELECT q1 FROM int8_tbl ORDER BY 1)));
        q1         
-------------------
               123
               123
  4567890123456789
  4567890123456789
  4567890123456789
 -4567890123456789
               456
(7 rows)

(((SELECT q1 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl))) EXCEPT SELECT q1 FROM int8_tbl ORDER BY 1;
        q1         
-------------------
 -4567890123456789
               456
(2 rows)

--
-- Subqueries with ORDER BY & LIMIT clauses
--
-- In this syntax, ORDER BY/LIMIT apply to the result of the EXCEPT
SELECT q1,q2 FROM int8_tbl EXCEPT SELECT q2,q1 FROM int8_tbl
ORDER BY q2,q1;
        q1        |        q2         
------------------+-------------------
 4567890123456789 | -4567890123456789
              123 |               456
(2 rows)

-- This should fail, because q2 isn't a name of an EXCEPT output column
SELECT q1 FROM int8_tbl EXCEPT SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1;
ERROR:  column "q2" does not exist
LINE 1: ... int8_tbl EXCEPT SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1...
                                                             ^
-- But this should work:
SELECT q1 FROM int8_tbl EXCEPT (((SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1)));
        q1        
------------------
 4567890123456789
              123
(2 rows)

--
-- New syntaxes (7.1) permit new tests
--
(((((select * from int8_tbl)))));
        q1        |        q2         
------------------+-------------------
              123 |               456
              123 |  4567890123456789
 4567890123456789 |               123
 4567890123456789 |  4567890123456789
 4567890123456789 | -4567890123456789
(5 rows)

--
-- Check handling of a case with unknown constants.  We don't guarantee
-- an undecorated constant will work in all cases, but historically this
-- usage has worked, so test we don't break it.
--
SELECT a.f1 FROM (SELECT 'test' AS f1 FROM varchar_tbl) a
UNION
SELECT b.f1 FROM (SELECT f1 FROM varchar_tbl) b
ORDER BY 1;
  f1  
------
 a
 ab
 abcd
 test
(4 rows)

-- This should fail, but it should produce an error cursor
SELECT '3.4'::numeric UNION SELECT 'foo';
ERROR:  invalid input syntax for type numeric: "foo"
LINE 1: SELECT '3.4'::numeric UNION SELECT 'foo';
                                           ^
-- Test that we push quals into UNION sub-selects only when it's safe
SELECT * FROM
  (SELECT 1 AS t, 2 AS x
   UNION
   SELECT 2 AS t, 4 AS x) ss
WHERE x < 4;
 t | x 
---+---
 1 | 2
(1 row)

SELECT * FROM
  (SELECT 1 AS t, generate_series(1,10) AS x
   UNION
   SELECT 2 AS t, 4 AS x) ss
WHERE x < 4
ORDER BY x;
 t | x 
---+---
 1 | 1
 1 | 2
 1 | 3
(3 rows)

SELECT * FROM
  (SELECT 1 AS t, (random()*3)::int AS x
   UNION
   SELECT 2 AS t, 4 AS x) ss
WHERE x > 3;
 t | x 
---+---
 2 | 4
(1 row)

