blob: 20640d29ac7c4d9c2e2786f1aaeac980f134a256 [file] [log] [blame]
dan99ebad92011-06-13 09:11:01 +00001# 2011 June 10
2#
3# May you do good and not evil.
4# May you find forgiveness for yourself and forgive others.
5# May you share freely, never taking more than you give.
6#
7#***********************************************************************
8#
9
10set testdir [file dirname $argv0]
11source $testdir/tester.tcl
12
13# If this build does not include FTS3, skip the tests in this file.
14#
15ifcapable !fts3 { finish_test ; return }
16source $testdir/fts3_common.tcl
17source $testdir/malloc_common.tcl
18
dan3fd65192011-06-13 13:48:36 +000019set testprefix fts3auto
20set sfep $sqlite_fts3_enable_parentheses
21set sqlite_fts3_enable_parentheses 1
dan99ebad92011-06-13 09:11:01 +000022
dan3fd65192011-06-13 13:48:36 +000023#--------------------------------------------------------------------------
dandb27fc02011-06-14 11:32:50 +000024# Start of Tcl infrastructure used by tests. The entry points are:
25#
26# do_fts3query_test
27# fts3_make_deferrable
28# fts3_zero_long_segments
dan99ebad92011-06-13 09:11:01 +000029#
dan653265d2011-06-13 18:21:11 +000030
dandb27fc02011-06-14 11:32:50 +000031#
dan653265d2011-06-13 18:21:11 +000032# do_fts3query_test TESTNAME ?OPTIONS? TABLE MATCHEXPR
33#
34# This proc runs several test cases on FTS3/4 table $TABLE using match
35# expression $MATCHEXPR. All documents in $TABLE must be formatted so that
36# they can be "tokenized" using the Tcl list commands (llength, lindex etc.).
37# The name and column names used by $TABLE must not require any quoting or
38# escaping when used in SQL statements.
39#
40# $MATCHINFO may be any expression accepted by the FTS4 MATCH operator,
41# except that the "<column-name>:token" syntax is not supported. Tcl list
42# commands are used to tokenize the expression. Any parenthesis must appear
43# either as separate list elements, or as the first (for opening) or last
44# (for closing) character of a list element. i.e. the expression "(a OR b)c"
45# will not be parsed correctly, but "( a OR b) c" will.
46#
dan2cf1a1d2011-06-14 09:00:27 +000047# Available OPTIONS are:
48#
49# -deferred TOKENLIST
50#
51# If the "deferred" option is supplied, it is passed a list of tokens that
52# are deferred by FTS and result in the relevant matchinfo() stats being an
53# approximation.
54#
dan653265d2011-06-13 18:21:11 +000055set sqlite_fts3_enable_parentheses 1
dan2cf1a1d2011-06-14 09:00:27 +000056proc do_fts3query_test {tn args} {
dan653265d2011-06-13 18:21:11 +000057
dan2cf1a1d2011-06-14 09:00:27 +000058 set nArg [llength $args]
59 if {$nArg < 2 || ($nArg % 2)} {
60 set cmd do_fts3query_test
61 error "wrong # args: should be \"$cmd ?-deferred LIST? TABLE MATCHEXPR\""
62 }
63 set tbl [lindex $args [expr $nArg-2]]
64 set match [lindex $args [expr $nArg-1]]
65 set deferred [list]
66
67 foreach {k v} [lrange $args 0 [expr $nArg-3]] {
68 switch -- $k {
69 -deferred {
dan4dc3d732012-08-20 17:24:48 +000070 ifcapable fts4_deferred { set deferred $v }
dan2cf1a1d2011-06-14 09:00:27 +000071 }
72 default {
73 error "bad option \"$k\": must be -deferred"
74 }
75 }
76 }
77
dan5cfed522012-05-10 17:43:14 +000078 get_near_results $tbl $match $deferred aHit
79 get_near_results $tbl [string map {AND OR} $match] $deferred aMatchinfo
dan653265d2011-06-13 18:21:11 +000080
81 set matchinfo_asc [list]
dan5cfed522012-05-10 17:43:14 +000082 foreach docid [lsort -integer -incr [array names aHit]] {
dan653265d2011-06-13 18:21:11 +000083 lappend matchinfo_asc $docid $aMatchinfo($docid)
84 }
85 set matchinfo_desc [list]
dan5cfed522012-05-10 17:43:14 +000086 foreach docid [lsort -integer -decr [array names aHit]] {
dan653265d2011-06-13 18:21:11 +000087 lappend matchinfo_desc $docid $aMatchinfo($docid)
88 }
89
dan5cfed522012-05-10 17:43:14 +000090 set title "(\"$match\" -> [llength [array names aHit]] rows)"
dan653265d2011-06-13 18:21:11 +000091
92 do_execsql_test $tn$title.1 "
93 SELECT docid FROM $tbl WHERE $tbl MATCH '$match' ORDER BY docid ASC
dan5cfed522012-05-10 17:43:14 +000094 " [lsort -integer -incr [array names aHit]]
dan653265d2011-06-13 18:21:11 +000095
96 do_execsql_test $tn$title.2 "
97 SELECT docid FROM $tbl WHERE $tbl MATCH '$match' ORDER BY docid DESC
dan5cfed522012-05-10 17:43:14 +000098 " [lsort -integer -decr [array names aHit]]
dan653265d2011-06-13 18:21:11 +000099
100 do_execsql_test $tn$title.3 "
101 SELECT docid, mit(matchinfo($tbl, 'x')) FROM $tbl
102 WHERE $tbl MATCH '$match' ORDER BY docid DESC
103 " $matchinfo_desc
104
105 do_execsql_test $tn$title.4 "
106 SELECT docid, mit(matchinfo($tbl, 'x')) FROM $tbl
107 WHERE $tbl MATCH '$match' ORDER BY docid ASC
108 " $matchinfo_asc
109}
110
danda7b4562011-06-28 11:58:09 +0000111# fts3_make_deferrable TABLE TOKEN ?NROW?
dandb27fc02011-06-14 11:32:50 +0000112#
danda7b4562011-06-28 11:58:09 +0000113proc fts3_make_deferrable {tbl token {nRow 0}} {
dandb27fc02011-06-14 11:32:50 +0000114
115 set stmt [sqlite3_prepare db "SELECT * FROM $tbl" -1 dummy]
116 set name [sqlite3_column_name $stmt 0]
117 sqlite3_finalize $stmt
118
danda7b4562011-06-28 11:58:09 +0000119 if {$nRow==0} {
120 set nRow [db one "SELECT count(*) FROM $tbl"]
121 }
dandb27fc02011-06-14 11:32:50 +0000122 set pgsz [db one "PRAGMA page_size"]
123 execsql BEGIN
124 for {set i 0} {$i < ($nRow * $pgsz * 1.2)/100} {incr i} {
125 set doc [string repeat "$token " 100]
126 execsql "INSERT INTO $tbl ($name) VALUES(\$doc)"
127 }
128 execsql "INSERT INTO $tbl ($name) VALUES('aaaaaaa ${token}aaaaa')"
129 execsql COMMIT
130
131 return [expr $nRow*$pgsz]
132}
133
134# fts3_zero_long_segments TABLE ?LIMIT?
135#
136proc fts3_zero_long_segments {tbl limit} {
137 execsql "
138 UPDATE ${tbl}_segments
139 SET block = zeroblob(length(block))
140 WHERE length(block)>$limit
141 "
142 return [db changes]
143}
144
dan653265d2011-06-13 18:21:11 +0000145
dan99ebad92011-06-13 09:11:01 +0000146proc mit {blob} {
147 set scan(littleEndian) i*
148 set scan(bigEndian) I*
149 binary scan $blob $scan($::tcl_platform(byteOrder)) r
150 return $r
151}
152db func mit mit
153
danb727d672011-06-20 10:46:49 +0000154proc fix_phrase_expr {cols expr colfiltervar} {
155 upvar $colfiltervar iColFilter
156
dan99ebad92011-06-13 09:11:01 +0000157 set out [list]
danb727d672011-06-20 10:46:49 +0000158 foreach t $expr {
159 if {[string match *:* $t]} {
160 set col [lindex [split $t :] 0]
161 set t [lindex [split $t :] 1]
162 set iCol [lsearch $cols $col]
163 if {$iCol<0} { error "unknown column: $col" }
164 if {$iColFilter < 0} {
165 set iColFilter $iCol
166 } elseif {$iColFilter != $iCol} {
167 set iColFilter [llength $cols]
168 }
169 }
170 lappend out $t
171 }
172
173 return $out
174}
175
176proc fix_near_expr {cols expr colfiltervar} {
177 upvar $colfiltervar iColFilter
178
179 set iColFilter -1
180
181 set out [list]
182 lappend out [fix_phrase_expr $cols [lindex $expr 0] iColFilter]
dan99ebad92011-06-13 09:11:01 +0000183 foreach {a b} [lrange $expr 1 end] {
184 if {[string match -nocase near $a]} { set a 10 }
185 if {[string match -nocase near/* $a]} { set a [string range $a 5 end] }
186 lappend out $a
danb727d672011-06-20 10:46:49 +0000187 lappend out [fix_phrase_expr $cols $b iColFilter]
dan99ebad92011-06-13 09:11:01 +0000188 }
189 return $out
190}
191
dan2cf1a1d2011-06-14 09:00:27 +0000192proc get_single_near_results {tbl expr deferred arrayvar nullvar} {
dan3fd65192011-06-13 13:48:36 +0000193 upvar $arrayvar aMatchinfo
194 upvar $nullvar nullentry
195 catch {array unset aMatchinfo}
dan99ebad92011-06-13 09:11:01 +0000196
danb727d672011-06-20 10:46:49 +0000197 set cols [list]
198 set miss [list]
199 db eval "PRAGMA table_info($tbl)" A { lappend cols $A(name) ; lappend miss 0 }
200 set expr [fix_near_expr $cols $expr iColFilter]
dan99ebad92011-06-13 09:11:01 +0000201
dan99ebad92011-06-13 09:11:01 +0000202 # Calculate the expected results using [fts3_near_match]. The following
203 # loop populates the "hits" and "counts" arrays as follows:
204 #
205 # 1. For each document in the table that matches the NEAR expression,
206 # hits($docid) is set to 1. The set of docids that match the expression
207 # can therefore be found using [array names hits].
208 #
209 # 2. For each column of each document in the table, counts($docid,$iCol)
210 # is set to the -phrasecountvar output.
211 #
212 set res [list]
213 catch { array unset hits }
214 db eval "SELECT docid, * FROM $tbl" d {
215 set iCol 0
216 foreach col [lrange $d(*) 1 end] {
217 set docid $d(docid)
danb727d672011-06-20 10:46:49 +0000218 if {$iColFilter<0 || $iCol==$iColFilter} {
219 set hit [fts3_near_match $d($col) $expr -p counts($docid,$iCol)]
220 if {$hit} { set hits($docid) 1 }
221 } else {
222 set counts($docid,$iCol) $miss
223 }
dan99ebad92011-06-13 09:11:01 +0000224 incr iCol
225 }
226 }
227 set nPhrase [expr ([llength $expr]+1)/2]
228 set nCol $iCol
229
230 # This block populates the nHit and nDoc arrays. For each phrase/column
231 # in the query/table, array elements are set as follows:
232 #
233 # nHit($iPhrase,$iCol) - Total number of hits for phrase $iPhrase in
234 # column $iCol.
235 #
236 # nDoc($iPhrase,$iCol) - Number of documents with at least one hit for
237 # phrase $iPhrase in column $iCol.
238 #
239 for {set iPhrase 0} {$iPhrase < $nPhrase} {incr iPhrase} {
240 for {set iCol 0} {$iCol < $nCol} {incr iCol} {
241 set nHit($iPhrase,$iCol) 0
242 set nDoc($iPhrase,$iCol) 0
243 }
244 }
245 foreach key [array names counts] {
246 set iCol [lindex [split $key ,] 1]
247 set iPhrase 0
248 foreach c $counts($key) {
dan2f779342011-06-13 17:00:12 +0000249 if {$c>0} { incr nDoc($iPhrase,$iCol) 1 }
250 incr nHit($iPhrase,$iCol) $c
dan99ebad92011-06-13 09:11:01 +0000251 incr iPhrase
252 }
253 }
254
dan2cf1a1d2011-06-14 09:00:27 +0000255 if {[llength $deferred] && [llength $expr]==1} {
dan2f779342011-06-13 17:00:12 +0000256 set phrase [lindex $expr 0]
257 set rewritten [list]
258 set partial 0
259 foreach tok $phrase {
dan2cf1a1d2011-06-14 09:00:27 +0000260 if {[lsearch $deferred $tok]>=0} {
dan2f779342011-06-13 17:00:12 +0000261 lappend rewritten *
262 } else {
263 lappend rewritten $tok
264 set partial 1
265 }
266 }
267 if {$partial==0} {
268 set tblsize [db one "SELECT count(*) FROM $tbl"]
269 for {set iCol 0} {$iCol < $nCol} {incr iCol} {
270 set nHit(0,$iCol) $tblsize
271 set nDoc(0,$iCol) $tblsize
272 }
273 } elseif {$rewritten != $phrase} {
274 while {[lindex $rewritten end] == "*"} {
275 set rewritten [lrange $rewritten 0 end-1]
276 }
277 while {[lindex $rewritten 0] == "*"} {
278 set rewritten [lrange $rewritten 1 end]
279 }
dan2cf1a1d2011-06-14 09:00:27 +0000280 get_single_near_results $tbl [list $rewritten] {} aRewrite nullentry
dan2f779342011-06-13 17:00:12 +0000281 foreach docid [array names hits] {
282 set aMatchinfo($docid) $aRewrite($docid)
283 }
284 return
285 }
286 }
287
dan99ebad92011-06-13 09:11:01 +0000288 # Set up the aMatchinfo array. For each document, set aMatchinfo($docid) to
289 # contain the output of matchinfo('x') for the document.
290 #
291 foreach docid [array names hits] {
292 set mi [list]
293 for {set iPhrase 0} {$iPhrase<$nPhrase} {incr iPhrase} {
294 for {set iCol 0} {$iCol<$nCol} {incr iCol} {
295 lappend mi [lindex $counts($docid,$iCol) $iPhrase]
dan99ebad92011-06-13 09:11:01 +0000296 lappend mi $nHit($iPhrase,$iCol)
dan2f779342011-06-13 17:00:12 +0000297 lappend mi $nDoc($iPhrase,$iCol)
dan99ebad92011-06-13 09:11:01 +0000298 }
299 }
300 set aMatchinfo($docid) $mi
301 }
302
dan3fd65192011-06-13 13:48:36 +0000303 # Set up the nullentry output.
304 #
305 set nullentry [list]
306 for {set iPhrase 0} {$iPhrase<$nPhrase} {incr iPhrase} {
307 for {set iCol 0} {$iCol<$nCol} {incr iCol} {
dan2f779342011-06-13 17:00:12 +0000308 lappend nullentry 0 $nHit($iPhrase,$iCol) $nDoc($iPhrase,$iCol)
dan3fd65192011-06-13 13:48:36 +0000309 }
310 }
311}
312
313
314proc matching_brackets {expr} {
315 if {[string range $expr 0 0]!="(" || [string range $expr end end] !=")"} {
316 return 0
317 }
318
319 set iBracket 1
320 set nExpr [string length $expr]
321 for {set i 1} {$iBracket && $i < $nExpr} {incr i} {
322 set c [string range $expr $i $i]
323 if {$c == "("} {incr iBracket}
324 if {$c == ")"} {incr iBracket -1}
325 }
326
327 return [expr ($iBracket==0 && $i==$nExpr)]
328}
329
dan2cf1a1d2011-06-14 09:00:27 +0000330proc get_near_results {tbl expr deferred arrayvar {nullvar ""}} {
dan3fd65192011-06-13 13:48:36 +0000331 upvar $arrayvar aMatchinfo
332 if {$nullvar != ""} { upvar $nullvar nullentry }
333
334 set expr [string trim $expr]
335 while { [matching_brackets $expr] } {
336 set expr [string trim [string range $expr 1 end-1]]
337 }
338
339 set prec(NOT) 1
340 set prec(AND) 2
341 set prec(OR) 3
342
343 set currentprec 0
344 set iBracket 0
345 set expr_length [llength $expr]
346 for {set i 0} {$i < $expr_length} {incr i} {
347 set op [lindex $expr $i]
348 if {$iBracket==0 && [info exists prec($op)] && $prec($op)>=$currentprec } {
349 set opidx $i
350 set currentprec $prec($op)
351 } else {
352 for {set j 0} {$j < [string length $op]} {incr j} {
353 set c [string range $op $j $j]
354 if {$c == "("} { incr iBracket +1 }
355 if {$c == ")"} { incr iBracket -1 }
356 }
357 }
358 }
359 if {$iBracket!=0} { error "mismatched brackets in: $expr" }
360
361 if {[info exists opidx]==0} {
dan2cf1a1d2011-06-14 09:00:27 +0000362 get_single_near_results $tbl $expr $deferred aMatchinfo nullentry
dan3fd65192011-06-13 13:48:36 +0000363 } else {
364 set eLeft [lrange $expr 0 [expr $opidx-1]]
365 set eRight [lrange $expr [expr $opidx+1] end]
366
dan2cf1a1d2011-06-14 09:00:27 +0000367 get_near_results $tbl $eLeft $deferred aLeft nullleft
368 get_near_results $tbl $eRight $deferred aRight nullright
dan3fd65192011-06-13 13:48:36 +0000369
370 switch -- [lindex $expr $opidx] {
371 "NOT" {
372 foreach hit [array names aLeft] {
373 if {0==[info exists aRight($hit)]} {
374 set aMatchinfo($hit) $aLeft($hit)
375 }
376 }
377 set nullentry $nullleft
378 }
379
380 "AND" {
381 foreach hit [array names aLeft] {
382 if {[info exists aRight($hit)]} {
383 set aMatchinfo($hit) [concat $aLeft($hit) $aRight($hit)]
384 }
385 }
386 set nullentry [concat $nullleft $nullright]
387 }
388
389 "OR" {
390 foreach hit [array names aLeft] {
391 if {[info exists aRight($hit)]} {
392 set aMatchinfo($hit) [concat $aLeft($hit) $aRight($hit)]
393 unset aRight($hit)
394 } else {
395 set aMatchinfo($hit) [concat $aLeft($hit) $nullright]
396 }
397 }
398 foreach hit [array names aRight] {
399 set aMatchinfo($hit) [concat $nullleft $aRight($hit)]
400 }
401
402 set nullentry [concat $nullleft $nullright]
403 }
404 }
405 }
406}
407
dan3fd65192011-06-13 13:48:36 +0000408
409# End of test procs. Actual tests are below this line.
410#--------------------------------------------------------------------------
411
412#--------------------------------------------------------------------------
413# The following test cases - fts3auto-1.* - focus on testing the Tcl
414# command [fts3_near_match], which is used by other tests in this file.
415#
416proc test_fts3_near_match {tn doc expr res} {
417 fts3_near_match $doc $expr -phrasecountvar p
418 uplevel do_test [list $tn] [list [list set {} $p]] [list $res]
dan99ebad92011-06-13 09:11:01 +0000419}
420
dan3fd65192011-06-13 13:48:36 +0000421test_fts3_near_match 1.1.1 {a b c a b} a {2}
422test_fts3_near_match 1.1.2 {a b c a b} {a 5 b 6 c} {2 2 1}
423test_fts3_near_match 1.1.3 {a b c a b} {"a b"} {2}
424test_fts3_near_match 1.1.4 {a b c a b} {"b c"} {1}
425test_fts3_near_match 1.1.5 {a b c a b} {"c c"} {0}
426
427test_fts3_near_match 1.2.1 "a b c d e f g" {b 2 f} {0 0}
428test_fts3_near_match 1.2.2 "a b c d e f g" {b 3 f} {1 1}
429test_fts3_near_match 1.2.3 "a b c d e f g" {f 2 b} {0 0}
430test_fts3_near_match 1.2.4 "a b c d e f g" {f 3 b} {1 1}
431test_fts3_near_match 1.2.5 "a b c d e f g" {"a b" 2 "f g"} {0 0}
432test_fts3_near_match 1.2.6 "a b c d e f g" {"a b" 3 "f g"} {1 1}
433
434set A "a b c d e f g h i j k l m n o p q r s t u v w x y z"
435test_fts3_near_match 1.3.1 $A {"c d" 5 "i j" 1 "e f"} {0 0 0}
436test_fts3_near_match 1.3.2 $A {"c d" 5 "i j" 2 "e f"} {1 1 1}
437
438#--------------------------------------------------------------------------
439# Test cases fts3auto-2.* run some simple tests using the
dan2f779342011-06-13 17:00:12 +0000440# [do_fts3query_test] proc.
dan3fd65192011-06-13 13:48:36 +0000441#
442foreach {tn create} {
dan2f779342011-06-13 17:00:12 +0000443 1 "fts4(a, b)"
444 2 "fts4(a, b, order=DESC)"
445 3 "fts4(a, b, order=ASC)"
446 4 "fts4(a, b, prefix=1)"
447 5 "fts4(a, b, order=DESC, prefix=1)"
448 6 "fts4(a, b, order=ASC, prefix=1)"
dan3fd65192011-06-13 13:48:36 +0000449} {
450 do_test 2.$tn.1 {
451 catchsql { DROP TABLE t1 }
dan2f779342011-06-13 17:00:12 +0000452 execsql "CREATE VIRTUAL TABLE t1 USING $create"
dan3fd65192011-06-13 13:48:36 +0000453 for {set i 0} {$i<32} {incr i} {
454 set doc [list]
455 if {$i&0x01} {lappend doc one}
456 if {$i&0x02} {lappend doc two}
457 if {$i&0x04} {lappend doc three}
458 if {$i&0x08} {lappend doc four}
459 if {$i&0x10} {lappend doc five}
460 execsql { INSERT INTO t1 VALUES($doc, null) }
461 }
462 } {}
dan2f779342011-06-13 17:00:12 +0000463
dan3fd65192011-06-13 13:48:36 +0000464 foreach {tn2 expr} {
465 1 {one}
466 2 {one NEAR/1 five}
467 3 {t*}
468 4 {t* NEAR/0 five}
469 5 {o* NEAR/1 f*}
470 6 {one NEAR five NEAR two NEAR four NEAR three}
471 7 {one NEAR xyz}
472 8 {one OR two}
473 9 {one AND two}
474 10 {one NOT two}
475 11 {one AND two OR three}
476 12 {three OR one AND two}
477 13 {(three OR one) AND two}
478 14 {(three OR one) AND two NOT (five NOT four)}
479 15 {"one two"}
480 16 {"one two" NOT "three four"}
481 } {
dan2f779342011-06-13 17:00:12 +0000482 do_fts3query_test 2.$tn.2.$tn2 t1 $expr
483 }
484}
485
486#--------------------------------------------------------------------------
487# Some test cases involving deferred tokens.
488#
dan2f779342011-06-13 17:00:12 +0000489
490foreach {tn create} {
491 1 "fts4(x)"
492 2 "fts4(x, order=DESC)"
493} {
494 catchsql { DROP TABLE t1 }
495 execsql "CREATE VIRTUAL TABLE t1 USING $create"
496 do_execsql_test 3.$tn.1 {
dan653265d2011-06-13 18:21:11 +0000497 INSERT INTO t1(docid, x) VALUES(-2, 'a b c d e f g h i j k');
498 INSERT INTO t1(docid, x) VALUES(-1, 'b c d e f g h i j k a');
499 INSERT INTO t1(docid, x) VALUES(0, 'c d e f g h i j k a b');
500 INSERT INTO t1(docid, x) VALUES(1, 'd e f g h i j k a b c');
501 INSERT INTO t1(docid, x) VALUES(2, 'e f g h i j k a b c d');
502 INSERT INTO t1(docid, x) VALUES(3, 'f g h i j k a b c d e');
503 INSERT INTO t1(docid, x) VALUES(4, 'a c e g i k');
504 INSERT INTO t1(docid, x) VALUES(5, 'a d g j');
505 INSERT INTO t1(docid, x) VALUES(6, 'c a b');
dan2f779342011-06-13 17:00:12 +0000506 }
507
dandb27fc02011-06-14 11:32:50 +0000508 set limit [fts3_make_deferrable t1 c]
dan2f779342011-06-13 17:00:12 +0000509
dandb27fc02011-06-14 11:32:50 +0000510 do_fts3query_test 3.$tn.2.1 t1 {a OR c}
dan2f779342011-06-13 17:00:12 +0000511
dan4dc3d732012-08-20 17:24:48 +0000512 ifcapable fts4_deferred {
513 do_test 3.$tn.3 { fts3_zero_long_segments t1 $limit } {1}
514 }
dandb27fc02011-06-14 11:32:50 +0000515
dan2cf1a1d2011-06-14 09:00:27 +0000516 foreach {tn2 expr def} {
517 1 {a NEAR c} {}
518 2 {a AND c} c
519 3 {"a c"} c
520 4 {"c a"} c
521 5 {"a c" NEAR/1 g} {}
522 6 {"a c" NEAR/0 g} {}
dan2f779342011-06-13 17:00:12 +0000523 } {
dandb27fc02011-06-14 11:32:50 +0000524 do_fts3query_test 3.$tn.4.$tn2 -deferred $def t1 $expr
dan2cf1a1d2011-06-14 09:00:27 +0000525 }
526}
527
528#--------------------------------------------------------------------------
dandb27fc02011-06-14 11:32:50 +0000529#
dan2cf1a1d2011-06-14 09:00:27 +0000530foreach {tn create} {
531 1 "fts4(x, y)"
532 2 "fts4(x, y, order=DESC)"
dandb27fc02011-06-14 11:32:50 +0000533 3 "fts4(x, y, order=DESC, prefix=2)"
dan2cf1a1d2011-06-14 09:00:27 +0000534} {
dan2cf1a1d2011-06-14 09:00:27 +0000535
dandb27fc02011-06-14 11:32:50 +0000536 execsql [subst {
537 DROP TABLE t1;
538 CREATE VIRTUAL TABLE t1 USING $create;
539 INSERT INTO t1 VALUES('one two five four five', '');
540 INSERT INTO t1 VALUES('', 'one two five four five');
541 INSERT INTO t1 VALUES('one two', 'five four five');
542 }]
dan2cf1a1d2011-06-14 09:00:27 +0000543
dandb27fc02011-06-14 11:32:50 +0000544 do_fts3query_test 4.$tn.1.1 t1 {one AND five}
545 do_fts3query_test 4.$tn.1.2 t1 {one NEAR five}
546 do_fts3query_test 4.$tn.1.3 t1 {one NEAR/1 five}
547 do_fts3query_test 4.$tn.1.4 t1 {one NEAR/2 five}
548 do_fts3query_test 4.$tn.1.5 t1 {one NEAR/3 five}
549
550 do_test 4.$tn.2 {
551 set limit [fts3_make_deferrable t1 five]
552 execsql { INSERT INTO t1(t1) VALUES('optimize') }
dan4dc3d732012-08-20 17:24:48 +0000553 ifcapable fts4_deferred {
554 expr {[fts3_zero_long_segments t1 $limit]>0}
555 } else {
556 expr 1
557 }
dandb27fc02011-06-14 11:32:50 +0000558 } {1}
559
560 do_fts3query_test 4.$tn.3.1 -deferred five t1 {one AND five}
561 do_fts3query_test 4.$tn.3.2 -deferred five t1 {one NEAR five}
562 do_fts3query_test 4.$tn.3.3 -deferred five t1 {one NEAR/1 five}
563 do_fts3query_test 4.$tn.3.4 -deferred five t1 {one NEAR/2 five}
dand4d21fe2011-06-16 16:06:05 +0000564
dandb27fc02011-06-14 11:32:50 +0000565 do_fts3query_test 4.$tn.3.5 -deferred five t1 {one NEAR/3 five}
566
567 do_fts3query_test 4.$tn.4.1 -deferred fi* t1 {on* AND fi*}
568 do_fts3query_test 4.$tn.4.2 -deferred fi* t1 {on* NEAR fi*}
569 do_fts3query_test 4.$tn.4.3 -deferred fi* t1 {on* NEAR/1 fi*}
570 do_fts3query_test 4.$tn.4.4 -deferred fi* t1 {on* NEAR/2 fi*}
571 do_fts3query_test 4.$tn.4.5 -deferred fi* t1 {on* NEAR/3 fi*}
dan3fd65192011-06-13 13:48:36 +0000572}
573
dan376d1e52011-06-15 08:30:29 +0000574#--------------------------------------------------------------------------
575# The following test cases - fts3auto-5.* - focus on using prefix indexes.
576#
577set chunkconfig [fts3_configure_incr_load 1 1]
dand4d21fe2011-06-16 16:06:05 +0000578foreach {tn create pending} {
dand4d21fe2011-06-16 16:06:05 +0000579 1 "fts4(a, b)" 1
danb727d672011-06-20 10:46:49 +0000580 2 "fts4(a, b, order=ASC, prefix=1)" 1
dan585db0e2012-01-25 16:29:45 +0000581 3 "fts4(a, b, order=ASC, prefix=\"1,3\")" 0
582 4 "fts4(a, b, order=DESC, prefix=\"2,4\")" 0
583 5 "fts4(a, b, order=DESC, prefix=\"1\")" 0
584 6 "fts4(a, b, order=ASC, prefix=\"1,3\")" 0
dan376d1e52011-06-15 08:30:29 +0000585} {
586
587 execsql [subst {
dand4d21fe2011-06-16 16:06:05 +0000588 DROP TABLE IF EXISTS t1;
dan376d1e52011-06-15 08:30:29 +0000589 CREATE VIRTUAL TABLE t1 USING $create;
590 }]
591
dand4d21fe2011-06-16 16:06:05 +0000592 if {$pending} {execsql BEGIN}
593
dan376d1e52011-06-15 08:30:29 +0000594 foreach {a b} {
595 "the song of songs which is solomons"
596 "let him kiss me with the kisses of his mouth for thy love is better than wine"
597 "because of the savour of thy good ointments thy name is as ointment poured forth therefore do the virgins love thee"
598 "draw me we will run after thee the king hath brought me into his chambers we will be glad and rejoice in thee we will remember thy love more than wine the upright love thee"
599 "i am black but comely o ye daughters of jerusalem as the tents of kedar as the curtains of solomon"
600 "look not upon me because i am black because the sun hath looked upon me my mothers children were angry with me they made me the keeper of the vineyards but mine own vineyard have i not kept"
601 "tell me o thou whom my soul loveth where thou feedest where thou makest thy flock to rest at noon for why should i be as one that turneth aside by the flocks of thy companions?"
602 "if thou know not o thou fairest among women go thy way forth by the footsteps of the flock and feed thy kids beside the shepherds tents"
603 "i have compared thee o my love to a company of horses in pharaohs chariots"
604 "thy cheeks are comely with rows of jewels thy neck with chains of gold"
605 "we will make thee borders of gold with studs of silver"
606 "while the king sitteth at his table my spikenard sendeth forth the smell thereof"
607 "a bundle of myrrh is my wellbeloved unto me he shall lie all night betwixt my breasts"
608 "my beloved is unto me as a cluster of camphire in the vineyards of en gedi"
609 "behold thou art fair my love behold thou art fair thou hast doves eyes"
610 "behold thou art fair my beloved yea pleasant also our bed is green"
611 "the beams of our house are cedar and our rafters of fir"
612 } {
613 execsql {INSERT INTO t1(a, b) VALUES($a, $b)}
614 }
615
dand4d21fe2011-06-16 16:06:05 +0000616
dan376d1e52011-06-15 08:30:29 +0000617 do_fts3query_test 5.$tn.1.1 t1 {s*}
618 do_fts3query_test 5.$tn.1.2 t1 {so*}
619 do_fts3query_test 5.$tn.1.3 t1 {"s* o*"}
620 do_fts3query_test 5.$tn.1.4 t1 {b* NEAR/3 a*}
dand4d21fe2011-06-16 16:06:05 +0000621 do_fts3query_test 5.$tn.1.5 t1 {a*}
622 do_fts3query_test 5.$tn.1.6 t1 {th* NEAR/5 a* NEAR/5 w*}
623 do_fts3query_test 5.$tn.1.7 t1 {"b* th* art* fair*"}
624
625 if {$pending} {execsql COMMIT}
dan376d1e52011-06-15 08:30:29 +0000626}
627eval fts3_configure_incr_load $chunkconfig
628
danb727d672011-06-20 10:46:49 +0000629foreach {tn pending create} {
630 1 0 "fts4(a, b, c, d)"
631 2 1 "fts4(a, b, c, d)"
632 3 0 "fts4(a, b, c, d, order=DESC)"
633 4 1 "fts4(a, b, c, d, order=DESC)"
634} {
635 execsql [subst {
636 DROP TABLE IF EXISTS t1;
637 CREATE VIRTUAL TABLE t1 USING $create;
638 }]
639
640
641 if {$pending} { execsql BEGIN }
642
643 foreach {a b c d} {
644 "A B C" "D E F" "G H I" "J K L"
645 "B C D" "E F G" "H I J" "K L A"
646 "C D E" "F G H" "I J K" "L A B"
647 "D E F" "G H I" "J K L" "A B C"
648 "E F G" "H I J" "K L A" "B C D"
649 "F G H" "I J K" "L A B" "C D E"
650 } {
651 execsql { INSERT INTO t1 VALUES($a, $b, $c, $d) }
652 }
653
654 do_fts3query_test 6.$tn.1 t1 {b:G}
655 do_fts3query_test 6.$tn.2 t1 {b:G AND c:I}
656 do_fts3query_test 6.$tn.3 t1 {b:G NEAR c:I}
657 do_fts3query_test 6.$tn.4 t1 {a:C OR b:G OR c:K OR d:C}
dan5cfed522012-05-10 17:43:14 +0000658
danb727d672011-06-20 10:46:49 +0000659 do_fts3query_test 6.$tn.5 t1 {a:G OR b:G}
660
661 catchsql { COMMIT }
662}
663
danda7b4562011-06-28 11:58:09 +0000664foreach {tn create} {
665 1 "fts4(x)"
666 2 "fts4(x, order=DESC)"
667} {
668 execsql [subst {
669 DROP TABLE IF EXISTS t1;
670 CREATE VIRTUAL TABLE t1 USING $create;
671 }]
672
673 foreach {x} {
674 "F E N O T K X V A X I E X A P G Q V H U"
675 "R V A E T C V Q N I E L O N U G J K L U"
676 "U Y I G W M V F J L X I D C H F P J Q B"
677 "S G D Z X R P G S S Y B K A S G A I L L"
678 "L S I C H T Z S R Q P R N K J X L F M J"
679 "C C C D P X B Z C M A D A C X S B T X V"
680 "W Y J M D R G V R K B X S A W R I T N C"
681 "P K L W T M S P O Y Y V V O E H Q A I R"
682 "C D Y I C Z F H J C O Y A Q F L S B D K"
683 "P G S C Y C Y V I M B D S Z D D Y W I E"
684 "Z K Z U E E S F Y X T U A L W O U J C Q"
685 "P A T Z S W L P L Q V Y Y I P W U X S S"
686 "I U I H U O F Z F R H R F T N D X A G M"
687 "N A B M S H K X S O Y D T X S B R Y H Z"
688 "L U D A S K I L S V Z J P U B E B Y H M"
689 } {
690 execsql { INSERT INTO t1 VALUES($x) }
691 }
692
693 # Add extra documents to the database such that token "B" will be considered
694 # deferrable if considering the other tokens means that 2 or fewer documents
695 # will be loaded into memory.
696 #
697 fts3_make_deferrable t1 B 2
698
699 # B is not deferred in either of the first two tests below, since filtering
700 # on "M" or "D" returns 10 documents or so. But filtering on "M * D" only
701 # returns 2, so B is deferred in this case.
702 #
703 do_fts3query_test 7.$tn.1 t1 {"M B"}
704 do_fts3query_test 7.$tn.2 t1 {"B D"}
705 do_fts3query_test 7.$tn.3 -deferred B t1 {"M B D"}
706}
707
dan3fd65192011-06-13 13:48:36 +0000708set sqlite_fts3_enable_parentheses $sfep
dan99ebad92011-06-13 09:11:01 +0000709finish_test