1-- 2-- UNION (also INTERSECT, EXCEPT) 3-- 4 5-- Simple UNION constructs 6 7SELECT 1 AS two UNION SELECT 2 ORDER BY 1; 8 9SELECT 1 AS one UNION SELECT 1 ORDER BY 1; 10 11SELECT 1 AS two UNION ALL SELECT 2; 12 13SELECT 1 AS two UNION ALL SELECT 1; 14 15SELECT 1 AS three UNION SELECT 2 UNION SELECT 3 ORDER BY 1; 16 17SELECT 1 AS two UNION SELECT 2 UNION SELECT 2 ORDER BY 1; 18 19SELECT 1 AS three UNION SELECT 2 UNION ALL SELECT 2 ORDER BY 1; 20 21SELECT 1.1 AS two UNION SELECT 2.2 ORDER BY 1; 22 23-- Mixed types 24 25SELECT 1.1 AS two UNION SELECT 2 ORDER BY 1; 26 27SELECT 1 AS two UNION SELECT 2.2 ORDER BY 1; 28 29SELECT 1 AS one UNION SELECT 1.0::float8 ORDER BY 1; 30 31SELECT 1.1 AS two UNION ALL SELECT 2 ORDER BY 1; 32 33SELECT 1.0::float8 AS two UNION ALL SELECT 1 ORDER BY 1; 34 35SELECT 1.1 AS three UNION SELECT 2 UNION SELECT 3 ORDER BY 1; 36 37SELECT 1.1::float8 AS two UNION SELECT 2 UNION SELECT 2.0::float8 ORDER BY 1; 38 39SELECT 1.1 AS three UNION SELECT 2 UNION ALL SELECT 2 ORDER BY 1; 40 41SELECT 1.1 AS two UNION (SELECT 2 UNION ALL SELECT 2) ORDER BY 1; 42 43-- 44-- Try testing from tables... 45-- 46 47SELECT f1 AS five FROM FLOAT8_TBL 48UNION 49SELECT f1 FROM FLOAT8_TBL 50ORDER BY 1; 51 52SELECT f1 AS ten FROM FLOAT8_TBL 53UNION ALL 54SELECT f1 FROM FLOAT8_TBL; 55 56SELECT f1 AS nine FROM FLOAT8_TBL 57UNION 58SELECT f1 FROM INT4_TBL 59ORDER BY 1; 60 61SELECT f1 AS ten FROM FLOAT8_TBL 62UNION ALL 63SELECT f1 FROM INT4_TBL; 64 65SELECT f1 AS five FROM FLOAT8_TBL 66 WHERE f1 BETWEEN -1e6 AND 1e6 67UNION 68SELECT f1 FROM INT4_TBL 69 WHERE f1 BETWEEN 0 AND 1000000 70ORDER BY 1; 71 72SELECT CAST(f1 AS char(4)) AS three FROM VARCHAR_TBL 73UNION 74SELECT f1 FROM CHAR_TBL 75ORDER BY 1; 76 77SELECT f1 AS three FROM VARCHAR_TBL 78UNION 79SELECT CAST(f1 AS varchar) FROM CHAR_TBL 80ORDER BY 1; 81 82SELECT f1 AS eight FROM VARCHAR_TBL 83UNION ALL 84SELECT f1 FROM CHAR_TBL; 85 86SELECT f1 AS five FROM TEXT_TBL 87UNION 88SELECT f1 FROM VARCHAR_TBL 89UNION 90SELECT TRIM(TRAILING FROM f1) FROM CHAR_TBL 91ORDER BY 1; 92 93-- 94-- INTERSECT and EXCEPT 95-- 96 97SELECT q2 FROM int8_tbl INTERSECT SELECT q1 FROM int8_tbl ORDER BY 1; 98 99SELECT q2 FROM int8_tbl INTERSECT ALL SELECT q1 FROM int8_tbl ORDER BY 1; 100 101SELECT q2 FROM int8_tbl EXCEPT SELECT q1 FROM int8_tbl ORDER BY 1; 102 103SELECT q2 FROM int8_tbl EXCEPT ALL SELECT q1 FROM int8_tbl ORDER BY 1; 104 105SELECT q2 FROM int8_tbl EXCEPT ALL SELECT DISTINCT q1 FROM int8_tbl ORDER BY 1; 106 107SELECT q1 FROM int8_tbl EXCEPT SELECT q2 FROM int8_tbl ORDER BY 1; 108 109SELECT q1 FROM int8_tbl EXCEPT ALL SELECT q2 FROM int8_tbl ORDER BY 1; 110 111SELECT q1 FROM int8_tbl EXCEPT ALL SELECT DISTINCT q2 FROM int8_tbl ORDER BY 1; 112 113SELECT q1 FROM int8_tbl EXCEPT ALL SELECT q1 FROM int8_tbl FOR NO KEY UPDATE; 114 115-- nested cases 116(SELECT 1,2,3 UNION SELECT 4,5,6) INTERSECT SELECT 4,5,6; 117(SELECT 1,2,3 UNION SELECT 4,5,6 ORDER BY 1,2) INTERSECT SELECT 4,5,6; 118(SELECT 1,2,3 UNION SELECT 4,5,6) EXCEPT SELECT 4,5,6; 119(SELECT 1,2,3 UNION SELECT 4,5,6 ORDER BY 1,2) EXCEPT SELECT 4,5,6; 120 121-- exercise both hashed and sorted implementations of INTERSECT/EXCEPT 122 123set enable_hashagg to on; 124 125explain (costs off) 126select count(*) from 127 ( select unique1 from tenk1 intersect select fivethous from tenk1 ) ss; 128select count(*) from 129 ( select unique1 from tenk1 intersect select fivethous from tenk1 ) ss; 130 131explain (costs off) 132select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; 133select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; 134 135set enable_hashagg to off; 136 137explain (costs off) 138select count(*) from 139 ( select unique1 from tenk1 intersect select fivethous from tenk1 ) ss; 140select count(*) from 141 ( select unique1 from tenk1 intersect select fivethous from tenk1 ) ss; 142 143explain (costs off) 144select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; 145select unique1 from tenk1 except select unique2 from tenk1 where unique2 != 10; 146 147reset enable_hashagg; 148 149-- 150-- Mixed types 151-- 152 153SELECT f1 FROM float8_tbl INTERSECT SELECT f1 FROM int4_tbl ORDER BY 1; 154 155SELECT f1 FROM float8_tbl EXCEPT SELECT f1 FROM int4_tbl ORDER BY 1; 156 157-- 158-- Operator precedence and (((((extra))))) parentheses 159-- 160 161SELECT q1 FROM int8_tbl INTERSECT SELECT q2 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl ORDER BY 1; 162 163SELECT q1 FROM int8_tbl INTERSECT (((SELECT q2 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl))) ORDER BY 1; 164 165(((SELECT q1 FROM int8_tbl INTERSECT SELECT q2 FROM int8_tbl ORDER BY 1))) UNION ALL SELECT q2 FROM int8_tbl; 166 167SELECT q1 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl EXCEPT SELECT q1 FROM int8_tbl ORDER BY 1; 168 169SELECT q1 FROM int8_tbl UNION ALL (((SELECT q2 FROM int8_tbl EXCEPT SELECT q1 FROM int8_tbl ORDER BY 1))); 170 171(((SELECT q1 FROM int8_tbl UNION ALL SELECT q2 FROM int8_tbl))) EXCEPT SELECT q1 FROM int8_tbl ORDER BY 1; 172 173-- 174-- Subqueries with ORDER BY & LIMIT clauses 175-- 176 177-- In this syntax, ORDER BY/LIMIT apply to the result of the EXCEPT 178SELECT q1,q2 FROM int8_tbl EXCEPT SELECT q2,q1 FROM int8_tbl 179ORDER BY q2,q1; 180 181-- This should fail, because q2 isn't a name of an EXCEPT output column 182SELECT q1 FROM int8_tbl EXCEPT SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1; 183 184-- But this should work: 185SELECT q1 FROM int8_tbl EXCEPT (((SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1))) ORDER BY 1; 186 187-- 188-- New syntaxes (7.1) permit new tests 189-- 190 191(((((select * from int8_tbl))))); 192 193-- 194-- Check behavior with empty select list (allowed since 9.4) 195-- 196 197select union select; 198select intersect select; 199select except select; 200 201-- check hashed implementation 202set enable_hashagg = true; 203set enable_sort = false; 204 205explain (costs off) 206select from generate_series(1,5) union select from generate_series(1,3); 207explain (costs off) 208select from generate_series(1,5) intersect select from generate_series(1,3); 209 210select from generate_series(1,5) union select from generate_series(1,3); 211select from generate_series(1,5) union all select from generate_series(1,3); 212select from generate_series(1,5) intersect select from generate_series(1,3); 213select from generate_series(1,5) intersect all select from generate_series(1,3); 214select from generate_series(1,5) except select from generate_series(1,3); 215select from generate_series(1,5) except all select from generate_series(1,3); 216 217-- check sorted implementation 218set enable_hashagg = false; 219set enable_sort = true; 220 221explain (costs off) 222select from generate_series(1,5) union select from generate_series(1,3); 223explain (costs off) 224select from generate_series(1,5) intersect select from generate_series(1,3); 225 226select from generate_series(1,5) union select from generate_series(1,3); 227select from generate_series(1,5) union all select from generate_series(1,3); 228select from generate_series(1,5) intersect select from generate_series(1,3); 229select from generate_series(1,5) intersect all select from generate_series(1,3); 230select from generate_series(1,5) except select from generate_series(1,3); 231select from generate_series(1,5) except all select from generate_series(1,3); 232 233reset enable_hashagg; 234reset enable_sort; 235 236-- 237-- Check handling of a case with unknown constants. We don't guarantee 238-- an undecorated constant will work in all cases, but historically this 239-- usage has worked, so test we don't break it. 240-- 241 242SELECT a.f1 FROM (SELECT 'test' AS f1 FROM varchar_tbl) a 243UNION 244SELECT b.f1 FROM (SELECT f1 FROM varchar_tbl) b 245ORDER BY 1; 246 247-- This should fail, but it should produce an error cursor 248SELECT '3.4'::numeric UNION SELECT 'foo'; 249 250-- 251-- Test that expression-index constraints can be pushed down through 252-- UNION or UNION ALL 253-- 254 255CREATE TEMP TABLE t1 (a text, b text); 256CREATE INDEX t1_ab_idx on t1 ((a || b)); 257CREATE TEMP TABLE t2 (ab text primary key); 258INSERT INTO t1 VALUES ('a', 'b'), ('x', 'y'); 259INSERT INTO t2 VALUES ('ab'), ('xy'); 260 261set enable_seqscan = off; 262set enable_indexscan = on; 263set enable_bitmapscan = off; 264 265explain (costs off) 266 SELECT * FROM 267 (SELECT a || b AS ab FROM t1 268 UNION ALL 269 SELECT * FROM t2) t 270 WHERE ab = 'ab'; 271 272explain (costs off) 273 SELECT * FROM 274 (SELECT a || b AS ab FROM t1 275 UNION 276 SELECT * FROM t2) t 277 WHERE ab = 'ab'; 278 279-- 280-- Test that ORDER BY for UNION ALL can be pushed down to inheritance 281-- children. 282-- 283 284CREATE TEMP TABLE t1c (b text, a text); 285ALTER TABLE t1c INHERIT t1; 286CREATE TEMP TABLE t2c (primary key (ab)) INHERITS (t2); 287INSERT INTO t1c VALUES ('v', 'w'), ('c', 'd'), ('m', 'n'), ('e', 'f'); 288INSERT INTO t2c VALUES ('vw'), ('cd'), ('mn'), ('ef'); 289CREATE INDEX t1c_ab_idx on t1c ((a || b)); 290 291set enable_seqscan = on; 292set enable_indexonlyscan = off; 293 294explain (costs off) 295 SELECT * FROM 296 (SELECT a || b AS ab FROM t1 297 UNION ALL 298 SELECT ab FROM t2) t 299 ORDER BY 1 LIMIT 8; 300 301 SELECT * FROM 302 (SELECT a || b AS ab FROM t1 303 UNION ALL 304 SELECT ab FROM t2) t 305 ORDER BY 1 LIMIT 8; 306 307reset enable_seqscan; 308reset enable_indexscan; 309reset enable_bitmapscan; 310 311-- This simpler variant of the above test has been observed to fail differently 312 313create table events (event_id int primary key); 314create table other_events (event_id int primary key); 315create table events_child () inherits (events); 316 317explain (costs off) 318select event_id 319 from (select event_id from events 320 union all 321 select event_id from other_events) ss 322 order by event_id; 323 324drop table events_child, events, other_events; 325 326reset enable_indexonlyscan; 327 328-- Test constraint exclusion of UNION ALL subqueries 329explain (costs off) 330 SELECT * FROM 331 (SELECT 1 AS t, * FROM tenk1 a 332 UNION ALL 333 SELECT 2 AS t, * FROM tenk1 b) c 334 WHERE t = 2; 335 336-- Test that we push quals into UNION sub-selects only when it's safe 337explain (costs off) 338SELECT * FROM 339 (SELECT 1 AS t, 2 AS x 340 UNION 341 SELECT 2 AS t, 4 AS x) ss 342WHERE x < 4 343ORDER BY x; 344 345SELECT * FROM 346 (SELECT 1 AS t, 2 AS x 347 UNION 348 SELECT 2 AS t, 4 AS x) ss 349WHERE x < 4 350ORDER BY x; 351 352explain (costs off) 353SELECT * FROM 354 (SELECT 1 AS t, generate_series(1,10) AS x 355 UNION 356 SELECT 2 AS t, 4 AS x) ss 357WHERE x < 4 358ORDER BY x; 359 360SELECT * FROM 361 (SELECT 1 AS t, generate_series(1,10) AS x 362 UNION 363 SELECT 2 AS t, 4 AS x) ss 364WHERE x < 4 365ORDER BY x; 366 367explain (costs off) 368SELECT * FROM 369 (SELECT 1 AS t, (random()*3)::int AS x 370 UNION 371 SELECT 2 AS t, 4 AS x) ss 372WHERE x > 3 373ORDER BY x; 374 375SELECT * FROM 376 (SELECT 1 AS t, (random()*3)::int AS x 377 UNION 378 SELECT 2 AS t, 4 AS x) ss 379WHERE x > 3 380ORDER BY x; 381 382-- Test cases where the native ordering of a sub-select has more pathkeys 383-- than the outer query cares about 384explain (costs off) 385select distinct q1 from 386 (select distinct * from int8_tbl i81 387 union all 388 select distinct * from int8_tbl i82) ss 389where q2 = q2; 390 391select distinct q1 from 392 (select distinct * from int8_tbl i81 393 union all 394 select distinct * from int8_tbl i82) ss 395where q2 = q2; 396 397explain (costs off) 398select distinct q1 from 399 (select distinct * from int8_tbl i81 400 union all 401 select distinct * from int8_tbl i82) ss 402where -q1 = q2; 403 404select distinct q1 from 405 (select distinct * from int8_tbl i81 406 union all 407 select distinct * from int8_tbl i82) ss 408where -q1 = q2; 409 410-- Test proper handling of parameterized appendrel paths when the 411-- potential join qual is expensive 412create function expensivefunc(int) returns int 413language plpgsql immutable strict cost 10000 414as $$begin return $1; end$$; 415 416create temp table t3 as select generate_series(-1000,1000) as x; 417create index t3i on t3 (expensivefunc(x)); 418analyze t3; 419 420explain (costs off) 421select * from 422 (select * from t3 a union all select * from t3 b) ss 423 join int4_tbl on f1 = expensivefunc(x); 424select * from 425 (select * from t3 a union all select * from t3 b) ss 426 join int4_tbl on f1 = expensivefunc(x); 427 428drop table t3; 429drop function expensivefunc(int); 430 431-- Test handling of appendrel quals that const-simplify into an AND 432explain (costs off) 433select * from 434 (select *, 0 as x from int8_tbl a 435 union all 436 select *, 1 as x from int8_tbl b) ss 437where (x = 0) or (q1 >= q2 and q1 <= q2); 438select * from 439 (select *, 0 as x from int8_tbl a 440 union all 441 select *, 1 as x from int8_tbl b) ss 442where (x = 0) or (q1 >= q2 and q1 <= q2); 443