Merge sqlite-release(3.30.1) into prerelease-integration
[sqlcipher.git] / test / vtabH.test
blobf1a0466554e8aeb74821caa741e1ff6a49c88747
1 # 2015 Nov 24
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 # This file implements regression tests for SQLite library. Specifically,
12 # it tests that the GLOB, LIKE and REGEXP operators are correctly exposed
13 # to virtual table implementations.
16 set testdir [file dirname $argv0]
17 source $testdir/tester.tcl
18 set testprefix vtabH
20 ifcapable !vtab {
21   finish_test
22   return
25 register_echo_module db
27 do_execsql_test 1.0 {
28   CREATE TABLE t6(a, b TEXT);
29   CREATE INDEX i6 ON t6(b, a);
30   CREATE VIRTUAL TABLE e6 USING echo(t6);
33 ifcapable !icu {
34   foreach {tn sql expect} {
35     1 "SELECT * FROM e6 WHERE b LIKE '8abc'" {
36       xBestIndex 
37          {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?}
38       xFilter
39          {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?}
40          8ABC 8abd 8abc
41     }
42   
43     2 "SELECT * FROM e6 WHERE b GLOB '8abc'" {
44        xBestIndex
45          {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b glob ?}
46        xFilter
47          {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b glob ?}
48          8abc 8abd 8abc
49     }
50     3 "SELECT * FROM e6 WHERE b LIKE '8e/'" {
51       xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b like ?}
52       xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8e/
53     }
54     4 "SELECT * FROM e6 WHERE b GLOB '8e/'" {
55       xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b glob ?}
56       xFilter {SELECT rowid, a, b FROM 't6' WHERE b glob ?} 8e/
57     }
58   } {
59     do_test 1.$tn {
60       set echo_module {}
61       execsql $sql
62       set ::echo_module
63     } [list {*}$expect]
64   }
68 #--------------------------------------------------------------------------
70 register_tclvar_module db
71 set ::xyz 10
72 do_execsql_test 2.0 {
73   CREATE VIRTUAL TABLE vars USING tclvar;
74   SELECT name, arrayname, value FROM vars WHERE name = 'xyz';
75 } {xyz {} 10}
77 set x1 aback
78 set x2 abaft
79 set x3 abandon
80 set x4 abandonint
81 set x5 babble
82 set x6 baboon
83 set x7 backbone
84 set x8 backarrow
85 set x9 castle
87 db func glob -argcount 2 gfunc
88 proc gfunc {a b} {
89   incr ::gfunc
90   return 1
93 db func like -argcount 2 lfunc
94 proc lfunc {a b} {
95   incr ::gfunc 100
96   return 1
99 db func regexp -argcount 2 rfunc
100 proc rfunc {a b} {
101   incr ::gfunc 10000
102   return 1
105 foreach ::tclvar_set_omit {0 1} {
106   foreach {tn expr res cnt} {
107     1 {value GLOB 'aban*'} {x3 abandon x4 abandonint} 2
108     2 {value LIKE '%ac%'}  {x1 aback x7 backbone x8 backarrow} 300
109     3 {value REGEXP '^......$'}  {x5 babble x6 baboon x9 castle} 30000
110   } {
111     db cache flush
112     set ::gfunc 0
113     if {$::tclvar_set_omit} {set cnt 0}
115     do_test 2.$tclvar_set_omit.$tn.1 {
116       execsql "SELECT name, value FROM vars WHERE name MATCH 'x*' AND $expr"
117     } $res
119     do_test 2.$tclvar_set_omit.$tn.2 {
120       set ::gfunc
121     } $cnt
122   }
125 #-------------------------------------------------------------------------
127 if {$tcl_platform(platform)=="windows"} {
128   set drive [string range [pwd] 0 1]
129   set ::env(fstreeDrive) $drive
131 if {$tcl_platform(platform)!="windows" || \
132     [regexp -nocase -- {^[A-Z]:} $drive]} {
133   reset_db
134   register_fs_module db
135   do_execsql_test 3.0 {
136     SELECT name FROM fsdir WHERE dir = '.' AND name = 'test.db';
137     SELECT name FROM fsdir WHERE dir = '.' AND name = '.'
138   } {test.db .}
140   proc sort_files { names {nocase false} } {
141     if {$nocase && $::tcl_platform(platform) eq "windows"} {
142       return [lsort -nocase $names]
143     } else {
144       return [lsort $names]
145     }
146   }
148   proc list_root_files {} {
149     if {$::tcl_platform(platform) eq "windows"} {
150       set res [list]; set dir $::env(fstreeDrive)/; set names [list]
151       eval lappend names [glob -nocomplain -directory $dir -- *]
152       foreach name $names {
153         if {[string index [file tail $name] 0] eq "."} continue
154         if {[file attributes $name -hidden]} continue
155         if {[file attributes $name -system]} continue
156         lappend res $name
157       }
158       return [sort_files $res true]
159     } else {
160       return [sort_files [string map {/ {}} [glob -nocomplain -- /*]]]
161     }
162   }
164   proc list_files { pattern } {
165     if {$::tcl_platform(platform) eq "windows"} {
166       set res [list]; set names [list]
167       eval lappend names [glob -nocomplain -- $pattern]
168       foreach name $names {
169         if {[string index [file tail $name] 0] eq "."} continue
170         if {[file attributes $name -hidden]} continue
171         if {[file attributes $name -system]} continue
172         lappend res $name
173       }
174       return [sort_files $res]
175     } else {
176       return [sort_files [glob -nocomplain -- $pattern]]
177     }
178   }
180   # Read the first 5 entries from the root directory.  Except, ignore
181   # files that contain the "$" character in their names as these are
182   # special files on some Windows platforms.
183   #
184   set res [list]
185   set root_files [list_root_files]
186   foreach p $root_files {
187     if {$::tcl_platform(platform) eq "windows"} {
188       if {![regexp {\$} $p]} {lappend res $p}
189     } else {
190       lappend res "/$p"
191     }
192   }
193   set num_root_files [llength $root_files]
194   do_test 3.1 {
195     sort_files [execsql {
196       SELECT path FROM fstree WHERE path NOT GLOB '*\$*' LIMIT $num_root_files;
197     }] true
198   } [sort_files $res true]
200   # Read all entries in the current directory.
201   #
202   proc contents {pattern} {
203     set res [list]
204     foreach f [list_files $pattern] {
205       lappend res $f
206       if {[file isdir $f]} {
207         set res [concat $res [contents "$f/*"]]
208       }
209     }
210     set res
211   }
212   set pwd "[pwd]/*"
213   set res [contents $pwd]
214   do_execsql_test 3.2 {
215     SELECT path FROM fstree WHERE path GLOB $pwd ORDER BY 1
216   } [sort_files $res]
218   # Add some sub-directories and files to the current directory.
219   #
220   do_test 3.3 {
221     catch { file delete -force subdir }
222     foreach {path sz} {
223       subdir/x1.txt     143
224       subdir/x2.txt     153
225     } {
226       set dir [file dirname $path]
227       catch { file mkdir $dir }
228       set fd [open $path w]
229       puts -nonewline $fd [string repeat 1 $sz]
230       close $fd
231     }
232   } {}
234   set pwd [pwd]
235   if {![string match {*[_%]*} $pwd]} {
236     do_execsql_test 3.5 {
237       SELECT path, size FROM fstree 
238        WHERE path GLOB $pwd || '/subdir/*' ORDER BY 1
239     } [list \
240       "$pwd/subdir/x1.txt" 143 \
241       "$pwd/subdir/x2.txt" 153 \
242     ]
243     do_execsql_test 3.6 {
244       SELECT path, size FROM fstree
245        WHERE path LIKE $pwd || '/subdir/%' ORDER BY 1
246     } [list \
247       "$pwd/subdir/x1.txt" 143 \
248       "$pwd/subdir/x2.txt" 153 \
249     ]
250     do_execsql_test 3.7 {
251       SELECT sum(size) FROM fstree WHERE path LIKE $pwd || '/subdir/%'
252     } 296
253     do_execsql_test 3.8 {
254       SELECT size FROM fstree WHERE path = $pwd || '/subdir/x1.txt'
255     } 143
256   }
261 finish_test