1 2#pragma ident "%Z%%M% %I% %E% SMI" 3 4# 2001 September 15 5# 6# The author disclaims copyright to this source code. In place of 7# a legal notice, here is a blessing: 8# 9# May you do good and not evil. 10# May you find forgiveness for yourself and forgive others. 11# May you share freely, never taking more than you give. 12# 13#*********************************************************************** 14# This file implements regression tests for SQLite library. The 15# focus of this file is testing UNION, INTERSECT and EXCEPT operators 16# in SELECT statements. 17# 18# $Id: select4.test,v 1.13 2003/02/02 12:41:27 drh Exp $ 19 20set testdir [file dirname $argv0] 21source $testdir/tester.tcl 22 23# Build some test data 24# 25set fd [open data1.txt w] 26for {set i 1} {$i<32} {incr i} { 27 for {set j 0} {pow(2,$j)<$i} {incr j} {} 28 puts $fd "$i\t$j" 29} 30close $fd 31execsql { 32 CREATE TABLE t1(n int, log int); 33 COPY t1 FROM 'data1.txt' 34} 35file delete data1.txt 36 37do_test select4-1.0 { 38 execsql {SELECT DISTINCT log FROM t1 ORDER BY log} 39} {0 1 2 3 4 5} 40 41# Union All operator 42# 43do_test select4-1.1a { 44 lsort [execsql {SELECT DISTINCT log FROM t1}] 45} {0 1 2 3 4 5} 46do_test select4-1.1b { 47 lsort [execsql {SELECT n FROM t1 WHERE log=3}] 48} {5 6 7 8} 49do_test select4-1.1c { 50 execsql { 51 SELECT DISTINCT log FROM t1 52 UNION ALL 53 SELECT n FROM t1 WHERE log=3 54 ORDER BY log; 55 } 56} {0 1 2 3 4 5 5 6 7 8} 57do_test select4-1.1d { 58 execsql { 59 CREATE TABLE t2 AS 60 SELECT DISTINCT log FROM t1 61 UNION ALL 62 SELECT n FROM t1 WHERE log=3 63 ORDER BY log; 64 SELECT * FROM t2; 65 } 66} {0 1 2 3 4 5 5 6 7 8} 67execsql {DROP TABLE t2} 68do_test select4-1.1e { 69 execsql { 70 CREATE TABLE t2 AS 71 SELECT DISTINCT log FROM t1 72 UNION ALL 73 SELECT n FROM t1 WHERE log=3 74 ORDER BY log DESC; 75 SELECT * FROM t2; 76 } 77} {8 7 6 5 5 4 3 2 1 0} 78execsql {DROP TABLE t2} 79do_test select4-1.1f { 80 execsql { 81 SELECT DISTINCT log FROM t1 82 UNION ALL 83 SELECT n FROM t1 WHERE log=2 84 } 85} {0 1 2 3 4 5 3 4} 86do_test select4-1.1g { 87 execsql { 88 CREATE TABLE t2 AS 89 SELECT DISTINCT log FROM t1 90 UNION ALL 91 SELECT n FROM t1 WHERE log=2; 92 SELECT * FROM t2; 93 } 94} {0 1 2 3 4 5 3 4} 95execsql {DROP TABLE t2} 96do_test select4-1.2 { 97 execsql { 98 SELECT log FROM t1 WHERE n IN 99 (SELECT DISTINCT log FROM t1 UNION ALL 100 SELECT n FROM t1 WHERE log=3) 101 ORDER BY log; 102 } 103} {0 1 2 2 3 3 3 3} 104do_test select4-1.3 { 105 set v [catch {execsql { 106 SELECT DISTINCT log FROM t1 ORDER BY log 107 UNION ALL 108 SELECT n FROM t1 WHERE log=3 109 ORDER BY log; 110 }} msg] 111 lappend v $msg 112} {1 {ORDER BY clause should come after UNION ALL not before}} 113 114# Union operator 115# 116do_test select4-2.1 { 117 execsql { 118 SELECT DISTINCT log FROM t1 119 UNION 120 SELECT n FROM t1 WHERE log=3 121 ORDER BY log; 122 } 123} {0 1 2 3 4 5 6 7 8} 124do_test select4-2.2 { 125 execsql { 126 SELECT log FROM t1 WHERE n IN 127 (SELECT DISTINCT log FROM t1 UNION 128 SELECT n FROM t1 WHERE log=3) 129 ORDER BY log; 130 } 131} {0 1 2 2 3 3 3 3} 132do_test select4-2.3 { 133 set v [catch {execsql { 134 SELECT DISTINCT log FROM t1 ORDER BY log 135 UNION 136 SELECT n FROM t1 WHERE log=3 137 ORDER BY log; 138 }} msg] 139 lappend v $msg 140} {1 {ORDER BY clause should come after UNION not before}} 141 142# Except operator 143# 144do_test select4-3.1.1 { 145 execsql { 146 SELECT DISTINCT log FROM t1 147 EXCEPT 148 SELECT n FROM t1 WHERE log=3 149 ORDER BY log; 150 } 151} {0 1 2 3 4} 152do_test select4-3.1.2 { 153 execsql { 154 CREATE TABLE t2 AS 155 SELECT DISTINCT log FROM t1 156 EXCEPT 157 SELECT n FROM t1 WHERE log=3 158 ORDER BY log; 159 SELECT * FROM t2; 160 } 161} {0 1 2 3 4} 162execsql {DROP TABLE t2} 163do_test select4-3.1.3 { 164 execsql { 165 CREATE TABLE t2 AS 166 SELECT DISTINCT log FROM t1 167 EXCEPT 168 SELECT n FROM t1 WHERE log=3 169 ORDER BY log DESC; 170 SELECT * FROM t2; 171 } 172} {4 3 2 1 0} 173execsql {DROP TABLE t2} 174do_test select4-3.2 { 175 execsql { 176 SELECT log FROM t1 WHERE n IN 177 (SELECT DISTINCT log FROM t1 EXCEPT 178 SELECT n FROM t1 WHERE log=3) 179 ORDER BY log; 180 } 181} {0 1 2 2} 182do_test select4-3.3 { 183 set v [catch {execsql { 184 SELECT DISTINCT log FROM t1 ORDER BY log 185 EXCEPT 186 SELECT n FROM t1 WHERE log=3 187 ORDER BY log; 188 }} msg] 189 lappend v $msg 190} {1 {ORDER BY clause should come after EXCEPT not before}} 191 192# Intersect operator 193# 194do_test select4-4.1.1 { 195 execsql { 196 SELECT DISTINCT log FROM t1 197 INTERSECT 198 SELECT n FROM t1 WHERE log=3 199 ORDER BY log; 200 } 201} {5} 202do_test select4-4.1.2 { 203 execsql { 204 SELECT DISTINCT log FROM t1 UNION ALL SELECT 6 205 INTERSECT 206 SELECT n FROM t1 WHERE log=3 207 ORDER BY log; 208 } 209} {5 6} 210do_test select4-4.1.3 { 211 execsql { 212 CREATE TABLE t2 AS 213 SELECT DISTINCT log FROM t1 UNION ALL SELECT 6 214 INTERSECT 215 SELECT n FROM t1 WHERE log=3 216 ORDER BY log; 217 SELECT * FROM t2; 218 } 219} {5 6} 220execsql {DROP TABLE t2} 221do_test select4-4.1.4 { 222 execsql { 223 CREATE TABLE t2 AS 224 SELECT DISTINCT log FROM t1 UNION ALL SELECT 6 225 INTERSECT 226 SELECT n FROM t1 WHERE log=3 227 ORDER BY log DESC; 228 SELECT * FROM t2; 229 } 230} {6 5} 231execsql {DROP TABLE t2} 232do_test select4-4.2 { 233 execsql { 234 SELECT log FROM t1 WHERE n IN 235 (SELECT DISTINCT log FROM t1 INTERSECT 236 SELECT n FROM t1 WHERE log=3) 237 ORDER BY log; 238 } 239} {3} 240do_test select4-4.3 { 241 set v [catch {execsql { 242 SELECT DISTINCT log FROM t1 ORDER BY log 243 INTERSECT 244 SELECT n FROM t1 WHERE log=3 245 ORDER BY log; 246 }} msg] 247 lappend v $msg 248} {1 {ORDER BY clause should come after INTERSECT not before}} 249 250# Various error messages while processing UNION or INTERSECT 251# 252do_test select4-5.1 { 253 set v [catch {execsql { 254 SELECT DISTINCT log FROM t2 255 UNION ALL 256 SELECT n FROM t1 WHERE log=3 257 ORDER BY log; 258 }} msg] 259 lappend v $msg 260} {1 {no such table: t2}} 261do_test select4-5.2 { 262 set v [catch {execsql { 263 SELECT DISTINCT log AS "xyzzy" FROM t1 264 UNION ALL 265 SELECT n FROM t1 WHERE log=3 266 ORDER BY xyzzy; 267 }} msg] 268 lappend v $msg 269} {0 {0 1 2 3 4 5 5 6 7 8}} 270do_test select4-5.2b { 271 set v [catch {execsql { 272 SELECT DISTINCT log AS xyzzy FROM t1 273 UNION ALL 274 SELECT n FROM t1 WHERE log=3 275 ORDER BY 'xyzzy'; 276 }} msg] 277 lappend v $msg 278} {0 {0 1 2 3 4 5 5 6 7 8}} 279do_test select4-5.2c { 280 set v [catch {execsql { 281 SELECT DISTINCT log FROM t1 282 UNION ALL 283 SELECT n FROM t1 WHERE log=3 284 ORDER BY 'xyzzy'; 285 }} msg] 286 lappend v $msg 287} {1 {ORDER BY term number 1 does not match any result column}} 288do_test select4-5.2d { 289 set v [catch {execsql { 290 SELECT DISTINCT log FROM t1 291 INTERSECT 292 SELECT n FROM t1 WHERE log=3 293 ORDER BY 'xyzzy'; 294 }} msg] 295 lappend v $msg 296} {1 {ORDER BY term number 1 does not match any result column}} 297do_test select4-5.2e { 298 set v [catch {execsql { 299 SELECT DISTINCT log FROM t1 300 UNION ALL 301 SELECT n FROM t1 WHERE log=3 302 ORDER BY n; 303 }} msg] 304 lappend v $msg 305} {0 {0 1 2 3 4 5 5 6 7 8}} 306do_test select4-5.2f { 307 catchsql { 308 SELECT DISTINCT log FROM t1 309 UNION ALL 310 SELECT n FROM t1 WHERE log=3 311 ORDER BY log; 312 } 313} {0 {0 1 2 3 4 5 5 6 7 8}} 314do_test select4-5.2g { 315 catchsql { 316 SELECT DISTINCT log FROM t1 317 UNION ALL 318 SELECT n FROM t1 WHERE log=3 319 ORDER BY 1; 320 } 321} {0 {0 1 2 3 4 5 5 6 7 8}} 322do_test select4-5.2h { 323 catchsql { 324 SELECT DISTINCT log FROM t1 325 UNION ALL 326 SELECT n FROM t1 WHERE log=3 327 ORDER BY 2; 328 } 329} {1 {ORDER BY position 2 should be between 1 and 1}} 330do_test select4-5.2i { 331 catchsql { 332 SELECT DISTINCT 1, log FROM t1 333 UNION ALL 334 SELECT 2, n FROM t1 WHERE log=3 335 ORDER BY 2, 1; 336 } 337} {0 {1 0 1 1 1 2 1 3 1 4 1 5 2 5 2 6 2 7 2 8}} 338do_test select4-5.2j { 339 catchsql { 340 SELECT DISTINCT 1, log FROM t1 341 UNION ALL 342 SELECT 2, n FROM t1 WHERE log=3 343 ORDER BY 1, 2 DESC; 344 } 345} {0 {1 5 1 4 1 3 1 2 1 1 1 0 2 8 2 7 2 6 2 5}} 346do_test select4-5.2k { 347 catchsql { 348 SELECT DISTINCT 1, log FROM t1 349 UNION ALL 350 SELECT 2, n FROM t1 WHERE log=3 351 ORDER BY n, 1; 352 } 353} {0 {1 0 1 1 1 2 1 3 1 4 1 5 2 5 2 6 2 7 2 8}} 354do_test select4-5.3 { 355 set v [catch {execsql { 356 SELECT DISTINCT log, n FROM t1 357 UNION ALL 358 SELECT n FROM t1 WHERE log=3 359 ORDER BY log; 360 }} msg] 361 lappend v $msg 362} {1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}} 363do_test select4-5.4 { 364 set v [catch {execsql { 365 SELECT log FROM t1 WHERE n=2 366 UNION ALL 367 SELECT log FROM t1 WHERE n=3 368 UNION ALL 369 SELECT log FROM t1 WHERE n=4 370 UNION ALL 371 SELECT log FROM t1 WHERE n=5 372 ORDER BY log; 373 }} msg] 374 lappend v $msg 375} {0 {1 2 2 3}} 376 377do_test select4-6.1 { 378 execsql { 379 SELECT log, count(*) as cnt FROM t1 GROUP BY log 380 UNION 381 SELECT log, n FROM t1 WHERE n=7 382 ORDER BY cnt, log; 383 } 384} {0 1 1 1 2 2 3 4 3 7 4 8 5 15} 385do_test select4-6.2 { 386 execsql { 387 SELECT log, count(*) FROM t1 GROUP BY log 388 UNION 389 SELECT log, n FROM t1 WHERE n=7 390 ORDER BY count(*), log; 391 } 392} {0 1 1 1 2 2 3 4 3 7 4 8 5 15} 393 394# NULLs are indistinct for the UNION operator. 395# Make sure the UNION operator recognizes this 396# 397do_test select4-6.3 { 398 execsql { 399 SELECT NULL UNION SELECT NULL UNION 400 SELECT 1 UNION SELECT 2 AS 'x' 401 ORDER BY x; 402 } 403} {{} 1 2} 404do_test select4-6.3.1 { 405 execsql { 406 SELECT NULL UNION ALL SELECT NULL UNION ALL 407 SELECT 1 UNION ALL SELECT 2 AS 'x' 408 ORDER BY x; 409 } 410} {{} {} 1 2} 411 412# Make sure the DISTINCT keyword treats NULLs as indistinct. 413# 414do_test select4-6.4 { 415 execsql { 416 SELECT * FROM ( 417 SELECT NULL, 1 UNION ALL SELECT NULL, 1 418 ); 419 } 420} {{} 1 {} 1} 421do_test select4-6.5 { 422 execsql { 423 SELECT DISTINCT * FROM ( 424 SELECT NULL, 1 UNION ALL SELECT NULL, 1 425 ); 426 } 427} {{} 1} 428do_test select4-6.6 { 429 execsql { 430 SELECT DISTINCT * FROM ( 431 SELECT 1,2 UNION ALL SELECT 1,2 432 ); 433 } 434} {1 2} 435 436# Test distinctness of NULL in other ways. 437# 438do_test select4-6.7 { 439 execsql { 440 SELECT NULL EXCEPT SELECT NULL 441 } 442} {} 443 444 445# Make sure column names are correct when a compound select appears as 446# an expression in the WHERE clause. 447# 448do_test select4-7.1 { 449 execsql { 450 CREATE TABLE t2 AS SELECT log AS 'x', count(*) AS 'y' FROM t1 GROUP BY log; 451 SELECT * FROM t2 ORDER BY x; 452 } 453} {0 1 1 1 2 2 3 4 4 8 5 15} 454do_test select4-7.2 { 455 execsql2 { 456 SELECT * FROM t1 WHERE n IN (SELECT n FROM t1 INTERSECT SELECT x FROM t2) 457 ORDER BY n 458 } 459} {n 1 log 0 n 2 log 1 n 3 log 2 n 4 log 2 n 5 log 3} 460do_test select4-7.3 { 461 execsql2 { 462 SELECT * FROM t1 WHERE n IN (SELECT n FROM t1 EXCEPT SELECT x FROM t2) 463 ORDER BY n LIMIT 2 464 } 465} {n 6 log 3 n 7 log 3} 466do_test select4-7.4 { 467 execsql2 { 468 SELECT * FROM t1 WHERE n IN (SELECT n FROM t1 UNION SELECT x FROM t2) 469 ORDER BY n LIMIT 2 470 } 471} {n 1 log 0 n 2 log 1} 472 473# Make sure DISTINCT works appropriately on TEXT and NUMERIC columns. 474# 475do_test select4-8.1 { 476 execsql { 477 BEGIN; 478 CREATE TABLE t3(a text, b float, c text); 479 INSERT INTO t3 VALUES(1, 1.1, '1.1'); 480 INSERT INTO t3 VALUES(2, 1.10, '1.10'); 481 INSERT INTO t3 VALUES(3, 1.10, '1.1'); 482 INSERT INTO t3 VALUES(4, 1.1, '1.10'); 483 INSERT INTO t3 VALUES(5, 1.2, '1.2'); 484 INSERT INTO t3 VALUES(6, 1.3, '1.3'); 485 COMMIT; 486 } 487 execsql { 488 SELECT DISTINCT b FROM t3 ORDER BY c; 489 } 490} {1.1 1.2 1.3} 491do_test select4-8.2 { 492 execsql { 493 SELECT DISTINCT c FROM t3 ORDER BY c; 494 } 495} {1.1 1.10 1.2 1.3} 496 497 498finish_test 499