OLD | NEW |
1 # 2014 June 17 | 1 # 2014 June 17 |
2 # | 2 # |
3 # The author disclaims copyright to this source code. In place of | 3 # The author disclaims copyright to this source code. In place of |
4 # a legal notice, here is a blessing: | 4 # a legal notice, here is a blessing: |
5 # | 5 # |
6 # May you do good and not evil. | 6 # May you do good and not evil. |
7 # May you find forgiveness for yourself and forgive others. | 7 # May you find forgiveness for yourself and forgive others. |
8 # May you share freely, never taking more than you give. | 8 # May you share freely, never taking more than you give. |
9 # | 9 # |
10 #************************************************************************* | 10 #************************************************************************* |
11 # This file implements regression tests for SQLite library. The | 11 # This file implements regression tests for SQLite library. The |
12 # focus of this script is testing the FTS5 module. | 12 # focus of this script is testing the FTS5 module. |
13 # | 13 # |
14 # | 14 # |
15 | 15 |
16 source [file join [file dirname [info script]] fts5_common.tcl] | 16 source [file join [file dirname [info script]] fts5_common.tcl] |
17 set testprefix fts5ac | 17 set testprefix fts5ac |
18 | 18 |
19 # If SQLITE_ENABLE_FTS5 is defined, omit this file. | 19 # If SQLITE_ENABLE_FTS5 is defined, omit this file. |
20 ifcapable !fts5 { | 20 ifcapable !fts5 { |
21 finish_test | 21 finish_test |
22 return | 22 return |
23 } | 23 } |
24 | 24 |
| 25 foreach_detail_mode $testprefix { |
| 26 |
25 set data { | 27 set data { |
26 0 {p o q e z k z p n f y u z y n y} {l o o l v v k} | 28 0 {p o q e z k z p n f y u z y n y} {l o o l v v k} |
27 1 {p k h h p y l l h i p v n} {p p l u r i f a j g e r r x w} | 29 1 {p k h h p y l l h i p v n} {p p l u r i f a j g e r r x w} |
28 2 {l s z j k i m p s} {l w e j t j e e i t w r o p o} | 30 2 {l s z j k i m p s} {l w e j t j e e i t w r o p o} |
29 3 {x g y m y m h p} {k j j b r e y y a k y} | 31 3 {x g y m y m h p} {k j j b r e y y a k y} |
30 4 {q m a i y i z} {o w a g k x g j m w e u k} | 32 4 {q m a i y i z} {o w a g k x g j m w e u k} |
31 5 {k o a w y b s z} {s g l m m l m g p} | 33 5 {k o a w y b s z} {s g l m m l m g p} |
32 6 {d a q i z h b l c p k j g k} {p x u j x t v c z} | 34 6 {d a q i z h b l c p k j g k} {p x u j x t v c z} |
33 7 {f d a g o c t i} {w f c x l d r k i j} | 35 7 {f d a g o c t i} {w f c x l d r k i j} |
34 8 {y g w u b q p o m j y b p a e k} {r i d k y w o z q m a t p} | 36 8 {y g w u b q p o m j y b p a e k} {r i d k y w o z q m a t p} |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 92 {f y d j o q t c c q m f j s t} {f h e d y m o k} | 120 92 {f y d j o q t c c q m f j s t} {f h e d y m o k} |
119 93 {k x j r m a d o i z j} {r t t t f e b r x i v j v g o} | 121 93 {k x j r m a d o i z j} {r t t t f e b r x i v j v g o} |
120 94 {s f e a e t i h h d q p z t q} {b k m k w h c} | 122 94 {s f e a e t i h h d q p z t q} {b k m k w h c} |
121 95 {h b n j t k i h o q u} {w n g i t o k c a m y p f l x c p} | 123 95 {h b n j t k i h o q u} {w n g i t o k c a m y p f l x c p} |
122 96 {f c x p y r b m o l m o a} {p c a q s u n n x d c f a o} | 124 96 {f c x p y r b m o l m o a} {p c a q s u n n x d c f a o} |
123 97 {u h h k m n k} {u b v n u a o c} | 125 97 {u h h k m n k} {u b v n u a o c} |
124 98 {s p e t c z d f n w f} {l s f j b l c e s h} | 126 98 {s p e t c z d f n w f} {l s f j b l c e s h} |
125 99 {r c v w i v h a t a c v c r e} {h h u m g o f b a e o} | 127 99 {r c v w i v h a t a c v c r e} {h h u m g o f b a e o} |
126 } | 128 } |
127 | 129 |
128 # Argument $expr is an FTS5 match expression designed to be executed against | |
129 # an FTS5 table with the following schema: | |
130 # | |
131 # CREATE VIRTUAL TABLE xy USING fts5(x, y); | |
132 # | |
133 # Assuming the table contains the same records as stored int the global | |
134 # $::data array (see above), this function returns a list containing one | |
135 # element for each match in the dataset. The elements are themselves lists | |
136 # formatted as follows: | |
137 # | |
138 # <rowid> {<phrase 0 matches> <phrase 1 matches>...} | |
139 # | |
140 # where each <phrase X matches> element is a list of phrase matches in the | |
141 # same form as returned by auxiliary scalar function fts5_test(). | |
142 # | |
143 proc matchdata {bPos expr {bAsc 1}} { | |
144 | |
145 set tclexpr [db one { | |
146 SELECT fts5_expr_tcl($expr, 'nearset $cols -pc ::pc', 'x', 'y') | |
147 }] | |
148 set res [list] | |
149 | |
150 #puts $tclexpr | |
151 foreach {id x y} $::data { | |
152 set cols [list $x $y] | |
153 set ::pc 0 | |
154 #set hits [lsort -command instcompare [eval $tclexpr]] | |
155 set hits [eval $tclexpr] | |
156 if {[llength $hits]>0} { | |
157 if {$bPos} { | |
158 lappend res [list $id $hits] | |
159 } else { | |
160 lappend res $id | |
161 } | |
162 } | |
163 } | |
164 | |
165 if {$bAsc} { | |
166 set res [lsort -integer -increasing -index 0 $res] | |
167 } else { | |
168 set res [lsort -integer -decreasing -index 0 $res] | |
169 } | |
170 | |
171 return [concat {*}$res] | |
172 } | |
173 | |
174 # | |
175 # End of test code | |
176 #------------------------------------------------------------------------- | |
177 | |
178 proc fts5_test_poslist {cmd} { | |
179 set res [list] | |
180 for {set i 0} {$i < [$cmd xInstCount]} {incr i} { | |
181 lappend res [string map {{ } .} [$cmd xInst $i]] | |
182 } | |
183 set res | |
184 } | |
185 | |
186 | |
187 foreach {tn2 sql} { | 130 foreach {tn2 sql} { |
188 1 {} | 131 1 {} |
189 2 {BEGIN} | 132 2 {BEGIN} |
190 } { | 133 } { |
191 reset_db | 134 reset_db |
192 sqlite3_fts5_create_function db fts5_test_poslist fts5_test_poslist | 135 fts5_aux_test_functions db |
193 | 136 |
194 do_execsql_test 1.0 { | 137 do_execsql_test 1.$tn2.0 { |
195 CREATE VIRTUAL TABLE xx USING fts5(x,y); | 138 CREATE VIRTUAL TABLE xx USING fts5(x,y, detail=%DETAIL%); |
196 INSERT INTO xx(xx, rank) VALUES('pgsz', 32); | 139 INSERT INTO xx(xx, rank) VALUES('pgsz', 32); |
197 } | 140 } |
198 | 141 |
199 execsql $sql | 142 execsql $sql |
200 | 143 |
201 do_test $tn2.1.1 { | 144 do_test 1.$tn2.1.1 { |
202 foreach {id x y} $data { | 145 foreach {id x y} $data { |
203 execsql { INSERT INTO xx(rowid, x, y) VALUES($id, $x, $y) } | 146 execsql { INSERT INTO xx(rowid, x, y) VALUES($id, $x, $y) } |
204 } | 147 } |
205 execsql { INSERT INTO xx(xx) VALUES('integrity-check') } | 148 execsql { INSERT INTO xx(xx) VALUES('integrity-check') } |
206 } {} | 149 } {} |
207 | 150 |
208 | 151 |
209 #------------------------------------------------------------------------- | 152 #------------------------------------------------------------------------- |
210 # Test phrase queries. | |
211 # | 153 # |
212 foreach {tn phrase} { | 154 do_execsql_test 1.$tn2.integrity { |
213 1 "o" | 155 INSERT INTO xx(xx) VALUES('integrity-check'); |
214 2 "b q" | |
215 3 "e a e" | |
216 4 "m d g q q b k b w f q q p p" | |
217 5 "l o o l v v k" | |
218 6 "a" | |
219 7 "b" | |
220 8 "c" | |
221 9 "no" | |
222 10 "L O O L V V K" | |
223 } { | |
224 set expr "\"$phrase\"" | |
225 set res [matchdata 1 $expr] | |
226 | |
227 do_execsql_test $tn2.1.2.$tn.[llength $res] { | |
228 SELECT rowid, fts5_test_poslist(xx) FROM xx WHERE xx match $expr | |
229 } $res | |
230 } | |
231 | |
232 #------------------------------------------------------------------------- | |
233 # Test some AND and OR queries. | |
234 # | |
235 foreach {tn expr} { | |
236 1.1 "a AND b" | |
237 1.2 "a+b AND c" | |
238 1.3 "d+c AND u" | |
239 1.4 "d+c AND u+d" | |
240 | |
241 2.1 "a OR b" | |
242 2.2 "a+b OR c" | |
243 2.3 "d+c OR u" | |
244 2.4 "d+c OR u+d" | |
245 | |
246 3.1 { a AND b AND c } | |
247 } { | |
248 set res [matchdata 1 $expr] | |
249 do_execsql_test $tn2.2.$tn.[llength $res] { | |
250 SELECT rowid, fts5_test_poslist(xx) FROM xx WHERE xx match $expr | |
251 } $res | |
252 } | |
253 | |
254 #------------------------------------------------------------------------- | |
255 # Queries on a specific column. | |
256 # | |
257 foreach {tn expr} { | |
258 1.1 "x:a" | |
259 1.2 "y:a" | |
260 1.3 "x:b" | |
261 1.4 "y:b" | |
262 2.1 "{x}:a" | |
263 2.2 "{y}:a" | |
264 2.3 "{x}:b" | |
265 2.4 "{y}:b" | |
266 | |
267 3.1 "{x y}:a" | |
268 3.2 "{y x}:a" | |
269 3.3 "{x x}:b" | |
270 3.4 "{y y}:b" | |
271 | |
272 4.1 {{"x" "y"}:a} | |
273 4.2 {{"y" x}:a} | |
274 4.3 {{x "x"}:b} | |
275 4.4 {{"y" y}:b} | |
276 } { | |
277 set res [matchdata 1 $expr] | |
278 do_execsql_test $tn2.3.$tn.[llength $res] { | |
279 SELECT rowid, fts5_test_poslist(xx) FROM xx WHERE xx match $expr | |
280 } $res | |
281 } | |
282 | |
283 #------------------------------------------------------------------------- | |
284 # Some NEAR queries. | |
285 # | |
286 foreach {tn expr} { | |
287 1 "NEAR(a b)" | |
288 2 "NEAR(r c)" | |
289 2 { NEAR(r c, 5) } | |
290 3 { NEAR(r c, 3) } | |
291 4 { NEAR(r c, 2) } | |
292 5 { NEAR(r c, 0) } | |
293 6 { NEAR(a b c) } | |
294 7 { NEAR(a b c, 8) } | |
295 8 { x : NEAR(r c) } | |
296 9 { y : NEAR(r c) } | |
297 } { | |
298 set res [matchdata 1 $expr] | |
299 do_execsql_test $tn2.4.1.$tn.[llength $res] { | |
300 SELECT rowid, fts5_test_poslist(xx) FROM xx WHERE xx match $expr | |
301 } $res | |
302 } | |
303 | |
304 do_test $tn2.4.1 { nearset {{a b c}} -- a } {0.0.0} | |
305 do_test $tn2.4.2 { nearset {{a b c}} -- c } {0.0.2} | |
306 | |
307 foreach {tn expr tclexpr} { | |
308 1 {a b} {AND [N $x -- {a}] [N $x -- {b}]} | |
309 } { | |
310 do_execsql_test $tn2.5.$tn { | |
311 SELECT fts5_expr_tcl($expr, 'N $x') | |
312 } [list $tclexpr] | |
313 } | 156 } |
314 | 157 |
315 #------------------------------------------------------------------------- | 158 #------------------------------------------------------------------------- |
316 # | 159 # |
317 do_execsql_test $tn2.6.integrity { | 160 foreach {tn expr} { |
318 INSERT INTO xx(xx) VALUES('integrity-check'); | 161 1.1 "a AND b" |
319 } | 162 1.2 "a OR b" |
320 #db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM xx_data} {puts $r} | 163 1.3 "o" |
321 foreach {bAsc sql} { | 164 1.4 "b q" |
322 1 {SELECT rowid FROM xx WHERE xx MATCH $expr} | 165 1.5 "e a e" |
323 0 {SELECT rowid FROM xx WHERE xx MATCH $expr ORDER BY rowid DESC} | 166 1.6 "m d g q q b k b w f q q p p" |
| 167 1.7 "l o o l v v k" |
| 168 1.8 "a" |
| 169 1.9 "b" |
| 170 1.10 "c" |
| 171 1.11 "no" |
| 172 1.12 "L O O L V V K" |
| 173 1.13 "a AND b AND c" |
| 174 1.14 "x:a" |
| 175 |
| 176 2.1 "x:a" |
| 177 2.2 "y:a" |
| 178 2.3 "x:b" |
| 179 2.4 "y:b" |
| 180 |
| 181 3.1 "{x}:a" |
| 182 3.2 "{y}:a" |
| 183 3.3 "{x}:b" |
| 184 3.4 "{y}:b" |
| 185 |
| 186 4.1 "{x y}:a" |
| 187 4.2 "{y x}:a" |
| 188 4.3 "{x x}:b" |
| 189 4.4 "{y y}:b" |
| 190 |
| 191 5.1 {{"x" "y"}:a} |
| 192 5.2 {{"y" x}:a} |
| 193 5.3 {{x "x"}:b} |
| 194 5.4 {{"y" y}:b} |
| 195 |
| 196 6.1 "b + q" |
| 197 6.2 "e + a + e" |
| 198 6.3 "m + d + g + q + q + b + k + b + w + f + q + q + p + p" |
| 199 6.4 "l + o + o + l + v + v + k" |
| 200 6.5 "L + O + O + L + V + V + K" |
| 201 |
| 202 7.1 "a+b AND c" |
| 203 7.2 "d+c AND u" |
| 204 7.3 "d+c AND u+d" |
| 205 7.4 "a+b OR c" |
| 206 7.5 "d+c OR u" |
| 207 7.6 "d+c OR u+d" |
| 208 |
| 209 8.1 "NEAR(a b)" |
| 210 8.2 "NEAR(r c)" |
| 211 8.2 { NEAR(r c, 5) } |
| 212 8.3 { NEAR(r c, 3) } |
| 213 8.4 { NEAR(r c, 2) } |
| 214 8.5 { NEAR(r c, 0) } |
| 215 8.6 { NEAR(a b c) } |
| 216 8.7 { NEAR(a b c, 8) } |
| 217 8.8 { x : NEAR(r c) } |
| 218 8.9 { y : NEAR(r c) } |
| 219 |
| 220 9.1 { NEAR(r c) } |
| 221 9.2 { NEAR(r c, 5) } |
| 222 9.3 { NEAR(r c, 3) } |
| 223 9.4 { NEAR(r c, 2) } |
| 224 9.5 { NEAR(r c, 0) } |
| 225 9.6 { NEAR(a b c) } |
| 226 9.7 { NEAR(a b c, 8) } |
| 227 9.8 { x : NEAR(r c) } |
| 228 9.9 { y : NEAR(r c) } |
| 229 9.10 { x : "r c" } |
| 230 9.11 { y : "r c" } |
| 231 9.12 { a AND b } |
| 232 9.13 { a AND b AND c } |
| 233 9.14a { a } |
| 234 9.14b { a OR b } |
| 235 9.15 { a OR b AND c } |
| 236 9.16 { c AND b OR a } |
| 237 9.17 { c AND (b OR a) } |
| 238 9.18 { c NOT (b OR a) } |
| 239 9.19 { (c NOT b) OR (a AND d) } |
324 } { | 240 } { |
325 foreach {tn expr} { | 241 |
326 0.1 x | 242 if {[fts5_expr_ok $expr xx]==0} { |
327 1 { NEAR(r c) } | 243 do_test 1.$tn2.$tn.OMITTED { list } [list] |
328 2 { NEAR(r c, 5) } | 244 continue |
329 3 { NEAR(r c, 3) } | |
330 4 { NEAR(r c, 2) } | |
331 5 { NEAR(r c, 0) } | |
332 6 { NEAR(a b c) } | |
333 7 { NEAR(a b c, 8) } | |
334 8 { x : NEAR(r c) } | |
335 9 { y : NEAR(r c) } | |
336 10 { x : "r c" } | |
337 11 { y : "r c" } | |
338 12 { a AND b } | |
339 13 { a AND b AND c } | |
340 14a { a } | |
341 14b { a OR b } | |
342 15 { a OR b AND c } | |
343 16 { c AND b OR a } | |
344 17 { c AND (b OR a) } | |
345 18 { c NOT (b OR a) } | |
346 19 { c NOT b OR a AND d } | |
347 } { | |
348 set res [matchdata 0 $expr $bAsc] | |
349 do_execsql_test $tn2.6.$bAsc.$tn.[llength $res] $sql $res | |
350 } | 245 } |
| 246 |
| 247 set res [fts5_query_data $expr xx] |
| 248 do_execsql_test 1.$tn2.$tn.[llength $res].asc { |
| 249 SELECT rowid, fts5_test_poslist(xx), fts5_test_collist(xx) |
| 250 FROM xx WHERE xx match $expr |
| 251 } $res |
| 252 |
| 253 set res [fts5_query_data $expr xx DESC] |
| 254 do_execsql_test 1.$tn2.$tn.[llength $res].desc { |
| 255 SELECT rowid, fts5_test_poslist(xx), fts5_test_collist(xx) |
| 256 FROM xx WHERE xx match $expr ORDER BY 1 DESC |
| 257 } $res |
351 } | 258 } |
352 } | 259 } |
353 | 260 |
354 do_execsql_test 3.1 { | 261 } |
| 262 |
| 263 do_execsql_test 2.1 { |
355 SELECT fts5_expr_tcl('a AND b'); | 264 SELECT fts5_expr_tcl('a AND b'); |
356 } {{AND [nearset -- {a}] [nearset -- {b}]}} | 265 } {{AND [nearset -- {a}] [nearset -- {b}]}} |
357 | 266 |
| 267 do_test 2.2.1 { nearset {{a b c}} -- a } {0.0.0} |
| 268 do_test 2.2.2 { nearset {{a b c}} -- c } {0.0.2} |
| 269 |
| 270 foreach {tn expr tclexpr} { |
| 271 1 {a b} {AND [N $x -- {a}] [N $x -- {b}]} |
| 272 } { |
| 273 do_execsql_test 2.3.$tn { |
| 274 SELECT fts5_expr_tcl($expr, 'N $x') |
| 275 } [list $tclexpr] |
| 276 } |
| 277 |
358 finish_test | 278 finish_test |
359 | 279 |
OLD | NEW |