modernc.org/cc@v1.0.1/v2/testdata/_sqlite/test/bestindex3.test (about) 1 # 2016 May 29 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 12 set testdir [file dirname $argv0] 13 source $testdir/tester.tcl 14 set testprefix bestindex3 15 16 ifcapable !vtab { 17 finish_test 18 return 19 } 20 21 #------------------------------------------------------------------------- 22 # Virtual table callback for a virtual table named $tbl. 23 # 24 # The table created is: 25 # 26 # "CREATE TABLE t1 (a, b, c)" 27 # 28 # This virtual table supports both LIKE and = operators on all columns. 29 # 30 proc vtab_cmd {bOmit method args} { 31 switch -- $method { 32 xConnect { 33 return "CREATE TABLE t1(a, b, c)" 34 } 35 36 xBestIndex { 37 foreach {clist orderby mask} $args {} 38 39 set ret [list] 40 set use use 41 if {$bOmit} {set use omit} 42 43 for {set i 0} {$i < [llength $clist]} {incr i} { 44 array unset C 45 array set C [lindex $clist $i] 46 if {$C(usable) && ($C(op)=="like" || $C(op)=="eq")} { 47 lappend ret $use $i 48 lappend ret idxstr 49 lappend ret "[lindex {a b c} $C(column)] [string toupper $C(op)] ?" 50 break 51 } 52 } 53 54 if {$ret==""} { 55 lappend ret cost 1000000 rows 1000000 56 } else { 57 lappend ret cost 100 rows 10 58 } 59 return $ret 60 } 61 62 xFilter { 63 foreach {idxnum idxstr param} $args {} 64 set where "" 65 if {$bOmit && $idxstr != ""} { 66 set where " WHERE [string map [list ? '$param' EQ =] $idxstr]" 67 } 68 return [list sql "SELECT rowid, * FROM ttt$where"] 69 } 70 } 71 return "" 72 } 73 74 register_tcl_module db 75 76 do_execsql_test 1.0 { 77 CREATE VIRTUAL TABLE t1 USING tcl("vtab_cmd 0"); 78 } 79 80 do_eqp_test 1.1 { 81 SELECT * FROM t1 WHERE a LIKE 'abc'; 82 } { 83 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?} 84 } 85 86 do_eqp_test 1.2 { 87 SELECT * FROM t1 WHERE a = 'abc'; 88 } { 89 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?} 90 } 91 92 do_eqp_test 1.3 { 93 SELECT * FROM t1 WHERE a = 'abc' OR b = 'def'; 94 } { 95 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?} 96 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?} 97 } 98 99 do_eqp_test 1.4 { 100 SELECT * FROM t1 WHERE a LIKE 'abc%' OR b = 'def'; 101 } { 102 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?} 103 0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?} 104 } 105 106 do_execsql_test 1.5 { 107 CREATE TABLE ttt(a, b, c); 108 109 INSERT INTO ttt VALUES(1, 'two', 'three'); 110 INSERT INTO ttt VALUES(2, 'one', 'two'); 111 INSERT INTO ttt VALUES(3, 'three', 'one'); 112 INSERT INTO ttt VALUES(4, 'y', 'one'); 113 INSERT INTO ttt VALUES(5, 'x', 'two'); 114 INSERT INTO ttt VALUES(6, 'y', 'three'); 115 } 116 117 foreach omit {0 1} { 118 do_execsql_test 1.6.$omit.0 " 119 DROP TABLE t1; 120 CREATE VIRTUAL TABLE t1 USING tcl('vtab_cmd $omit'); 121 " 122 do_execsql_test 1.6.$omit.1 { 123 SELECT rowid FROM t1 WHERE c LIKE 'o%' 124 } {3 4} 125 126 do_execsql_test 1.6.$omit.2 { 127 SELECT rowid FROM t1 WHERE c LIKE 'o%' OR b='y' 128 } {3 4 6} 129 130 do_execsql_test 1.6.$omit.3 { 131 SELECT rowid FROM t1 WHERE c = 'three' OR c LIKE 'o%' 132 } {1 6 3 4} 133 } 134 135 #------------------------------------------------------------------------- 136 # Test the same pattern works with ordinary tables. 137 # 138 # This test does not work if the ICU extension is enabled. ICU overrides 139 # LIKE - and this optimization only works with the built-in LIKE function. 140 # 141 ifcapable !icu { 142 do_execsql_test 2.1 { 143 CREATE TABLE t2(x TEXT COLLATE nocase, y TEXT); 144 CREATE INDEX t2x ON t2(x COLLATE nocase); 145 CREATE INDEX t2y ON t2(y); 146 } 147 148 do_eqp_test 2.2 { 149 SELECT * FROM t2 WHERE x LIKE 'abc%' OR y = 'def' 150 } { 151 0 0 0 {SEARCH TABLE t2 USING INDEX t2x (x>? AND x<?)} 152 0 0 0 {SEARCH TABLE t2 USING INDEX t2y (y=?)} 153 } 154 } 155 156 #------------------------------------------------------------------------- 157 # Test that any PRIMARY KEY within a sqlite3_decl_vtab() CREATE TABLE 158 # statement is currently ignored. 159 # 160 proc vvv_command {method args} { 161 switch -- $method { 162 xConnect { return "CREATE TABLE t1(a PRIMARY KEY, b, c)" } 163 } 164 } 165 proc yyy_command {method args} { 166 switch -- $method { 167 xConnect { return "CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b))" } 168 } 169 } 170 171 do_execsql_test 3.1 { CREATE VIRTUAL TABLE t3 USING tcl('vvv_command') } 172 do_execsql_test 3.2 { CREATE VIRTUAL TABLE t4 USING tcl('yyy_command') } 173 174 finish_test