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