1ab31a845Sdan# 2017 April 30 2ab31a845Sdan# 3ab31a845Sdan# The author disclaims copyright to this source code. In place of 4ab31a845Sdan# a legal notice, here is a blessing: 5ab31a845Sdan# 6ab31a845Sdan# May you do good and not evil. 7ab31a845Sdan# May you find forgiveness for yourself and forgive others. 8ab31a845Sdan# May you share freely, never taking more than you give. 9ab31a845Sdan# 10ab31a845Sdan#*********************************************************************** 11ab31a845Sdan# 12ab31a845Sdan# Test the HAVING->WHERE optimization. 13ab31a845Sdan# 14ab31a845Sdan 15ab31a845Sdanset testdir [file dirname $argv0] 16ab31a845Sdansource $testdir/tester.tcl 17ab31a845Sdanset testprefix having 18ab31a845Sdan 19ab31a845Sdando_execsql_test 1.0 { 20181a1167Sdan CREATE TABLE t2(c, d); 21181a1167Sdan 22ab31a845Sdan CREATE TABLE t1(a, b); 23ab31a845Sdan INSERT INTO t1 VALUES(1, 1); 24ab31a845Sdan INSERT INTO t1 VALUES(2, 2); 25ab31a845Sdan INSERT INTO t1 VALUES(1, 3); 26ab31a845Sdan INSERT INTO t1 VALUES(2, 4); 27ab31a845Sdan INSERT INTO t1 VALUES(1, 5); 28ab31a845Sdan INSERT INTO t1 VALUES(2, 6); 29ab31a845Sdan} {} 30ab31a845Sdan 31ab31a845Sdanforeach {tn sql res} { 32ab31a845Sdan 1 "SELECT a, sum(b) FROM t1 GROUP BY a HAVING a=2" {2 12} 33ab31a845Sdan 2 "SELECT a, sum(b) FROM t1 GROUP BY a HAVING a=2 AND sum(b)>10" {2 12} 34ab31a845Sdan 3 "SELECT a, sum(b) FROM t1 GROUP BY a HAVING sum(b)>12" {} 35ab31a845Sdan} { 36ab31a845Sdan do_execsql_test 1.$tn $sql $res 37ab31a845Sdan} 38ab31a845Sdan 39181a1167Sdan# Run an EXPLAIN command for both SQL statements. Return true if 40181a1167Sdan# the outputs are identical, or false otherwise. 41181a1167Sdan# 42ab31a845Sdanproc compare_vdbe {sql1 sql2} { 43ab31a845Sdan set r1 [list] 44ab31a845Sdan set r2 [list] 45181a1167Sdan db eval "explain $sql1" { lappend r1 $opcode $p1 $p2 $p3 $p4 $p5} 46181a1167Sdan db eval "explain $sql2" { lappend r2 $opcode $p1 $p2 $p3 $p4 $p5} 47ab31a845Sdan return [expr {$r1==$r2}] 48ab31a845Sdan} 49ab31a845Sdan 50ab31a845Sdanproc do_compare_vdbe_test {tn sql1 sql2 res} { 51ab31a845Sdan uplevel [list do_test $tn [list compare_vdbe $sql1 $sql2] $res] 52ab31a845Sdan} 53ab31a845Sdan 54181a1167Sdan#------------------------------------------------------------------------- 55181a1167Sdan# Test that various statements that are eligible for the optimization 56181a1167Sdan# produce the same VDBE code as optimizing by hand does. 57181a1167Sdan# 58ab31a845Sdanforeach {tn sql1 sql2} { 59ab31a845Sdan 1 "SELECT a, sum(b) FROM t1 GROUP BY a HAVING a=2" 60ab31a845Sdan "SELECT a, sum(b) FROM t1 WHERE a=2 GROUP BY a" 61ab31a845Sdan 62ab31a845Sdan 2 "SELECT a, sum(b) FROM t1 GROUP BY a HAVING sum(b)>5 AND a=2" 63ab31a845Sdan "SELECT a, sum(b) FROM t1 WHERE a=2 GROUP BY a HAVING sum(b)>5" 64ab31a845Sdan 65ab31a845Sdan 3 "SELECT a, sum(b) FROM t1 GROUP BY a COLLATE binary HAVING a=2" 66ab31a845Sdan "SELECT a, sum(b) FROM t1 WHERE a=2 GROUP BY a COLLATE binary" 67ab31a845Sdan 68f39168e4Sdan 5 "SELECT a, sum(b) FROM t1 GROUP BY a COLLATE binary HAVING 1" 69f39168e4Sdan "SELECT a, sum(b) FROM t1 WHERE 1 GROUP BY a COLLATE binary" 70181a1167Sdan 71181a1167Sdan 6 "SELECT count(*) FROM t1,t2 WHERE a=c GROUP BY b, d HAVING b=d" 72181a1167Sdan "SELECT count(*) FROM t1,t2 WHERE a=c AND b=d GROUP BY b, d" 73181a1167Sdan 74181a1167Sdan 7 { 75181a1167Sdan SELECT count(*) FROM t1,t2 WHERE a=c GROUP BY b, d 76181a1167Sdan HAVING b=d COLLATE nocase 77ab31a845Sdan } { 78181a1167Sdan SELECT count(*) FROM t1,t2 WHERE a=c AND b=d COLLATE nocase 79181a1167Sdan GROUP BY b, d 80ab31a845Sdan } 81ab31a845Sdan 82181a1167Sdan 8 "SELECT a, sum(b) FROM t1 GROUP BY a||b HAVING substr(a||b, 1, 1)='a'" 83181a1167Sdan "SELECT a, sum(b) FROM t1 WHERE substr(a||b, 1, 1)='a' GROUP BY a||b" 84181a1167Sdan} { 85181a1167Sdan do_compare_vdbe_test 2.$tn $sql1 $sql2 1 86181a1167Sdan} 87181a1167Sdan 88508e2d00Sdrh# The (4) test in the above set used to generate identical bytecode, but 89508e2d00Sdrh# that is no longer the case. The byte code is equivalent, though. 90508e2d00Sdrh# 91508e2d00Sdrhdo_execsql_test 2.4a { 92508e2d00Sdrh SELECT x,y FROM ( 93508e2d00Sdrh SELECT a AS x, sum(b) AS y FROM t1 94508e2d00Sdrh GROUP BY a 95508e2d00Sdrh ) WHERE x BETWEEN 2 AND 9999 96508e2d00Sdrh} {2 12} 97508e2d00Sdrhdo_execsql_test 2.4b { 98508e2d00Sdrh SELECT x,y FROM ( 99508e2d00Sdrh SELECT a AS x, sum(b) AS y FROM t1 100508e2d00Sdrh WHERE x BETWEEN 2 AND 9999 101508e2d00Sdrh GROUP BY a 102508e2d00Sdrh ) 103508e2d00Sdrh} {2 12} 104508e2d00Sdrh 105508e2d00Sdrh 106181a1167Sdan#------------------------------------------------------------------------- 107181a1167Sdan# 1: Test that the optimization is only applied if the GROUP BY term 108181a1167Sdan# uses BINARY collation. 109181a1167Sdan# 110181a1167Sdan# 2: Not applied if there is a non-deterministic function in the HAVING 111181a1167Sdan# term. 112181a1167Sdan# 113ab31a845Sdanforeach {tn sql1 sql2} { 114ab31a845Sdan 1 "SELECT a, sum(b) FROM t1 GROUP BY a COLLATE nocase HAVING a=2" 115ab31a845Sdan "SELECT a, sum(b) FROM t1 WHERE a=2 GROUP BY a COLLATE nocase" 116181a1167Sdan 117181a1167Sdan 2 "SELECT a, sum(b) FROM t1 GROUP BY a HAVING randomblob(a)<X'88'" 118181a1167Sdan "SELECT a, sum(b) FROM t1 WHERE randomblob(a)<X'88' GROUP BY a" 119ab31a845Sdan} { 120181a1167Sdan do_compare_vdbe_test 3.$tn $sql1 $sql2 0 121ab31a845Sdan} 122ab31a845Sdan 123181a1167Sdan 124181a1167Sdan#------------------------------------------------------------------------- 125181a1167Sdan# Test that non-deterministic functions disqualify a term from being 126181a1167Sdan# moved from the HAVING to WHERE clause. 127181a1167Sdan# 128181a1167Sdando_execsql_test 4.1 { 129181a1167Sdan CREATE TABLE t3(a, b); 130181a1167Sdan INSERT INTO t3 VALUES(1, 1); 131181a1167Sdan INSERT INTO t3 VALUES(1, 2); 132181a1167Sdan INSERT INTO t3 VALUES(1, 3); 133181a1167Sdan INSERT INTO t3 VALUES(2, 1); 134181a1167Sdan INSERT INTO t3 VALUES(2, 2); 135181a1167Sdan INSERT INTO t3 VALUES(2, 3); 136181a1167Sdan} 137181a1167Sdan 138181a1167Sdanproc nondeter {args} { 139181a1167Sdan incr ::nondeter_ret 140181a1167Sdan expr {$::nondeter_ret % 2} 141181a1167Sdan} 142181a1167Sdandb func nondeter nondeter 143181a1167Sdan 144181a1167Sdanset ::nondeter_ret 0 145181a1167Sdando_execsql_test 4.2 { 146181a1167Sdan SELECT a, sum(b) FROM t3 GROUP BY a HAVING nondeter(a) 147181a1167Sdan} {1 6} 148181a1167Sdan 149181a1167Sdan# If the term where moved, the query above would return the same 150181a1167Sdan# result as the following. But it does not. 151181a1167Sdan# 152181a1167Sdanset ::nondeter_ret 0 153181a1167Sdando_execsql_test 4.3 { 154181a1167Sdan SELECT a, sum(b) FROM t3 WHERE nondeter(a) GROUP BY a 155181a1167Sdan} {1 4 2 2} 156181a1167Sdan 157f39168e4Sdan#------------------------------------------------------------------------- 158f39168e4Sdanreset_db 159f39168e4Sdando_execsql_test 5.0 { 160f39168e4Sdan CREATE TABLE t1(a, b); 161f39168e4Sdan CREATE TABLE t2(x, y); 162f39168e4Sdan INSERT INTO t1 VALUES('a', 'b'); 163f39168e4Sdan} 164f39168e4Sdan 165f39168e4Sdan# The WHERE clause (a=2), uses an aggregate column from the outer query. 166f39168e4Sdan# If the HAVING term (0) is moved into the WHERE clause in this case, 167f39168e4Sdan# SQLite would at one point optimize (a=2 AND 0) to simply (0). Which 168f39168e4Sdan# is logically correct, but happened to cause problems in aggregate 169f39168e4Sdan# processing for the outer query. This test case verifies that those 170f39168e4Sdan# problems are no longer present. 171f39168e4Sdando_execsql_test 5.1 { 172f39168e4Sdan SELECT min(b), ( 173f39168e4Sdan SELECT x FROM t2 WHERE a=2 GROUP BY y HAVING 0 174f39168e4Sdan ) FROM t1; 175f39168e4Sdan} {b {}} 176f39168e4Sdan 177*85d31b9fSdrh# From chromium 178*85d31b9fSdrh# https://bugs.chromium.org/p/chromium/issues/detail?id=1161869 179*85d31b9fSdrh# 180*85d31b9fSdrhdo_execsql_test 5.2 { 181*85d31b9fSdrh SELECT EXISTS ( 182*85d31b9fSdrh SELECT * FROM ( 183*85d31b9fSdrh SELECT * FROM ( 184*85d31b9fSdrh SELECT 1 185*85d31b9fSdrh ) WHERE Col0 = 1 GROUP BY 1 186*85d31b9fSdrh ) WHERE 0 187*85d31b9fSdrh ) 188*85d31b9fSdrh FROM (SELECT 1 Col0) GROUP BY 1 189*85d31b9fSdrh} {0} 190181a1167Sdan 191ab31a845Sdanfinish_test 192