xref: /sqlite-3.40.0/test/vtabH.test (revision 7c2321fd)
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
33ifcapable !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  }
65}
66
67
68#--------------------------------------------------------------------------
69
70register_tclvar_module db
71set ::xyz 10
72do_execsql_test 2.0 {
73  CREATE VIRTUAL TABLE vars USING tclvar;
74  SELECT name, arrayname, value FROM vars WHERE name = 'xyz';
75} {xyz {} 10}
76
77set x1 aback
78set x2 abaft
79set x3 abandon
80set x4 abandonint
81set x5 babble
82set x6 baboon
83set x7 backbone
84set x8 backarrow
85set x9 castle
86
87db func glob -argcount 2 gfunc
88proc gfunc {a b} {
89  incr ::gfunc
90  return 1
91}
92
93db func like -argcount 2 lfunc
94proc lfunc {a b} {
95  incr ::gfunc 100
96  return 1
97}
98
99db func regexp -argcount 2 rfunc
100proc rfunc {a b} {
101  incr ::gfunc 10000
102  return 1
103}
104
105foreach ::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}
114
115    do_test 2.$tclvar_set_omit.$tn.1 {
116      execsql "SELECT name, value FROM vars WHERE name MATCH 'x*' AND $expr"
117    } $res
118
119    do_test 2.$tclvar_set_omit.$tn.2 {
120      set ::gfunc
121    } $cnt
122  }
123}
124
125#-------------------------------------------------------------------------
126#
127if {$tcl_platform(platform)=="windows"} {
128  set drive [string range [pwd] 0 1]
129  set ::env(fstreeDrive) $drive
130}
131if {$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 .}
139
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  }
147
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  }
163
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  }
179
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]
199
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]
217
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  } {}
233
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  }
257
258}
259
260
261finish_test
262