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