1# 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 19set testprefix fts3auto 20set sfep $sqlite_fts3_enable_parentheses 21set sqlite_fts3_enable_parentheses 1 22 23#-------------------------------------------------------------------------- 24# 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 29# 30 31# 32# 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# 47# 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# 55set sqlite_fts3_enable_parentheses 1 56proc do_fts3query_test {tn args} { 57 58 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 { 70 ifcapable fts4_deferred { set deferred $v } 71 } 72 default { 73 error "bad option \"$k\": must be -deferred" 74 } 75 } 76 } 77 78 get_near_results $tbl $match $deferred aHit 79 get_near_results $tbl [string map {AND OR} $match] $deferred aMatchinfo 80 81 set matchinfo_asc [list] 82 foreach docid [lsort -integer -incr [array names aHit]] { 83 lappend matchinfo_asc $docid $aMatchinfo($docid) 84 } 85 set matchinfo_desc [list] 86 foreach docid [lsort -integer -decr [array names aHit]] { 87 lappend matchinfo_desc $docid $aMatchinfo($docid) 88 } 89 90 set title "(\"$match\" -> [llength [array names aHit]] rows)" 91 92 do_execsql_test $tn$title.1 " 93 SELECT docid FROM $tbl WHERE $tbl MATCH '$match' ORDER BY docid ASC 94 " [lsort -integer -incr [array names aHit]] 95 96 do_execsql_test $tn$title.2 " 97 SELECT docid FROM $tbl WHERE $tbl MATCH '$match' ORDER BY docid DESC 98 " [lsort -integer -decr [array names aHit]] 99 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 111# fts3_make_deferrable TABLE TOKEN ?NROW? 112# 113proc fts3_make_deferrable {tbl token {nRow 0}} { 114 115 set stmt [sqlite3_prepare db "SELECT * FROM $tbl" -1 dummy] 116 set name [sqlite3_column_name $stmt 0] 117 sqlite3_finalize $stmt 118 119 if {$nRow==0} { 120 set nRow [db one "SELECT count(*) FROM $tbl"] 121 } 122 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 145 146proc 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 154proc fix_phrase_expr {cols expr colfiltervar} { 155 upvar $colfiltervar iColFilter 156 157 set out [list] 158 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] 183 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 187 lappend out [fix_phrase_expr $cols $b iColFilter] 188 } 189 return $out 190} 191 192proc get_single_near_results {tbl expr deferred arrayvar nullvar} { 193 upvar $arrayvar aMatchinfo 194 upvar $nullvar nullentry 195 catch {array unset aMatchinfo} 196 197 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] 201 202 # 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) 218 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 } 224 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) { 249 if {$c>0} { incr nDoc($iPhrase,$iCol) 1 } 250 incr nHit($iPhrase,$iCol) $c 251 incr iPhrase 252 } 253 } 254 255 if {[llength $deferred] && [llength $expr]==1} { 256 set phrase [lindex $expr 0] 257 set rewritten [list] 258 set partial 0 259 foreach tok $phrase { 260 if {[lsearch $deferred $tok]>=0} { 261 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 } 280 get_single_near_results $tbl [list $rewritten] {} aRewrite nullentry 281 foreach docid [array names hits] { 282 set aMatchinfo($docid) $aRewrite($docid) 283 } 284 return 285 } 286 } 287 288 # 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] 296 lappend mi $nHit($iPhrase,$iCol) 297 lappend mi $nDoc($iPhrase,$iCol) 298 } 299 } 300 set aMatchinfo($docid) $mi 301 } 302 303 # 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} { 308 lappend nullentry 0 $nHit($iPhrase,$iCol) $nDoc($iPhrase,$iCol) 309 } 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 330proc get_near_results {tbl expr deferred arrayvar {nullvar ""}} { 331 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} { 362 get_single_near_results $tbl $expr $deferred aMatchinfo nullentry 363 } else { 364 set eLeft [lrange $expr 0 [expr $opidx-1]] 365 set eRight [lrange $expr [expr $opidx+1] end] 366 367 get_near_results $tbl $eLeft $deferred aLeft nullleft 368 get_near_results $tbl $eRight $deferred aRight nullright 369 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 408 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] 419} 420 421test_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 440# [do_fts3query_test] proc. 441# 442foreach {tn create} { 443 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)" 449} { 450 do_test 2.$tn.1 { 451 catchsql { DROP TABLE t1 } 452 execsql "CREATE VIRTUAL TABLE t1 USING $create" 453 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 } {} 463 464 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 } { 482 do_fts3query_test 2.$tn.2.$tn2 t1 $expr 483 } 484} 485 486#-------------------------------------------------------------------------- 487# Some test cases involving deferred tokens. 488# 489 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 { 497 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'); 506 } 507 508 set limit [fts3_make_deferrable t1 c] 509 510 do_fts3query_test 3.$tn.2.1 t1 {a OR c} 511 512 ifcapable fts4_deferred { 513 do_test 3.$tn.3 { fts3_zero_long_segments t1 $limit } {1} 514 } 515 516 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} {} 523 } { 524 do_fts3query_test 3.$tn.4.$tn2 -deferred $def t1 $expr 525 } 526} 527 528#-------------------------------------------------------------------------- 529# 530foreach {tn create} { 531 1 "fts4(x, y)" 532 2 "fts4(x, y, order=DESC)" 533 3 "fts4(x, y, order=DESC, prefix=2)" 534} { 535 536 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 }] 543 544 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') } 553 ifcapable fts4_deferred { 554 expr {[fts3_zero_long_segments t1 $limit]>0} 555 } else { 556 expr 1 557 } 558 } {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} 564 565 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*} 572} 573 574#-------------------------------------------------------------------------- 575# The following test cases - fts3auto-5.* - focus on using prefix indexes. 576# 577set chunkconfig [fts3_configure_incr_load 1 1] 578foreach {tn create pending} { 579 1 "fts4(a, b)" 1 580 2 "fts4(a, b, order=ASC, prefix=1)" 1 581 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 585} { 586 587 execsql [subst { 588 DROP TABLE IF EXISTS t1; 589 CREATE VIRTUAL TABLE t1 USING $create; 590 }] 591 592 if {$pending} {execsql BEGIN} 593 594 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 616 617 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*} 621 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} 626} 627eval fts3_configure_incr_load $chunkconfig 628 629foreach {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} 658 659 do_fts3query_test 6.$tn.5 t1 {a:G OR b:G} 660 661 catchsql { COMMIT } 662} 663 664foreach {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 708set sqlite_fts3_enable_parentheses $sfep 709finish_test 710