1# 2007 July 17 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. This file makes sure that the min/max 15# optimization works right in the presence of descending 16# indices. Ticket #2514. 17# 18# $Id: minmax2.test,v 1.2 2008/01/05 17:39:30 danielk1977 Exp $ 19 20set testdir [file dirname $argv0] 21source $testdir/tester.tcl 22 23do_test minmax2-1.0 { 24 sqlite3_db_config db LEGACY_FILE_FORMAT 0 25 execsql { 26 BEGIN; 27 CREATE TABLE t1(x, y); 28 INSERT INTO t1 VALUES(1,1); 29 INSERT INTO t1 VALUES(2,2); 30 INSERT INTO t1 VALUES(3,2); 31 INSERT INTO t1 VALUES(4,3); 32 INSERT INTO t1 VALUES(5,3); 33 INSERT INTO t1 VALUES(6,3); 34 INSERT INTO t1 VALUES(7,3); 35 INSERT INTO t1 VALUES(8,4); 36 INSERT INTO t1 VALUES(9,4); 37 INSERT INTO t1 VALUES(10,4); 38 INSERT INTO t1 VALUES(11,4); 39 INSERT INTO t1 VALUES(12,4); 40 INSERT INTO t1 VALUES(13,4); 41 INSERT INTO t1 VALUES(14,4); 42 INSERT INTO t1 VALUES(15,4); 43 INSERT INTO t1 VALUES(16,5); 44 INSERT INTO t1 VALUES(17,5); 45 INSERT INTO t1 VALUES(18,5); 46 INSERT INTO t1 VALUES(19,5); 47 INSERT INTO t1 VALUES(20,5); 48 COMMIT; 49 SELECT DISTINCT y FROM t1 ORDER BY y; 50 } 51} {1 2 3 4 5} 52 53do_test minmax2-1.1 { 54 set sqlite_search_count 0 55 execsql {SELECT min(x) FROM t1} 56} {1} 57do_test minmax2-1.2 { 58 set sqlite_search_count 59} {19} 60do_test minmax2-1.3 { 61 set sqlite_search_count 0 62 execsql {SELECT max(x) FROM t1} 63} {20} 64do_test minmax2-1.4 { 65 set sqlite_search_count 66} {19} 67do_test minmax2-1.5 { 68 execsql {CREATE INDEX t1i1 ON t1(x DESC)} 69 set sqlite_search_count 0 70 execsql {SELECT min(x) FROM t1} 71} {1} 72do_test minmax2-1.6 { 73 set sqlite_search_count 74} {1} 75do_test minmax2-1.7 { 76 set sqlite_search_count 0 77 execsql {SELECT max(x) FROM t1} 78} {20} 79do_test minmax2-1.8 { 80 set sqlite_search_count 81} {0} 82do_test minmax2-1.9 { 83 set sqlite_search_count 0 84 execsql {SELECT max(y) FROM t1} 85} {5} 86do_test minmax2-1.10 { 87 set sqlite_search_count 88} {19} 89 90do_test minmax2-2.0 { 91 execsql { 92 CREATE TABLE t2(a INTEGER PRIMARY KEY, b); 93 INSERT INTO t2 SELECT * FROM t1; 94 } 95 set sqlite_search_count 0 96 execsql {SELECT min(a) FROM t2} 97} {1} 98do_test minmax2-2.1 { 99 set sqlite_search_count 100} {0} 101do_test minmax2-2.2 { 102 set sqlite_search_count 0 103 execsql {SELECT max(a) FROM t2} 104} {20} 105do_test minmax2-2.3 { 106 set sqlite_search_count 107} {0} 108 109do_test minmax2-3.0 { 110 ifcapable subquery { 111 execsql {INSERT INTO t2 VALUES((SELECT max(a) FROM t2)+1,999)} 112 } else { 113 db function max_a_t2 {execsql {SELECT max(a) FROM t2}} 114 execsql {INSERT INTO t2 VALUES(max_a_t2()+1,999)} 115 } 116 set sqlite_search_count 0 117 execsql {SELECT max(a) FROM t2} 118} {21} 119do_test minmax2-3.1 { 120 set sqlite_search_count 121} {0} 122do_test minmax2-3.2 { 123 ifcapable subquery { 124 execsql {INSERT INTO t2 VALUES((SELECT max(a) FROM t2)+1,999)} 125 } else { 126 db function max_a_t2 {execsql {SELECT max(a) FROM t2}} 127 execsql {INSERT INTO t2 VALUES(max_a_t2()+1,999)} 128 } 129 set sqlite_search_count 0 130 ifcapable subquery { 131 execsql { SELECT b FROM t2 WHERE a=(SELECT max(a) FROM t2) } 132 } else { 133 execsql { SELECT b FROM t2 WHERE a=max_a_t2() } 134 } 135} {999} 136do_test minmax2-3.3 { 137 set sqlite_search_count 138} {0} 139 140ifcapable {compound && subquery} { 141 do_test minmax2-4.1 { 142 execsql { 143 SELECT coalesce(min(x+0),-1), coalesce(max(x+0),-1) FROM 144 (SELECT * FROM t1 UNION SELECT NULL as 'x', NULL as 'y') 145 } 146 } {1 20} 147 do_test minmax2-4.2 { 148 execsql { 149 SELECT y, coalesce(sum(x),0) FROM 150 (SELECT null AS x, y+1 AS y FROM t1 UNION SELECT * FROM t1) 151 GROUP BY y ORDER BY y; 152 } 153 } {1 1 2 5 3 22 4 92 5 90 6 0} 154 do_test minmax2-4.3 { 155 execsql { 156 SELECT y, count(x), count(*) FROM 157 (SELECT null AS x, y+1 AS y FROM t1 UNION SELECT * FROM t1) 158 GROUP BY y ORDER BY y; 159 } 160 } {1 1 1 2 2 3 3 4 5 4 8 9 5 5 6 6 0 1} 161} ;# ifcapable compound 162 163# Make sure the min(x) and max(x) optimizations work on empty tables 164# including empty tables with indices. Ticket #296. 165# 166do_test minmax2-5.1 { 167 execsql { 168 CREATE TABLE t3(x INTEGER UNIQUE NOT NULL); 169 SELECT coalesce(min(x),999) FROM t3; 170 } 171} {999} 172do_test minmax2-5.2 { 173 execsql { 174 SELECT coalesce(min(rowid),999) FROM t3; 175 } 176} {999} 177do_test minmax2-5.3 { 178 execsql { 179 SELECT coalesce(max(x),999) FROM t3; 180 } 181} {999} 182do_test minmax2-5.4 { 183 execsql { 184 SELECT coalesce(max(rowid),999) FROM t3; 185 } 186} {999} 187do_test minmax2-5.5 { 188 execsql { 189 SELECT coalesce(max(rowid),999) FROM t3 WHERE rowid<25; 190 } 191} {999} 192 193# Make sure the min(x) and max(x) optimizations work when there 194# is a LIMIT clause. Ticket #396. 195# 196do_test minmax2-6.1 { 197 execsql { 198 SELECT min(a) FROM t2 LIMIT 1 199 } 200} {1} 201do_test minmax2-6.2 { 202 execsql { 203 SELECT max(a) FROM t2 LIMIT 3 204 } 205} {22} 206do_test minmax2-6.3 { 207 execsql { 208 SELECT min(a) FROM t2 LIMIT 0,100 209 } 210} {1} 211do_test minmax2-6.4 { 212 execsql { 213 SELECT max(a) FROM t2 LIMIT 1,100 214 } 215} {} 216do_test minmax2-6.5 { 217 execsql { 218 SELECT min(x) FROM t3 LIMIT 1 219 } 220} {{}} 221do_test minmax2-6.6 { 222 execsql { 223 SELECT max(x) FROM t3 LIMIT 0 224 } 225} {} 226do_test minmax2-6.7 { 227 execsql { 228 SELECT max(a) FROM t2 LIMIT 0 229 } 230} {} 231 232# Make sure the max(x) and min(x) optimizations work for nested 233# queries. Ticket #587. 234# 235do_test minmax2-7.1 { 236 execsql { 237 SELECT max(x) FROM t1; 238 } 239} 20 240ifcapable subquery { 241 do_test minmax2-7.2 { 242 execsql { 243 SELECT * FROM (SELECT max(x) FROM t1); 244 } 245 } 20 246} 247do_test minmax2-7.3 { 248 execsql { 249 SELECT min(x) FROM t1; 250 } 251} 1 252ifcapable subquery { 253 do_test minmax2-7.4 { 254 execsql { 255 SELECT * FROM (SELECT min(x) FROM t1); 256 } 257 } 1 258} 259 260# Make sure min(x) and max(x) work correctly when the datatype is 261# TEXT instead of NUMERIC. Ticket #623. 262# 263do_test minmax2-8.1 { 264 execsql { 265 CREATE TABLE t4(a TEXT); 266 INSERT INTO t4 VALUES('1234'); 267 INSERT INTO t4 VALUES('234'); 268 INSERT INTO t4 VALUES('34'); 269 SELECT min(a), max(a) FROM t4; 270 } 271} {1234 34} 272do_test minmax2-8.2 { 273 execsql { 274 CREATE TABLE t5(a INTEGER); 275 INSERT INTO t5 VALUES('1234'); 276 INSERT INTO t5 VALUES('234'); 277 INSERT INTO t5 VALUES('34'); 278 SELECT min(a), max(a) FROM t5; 279 } 280} {34 1234} 281 282# Ticket #658: Test the min()/max() optimization when the FROM clause 283# is a subquery. 284# 285ifcapable {compound && subquery} { 286 do_test minmax2-9.0 { 287 execsql { 288 SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5 289 } 290 } {3} 291 do_test minmax2-9.1 { 292 execsql { 293 SELECT max(yy) FROM ( 294 SELECT max(rowid) AS yy FROM t4 UNION SELECT max(rowid) FROM t5 295 ) 296 } 297 } {3} 298 do_test minmax2-9.2 { 299 execsql { 300 SELECT max(yy) FROM ( 301 SELECT max(rowid) AS yy FROM t4 EXCEPT SELECT max(rowid) FROM t5 302 ) 303 } 304 } {{}} 305} ;# ifcapable compound&&subquery 306 307# If there is a NULL in an aggregate max() or min(), ignore it. An 308# aggregate min() or max() will only return NULL if all values are NULL. 309# 310do_test minmax2-10.1 { 311 execsql { 312 CREATE TABLE t6(x); 313 INSERT INTO t6 VALUES(1); 314 INSERT INTO t6 VALUES(2); 315 INSERT INTO t6 VALUES(NULL); 316 SELECT coalesce(min(x),-1) FROM t6; 317 } 318} {1} 319do_test minmax2-10.2 { 320 execsql { 321 SELECT max(x) FROM t6; 322 } 323} {2} 324do_test minmax2-10.3 { 325 execsql { 326 CREATE INDEX i6 ON t6(x DESC); 327 SELECT coalesce(min(x),-1) FROM t6; 328 } 329} {1} 330do_test minmax2-10.4 { 331 execsql { 332 SELECT max(x) FROM t6; 333 } 334} {2} 335do_test minmax2-10.5 { 336 execsql { 337 DELETE FROM t6 WHERE x NOT NULL; 338 SELECT count(*) FROM t6; 339 } 340} 1 341do_test minmax2-10.6 { 342 execsql { 343 SELECT count(x) FROM t6; 344 } 345} 0 346ifcapable subquery { 347 do_test minmax2-10.7 { 348 execsql { 349 SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6); 350 } 351 } {{} {}} 352} 353do_test minmax2-10.8 { 354 execsql { 355 SELECT min(x), max(x) FROM t6; 356 } 357} {{} {}} 358do_test minmax2-10.9 { 359 execsql { 360 INSERT INTO t6 SELECT * FROM t6; 361 INSERT INTO t6 SELECT * FROM t6; 362 INSERT INTO t6 SELECT * FROM t6; 363 INSERT INTO t6 SELECT * FROM t6; 364 INSERT INTO t6 SELECT * FROM t6; 365 INSERT INTO t6 SELECT * FROM t6; 366 INSERT INTO t6 SELECT * FROM t6; 367 INSERT INTO t6 SELECT * FROM t6; 368 INSERT INTO t6 SELECT * FROM t6; 369 INSERT INTO t6 SELECT * FROM t6; 370 SELECT count(*) FROM t6; 371 } 372} 1024 373do_test minmax2-10.10 { 374 execsql { 375 SELECT count(x) FROM t6; 376 } 377} 0 378ifcapable subquery { 379 do_test minmax2-10.11 { 380 execsql { 381 SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6); 382 } 383 } {{} {}} 384} 385do_test minmax2-10.12 { 386 execsql { 387 SELECT min(x), max(x) FROM t6; 388 } 389} {{} {}} 390 391# 2017-10-26. Extend the min/max optimization to indexes on expressions 392# 393do_execsql_test minmax2-11.100 { 394 CREATE TABLE t11(a,b,c); 395 INSERT INTO t11(a,b,c) VALUES(1,10,5),(2,8,11),(3,1,4),(4,20,1),(5,16,4); 396 CREATE INDEX t11bc ON t11(b+c); 397 SELECT max(b+c) FROM t11; 398} {21} 399do_execsql_test minmax2-11.110 { 400 SELECT a, max(b+c) FROM t11; 401} {4 21} 402do_test minmax2-11.111 { 403 db eval {SELECT max(b+c) FROM t11} 404 db status step 405} {0} 406do_test minmax2-11.112 { 407 db eval {SELECT max(c+b) FROM t11} 408 db status step 409} {4} 410do_execsql_test minmax2-11.120 { 411 SELECT a, min(b+c) FROM t11; 412} {3 5} 413do_test minmax2-11.121 { 414 db eval {SELECT min(b+c) FROM t11} 415 db status step 416} {0} 417do_test minmax2-11.122 { 418 db eval {SELECT min(c+b) FROM t11} 419 db status step 420} {4} 421do_execsql_test minmax2-11.130 { 422 INSERT INTO t11(a,b,c) VALUES(6,NULL,0),(7,0,NULL); 423 SELECT a, min(b+c) FROM t11; 424} {3 5} 425 426finish_test 427