Update test file walprotocol.test to account for the changes in the wal
[sqlite.git] / test / bestindex1.test
blobf90f96bf443399cdcb7408344efd4398abe2790f
1 # 2016-03-01
3 # The author disclaims copyright to this source code.  In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
11
14 set testdir [file dirname $argv0]
15 source $testdir/tester.tcl
16 set testprefix bestindex1
18 ifcapable !vtab {
19   finish_test
20   return
23 register_tcl_module db
25 proc vtab_command {method args} {
26   switch -- $method {
27     xConnect {
28       return "CREATE TABLE t1(a, b, c)"
29     }
31     xBestIndex {
32       set clist [lindex $args 0]
33       if {[llength $clist]!=1} { error "unexpected constraint list" }
34       catch { array unset C }
35       array set C [lindex $clist 0]
36       if {$C(usable)} {
37         return "omit 0 cost 0 rows 1 idxnum 555 idxstr eq!"
38       } else {
39         return "cost 1000000 rows 0 idxnum 0 idxstr scan..."
40       }
41     }
43   }
45   return {}
48 do_execsql_test 1.0 {
49   CREATE VIRTUAL TABLE x1 USING tcl(vtab_command);
50 } {}
52 do_eqp_test 1.1 {
53   SELECT * FROM x1 WHERE a = 'abc'
54 } {
55   0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
58 do_eqp_test 1.2 {
59   SELECT * FROM x1 WHERE a IN ('abc', 'def');
60 } {
61   0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
62   0 0 0 {EXECUTE LIST SUBQUERY 1}
65 #-------------------------------------------------------------------------
67 reset_db
68 register_tcl_module db
70 # Parameter $mode may be one of:
72 #   "omit" - Implement filtering. Set the omit flag.
73 #   "use"  - Implement filtering. Use the constraint, but do not set omit.
74 #   "use2" - Do not implement filtering. Use the constraint anyway.
76 #   
77 proc t1_vtab {mode method args} {
78   switch -- $method {
79     xConnect {
80       return "CREATE TABLE t1(a, b)"
81     }
83     xBestIndex {
84       set SQL_FILTER {SELECT * FROM t1x WHERE a='%1%'}
85       set SQL_SCAN   {SELECT * FROM t1x}
87       set clist [lindex $args 0]
88       set idx 0
89       for {set idx 0} {$idx < [llength $clist]} {incr idx} {
90         array unset C
91         array set C [lindex $clist $idx]
92         if {$C(column)==0 && $C(op)=="eq" && $C(usable)} {
93           switch -- $mode {
94             "omit" {
95               return [list omit $idx rows 10 cost 10 idxstr $SQL_FILTER]
96             }
97             "use" {
98               return [list use $idx rows 10 cost 10 idxstr $SQL_FILTER]
99             }
100             "use2" {
101               return [list use $idx rows 10 cost 10 idxstr $SQL_SCAN]
102             }
103             default {
104               error "Bad mode - $mode"
105             }
106           }
107         }
108       }
110       return [list idxstr {SELECT * FROM t1x}]
111     }
113     xFilter {
114       set map [list %1% [lindex $args 2 0]]
115       set sql [string map $map [lindex $args 1]]
116       return [list sql $sql]
117     }
118   }
120   return {}
123 do_execsql_test 2.1 {
124   CREATE TABLE t1x(i INTEGER PRIMARY KEY, a, b);
125   INSERT INTO t1x VALUES(1, 'one', 1);
126   INSERT INTO t1x VALUES(2, 'two', 2);
127   INSERT INTO t1x VALUES(3, 'three', 3);
128   INSERT INTO t1x VALUES(4, 'four', 4);
131 foreach {tn mode} {
132   1 use 2 omit 3 use2
133 } {
134   do_execsql_test 2.2.$mode.1 "
135     DROP TABLE IF EXISTS t1;
136     CREATE VIRTUAL TABLE t1 USING tcl(t1_vtab $mode);
137   "
139   do_execsql_test 2.2.$mode.2 {SELECT * FROM t1} {one 1 two 2 three 3 four 4}
140   do_execsql_test 2.2.$mode.3 {SELECT rowid FROM t1} {1 2 3 4}
141   do_execsql_test 2.2.$mode.4 {SELECT rowid FROM t1 WHERE a='two'} {2} 
143   do_execsql_test 2.2.$mode.5 {
144     SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid
145   } {1 4} 
147   set plan(use) {
148     0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'}
149     0 0 0 {EXECUTE LIST SUBQUERY 1}
150     0 0 0 {USE TEMP B-TREE FOR ORDER BY}
151   }
152   set plan(omit) {
153     0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'}
154     0 0 0 {EXECUTE LIST SUBQUERY 1}
155     0 0 0 {USE TEMP B-TREE FOR ORDER BY}
156   }
157   set plan(use2) {
158     0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x}
159     0 0 0 {EXECUTE LIST SUBQUERY 1}
160     0 0 0 {USE TEMP B-TREE FOR ORDER BY}
161   }
163   do_eqp_test 2.2.$mode.6 { 
164     SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid
165   } $plan($mode)
168 # 2016-04-09.
169 # Demonstrate a register overwrite problem when using two virtual
170 # tables where the outer loop uses the IN operator.
172 set G(collist) [list PrimaryKey flagA columnA]
173 set G(cols) [join $G(collist) ,]
174 set G(nulls) "NULL"
176 proc vtab_command {method args} {
177   global G
179   switch -- $method {
180     xConnect {
181       return "CREATE TABLE t1($G(cols))"
182     }
184     xBestIndex {
185       set clist [lindex $args 0]
186       #puts $clist
187       set W [list]
188       set U [list]
190       set i 0
191       for {set idx 0} {$idx < [llength $clist]} {incr idx} {
192         array set c [lindex $clist $idx]
193         if {$c(op)=="eq" && $c(usable)} {
194           lappend W "[lindex $G(collist) $c(column)] = %$i%"
195           lappend U use $idx
196           incr i
197         }
198       }
200       if {$W==""} {
201         set sql "SELECT rowid, * FROM t1"
202       } else {
203         set sql "SELECT rowid, * FROM t1 WHERE [join $W { AND }]"
204       }
206       return [concat [list idxstr $sql] $U]
207     }
209     xFilter {
210       foreach {idxnum idxstr vals} $args {}
212       set map [list]
213       for {set i 0} {$i < [llength $vals]} {incr i} {
214         lappend map "%$i%" 
215         set v [lindex $vals $i]
216         if {[string is integer $v]} { 
217           lappend map $v 
218         } else {
219           lappend map "'$v'"
220         }
221       }
222       set sql [string map $map $idxstr]
224       #puts "SQL: $sql"
225       return [list sql $sql]
226     }
227   }
229   return {}
232 db close
233 forcedelete test.db
234 sqlite3 db test.db
235 register_tcl_module db
237 do_execsql_test 3.1 "
238   CREATE TABLE t1($G(cols));
239   INSERT INTO t1 VALUES(1, 0, 'ValueA');
240   INSERT INTO t1 VALUES(2, 0, 'ValueA');
241   INSERT INTO t1 VALUES(3, 0, 'ValueB');
242   INSERT INTO t1 VALUES(4, 0, 'ValueB');
245 do_execsql_test 3.2 {
246   CREATE VIRTUAL TABLE VirtualTableA USING tcl(vtab_command);
247   CREATE VIRTUAL TABLE VirtualTableB USING tcl(vtab_command);
250 do_execsql_test 3.3 { SELECT primarykey FROM VirtualTableA } {1 2 3 4}
252 do_execsql_test 3.4 {
253   SELECT * FROM 
254   VirtualTableA a CROSS JOIN VirtualTableB b ON b.PrimaryKey=a.PrimaryKey
255   WHERE a.ColumnA IN ('ValueA', 'ValueB') AND a.FlagA=0
256 } {
257   1 0 ValueA 1 0 ValueA
258   2 0 ValueA 2 0 ValueA
259   3 0 ValueB 3 0 ValueB
260   4 0 ValueB 4 0 ValueB
263 do_execsql_test 3.5 {
264   SELECT * FROM 
265   VirtualTableA a CROSS JOIN VirtualTableB b ON b.PrimaryKey=a.PrimaryKey
266   WHERE a.FlagA=0 AND a.ColumnA IN ('ValueA', 'ValueB') 
267 } {
268   1 0 ValueA 1 0 ValueA
269   2 0 ValueA 2 0 ValueA
270   3 0 ValueB 3 0 ValueB
271   4 0 ValueB 4 0 ValueB
275 finish_test