171c57db0Sdan# 2016 June 17 271c57db0Sdan# 371c57db0Sdan# The author disclaims copyright to this source code. In place of 471c57db0Sdan# a legal notice, here is a blessing: 571c57db0Sdan# 671c57db0Sdan# May you do good and not evil. 771c57db0Sdan# May you find forgiveness for yourself and forgive others. 871c57db0Sdan# May you share freely, never taking more than you give. 971c57db0Sdan# 1071c57db0Sdan#*********************************************************************** 1171c57db0Sdan# This file implements regression tests for SQLite library. The 1271c57db0Sdan# focus of this file is testing the SELECT statement. 1371c57db0Sdan# 1471c57db0Sdan 1571c57db0Sdanset testdir [file dirname $argv0] 1671c57db0Sdansource $testdir/tester.tcl 1771c57db0Sdanset ::testprefix rowvalue2 1871c57db0Sdan 1971c57db0Sdando_execsql_test 1.0 { 2071c57db0Sdan CREATE TABLE t1(a, b, c); 2171c57db0Sdan INSERT INTO t1 VALUES(0, 0, 0); 2271c57db0Sdan INSERT INTO t1 VALUES(0, 1, 1); 2371c57db0Sdan INSERT INTO t1 VALUES(1, 0, 2); 2471c57db0Sdan INSERT INTO t1 VALUES(1, 1, 3); 2571c57db0Sdan 2671c57db0Sdan CREATE INDEX i1 ON t1(a, b); 2771c57db0Sdan} 2871c57db0Sdan 2971c57db0Sdando_execsql_test 1.1.1 { SELECT c FROM t1 WHERE (a, b) >= (1, 0) } {2 3} 3071c57db0Sdando_execsql_test 1.1.2 { SELECT c FROM t1 WHERE (a, b) > (1, 0) } {3} 3171c57db0Sdan 3271c57db0Sdan#------------------------------------------------------------------------- 3371c57db0Sdan 3471c57db0Sdando_execsql_test 2.0.1 { 3571c57db0Sdan CREATE TABLE t2(a INTEGER, b INTEGER, c INTEGER, d INTEGER); 3671c57db0Sdan CREATE INDEX i2 ON t2(a, b, c); 3771c57db0Sdan} 3871c57db0Sdando_test 2.0.2 { 3971c57db0Sdan foreach a {0 1 2 3} { 4071c57db0Sdan foreach b {0 1 2 3} { 4171c57db0Sdan foreach c {0 1 2 3} { 4271c57db0Sdan execsql { INSERT INTO t2 VALUES($a, $b, $c, $c + $b*4 + $a*16); } 4371c57db0Sdan }}} 4471c57db0Sdan} {} 4571c57db0Sdan 4671c57db0Sdando_execsql_test 2.1 { 4771c57db0Sdan SELECT d FROM t2 WHERE (a, b) > (2, 2); 4871c57db0Sdan} [db eval { SELECT d FROM t2 WHERE a>2 OR (a=2 AND b>2) }] 4971c57db0Sdan 5071c57db0Sdando_execsql_test 2.2 { 5171c57db0Sdan SELECT d FROM t2 WHERE (a, b) >= (2, 2); 5271c57db0Sdan} [db eval { SELECT d FROM t2 WHERE a>2 OR (a=2 AND b>=2) }] 5371c57db0Sdan 5471c57db0Sdando_execsql_test 2.3 { 5571c57db0Sdan SELECT d FROM t2 WHERE a=1 AND (b, c) >= (1, 2); 5671c57db0Sdan} [db eval { SELECT d FROM t2 WHERE +a=1 AND (b>1 OR (b==1 AND c>=2)) }] 5771c57db0Sdan 5871c57db0Sdando_execsql_test 2.4 { 5971c57db0Sdan SELECT d FROM t2 WHERE a=1 AND (b, c) > (1, 2); 6071c57db0Sdan} [db eval { SELECT d FROM t2 WHERE +a=1 AND (b>1 OR (b==1 AND c>2)) }] 6171c57db0Sdan 6271c57db0Sdan#------------------------------------------------------------------------- 6371c57db0Sdan 6471c57db0Sdanset words { 6571c57db0Sdanairfare airfield airfields airflow airfoil 6671c57db0Sdanairfoils airframe airframes airily airing 6771c57db0Sdanairings airless airlift airlifts airline 6871c57db0Sdanairliner airlines airlock airlocks airmail 6971c57db0Sdanairmails airman airmen airplane airplanes 7071c57db0Sdan 7171c57db0Sdanarraignment arraignments arraigns arrange arranged 7271c57db0Sdanarrangement arrangements arranger arrangers arranges 7371c57db0Sdanarranging arrant array arrayed arrays 7471c57db0Sdanarrears arrest arrested arrester arresters 7571c57db0Sdanarresting arrestingly arrestor arrestors arrests 7671c57db0Sdan 7771c57db0Sdanedifices edit edited editing edition 7871c57db0Sdaneditions editor editorial editorially editorials 7971c57db0Sdaneditors edits educable educate educated 8071c57db0Sdaneducates educating education educational educationally 8171c57db0Sdaneducations educator educators eel eelgrass 8271c57db0Sdan} 8371c57db0Sdan 8471c57db0Sdando_test 3.0 { 8571c57db0Sdan execsql { CREATE TABLE t3(a, b, c, w); } 8671c57db0Sdan foreach w $words { 8771c57db0Sdan set a [string range $w 0 2] 8871c57db0Sdan set b [string range $w 3 5] 8971c57db0Sdan set c [string range $w 6 end] 9071c57db0Sdan execsql { INSERT INTO t3 VALUES($a, $b, $c, $w) } 9171c57db0Sdan } 9271c57db0Sdan} {} 9371c57db0Sdan 9471c57db0Sdan 9571c57db0Sdanforeach {tn idx} { 9671c57db0Sdan IDX1 {} 9771c57db0Sdan IDX2 { CREATE INDEX i3 ON t3(a, b, c); } 9871c57db0Sdan IDX3 { CREATE INDEX i3 ON t3(a, b); } 9971c57db0Sdan IDX4 { CREATE INDEX i3 ON t3(a); } 10071c57db0Sdan} { 10171c57db0Sdan execsql { DROP INDEX IF EXISTS i3 } 10271c57db0Sdan execsql $idx 10371c57db0Sdan 10471c57db0Sdan foreach w $words { 10571c57db0Sdan set a [string range $w 0 2] 10671c57db0Sdan set b [string range $w 3 5] 10771c57db0Sdan set c [string range $w 6 end] 10871c57db0Sdan 10971c57db0Sdan foreach op [list > >= < <= == IS] { 11071c57db0Sdan do_execsql_test 3.1.$tn.$w.$op [subst -novar { 11171c57db0Sdan SELECT rowid FROM t3 WHERE (a, b, c) [set op] ($a, $b, $c) 11271c57db0Sdan ORDER BY +rowid 11371c57db0Sdan }] [db eval [subst -novar { 11471c57db0Sdan SELECT rowid FROM t3 WHERE w [set op] $w ORDER BY +rowid 11571c57db0Sdan }]] 11671c57db0Sdan 11771c57db0Sdan do_execsql_test 3.1.$tn.$w.$op.subselect [subst -novar { 11871c57db0Sdan SELECT rowid FROM t3 WHERE (a, b, c) [set op] ( 11971c57db0Sdan SELECT a, b, c FROM t3 WHERE w = $w 12071c57db0Sdan ) 12171c57db0Sdan ORDER BY +rowid 12271c57db0Sdan }] [db eval [subst -novar { 12371c57db0Sdan SELECT rowid FROM t3 WHERE w [set op] $w ORDER BY +rowid 12471c57db0Sdan }]] 12571c57db0Sdan } 12671c57db0Sdan 12771c57db0Sdan } 12871c57db0Sdan} 12971c57db0Sdan 13071c57db0Sdan#------------------------------------------------------------------------- 13171c57db0Sdan# 13271c57db0Sdan 13371c57db0Sdando_execsql_test 4.0 { 13471c57db0Sdan CREATE TABLE t4(a, b, c); 13571c57db0Sdan INSERT INTO t4 VALUES(NULL, NULL, NULL); 13671c57db0Sdan INSERT INTO t4 VALUES(NULL, NULL, 0); 13771c57db0Sdan INSERT INTO t4 VALUES(NULL, NULL, 1); 13871c57db0Sdan INSERT INTO t4 VALUES(NULL, 0, NULL); 13971c57db0Sdan INSERT INTO t4 VALUES(NULL, 0, 0); 14071c57db0Sdan INSERT INTO t4 VALUES(NULL, 0, 1); 14171c57db0Sdan INSERT INTO t4 VALUES(NULL, 1, NULL); 14271c57db0Sdan INSERT INTO t4 VALUES(NULL, 1, 0); 14371c57db0Sdan INSERT INTO t4 VALUES(NULL, 1, 1); 14471c57db0Sdan 14571c57db0Sdan INSERT INTO t4 VALUES( 0, NULL, NULL); 14671c57db0Sdan INSERT INTO t4 VALUES( 0, NULL, 0); 14771c57db0Sdan INSERT INTO t4 VALUES( 0, NULL, 1); 14871c57db0Sdan INSERT INTO t4 VALUES( 0, 0, NULL); 14971c57db0Sdan INSERT INTO t4 VALUES( 0, 0, 0); 15071c57db0Sdan INSERT INTO t4 VALUES( 0, 0, 1); 15171c57db0Sdan INSERT INTO t4 VALUES( 0, 1, NULL); 15271c57db0Sdan INSERT INTO t4 VALUES( 0, 1, 0); 15371c57db0Sdan INSERT INTO t4 VALUES( 0, 1, 1); 15471c57db0Sdan 15571c57db0Sdan INSERT INTO t4 VALUES( 1, NULL, NULL); 15671c57db0Sdan INSERT INTO t4 VALUES( 1, NULL, 0); 15771c57db0Sdan INSERT INTO t4 VALUES( 1, NULL, 1); 15871c57db0Sdan INSERT INTO t4 VALUES( 1, 0, NULL); 15971c57db0Sdan INSERT INTO t4 VALUES( 1, 0, 0); 16071c57db0Sdan INSERT INTO t4 VALUES( 1, 0, 1); 16171c57db0Sdan INSERT INTO t4 VALUES( 1, 1, NULL); 16271c57db0Sdan INSERT INTO t4 VALUES( 1, 1, 0); 16371c57db0Sdan INSERT INTO t4 VALUES( 1, 1, 1); 16471c57db0Sdan} 16571c57db0Sdan 16671c57db0Sdanproc make_expr1 {cList vList op} { 16771c57db0Sdan return "([join $cList ,]) $op ([join $vList ,])" 16871c57db0Sdan} 16971c57db0Sdan 17071c57db0Sdanproc make_expr3 {cList vList op} { 17171c57db0Sdan set n [llength $cList] 17271c57db0Sdan 17371c57db0Sdan set aList [list] 17471c57db0Sdan foreach c [lrange $cList 0 end-1] v [lrange $vList 0 end-1] { 17571c57db0Sdan lappend aList "$c == $v" 17671c57db0Sdan } 17771c57db0Sdan lappend aList "[lindex $cList end] $op [lindex $vList end]" 17871c57db0Sdan 17971c57db0Sdan return "([join $aList { AND }])" 18071c57db0Sdan} 18171c57db0Sdan 18271c57db0Sdanproc make_expr2 {cList vList op} { 18371c57db0Sdan set ret "" 18471c57db0Sdan 18571c57db0Sdan switch -- $op { 18671c57db0Sdan == - IS { 18771c57db0Sdan set aList [list] 18871c57db0Sdan foreach c $cList v $vList { lappend aList "($c $op $v)" } 18971c57db0Sdan set ret [join $aList " AND "] 19071c57db0Sdan } 19171c57db0Sdan 19271c57db0Sdan < - > { 19371c57db0Sdan set oList [list] 19471c57db0Sdan for {set i 0} {$i < [llength $cList]} {incr i} { 19571c57db0Sdan lappend oList [make_expr3 [lrange $cList 0 $i] [lrange $vList 0 $i] $op] 19671c57db0Sdan } 19771c57db0Sdan set ret [join $oList " OR "] 19871c57db0Sdan } 19971c57db0Sdan 20071c57db0Sdan <= - >= { 20171c57db0Sdan set o2 [string range $op 0 0] 20271c57db0Sdan set oList [list] 20371c57db0Sdan for {set i 0} {$i < [llength $cList]-1} {incr i} { 20471c57db0Sdan lappend oList [make_expr3 [lrange $cList 0 $i] [lrange $vList 0 $i] $o2] 20571c57db0Sdan } 20671c57db0Sdan lappend oList [make_expr3 $cList $vList $op] 20771c57db0Sdan set ret [join $oList " OR "] 20871c57db0Sdan } 20971c57db0Sdan 21071c57db0Sdan 21171c57db0Sdan default { 21271c57db0Sdan error "Unknown op: $op" 21371c57db0Sdan } 21471c57db0Sdan } 21571c57db0Sdan 21671c57db0Sdan set ret 21771c57db0Sdan} 21871c57db0Sdan 21971c57db0Sdanforeach {tn idx} { 22071c57db0Sdan IDX1 {} 22171c57db0Sdan IDX2 { CREATE INDEX i4 ON t4(a, b, c); } 22271c57db0Sdan IDX3 { CREATE INDEX i4 ON t4(a, b); } 22371c57db0Sdan IDX4 { CREATE INDEX i4 ON t4(a); } 22471c57db0Sdan} { 22571c57db0Sdan execsql { DROP INDEX IF EXISTS i4 } 22671c57db0Sdan execsql $idx 22771c57db0Sdan 22871c57db0Sdan foreach {tn2 vector} { 22971c57db0Sdan 1 {0 0 0} 23071c57db0Sdan 2 {1 1 1} 23171c57db0Sdan 3 {0 0 NULL} 23271c57db0Sdan 4 {0 NULL 0} 23371c57db0Sdan 5 {NULL 0 0} 23471c57db0Sdan 6 {1 1 NULL} 23571c57db0Sdan 7 {1 NULL 1} 23671c57db0Sdan 8 {NULL 1 1} 23771c57db0Sdan } { 23871c57db0Sdan foreach op { IS == < <= > >= } { 23971c57db0Sdan set e1 [make_expr1 {a b c} $vector $op] 24071c57db0Sdan set e2 [make_expr2 {a b c} $vector $op] 24171c57db0Sdan 24271c57db0Sdan do_execsql_test 4.$tn.$tn2.$op \ 24371c57db0Sdan "SELECT rowid FROM t4 WHERE $e2 ORDER BY +rowid" [ 24471c57db0Sdan db eval "SELECT rowid FROM t4 WHERE $e1 ORDER BY +rowid" 24571c57db0Sdan ] 24671c57db0Sdan } 24771c57db0Sdan } 24871c57db0Sdan} 24971c57db0Sdan 250*4b4f5114Sdando_execsql_test 5.0 { 251*4b4f5114Sdan CREATE TABLE r1(a TEXT, iB TEXT); 252*4b4f5114Sdan CREATE TABLE r2(x TEXT, zY INTEGER); 253*4b4f5114Sdan CREATE INDEX r1ab ON r1(a, iB); 254*4b4f5114Sdan 255*4b4f5114Sdan INSERT INTO r1 VALUES(35, 35); 256*4b4f5114Sdan INSERT INTO r2 VALUES(35, 36); 257*4b4f5114Sdan INSERT INTO r2 VALUES(35, 4); 258*4b4f5114Sdan INSERT INTO r2 VALUES(35, 35); 259*4b4f5114Sdan} {} 260*4b4f5114Sdan 261*4b4f5114Sdanforeach {tn lhs rhs} { 262*4b4f5114Sdan 1 {x +zY} {a iB} 263*4b4f5114Sdan 2 {x zY} {a iB} 264*4b4f5114Sdan 3 {x zY} {a +iB} 265*4b4f5114Sdan 4 {+x zY} {a iB} 266*4b4f5114Sdan 5 {x zY} {+a iB} 267*4b4f5114Sdan} { 268*4b4f5114Sdan foreach op { IS == < <= > >= } { 269*4b4f5114Sdan set e1 [make_expr1 $lhs $rhs $op] 270*4b4f5114Sdan set e2 [make_expr2 $lhs $rhs $op] 271*4b4f5114Sdan do_execsql_test 5.$tn.$op \ 272*4b4f5114Sdan "SELECT * FROM r1, r2 WHERE $e2 ORDER BY iB" [db eval \ 273*4b4f5114Sdan "SELECT * FROM r1, r2 WHERE $e1 ORDER BY iB" 274*4b4f5114Sdan ] 275*4b4f5114Sdan } 276*4b4f5114Sdan} 277*4b4f5114Sdan 27871c57db0Sdan 27971c57db0Sdanfinish_test 280