1# 2001 September 15 2# 3# The author disclaims copyright to this source code. In place of 4# a legal notice, here is a blessing: 5# 6# May you do good and not evil. 7# May you find forgiveness for yourself and forgive others. 8# May you share freely, never taking more than you give. 9# 10#*********************************************************************** 11# This file implements regression tests for SQLite library. The 12# focus of this file is testing SELECT statements that contain 13# aggregate min() and max() functions and which are handled as 14# as a special case. 15# 16# $Id: minmax.test,v 1.21 2008/07/08 18:05:26 drh Exp $ 17 18set testdir [file dirname $argv0] 19source $testdir/tester.tcl 20set ::testprefix minmax 21 22do_test minmax-1.0 { 23 execsql { 24 BEGIN; 25 CREATE TABLE t1(x, y); 26 INSERT INTO t1 VALUES(1,1); 27 INSERT INTO t1 VALUES(2,2); 28 INSERT INTO t1 VALUES(3,2); 29 INSERT INTO t1 VALUES(4,3); 30 INSERT INTO t1 VALUES(5,3); 31 INSERT INTO t1 VALUES(6,3); 32 INSERT INTO t1 VALUES(7,3); 33 INSERT INTO t1 VALUES(8,4); 34 INSERT INTO t1 VALUES(9,4); 35 INSERT INTO t1 VALUES(10,4); 36 INSERT INTO t1 VALUES(11,4); 37 INSERT INTO t1 VALUES(12,4); 38 INSERT INTO t1 VALUES(13,4); 39 INSERT INTO t1 VALUES(14,4); 40 INSERT INTO t1 VALUES(15,4); 41 INSERT INTO t1 VALUES(16,5); 42 INSERT INTO t1 VALUES(17,5); 43 INSERT INTO t1 VALUES(18,5); 44 INSERT INTO t1 VALUES(19,5); 45 INSERT INTO t1 VALUES(20,5); 46 COMMIT; 47 SELECT DISTINCT y FROM t1 ORDER BY y; 48 } 49} {1 2 3 4 5} 50 51do_test minmax-1.1 { 52 set sqlite_search_count 0 53 execsql {SELECT min(x) FROM t1} 54} {1} 55do_test minmax-1.2 { 56 set sqlite_search_count 57} {19} 58do_test minmax-1.3 { 59 set sqlite_search_count 0 60 execsql {SELECT max(x) FROM t1} 61} {20} 62do_test minmax-1.4 { 63 set sqlite_search_count 64} {19} 65do_test minmax-1.5 { 66 execsql {CREATE INDEX t1i1 ON t1(x)} 67 set sqlite_search_count 0 68 execsql {SELECT min(x) FROM t1} 69} {1} 70do_test minmax-1.6 { 71 set sqlite_search_count 72} {1} 73do_test minmax-1.7 { 74 set sqlite_search_count 0 75 execsql {SELECT max(x) FROM t1} 76} {20} 77do_test minmax-1.8 { 78 set sqlite_search_count 79} {0} 80do_test minmax-1.9 { 81 set sqlite_search_count 0 82 execsql {SELECT max(y) FROM t1} 83} {5} 84do_test minmax-1.10 { 85 set sqlite_search_count 86} {19} 87 88do_test minmax-1.21 { 89 execsql {SELECT min(x) FROM t1 WHERE x=5} 90} {5} 91do_test minmax-1.22 { 92 execsql {SELECT min(x) FROM t1 WHERE x>=5} 93} {5} 94do_test minmax-1.23 { 95 execsql {SELECT min(x) FROM t1 WHERE x>=4.5} 96} {5} 97do_test minmax-1.24 { 98 execsql {SELECT min(x) FROM t1 WHERE x<4.5} 99} {1} 100 101do_test minmax-2.0 { 102 execsql { 103 CREATE TABLE t2(a INTEGER PRIMARY KEY, b); 104 INSERT INTO t2 SELECT * FROM t1; 105 } 106 set sqlite_search_count 0 107 execsql {SELECT min(a) FROM t2} 108} {1} 109do_test minmax-2.1 { 110 set sqlite_search_count 111} {0} 112do_test minmax-2.2 { 113 set sqlite_search_count 0 114 execsql {SELECT max(a) FROM t2} 115} {20} 116do_test minmax-2.3 { 117 set sqlite_search_count 118} {0} 119 120do_test minmax-3.0 { 121 ifcapable subquery { 122 execsql {INSERT INTO t2 VALUES((SELECT max(a) FROM t2)+1,999)} 123 } else { 124 db function max_a_t2 {execsql {SELECT max(a) FROM t2}} 125 execsql {INSERT INTO t2 VALUES(max_a_t2()+1,999)} 126 } 127 set sqlite_search_count 0 128 execsql {SELECT max(a) FROM t2} 129} {21} 130do_test minmax-3.1 { 131 set sqlite_search_count 132} {0} 133do_test minmax-3.2 { 134 ifcapable subquery { 135 execsql {INSERT INTO t2 VALUES((SELECT max(a) FROM t2)+1,999)} 136 } else { 137 db function max_a_t2 {execsql {SELECT max(a) FROM t2}} 138 execsql {INSERT INTO t2 VALUES(max_a_t2()+1,999)} 139 } 140 set sqlite_search_count 0 141 ifcapable subquery { 142 execsql { SELECT b FROM t2 WHERE a=(SELECT max(a) FROM t2) } 143 } else { 144 execsql { SELECT b FROM t2 WHERE a=max_a_t2() } 145 } 146} {999} 147do_test minmax-3.3 { 148 set sqlite_search_count 149} {0} 150 151ifcapable {compound && subquery} { 152 do_test minmax-4.1 { 153 execsql { 154 SELECT coalesce(min(x+0),-1), coalesce(max(x+0),-1) FROM 155 (SELECT * FROM t1 UNION SELECT NULL as 'x', NULL as 'y') 156 } 157 } {1 20} 158 do_test minmax-4.2 { 159 execsql { 160 SELECT y, coalesce(sum(x),0) FROM 161 (SELECT null AS x, y+1 AS y FROM t1 UNION SELECT * FROM t1) 162 GROUP BY y ORDER BY y; 163 } 164 } {1 1 2 5 3 22 4 92 5 90 6 0} 165 do_test minmax-4.3 { 166 execsql { 167 SELECT y, count(x), count(*) FROM 168 (SELECT null AS x, y+1 AS y FROM t1 UNION SELECT * FROM t1) 169 GROUP BY y ORDER BY y; 170 } 171 } {1 1 1 2 2 3 3 4 5 4 8 9 5 5 6 6 0 1} 172} ;# ifcapable compound 173 174# Make sure the min(x) and max(x) optimizations work on empty tables 175# including empty tables with indices. Ticket #296. 176# 177do_test minmax-5.1 { 178 execsql { 179 CREATE TABLE t3(x INTEGER UNIQUE NOT NULL); 180 SELECT coalesce(min(x),999) FROM t3; 181 } 182} {999} 183do_test minmax-5.2 { 184 execsql { 185 SELECT coalesce(min(rowid),999) FROM t3; 186 } 187} {999} 188do_test minmax-5.3 { 189 execsql { 190 SELECT coalesce(max(x),999) FROM t3; 191 } 192} {999} 193do_test minmax-5.4 { 194 execsql { 195 SELECT coalesce(max(rowid),999) FROM t3; 196 } 197} {999} 198do_test minmax-5.5 { 199 execsql { 200 SELECT coalesce(max(rowid),999) FROM t3 WHERE rowid<25; 201 } 202} {999} 203 204# Make sure the min(x) and max(x) optimizations work when there 205# is a LIMIT clause. Ticket #396. 206# 207do_test minmax-6.1 { 208 execsql { 209 SELECT min(a) FROM t2 LIMIT 1 210 } 211} {1} 212do_test minmax-6.2 { 213 execsql { 214 SELECT max(a) FROM t2 LIMIT 3 215 } 216} {22} 217do_test minmax-6.3 { 218 execsql { 219 SELECT min(a) FROM t2 LIMIT 0,100 220 } 221} {1} 222do_test minmax-6.4 { 223 execsql { 224 SELECT max(a) FROM t2 LIMIT 1,100 225 } 226} {} 227do_test minmax-6.5 { 228 execsql { 229 SELECT min(x) FROM t3 LIMIT 1 230 } 231} {{}} 232do_test minmax-6.6 { 233 execsql { 234 SELECT max(x) FROM t3 LIMIT 0 235 } 236} {} 237do_test minmax-6.7 { 238 execsql { 239 SELECT max(a) FROM t2 LIMIT 0 240 } 241} {} 242 243# Make sure the max(x) and min(x) optimizations work for nested 244# queries. Ticket #587. 245# 246do_test minmax-7.1 { 247 execsql { 248 SELECT max(x) FROM t1; 249 } 250} 20 251ifcapable subquery { 252 do_test minmax-7.2 { 253 execsql { 254 SELECT * FROM (SELECT max(x) FROM t1); 255 } 256 } 20 257} 258do_test minmax-7.3 { 259 execsql { 260 SELECT min(x) FROM t1; 261 } 262} 1 263ifcapable subquery { 264 do_test minmax-7.4 { 265 execsql { 266 SELECT * FROM (SELECT min(x) FROM t1); 267 } 268 } 1 269} 270 271# Make sure min(x) and max(x) work correctly when the datatype is 272# TEXT instead of NUMERIC. Ticket #623. 273# 274do_test minmax-8.1 { 275 execsql { 276 CREATE TABLE t4(a TEXT); 277 INSERT INTO t4 VALUES('1234'); 278 INSERT INTO t4 VALUES('234'); 279 INSERT INTO t4 VALUES('34'); 280 SELECT min(a), max(a) FROM t4; 281 } 282} {1234 34} 283do_test minmax-8.2 { 284 execsql { 285 CREATE TABLE t5(a INTEGER); 286 INSERT INTO t5 VALUES('1234'); 287 INSERT INTO t5 VALUES('234'); 288 INSERT INTO t5 VALUES('34'); 289 SELECT min(a), max(a) FROM t5; 290 } 291} {34 1234} 292 293# Ticket #658: Test the min()/max() optimization when the FROM clause 294# is a subquery. 295# 296ifcapable {compound && subquery} { 297 do_test minmax-9.0 { 298 execsql { 299 SELECT max(rowid) AS yy FROM t4 UNION SELECT max(rowid) FROM t5 300 } 301 } {3} 302 do_test minmax-9.1 { 303 execsql { 304 SELECT max(yy) FROM ( 305 SELECT max(rowid) AS yy FROM t4 UNION SELECT max(rowid) FROM t5 306 ) 307 } 308 } {3} 309 do_test minmax-9.2 { 310 execsql { 311 SELECT max(yy) FROM ( 312 SELECT max(rowid) AS yy FROM t4 EXCEPT SELECT max(rowid) FROM t5 313 ) 314 } 315 } {{}} 316} ;# ifcapable compound&&subquery 317 318# If there is a NULL in an aggregate max() or min(), ignore it. An 319# aggregate min() or max() will only return NULL if all values are NULL. 320# 321do_test minmax-10.1 { 322 execsql { 323 CREATE TABLE t6(x); 324 INSERT INTO t6 VALUES(1); 325 INSERT INTO t6 VALUES(2); 326 INSERT INTO t6 VALUES(NULL); 327 SELECT coalesce(min(x),-1) FROM t6; 328 } 329} {1} 330do_test minmax-10.2 { 331 execsql { 332 SELECT max(x) FROM t6; 333 } 334} {2} 335do_test minmax-10.3 { 336 execsql { 337 CREATE INDEX i6 ON t6(x); 338 SELECT coalesce(min(x),-1) FROM t6; 339 } 340} {1} 341do_test minmax-10.4 { 342 execsql { 343 SELECT max(x) FROM t6; 344 } 345} {2} 346do_test minmax-10.5 { 347 execsql { 348 DELETE FROM t6 WHERE x NOT NULL; 349 SELECT count(*) FROM t6; 350 } 351} 1 352do_test minmax-10.6 { 353 execsql { 354 SELECT count(x) FROM t6; 355 } 356} 0 357ifcapable subquery { 358 do_test minmax-10.7 { 359 execsql { 360 SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6); 361 } 362 } {{} {}} 363} 364do_test minmax-10.8 { 365 execsql { 366 SELECT min(x), max(x) FROM t6; 367 } 368} {{} {}} 369do_test minmax-10.9 { 370 execsql { 371 INSERT INTO t6 SELECT * FROM t6; 372 INSERT INTO t6 SELECT * FROM t6; 373 INSERT INTO t6 SELECT * FROM t6; 374 INSERT INTO t6 SELECT * FROM t6; 375 INSERT INTO t6 SELECT * FROM t6; 376 INSERT INTO t6 SELECT * FROM t6; 377 INSERT INTO t6 SELECT * FROM t6; 378 INSERT INTO t6 SELECT * FROM t6; 379 INSERT INTO t6 SELECT * FROM t6; 380 INSERT INTO t6 SELECT * FROM t6; 381 SELECT count(*) FROM t6; 382 } 383} 1024 384do_test minmax-10.10 { 385 execsql { 386 SELECT count(x) FROM t6; 387 } 388} 0 389ifcapable subquery { 390 do_test minmax-10.11 { 391 execsql { 392 SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6); 393 } 394 } {{} {}} 395} 396do_test minmax-10.12 { 397 execsql { 398 SELECT min(x), max(x) FROM t6; 399 } 400} {{} {}} 401 402 403do_test minmax-11.1 { 404 execsql { 405 CREATE INDEX t1i2 ON t1(y,x); 406 SELECT min(x) FROM t1 WHERE y=5; 407 } 408} {16} 409do_test minmax-11.2 { 410 execsql { 411 SELECT max(x) FROM t1 WHERE y=5; 412 } 413} {20} 414do_test minmax-11.3 { 415 execsql { 416 SELECT min(x) FROM t1 WHERE y=6; 417 } 418} {{}} 419do_test minmax-11.4 { 420 execsql { 421 SELECT max(x) FROM t1 WHERE y=6; 422 } 423} {{}} 424do_test minmax-11.5 { 425 execsql { 426 SELECT min(x) FROM t1 WHERE y=1; 427 } 428} {1} 429do_test minmax-11.6 { 430 execsql { 431 SELECT max(x) FROM t1 WHERE y=1; 432 } 433} {1} 434do_test minmax-11.7 { 435 execsql { 436 SELECT min(x) FROM t1 WHERE y=0; 437 } 438} {{}} 439do_test minmax-11.8 { 440 execsql { 441 SELECT max(x) FROM t1 WHERE y=0; 442 } 443} {{}} 444do_test minmax-11.9 { 445 execsql { 446 SELECT min(x) FROM t1 WHERE y=5 AND x>=17.5; 447 } 448} {18} 449do_test minmax-11.10 { 450 execsql { 451 SELECT max(x) FROM t1 WHERE y=5 AND x>=17.5; 452 } 453} {20} 454 455do_test minmax-12.1 { 456 execsql { 457 CREATE TABLE t7(a,b,c); 458 INSERT INTO t7 SELECT y, x, x*y FROM t1; 459 INSERT INTO t7 SELECT y, x, x*y+1000 FROM t1; 460 CREATE INDEX t7i1 ON t7(a,b,c); 461 SELECT min(a) FROM t7; 462 } 463} {1} 464do_test minmax-12.2 { 465 execsql { 466 SELECT max(a) FROM t7; 467 } 468} {5} 469do_test minmax-12.3 { 470 execsql { 471 SELECT max(a) FROM t7 WHERE a=5; 472 } 473} {5} 474do_test minmax-12.4 { 475 execsql { 476 SELECT min(b) FROM t7 WHERE a=5; 477 } 478} {16} 479do_test minmax-12.5 { 480 execsql { 481 SELECT max(b) FROM t7 WHERE a=5; 482 } 483} {20} 484do_test minmax-12.6 { 485 execsql { 486 SELECT min(b) FROM t7 WHERE a=4; 487 } 488} {8} 489do_test minmax-12.7 { 490 execsql { 491 SELECT max(b) FROM t7 WHERE a=4; 492 } 493} {15} 494do_test minmax-12.8 { 495 execsql { 496 SELECT min(c) FROM t7 WHERE a=4 AND b=10; 497 } 498} {40} 499do_test minmax-12.9 { 500 execsql { 501 SELECT max(c) FROM t7 WHERE a=4 AND b=10; 502 } 503} {1040} 504do_test minmax-12.10 { 505 execsql { 506 SELECT min(rowid) FROM t7; 507 } 508} {1} 509do_test minmax-12.11 { 510 execsql { 511 SELECT max(rowid) FROM t7; 512 } 513} {40} 514do_test minmax-12.12 { 515 execsql { 516 SELECT min(rowid) FROM t7 WHERE a=3; 517 } 518} {4} 519do_test minmax-12.13 { 520 execsql { 521 SELECT max(rowid) FROM t7 WHERE a=3; 522 } 523} {27} 524do_test minmax-12.14 { 525 execsql { 526 SELECT min(rowid) FROM t7 WHERE a=3 AND b=5; 527 } 528} {5} 529do_test minmax-12.15 { 530 execsql { 531 SELECT max(rowid) FROM t7 WHERE a=3 AND b=5; 532 } 533} {25} 534do_test minmax-12.16 { 535 execsql { 536 SELECT min(rowid) FROM t7 WHERE a=3 AND b=5 AND c=1015; 537 } 538} {25} 539do_test minmax-12.17 { 540 execsql { 541 SELECT max(rowid) FROM t7 WHERE a=3 AND b=5 AND c=15; 542 } 543} {5} 544 545#------------------------------------------------------------------------- 546reset_db 547 548proc do_test_13 {op name sql1 sql2 res} { 549 set ::sqlite_search_count 0 550 uplevel [list do_execsql_test $name.1 $sql1 $res] 551 set a $::sqlite_search_count 552 553 set ::sqlite_search_count 0 554 uplevel [list do_execsql_test $name.2 $sql2 $res] 555 set b $::sqlite_search_count 556 557 uplevel [list do_test $name.3 [list expr "$a $op $b"] 1] 558} 559 560# Run a test named $name. Check that SQL statements $sql1 and $sql2 both 561# return the same result, but that $sql2 increments the $sqlite_search_count 562# variable more often (indicating that it is visiting more rows to determine 563# the result). 564# 565proc do_test_13_opt {name sql1 sql2 res} { 566 uplevel [list do_test_13 < $name $sql1 $sql2 $res] 567} 568 569# Like [do_test_13_noopt], except this time check that the $sqlite_search_count 570# variable is incremented the same number of times by both SQL statements. 571# 572proc do_test_13_noopt {name sql1 sql2 res} { 573 uplevel [list do_test_13 == $name $sql1 $sql2 $res] 574} 575 576do_execsql_test 13.1 { 577 CREATE TABLE t1(a, b, c); 578 INSERT INTO t1 VALUES('a', 1, 1); 579 INSERT INTO t1 VALUES('b', 6, 6); 580 INSERT INTO t1 VALUES('c', 5, 5); 581 INSERT INTO t1 VALUES('a', 4, 4); 582 INSERT INTO t1 VALUES('a', 5, 5); 583 INSERT INTO t1 VALUES('c', 6, 6); 584 INSERT INTO t1 VALUES('b', 4, 4); 585 INSERT INTO t1 VALUES('c', 7, 7); 586 INSERT INTO t1 VALUES('b', 2, 2); 587 INSERT INTO t1 VALUES('b', 3, 3); 588 INSERT INTO t1 VALUES('a', 3, 3); 589 INSERT INTO t1 VALUES('b', 5, 5); 590 INSERT INTO t1 VALUES('c', 4, 4); 591 INSERT INTO t1 VALUES('c', 3, 3); 592 INSERT INTO t1 VALUES('a', 2, 2); 593 SELECT * FROM t1 ORDER BY a, b, c; 594} {a 1 1 a 2 2 a 3 3 a 4 4 a 5 5 595 b 2 2 b 3 3 b 4 4 b 5 5 b 6 6 596 c 3 3 c 4 4 c 5 5 c 6 6 c 7 7 597} 598do_execsql_test 13.2 { CREATE INDEX i1 ON t1(a, b, c) } 599 600do_test_13_opt 13.3 { 601 SELECT min(b) FROM t1 WHERE a='b' 602} { 603 SELECT min(c) FROM t1 WHERE a='b' 604} {2} 605 606do_test_13_opt 13.4 { 607 SELECT a, min(b) FROM t1 WHERE a='b' 608} { 609 SELECT a, min(c) FROM t1 WHERE a='b' 610} {b 2} 611 612do_test_13_opt 13.4 { 613 SELECT a||c, max(b)+4 FROM t1 WHERE a='c' 614} { 615 SELECT a||c, max(c)+4 FROM t1 WHERE a='c' 616} {c7 11} 617 618do_test_13_noopt 13.5 { 619 SELECT a||c, max(b+1) FROM t1 WHERE a='c' 620} { 621 SELECT a||c, max(c+1) FROM t1 WHERE a='c' 622} {c7 8} 623 624do_test_13_noopt 13.6 { 625 SELECT count(b) FROM t1 WHERE a='c' 626} { 627 SELECT count(c) FROM t1 WHERE a='c' 628} {5} 629 630do_test_13_noopt 13.7 { 631 SELECT min(b), count(b) FROM t1 WHERE a='a'; 632} { 633 SELECT min(c), count(c) FROM t1 WHERE a='a'; 634} {1 5} 635 636# 2016-07-26. https://www.sqlite.org/src/info/a0bac8b3c3d1bb75 637# Incorrect result on a min() query after a CREATE INDEX. 638# 639do_execsql_test 14.1 { 640 CREATE TABLE t14(a INTEGER, b INTEGER); 641 INSERT INTO t14(a,b) VALUES(100,2),(200,2),(300,2),(400,1),(500,2); 642 SELECT min(a) FROM t14 WHERE b='2' AND a>'50'; 643} {100} 644do_execsql_test 14.2 { 645 CREATE INDEX t14ba ON t14(b,a); 646 SELECT min(a) FROM t14 WHERE b='2' AND a>'50'; 647} {100} 648 649# 2021-08-21. https://sqlite.org/forum/forumpost/cfcb4b461d 650# 651reset_db 652do_execsql_test 15.1 { 653 CREATE TABLE t1(a); 654 CREATE TABLE t2(b); 655 CREATE TABLE t3(c); 656 INSERT INTO t1 VALUES(0); 657 INSERT INTO t2 VALUES(5); 658 SELECT MIN((SELECT b FROM t2 UNION SELECT x FROM (SELECT x FROM (SELECT 1 AS x WHERE t1.a=1) UNION ALL SELECT c FROM t3))) FROM t1; 659} {5} 660 661finish_test 662