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 20 set testdir [file dirname $argv0] 21 source $testdir/tester.tcl 22 23 do_test minmax2-1.0 { 24 execsql { 25 PRAGMA legacy_file_format=0; 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 53 do_test minmax2-1.1 { 54 set sqlite_search_count 0 55 execsql {SELECT min(x) FROM t1} 56 } {1} 57 do_test minmax2-1.2 { 58 set sqlite_search_count 59 } {19} 60 do_test minmax2-1.3 { 61 set sqlite_search_count 0 62 execsql {SELECT max(x) FROM t1} 63 } {20} 64 do_test minmax2-1.4 { 65 set sqlite_search_count 66 } {19} 67 do_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} 72 do_test minmax2-1.6 { 73 set sqlite_search_count 74 } {1} 75 do_test minmax2-1.7 { 76 set sqlite_search_count 0 77 execsql {SELECT max(x) FROM t1} 78 } {20} 79 do_test minmax2-1.8 { 80 set sqlite_search_count 81 } {0} 82 do_test minmax2-1.9 { 83 set sqlite_search_count 0 84 execsql {SELECT max(y) FROM t1} 85 } {5} 86 do_test minmax2-1.10 { 87 set sqlite_search_count 88 } {19} 89 90 do_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} 98 do_test minmax2-2.1 { 99 set sqlite_search_count 100 } {0} 101 do_test minmax2-2.2 { 102 set sqlite_search_count 0 103 execsql {SELECT max(a) FROM t2} 104 } {20} 105 do_test minmax2-2.3 { 106 set sqlite_search_count 107 } {0} 108 109 do_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} 119 do_test minmax2-3.1 { 120 set sqlite_search_count 121 } {0} 122 do_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} 136 do_test minmax2-3.3 { 137 set sqlite_search_count 138 } {0} 139 140 ifcapable {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 # 166 do_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} 172 do_test minmax2-5.2 { 173 execsql { 174 SELECT coalesce(min(rowid),999) FROM t3; 175 } 176 } {999} 177 do_test minmax2-5.3 { 178 execsql { 179 SELECT coalesce(max(x),999) FROM t3; 180 } 181 } {999} 182 do_test minmax2-5.4 { 183 execsql { 184 SELECT coalesce(max(rowid),999) FROM t3; 185 } 186 } {999} 187 do_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 # 196 do_test minmax2-6.1 { 197 execsql { 198 SELECT min(a) FROM t2 LIMIT 1 199 } 200 } {1} 201 do_test minmax2-6.2 { 202 execsql { 203 SELECT max(a) FROM t2 LIMIT 3 204 } 205 } {22} 206 do_test minmax2-6.3 { 207 execsql { 208 SELECT min(a) FROM t2 LIMIT 0,100 209 } 210 } {1} 211 do_test minmax2-6.4 { 212 execsql { 213 SELECT max(a) FROM t2 LIMIT 1,100 214 } 215 } {} 216 do_test minmax2-6.5 { 217 execsql { 218 SELECT min(x) FROM t3 LIMIT 1 219 } 220 } {{}} 221 do_test minmax2-6.6 { 222 execsql { 223 SELECT max(x) FROM t3 LIMIT 0 224 } 225 } {} 226 do_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 # 235 do_test minmax2-7.1 { 236 execsql { 237 SELECT max(x) FROM t1; 238 } 239 } 20 240 ifcapable subquery { 241 do_test minmax2-7.2 { 242 execsql { 243 SELECT * FROM (SELECT max(x) FROM t1); 244 } 245 } 20 246 } 247 do_test minmax2-7.3 { 248 execsql { 249 SELECT min(x) FROM t1; 250 } 251 } 1 252 ifcapable 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 # 263 do_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} 272 do_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 # 285 ifcapable {compound && subquery} { 286 do_test minmax2-9.1 { 287 execsql { 288 SELECT max(rowid) FROM ( 289 SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5 290 ) 291 } 292 } {1} 293 do_test minmax2-9.2 { 294 execsql { 295 SELECT max(rowid) FROM ( 296 SELECT max(rowid) FROM t4 EXCEPT SELECT max(rowid) FROM t5 297 ) 298 } 299 } {{}} 300 } ;# ifcapable compound&&subquery 301 302 # If there is a NULL in an aggregate max() or min(), ignore it. An 303 # aggregate min() or max() will only return NULL if all values are NULL. 304 # 305 do_test minmax2-10.1 { 306 execsql { 307 CREATE TABLE t6(x); 308 INSERT INTO t6 VALUES(1); 309 INSERT INTO t6 VALUES(2); 310 INSERT INTO t6 VALUES(NULL); 311 SELECT coalesce(min(x),-1) FROM t6; 312 } 313 } {1} 314 do_test minmax2-10.2 { 315 execsql { 316 SELECT max(x) FROM t6; 317 } 318 } {2} 319 do_test minmax2-10.3 { 320 execsql { 321 CREATE INDEX i6 ON t6(x DESC); 322 SELECT coalesce(min(x),-1) FROM t6; 323 } 324 } {1} 325 do_test minmax2-10.4 { 326 execsql { 327 SELECT max(x) FROM t6; 328 } 329 } {2} 330 do_test minmax2-10.5 { 331 execsql { 332 DELETE FROM t6 WHERE x NOT NULL; 333 SELECT count(*) FROM t6; 334 } 335 } 1 336 do_test minmax2-10.6 { 337 execsql { 338 SELECT count(x) FROM t6; 339 } 340 } 0 341 ifcapable subquery { 342 do_test minmax2-10.7 { 343 execsql { 344 SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6); 345 } 346 } {{} {}} 347 } 348 do_test minmax2-10.8 { 349 execsql { 350 SELECT min(x), max(x) FROM t6; 351 } 352 } {{} {}} 353 do_test minmax2-10.9 { 354 execsql { 355 INSERT INTO t6 SELECT * FROM t6; 356 INSERT INTO t6 SELECT * FROM t6; 357 INSERT INTO t6 SELECT * FROM t6; 358 INSERT INTO t6 SELECT * FROM t6; 359 INSERT INTO t6 SELECT * FROM t6; 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 SELECT count(*) FROM t6; 366 } 367 } 1024 368 do_test minmax2-10.10 { 369 execsql { 370 SELECT count(x) FROM t6; 371 } 372 } 0 373 ifcapable subquery { 374 do_test minmax2-10.11 { 375 execsql { 376 SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6); 377 } 378 } {{} {}} 379 } 380 do_test minmax2-10.12 { 381 execsql { 382 SELECT min(x), max(x) FROM t6; 383 } 384 } {{} {}} 385 386 387 finish_test 388