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