github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/bestindex5.test (about) 1 # 2017 September 10 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 # Test the virtual table interface. In particular the xBestIndex 12 # method. 13 # 14 15 set testdir [file dirname $argv0] 16 source $testdir/tester.tcl 17 set testprefix bestindex4 18 19 ifcapable !vtab { 20 finish_test 21 return 22 } 23 24 #------------------------------------------------------------------------- 25 # Virtual table callback for a virtual table named $tbl. 26 # 27 proc vtab_cmd {method args} { 28 29 set binops(ne) != 30 set binops(eq) = 31 set binops(isnot) "IS NOT" 32 set binops(is) "IS" 33 34 set unops(isnotnull) "IS NOT NULL" 35 set unops(isnull) "IS NULL" 36 37 set cols(0) a 38 set cols(1) b 39 set cols(2) c 40 41 switch -- $method { 42 xConnect { 43 return "CREATE TABLE t1(a, b, c)" 44 } 45 46 xBestIndex { 47 foreach {clist orderby mask} $args {} 48 49 set cost 1000000.0 50 set ret [list] 51 set str [list] 52 53 set v 0 54 for {set i 0} {$i < [llength $clist]} {incr i} { 55 array unset C 56 array set C [lindex $clist $i] 57 if {$C(usable)} { 58 if {[info exists binops($C(op))]} { 59 lappend ret omit $i 60 lappend str "$cols($C(column)) $binops($C(op)) %$v%" 61 incr v 62 set cost [expr $cost / 2] 63 } 64 if {[info exists unops($C(op))]} { 65 lappend ret omit $i 66 lappend str "$cols($C(column)) $unops($C(op))" 67 incr v 68 set cost [expr $cost / 2] 69 } 70 } 71 } 72 73 lappend ret idxstr [join $str " AND "] 74 lappend ret cost $cost 75 return $ret 76 } 77 78 xFilter { 79 set q [lindex $args 1] 80 set a [lindex $args 2] 81 for {set v 0} {$v < [llength $a]} {incr v} { 82 set val [lindex $a $v] 83 set q [string map [list %$v% '$val'] $q] 84 } 85 if {$q==""} { set q 1 } 86 lappend ::xFilterQueries "WHERE $q" 87 return [list sql "SELECT rowid, * FROM t1x WHERE $q"] 88 } 89 } 90 return "" 91 } 92 93 proc vtab_simple {method args} { 94 switch -- $method { 95 xConnect { 96 return "CREATE TABLE t2(x)" 97 } 98 xBestIndex { 99 return [list cost 999999.0] 100 } 101 xFilter { 102 return [list sql "SELECT rowid, * FROM t2x"] 103 } 104 } 105 return "" 106 } 107 108 register_tcl_module db 109 110 proc do_vtab_query_test {tn query result} { 111 set ::xFilterQueries [list] 112 uplevel [list 113 do_test $tn [string map [list %QUERY% $query] { 114 set r [execsql {%QUERY%}] 115 set r [concat $::xFilterQueries $r] 116 set r 117 }] [list {*}$result] 118 ] 119 } 120 121 do_execsql_test 1.0 { 122 CREATE VIRTUAL TABLE t1 USING tcl('vtab_cmd'); 123 CREATE TABLE t1x(a INTEGER, b TEXT, c REAL); 124 INSERT INTO t1x VALUES(1, 2, 3); 125 INSERT INTO t1x VALUES(4, 5, 6); 126 INSERT INTO t1x VALUES(7, 8, 9); 127 128 CREATE VIRTUAL TABLE t2 USING tcl('vtab_simple'); 129 CREATE TABLE t2x(x INTEGER); 130 INSERT INTO t2x VALUES(1); 131 } 132 133 do_vtab_query_test 1.1 { SELECT * FROM t1 WHERE a!='hello'; } { 134 "WHERE a != 'hello'" 135 1 2 3.0 4 5 6.0 7 8 9.0 136 } 137 138 do_vtab_query_test 1.2.1 { SELECT * FROM t1 WHERE b!=8 } { 139 "WHERE b != '8'" 140 1 2 3.0 4 5 6.0 141 } 142 do_vtab_query_test 1.2.2 { SELECT * FROM t1 WHERE 8!=b } { 143 "WHERE b != '8'" 144 1 2 3.0 4 5 6.0 145 } 146 147 do_vtab_query_test 1.3 { SELECT * FROM t1 WHERE c IS NOT 3 } { 148 "WHERE c IS NOT '3'" 149 4 5 6.0 7 8 9.0 150 } 151 do_vtab_query_test 1.3.2 { SELECT * FROM t1 WHERE 3 IS NOT c } { 152 "WHERE c IS NOT '3'" 153 4 5 6.0 7 8 9.0 154 } 155 156 do_vtab_query_test 1.4.1 { SELECT * FROM t1, t2 WHERE x != a } { 157 "WHERE a != '1'" 158 4 5 6.0 1 7 8 9.0 1 159 } 160 do_vtab_query_test 1.4.2 { SELECT * FROM t1, t2 WHERE a != x } { 161 "WHERE a != '1'" 162 4 5 6.0 1 7 8 9.0 1 163 } 164 165 do_vtab_query_test 1.5.1 { SELECT * FROM t1 WHERE a IS NOT NULL } { 166 "WHERE a IS NOT NULL" 167 1 2 3.0 4 5 6.0 7 8 9.0 168 } 169 do_vtab_query_test 1.5.2 { SELECT * FROM t1 WHERE NULL IS NOT a } { 170 "WHERE a IS NOT ''" 171 1 2 3.0 4 5 6.0 7 8 9.0 172 } 173 174 do_vtab_query_test 1.6.1 { SELECT * FROM t1 WHERE a IS NULL } { 175 "WHERE a IS NULL" 176 } 177 178 do_vtab_query_test 1.6.2 { SELECT * FROM t1 WHERE NULL IS a } { 179 "WHERE a IS ''" 180 } 181 182 do_vtab_query_test 1.7.1 { SELECT * FROM t1 WHERE (a, b) IS (1, 2) } { 183 "WHERE a IS '1' AND b IS '2'" 184 1 2 3.0 185 } 186 do_vtab_query_test 1.7.2 { SELECT * FROM t1 WHERE (5, 4) IS (b, a) } { 187 {WHERE b IS '5' AND a IS '4'} 188 4 5 6.0 189 } 190 191 #--------------------------------------------------------------------- 192 do_execsql_test 2.0.0 { 193 DELETE FROM t1x; 194 INSERT INTO t1x VALUES('a', 'b', 'c'); 195 } 196 do_execsql_test 2.0.1 { SELECT * FROM t1 } {a b c} 197 do_execsql_test 2.0.2 { SELECT * FROM t1 WHERE (a, b) != ('a', 'b'); } {} 198 199 do_execsql_test 2.1.0 { 200 DELETE FROM t1x; 201 INSERT INTO t1x VALUES(7, 8, 9); 202 } 203 do_execsql_test 2.1.1 { SELECT * FROM t1 } {7 8 9.0} 204 do_execsql_test 2.1.2 { SELECT * FROM t1 WHERE (a, b) != (7, '8') } {} 205 do_execsql_test 2.1.3 { SELECT * FROM t1 WHERE a!=7 OR b!='8' } 206 do_execsql_test 2.1.4 { SELECT * FROM t1 WHERE a!=7 OR b!='8' } 207 208 209 do_execsql_test 2.2.1 { 210 CREATE TABLE t3(a INTEGER, b TEXT); 211 INSERT INTO t3 VALUES(45, 46); 212 } 213 do_execsql_test 2.2.2 { SELECT * FROM t3 WHERE (a, b) != (45, 46); } 214 do_execsql_test 2.2.3 { SELECT * FROM t3 WHERE (a, b) != ('45', '46'); } 215 do_execsql_test 2.2.4 { SELECT * FROM t3 WHERE (a, b) == (45, 46); } {45 46} 216 do_execsql_test 2.2.5 { SELECT * FROM t3 WHERE (a, b) == ('45', '46'); } {45 46} 217 218 #--------------------------------------------------------------------- 219 # Test the != operator on a virtual table with column affinities. 220 # 221 proc vtab_simple_integer {method args} { 222 switch -- $method { 223 xConnect { 224 return "CREATE TABLE t4(x INTEGER)" 225 } 226 xBestIndex { 227 return [list cost 999999.0] 228 } 229 xFilter { 230 return [list sql "SELECT rowid, * FROM t4x"] 231 } 232 } 233 return "" 234 } 235 236 do_execsql_test 3.0 { 237 CREATE TABLE t4x(a INTEGER); 238 INSERT INTO t4x VALUES(245); 239 CREATE VIRTUAL TABLE t4 USING tcl('vtab_simple_integer'); 240 } 241 do_execsql_test 3.1 { SELECT rowid, * FROM t4 WHERE x=245; } {1 245} 242 do_execsql_test 3.2 { SELECT rowid, * FROM t4 WHERE x='245'; } {1 245} 243 do_execsql_test 3.3 { SELECT rowid, * FROM t4 WHERE x!=245; } {} 244 do_execsql_test 3.4 { SELECT rowid, * FROM t4 WHERE x!='245'; } {} 245 246 do_execsql_test 3.5 { SELECT rowid, * FROM t4 WHERE rowid!=1 OR x!='245'; } {} 247 248 249 finish_test