1*4520Snw141292 2*4520Snw141292#pragma ident "%Z%%M% %I% %E% SMI" 3*4520Snw141292 4*4520Snw141292# 2001 September 15 5*4520Snw141292# 6*4520Snw141292# The author disclaims copyright to this source code. In place of 7*4520Snw141292# a legal notice, here is a blessing: 8*4520Snw141292# 9*4520Snw141292# May you do good and not evil. 10*4520Snw141292# May you find forgiveness for yourself and forgive others. 11*4520Snw141292# May you share freely, never taking more than you give. 12*4520Snw141292# 13*4520Snw141292#*********************************************************************** 14*4520Snw141292# This file implements regression tests for SQLite library. The 15*4520Snw141292# focus of this file is testing SELECT statements that contain 16*4520Snw141292# aggregate min() and max() functions and which are handled as 17*4520Snw141292# as a special case. 18*4520Snw141292# 19*4520Snw141292# $Id: minmax.test,v 1.9.2.2 2004/07/18 21:14:05 drh Exp $ 20*4520Snw141292 21*4520Snw141292set testdir [file dirname $argv0] 22*4520Snw141292source $testdir/tester.tcl 23*4520Snw141292 24*4520Snw141292do_test minmax-1.0 { 25*4520Snw141292 execsql { 26*4520Snw141292 BEGIN; 27*4520Snw141292 CREATE TABLE t1(x, y); 28*4520Snw141292 INSERT INTO t1 VALUES(1,1); 29*4520Snw141292 INSERT INTO t1 VALUES(2,2); 30*4520Snw141292 INSERT INTO t1 VALUES(3,2); 31*4520Snw141292 INSERT INTO t1 VALUES(4,3); 32*4520Snw141292 INSERT INTO t1 VALUES(5,3); 33*4520Snw141292 INSERT INTO t1 VALUES(6,3); 34*4520Snw141292 INSERT INTO t1 VALUES(7,3); 35*4520Snw141292 INSERT INTO t1 VALUES(8,4); 36*4520Snw141292 INSERT INTO t1 VALUES(9,4); 37*4520Snw141292 INSERT INTO t1 VALUES(10,4); 38*4520Snw141292 INSERT INTO t1 VALUES(11,4); 39*4520Snw141292 INSERT INTO t1 VALUES(12,4); 40*4520Snw141292 INSERT INTO t1 VALUES(13,4); 41*4520Snw141292 INSERT INTO t1 VALUES(14,4); 42*4520Snw141292 INSERT INTO t1 VALUES(15,4); 43*4520Snw141292 INSERT INTO t1 VALUES(16,5); 44*4520Snw141292 INSERT INTO t1 VALUES(17,5); 45*4520Snw141292 INSERT INTO t1 VALUES(18,5); 46*4520Snw141292 INSERT INTO t1 VALUES(19,5); 47*4520Snw141292 INSERT INTO t1 VALUES(20,5); 48*4520Snw141292 COMMIT; 49*4520Snw141292 SELECT DISTINCT y FROM t1 ORDER BY y; 50*4520Snw141292 } 51*4520Snw141292} {1 2 3 4 5} 52*4520Snw141292 53*4520Snw141292do_test minmax-1.1 { 54*4520Snw141292 set sqlite_search_count 0 55*4520Snw141292 execsql {SELECT min(x) FROM t1} 56*4520Snw141292} {1} 57*4520Snw141292do_test minmax-1.2 { 58*4520Snw141292 set sqlite_search_count 59*4520Snw141292} {19} 60*4520Snw141292do_test minmax-1.3 { 61*4520Snw141292 set sqlite_search_count 0 62*4520Snw141292 execsql {SELECT max(x) FROM t1} 63*4520Snw141292} {20} 64*4520Snw141292do_test minmax-1.4 { 65*4520Snw141292 set sqlite_search_count 66*4520Snw141292} {19} 67*4520Snw141292do_test minmax-1.5 { 68*4520Snw141292 execsql {CREATE INDEX t1i1 ON t1(x)} 69*4520Snw141292 set sqlite_search_count 0 70*4520Snw141292 execsql {SELECT min(x) FROM t1} 71*4520Snw141292} {1} 72*4520Snw141292do_test minmax-1.6 { 73*4520Snw141292 set sqlite_search_count 74*4520Snw141292} {2} 75*4520Snw141292do_test minmax-1.7 { 76*4520Snw141292 set sqlite_search_count 0 77*4520Snw141292 execsql {SELECT max(x) FROM t1} 78*4520Snw141292} {20} 79*4520Snw141292do_test minmax-1.8 { 80*4520Snw141292 set sqlite_search_count 81*4520Snw141292} {1} 82*4520Snw141292do_test minmax-1.9 { 83*4520Snw141292 set sqlite_search_count 0 84*4520Snw141292 execsql {SELECT max(y) FROM t1} 85*4520Snw141292} {5} 86*4520Snw141292do_test minmax-1.10 { 87*4520Snw141292 set sqlite_search_count 88*4520Snw141292} {19} 89*4520Snw141292 90*4520Snw141292do_test minmax-2.0 { 91*4520Snw141292 execsql { 92*4520Snw141292 CREATE TABLE t2(a INTEGER PRIMARY KEY, b); 93*4520Snw141292 INSERT INTO t2 SELECT * FROM t1; 94*4520Snw141292 } 95*4520Snw141292 set sqlite_search_count 0 96*4520Snw141292 execsql {SELECT min(a) FROM t2} 97*4520Snw141292} {1} 98*4520Snw141292do_test minmax-2.1 { 99*4520Snw141292 set sqlite_search_count 100*4520Snw141292} {0} 101*4520Snw141292do_test minmax-2.2 { 102*4520Snw141292 set sqlite_search_count 0 103*4520Snw141292 execsql {SELECT max(a) FROM t2} 104*4520Snw141292} {20} 105*4520Snw141292do_test minmax-2.3 { 106*4520Snw141292 set sqlite_search_count 107*4520Snw141292} {0} 108*4520Snw141292 109*4520Snw141292do_test minmax-3.0 { 110*4520Snw141292 execsql {INSERT INTO t2 VALUES((SELECT max(a) FROM t2)+1,999)} 111*4520Snw141292 set sqlite_search_count 0 112*4520Snw141292 execsql {SELECT max(a) FROM t2} 113*4520Snw141292} {21} 114*4520Snw141292do_test minmax-3.1 { 115*4520Snw141292 set sqlite_search_count 116*4520Snw141292} {0} 117*4520Snw141292do_test minmax-3.2 { 118*4520Snw141292 execsql {INSERT INTO t2 VALUES((SELECT max(a) FROM t2)+1,999)} 119*4520Snw141292 set sqlite_search_count 0 120*4520Snw141292 execsql { 121*4520Snw141292 SELECT b FROM t2 WHERE a=(SELECT max(a) FROM t2) 122*4520Snw141292 } 123*4520Snw141292} {999} 124*4520Snw141292do_test minmax-3.3 { 125*4520Snw141292 set sqlite_search_count 126*4520Snw141292} {0} 127*4520Snw141292 128*4520Snw141292do_test minmax-4.1 { 129*4520Snw141292 execsql { 130*4520Snw141292 SELECT coalesce(min(x+0),-1), coalesce(max(x+0),-1) FROM 131*4520Snw141292 (SELECT * FROM t1 UNION SELECT NULL as 'x', NULL as 'y') 132*4520Snw141292 } 133*4520Snw141292} {1 20} 134*4520Snw141292do_test minmax-4.2 { 135*4520Snw141292 execsql { 136*4520Snw141292 SELECT y, sum(x) FROM 137*4520Snw141292 (SELECT null, y+1 FROM t1 UNION SELECT * FROM t1) 138*4520Snw141292 GROUP BY y ORDER BY y; 139*4520Snw141292 } 140*4520Snw141292} {1 1 2 5 3 22 4 92 5 90 6 0} 141*4520Snw141292do_test minmax-4.3 { 142*4520Snw141292 execsql { 143*4520Snw141292 SELECT y, count(x), count(*) FROM 144*4520Snw141292 (SELECT null, y+1 FROM t1 UNION SELECT * FROM t1) 145*4520Snw141292 GROUP BY y ORDER BY y; 146*4520Snw141292 } 147*4520Snw141292} {1 1 1 2 2 3 3 4 5 4 8 9 5 5 6 6 0 1} 148*4520Snw141292 149*4520Snw141292# Make sure the min(x) and max(x) optimizations work on empty tables 150*4520Snw141292# including empty tables with indices. Ticket #296. 151*4520Snw141292# 152*4520Snw141292do_test minmax-5.1 { 153*4520Snw141292 execsql { 154*4520Snw141292 CREATE TABLE t3(x INTEGER UNIQUE NOT NULL); 155*4520Snw141292 SELECT coalesce(min(x),999) FROM t3; 156*4520Snw141292 } 157*4520Snw141292} {999} 158*4520Snw141292do_test minmax-5.2 { 159*4520Snw141292 execsql { 160*4520Snw141292 SELECT coalesce(min(rowid),999) FROM t3; 161*4520Snw141292 } 162*4520Snw141292} {999} 163*4520Snw141292do_test minmax-5.3 { 164*4520Snw141292 execsql { 165*4520Snw141292 SELECT coalesce(max(x),999) FROM t3; 166*4520Snw141292 } 167*4520Snw141292} {999} 168*4520Snw141292do_test minmax-5.4 { 169*4520Snw141292 execsql { 170*4520Snw141292 SELECT coalesce(max(rowid),999) FROM t3; 171*4520Snw141292 } 172*4520Snw141292} {999} 173*4520Snw141292do_test minmax-5.5 { 174*4520Snw141292 execsql { 175*4520Snw141292 SELECT coalesce(max(rowid),999) FROM t3 WHERE rowid<25; 176*4520Snw141292 } 177*4520Snw141292} {999} 178*4520Snw141292 179*4520Snw141292# Make sure the min(x) and max(x) optimizations work when there 180*4520Snw141292# is a LIMIT clause. Ticket #396. 181*4520Snw141292# 182*4520Snw141292do_test minmax-6.1 { 183*4520Snw141292 execsql { 184*4520Snw141292 SELECT min(a) FROM t2 LIMIT 1 185*4520Snw141292 } 186*4520Snw141292} {1} 187*4520Snw141292do_test minmax-6.2 { 188*4520Snw141292 execsql { 189*4520Snw141292 SELECT max(a) FROM t2 LIMIT 3 190*4520Snw141292 } 191*4520Snw141292} {22} 192*4520Snw141292do_test minmax-6.3 { 193*4520Snw141292 execsql { 194*4520Snw141292 SELECT min(a) FROM t2 LIMIT 0,100 195*4520Snw141292 } 196*4520Snw141292} {1} 197*4520Snw141292do_test minmax-6.4 { 198*4520Snw141292 execsql { 199*4520Snw141292 SELECT max(a) FROM t2 LIMIT 1,100 200*4520Snw141292 } 201*4520Snw141292} {} 202*4520Snw141292do_test minmax-6.5 { 203*4520Snw141292 execsql { 204*4520Snw141292 SELECT min(x) FROM t3 LIMIT 1 205*4520Snw141292 } 206*4520Snw141292} {{}} 207*4520Snw141292do_test minmax-6.6 { 208*4520Snw141292 execsql { 209*4520Snw141292 SELECT max(x) FROM t3 LIMIT 0 210*4520Snw141292 } 211*4520Snw141292} {} 212*4520Snw141292do_test minmax-6.7 { 213*4520Snw141292 execsql { 214*4520Snw141292 SELECT max(a) FROM t2 LIMIT 0 215*4520Snw141292 } 216*4520Snw141292} {} 217*4520Snw141292 218*4520Snw141292# Make sure the max(x) and min(x) optimizations work for nested 219*4520Snw141292# queries. Ticket #587. 220*4520Snw141292# 221*4520Snw141292do_test minmax-7.1 { 222*4520Snw141292 execsql { 223*4520Snw141292 SELECT max(x) FROM t1; 224*4520Snw141292 } 225*4520Snw141292} 20 226*4520Snw141292do_test minmax-7.2 { 227*4520Snw141292 execsql { 228*4520Snw141292 SELECT * FROM (SELECT max(x) FROM t1); 229*4520Snw141292 } 230*4520Snw141292} 20 231*4520Snw141292do_test minmax-7.3 { 232*4520Snw141292 execsql { 233*4520Snw141292 SELECT min(x) FROM t1; 234*4520Snw141292 } 235*4520Snw141292} 1 236*4520Snw141292do_test minmax-7.4 { 237*4520Snw141292 execsql { 238*4520Snw141292 SELECT * FROM (SELECT min(x) FROM t1); 239*4520Snw141292 } 240*4520Snw141292} 1 241*4520Snw141292 242*4520Snw141292# Make sure min(x) and max(x) work correctly when the datatype is 243*4520Snw141292# TEXT instead of NUMERIC. Ticket #623. 244*4520Snw141292# 245*4520Snw141292do_test minmax-8.1 { 246*4520Snw141292 execsql { 247*4520Snw141292 CREATE TABLE t4(a TEXT); 248*4520Snw141292 INSERT INTO t4 VALUES('1234'); 249*4520Snw141292 INSERT INTO t4 VALUES('234'); 250*4520Snw141292 INSERT INTO t4 VALUES('34'); 251*4520Snw141292 SELECT min(a), max(a) FROM t4; 252*4520Snw141292 } 253*4520Snw141292} {1234 34} 254*4520Snw141292do_test minmax-8.2 { 255*4520Snw141292 execsql { 256*4520Snw141292 CREATE TABLE t5(a INTEGER); 257*4520Snw141292 INSERT INTO t5 VALUES('1234'); 258*4520Snw141292 INSERT INTO t5 VALUES('234'); 259*4520Snw141292 INSERT INTO t5 VALUES('34'); 260*4520Snw141292 SELECT min(a), max(a) FROM t5; 261*4520Snw141292 } 262*4520Snw141292} {34 1234} 263*4520Snw141292 264*4520Snw141292# Ticket #658: Test the min()/max() optimization when the FROM clause 265*4520Snw141292# is a subquery. 266*4520Snw141292# 267*4520Snw141292do_test minmax-9.1 { 268*4520Snw141292 execsql { 269*4520Snw141292 SELECT max(rowid) FROM ( 270*4520Snw141292 SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5 271*4520Snw141292 ) 272*4520Snw141292 } 273*4520Snw141292} {1} 274*4520Snw141292do_test minmax-9.2 { 275*4520Snw141292 execsql { 276*4520Snw141292 SELECT max(rowid) FROM ( 277*4520Snw141292 SELECT max(rowid) FROM t4 EXCEPT SELECT max(rowid) FROM t5 278*4520Snw141292 ) 279*4520Snw141292 } 280*4520Snw141292} {{}} 281*4520Snw141292 282*4520Snw141292# If there is a NULL in an aggregate max() or min(), ignore it. An 283*4520Snw141292# aggregate min() or max() will only return NULL if all values are NULL. 284*4520Snw141292# 285*4520Snw141292do_test minmax-10.1 { 286*4520Snw141292 execsql { 287*4520Snw141292 CREATE TABLE t6(x); 288*4520Snw141292 INSERT INTO t6 VALUES(1); 289*4520Snw141292 INSERT INTO t6 VALUES(2); 290*4520Snw141292 INSERT INTO t6 VALUES(NULL); 291*4520Snw141292 SELECT coalesce(min(x),-1) FROM t6; 292*4520Snw141292 } 293*4520Snw141292} {1} 294*4520Snw141292do_test minmax-10.2 { 295*4520Snw141292 execsql { 296*4520Snw141292 SELECT max(x) FROM t6; 297*4520Snw141292 } 298*4520Snw141292} {2} 299*4520Snw141292do_test minmax-10.3 { 300*4520Snw141292 execsql { 301*4520Snw141292 CREATE INDEX i6 ON t6(x); 302*4520Snw141292 SELECT coalesce(min(x),-1) FROM t6; 303*4520Snw141292 } 304*4520Snw141292} {1} 305*4520Snw141292do_test minmax-10.4 { 306*4520Snw141292 execsql { 307*4520Snw141292 SELECT max(x) FROM t6; 308*4520Snw141292 } 309*4520Snw141292} {2} 310*4520Snw141292do_test minmax-10.5 { 311*4520Snw141292 execsql { 312*4520Snw141292 DELETE FROM t6 WHERE x NOT NULL; 313*4520Snw141292 SELECT count(*) FROM t6; 314*4520Snw141292 } 315*4520Snw141292} 1 316*4520Snw141292do_test minmax-10.6 { 317*4520Snw141292 execsql { 318*4520Snw141292 SELECT count(x) FROM t6; 319*4520Snw141292 } 320*4520Snw141292} 0 321*4520Snw141292do_test minmax-10.7 { 322*4520Snw141292 execsql { 323*4520Snw141292 SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6); 324*4520Snw141292 } 325*4520Snw141292} {{} {}} 326*4520Snw141292do_test minmax-10.8 { 327*4520Snw141292 execsql { 328*4520Snw141292 SELECT min(x), max(x) FROM t6; 329*4520Snw141292 } 330*4520Snw141292} {{} {}} 331*4520Snw141292do_test minmax-10.9 { 332*4520Snw141292 execsql { 333*4520Snw141292 INSERT INTO t6 SELECT * FROM t6; 334*4520Snw141292 INSERT INTO t6 SELECT * FROM t6; 335*4520Snw141292 INSERT INTO t6 SELECT * FROM t6; 336*4520Snw141292 INSERT INTO t6 SELECT * FROM t6; 337*4520Snw141292 INSERT INTO t6 SELECT * FROM t6; 338*4520Snw141292 INSERT INTO t6 SELECT * FROM t6; 339*4520Snw141292 INSERT INTO t6 SELECT * FROM t6; 340*4520Snw141292 INSERT INTO t6 SELECT * FROM t6; 341*4520Snw141292 INSERT INTO t6 SELECT * FROM t6; 342*4520Snw141292 INSERT INTO t6 SELECT * FROM t6; 343*4520Snw141292 SELECT count(*) FROM t6; 344*4520Snw141292 } 345*4520Snw141292} 1024 346*4520Snw141292do_test minmax-10.10 { 347*4520Snw141292 execsql { 348*4520Snw141292 SELECT count(x) FROM t6; 349*4520Snw141292 } 350*4520Snw141292} 0 351*4520Snw141292do_test minmax-10.11 { 352*4520Snw141292 execsql { 353*4520Snw141292 SELECT (SELECT min(x) FROM t6), (SELECT max(x) FROM t6); 354*4520Snw141292 } 355*4520Snw141292} {{} {}} 356*4520Snw141292do_test minmax-10.12 { 357*4520Snw141292 execsql { 358*4520Snw141292 SELECT min(x), max(x) FROM t6; 359*4520Snw141292 } 360*4520Snw141292} {{} {}} 361*4520Snw141292 362*4520Snw141292finish_test 363