github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/fts3auto.test (about) 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 10 set testdir [file dirname $argv0] 11 source $testdir/tester.tcl 12 13 # If this build does not include FTS3, skip the tests in this file. 14 # 15 ifcapable !fts3 { finish_test ; return } 16 source $testdir/fts3_common.tcl 17 source $testdir/malloc_common.tcl 18 19 set testprefix fts3auto 20 set sfep $sqlite_fts3_enable_parentheses 21 set 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 # 55 set sqlite_fts3_enable_parentheses 1 56 proc 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 # 113 proc 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 # 136 proc fts3_zero_long_segments {tbl limit} { 137 sqlite3_db_config db DEFENSIVE 0 138 execsql " 139 UPDATE ${tbl}_segments 140 SET block = zeroblob(length(block)) 141 WHERE length(block)>$limit 142 " 143 return [db changes] 144 } 145 146 147 proc mit {blob} { 148 set scan(littleEndian) i* 149 set scan(bigEndian) I* 150 binary scan $blob $scan($::tcl_platform(byteOrder)) r 151 return $r 152 } 153 db func mit mit 154 155 proc fix_phrase_expr {cols expr colfiltervar} { 156 upvar $colfiltervar iColFilter 157 158 set out [list] 159 foreach t $expr { 160 if {[string match *:* $t]} { 161 set col [lindex [split $t :] 0] 162 set t [lindex [split $t :] 1] 163 set iCol [lsearch $cols $col] 164 if {$iCol<0} { error "unknown column: $col" } 165 if {$iColFilter < 0} { 166 set iColFilter $iCol 167 } elseif {$iColFilter != $iCol} { 168 set iColFilter [llength $cols] 169 } 170 } 171 lappend out $t 172 } 173 174 return $out 175 } 176 177 proc fix_near_expr {cols expr colfiltervar} { 178 upvar $colfiltervar iColFilter 179 180 set iColFilter -1 181 182 set out [list] 183 lappend out [fix_phrase_expr $cols [lindex $expr 0] iColFilter] 184 foreach {a b} [lrange $expr 1 end] { 185 if {[string match -nocase near $a]} { set a 10 } 186 if {[string match -nocase near/* $a]} { set a [string range $a 5 end] } 187 lappend out $a 188 lappend out [fix_phrase_expr $cols $b iColFilter] 189 } 190 return $out 191 } 192 193 proc get_single_near_results {tbl expr deferred arrayvar nullvar} { 194 upvar $arrayvar aMatchinfo 195 upvar $nullvar nullentry 196 catch {array unset aMatchinfo} 197 198 set cols [list] 199 set miss [list] 200 db eval "PRAGMA table_info($tbl)" A { lappend cols $A(name) ; lappend miss 0 } 201 set expr [fix_near_expr $cols $expr iColFilter] 202 203 # Calculate the expected results using [fts3_near_match]. The following 204 # loop populates the "hits" and "counts" arrays as follows: 205 # 206 # 1. For each document in the table that matches the NEAR expression, 207 # hits($docid) is set to 1. The set of docids that match the expression 208 # can therefore be found using [array names hits]. 209 # 210 # 2. For each column of each document in the table, counts($docid,$iCol) 211 # is set to the -phrasecountvar output. 212 # 213 set res [list] 214 catch { array unset hits } 215 db eval "SELECT docid, * FROM $tbl" d { 216 set iCol 0 217 foreach col [lrange $d(*) 1 end] { 218 set docid $d(docid) 219 if {$iColFilter<0 || $iCol==$iColFilter} { 220 set hit [fts3_near_match $d($col) $expr -p counts($docid,$iCol)] 221 if {$hit} { set hits($docid) 1 } 222 } else { 223 set counts($docid,$iCol) $miss 224 } 225 incr iCol 226 } 227 } 228 set nPhrase [expr ([llength $expr]+1)/2] 229 set nCol $iCol 230 231 # This block populates the nHit and nDoc arrays. For each phrase/column 232 # in the query/table, array elements are set as follows: 233 # 234 # nHit($iPhrase,$iCol) - Total number of hits for phrase $iPhrase in 235 # column $iCol. 236 # 237 # nDoc($iPhrase,$iCol) - Number of documents with at least one hit for 238 # phrase $iPhrase in column $iCol. 239 # 240 for {set iPhrase 0} {$iPhrase < $nPhrase} {incr iPhrase} { 241 for {set iCol 0} {$iCol < $nCol} {incr iCol} { 242 set nHit($iPhrase,$iCol) 0 243 set nDoc($iPhrase,$iCol) 0 244 } 245 } 246 foreach key [array names counts] { 247 set iCol [lindex [split $key ,] 1] 248 set iPhrase 0 249 foreach c $counts($key) { 250 if {$c>0} { incr nDoc($iPhrase,$iCol) 1 } 251 incr nHit($iPhrase,$iCol) $c 252 incr iPhrase 253 } 254 } 255 256 if {[llength $deferred] && [llength $expr]==1} { 257 set phrase [lindex $expr 0] 258 set rewritten [list] 259 set partial 0 260 foreach tok $phrase { 261 if {[lsearch $deferred $tok]>=0} { 262 lappend rewritten * 263 } else { 264 lappend rewritten $tok 265 set partial 1 266 } 267 } 268 if {$partial==0} { 269 set tblsize [db one "SELECT count(*) FROM $tbl"] 270 for {set iCol 0} {$iCol < $nCol} {incr iCol} { 271 set nHit(0,$iCol) $tblsize 272 set nDoc(0,$iCol) $tblsize 273 } 274 } elseif {$rewritten != $phrase} { 275 while {[lindex $rewritten end] == "*"} { 276 set rewritten [lrange $rewritten 0 end-1] 277 } 278 while {[lindex $rewritten 0] == "*"} { 279 set rewritten [lrange $rewritten 1 end] 280 } 281 get_single_near_results $tbl [list $rewritten] {} aRewrite nullentry 282 foreach docid [array names hits] { 283 set aMatchinfo($docid) $aRewrite($docid) 284 } 285 return 286 } 287 } 288 289 # Set up the aMatchinfo array. For each document, set aMatchinfo($docid) to 290 # contain the output of matchinfo('x') for the document. 291 # 292 foreach docid [array names hits] { 293 set mi [list] 294 for {set iPhrase 0} {$iPhrase<$nPhrase} {incr iPhrase} { 295 for {set iCol 0} {$iCol<$nCol} {incr iCol} { 296 lappend mi [lindex $counts($docid,$iCol) $iPhrase] 297 lappend mi $nHit($iPhrase,$iCol) 298 lappend mi $nDoc($iPhrase,$iCol) 299 } 300 } 301 set aMatchinfo($docid) $mi 302 } 303 304 # Set up the nullentry output. 305 # 306 set nullentry [list] 307 for {set iPhrase 0} {$iPhrase<$nPhrase} {incr iPhrase} { 308 for {set iCol 0} {$iCol<$nCol} {incr iCol} { 309 lappend nullentry 0 $nHit($iPhrase,$iCol) $nDoc($iPhrase,$iCol) 310 } 311 } 312 } 313 314 315 proc matching_brackets {expr} { 316 if {[string range $expr 0 0]!="(" || [string range $expr end end] !=")"} { 317 return 0 318 } 319 320 set iBracket 1 321 set nExpr [string length $expr] 322 for {set i 1} {$iBracket && $i < $nExpr} {incr i} { 323 set c [string range $expr $i $i] 324 if {$c == "("} {incr iBracket} 325 if {$c == ")"} {incr iBracket -1} 326 } 327 328 return [expr ($iBracket==0 && $i==$nExpr)] 329 } 330 331 proc get_near_results {tbl expr deferred arrayvar {nullvar ""}} { 332 upvar $arrayvar aMatchinfo 333 if {$nullvar != ""} { upvar $nullvar nullentry } 334 335 set expr [string trim $expr] 336 while { [matching_brackets $expr] } { 337 set expr [string trim [string range $expr 1 end-1]] 338 } 339 340 set prec(NOT) 1 341 set prec(AND) 2 342 set prec(OR) 3 343 344 set currentprec 0 345 set iBracket 0 346 set expr_length [llength $expr] 347 for {set i 0} {$i < $expr_length} {incr i} { 348 set op [lindex $expr $i] 349 if {$iBracket==0 && [info exists prec($op)] && $prec($op)>=$currentprec } { 350 set opidx $i 351 set currentprec $prec($op) 352 } else { 353 for {set j 0} {$j < [string length $op]} {incr j} { 354 set c [string range $op $j $j] 355 if {$c == "("} { incr iBracket +1 } 356 if {$c == ")"} { incr iBracket -1 } 357 } 358 } 359 } 360 if {$iBracket!=0} { error "mismatched brackets in: $expr" } 361 362 if {[info exists opidx]==0} { 363 get_single_near_results $tbl $expr $deferred aMatchinfo nullentry 364 } else { 365 set eLeft [lrange $expr 0 [expr $opidx-1]] 366 set eRight [lrange $expr [expr $opidx+1] end] 367 368 get_near_results $tbl $eLeft $deferred aLeft nullleft 369 get_near_results $tbl $eRight $deferred aRight nullright 370 371 switch -- [lindex $expr $opidx] { 372 "NOT" { 373 foreach hit [array names aLeft] { 374 if {0==[info exists aRight($hit)]} { 375 set aMatchinfo($hit) $aLeft($hit) 376 } 377 } 378 set nullentry $nullleft 379 } 380 381 "AND" { 382 foreach hit [array names aLeft] { 383 if {[info exists aRight($hit)]} { 384 set aMatchinfo($hit) [concat $aLeft($hit) $aRight($hit)] 385 } 386 } 387 set nullentry [concat $nullleft $nullright] 388 } 389 390 "OR" { 391 foreach hit [array names aLeft] { 392 if {[info exists aRight($hit)]} { 393 set aMatchinfo($hit) [concat $aLeft($hit) $aRight($hit)] 394 unset aRight($hit) 395 } else { 396 set aMatchinfo($hit) [concat $aLeft($hit) $nullright] 397 } 398 } 399 foreach hit [array names aRight] { 400 set aMatchinfo($hit) [concat $nullleft $aRight($hit)] 401 } 402 403 set nullentry [concat $nullleft $nullright] 404 } 405 } 406 } 407 } 408 409 410 # End of test procs. Actual tests are below this line. 411 #-------------------------------------------------------------------------- 412 413 #-------------------------------------------------------------------------- 414 # The following test cases - fts3auto-1.* - focus on testing the Tcl 415 # command [fts3_near_match], which is used by other tests in this file. 416 # 417 proc test_fts3_near_match {tn doc expr res} { 418 fts3_near_match $doc $expr -phrasecountvar p 419 uplevel do_test [list $tn] [list [list set {} $p]] [list $res] 420 } 421 422 test_fts3_near_match 1.1.1 {a b c a b} a {2} 423 test_fts3_near_match 1.1.2 {a b c a b} {a 5 b 6 c} {2 2 1} 424 test_fts3_near_match 1.1.3 {a b c a b} {"a b"} {2} 425 test_fts3_near_match 1.1.4 {a b c a b} {"b c"} {1} 426 test_fts3_near_match 1.1.5 {a b c a b} {"c c"} {0} 427 428 test_fts3_near_match 1.2.1 "a b c d e f g" {b 2 f} {0 0} 429 test_fts3_near_match 1.2.2 "a b c d e f g" {b 3 f} {1 1} 430 test_fts3_near_match 1.2.3 "a b c d e f g" {f 2 b} {0 0} 431 test_fts3_near_match 1.2.4 "a b c d e f g" {f 3 b} {1 1} 432 test_fts3_near_match 1.2.5 "a b c d e f g" {"a b" 2 "f g"} {0 0} 433 test_fts3_near_match 1.2.6 "a b c d e f g" {"a b" 3 "f g"} {1 1} 434 435 set 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" 436 test_fts3_near_match 1.3.1 $A {"c d" 5 "i j" 1 "e f"} {0 0 0} 437 test_fts3_near_match 1.3.2 $A {"c d" 5 "i j" 2 "e f"} {1 1 1} 438 439 #-------------------------------------------------------------------------- 440 # Test cases fts3auto-2.* run some simple tests using the 441 # [do_fts3query_test] proc. 442 # 443 foreach {tn create} { 444 1 "fts4(a, b)" 445 2 "fts4(a, b, order=DESC)" 446 3 "fts4(a, b, order=ASC)" 447 4 "fts4(a, b, prefix=1)" 448 5 "fts4(a, b, order=DESC, prefix=1)" 449 6 "fts4(a, b, order=ASC, prefix=1)" 450 } { 451 do_test 2.$tn.1 { 452 catchsql { DROP TABLE t1 } 453 execsql "CREATE VIRTUAL TABLE t1 USING $create" 454 for {set i 0} {$i<32} {incr i} { 455 set doc [list] 456 if {$i&0x01} {lappend doc one} 457 if {$i&0x02} {lappend doc two} 458 if {$i&0x04} {lappend doc three} 459 if {$i&0x08} {lappend doc four} 460 if {$i&0x10} {lappend doc five} 461 execsql { INSERT INTO t1 VALUES($doc, null) } 462 } 463 } {} 464 465 foreach {tn2 expr} { 466 1 {one} 467 2 {one NEAR/1 five} 468 3 {t*} 469 4 {t* NEAR/0 five} 470 5 {o* NEAR/1 f*} 471 6 {one NEAR five NEAR two NEAR four NEAR three} 472 7 {one NEAR xyz} 473 8 {one OR two} 474 9 {one AND two} 475 10 {one NOT two} 476 11 {one AND two OR three} 477 12 {three OR one AND two} 478 13 {(three OR one) AND two} 479 14 {(three OR one) AND two NOT (five NOT four)} 480 15 {"one two"} 481 16 {"one two" NOT "three four"} 482 } { 483 do_fts3query_test 2.$tn.2.$tn2 t1 $expr 484 } 485 } 486 487 #-------------------------------------------------------------------------- 488 # Some test cases involving deferred tokens. 489 # 490 491 foreach {tn create} { 492 1 "fts4(x)" 493 2 "fts4(x, order=DESC)" 494 } { 495 catchsql { DROP TABLE t1 } 496 execsql "CREATE VIRTUAL TABLE t1 USING $create" 497 do_execsql_test 3.$tn.1 { 498 INSERT INTO t1(docid, x) VALUES(-2, 'a b c d e f g h i j k'); 499 INSERT INTO t1(docid, x) VALUES(-1, 'b c d e f g h i j k a'); 500 INSERT INTO t1(docid, x) VALUES(0, 'c d e f g h i j k a b'); 501 INSERT INTO t1(docid, x) VALUES(1, 'd e f g h i j k a b c'); 502 INSERT INTO t1(docid, x) VALUES(2, 'e f g h i j k a b c d'); 503 INSERT INTO t1(docid, x) VALUES(3, 'f g h i j k a b c d e'); 504 INSERT INTO t1(docid, x) VALUES(4, 'a c e g i k'); 505 INSERT INTO t1(docid, x) VALUES(5, 'a d g j'); 506 INSERT INTO t1(docid, x) VALUES(6, 'c a b'); 507 } 508 509 set limit [fts3_make_deferrable t1 c] 510 511 do_fts3query_test 3.$tn.2.1 t1 {a OR c} 512 513 ifcapable fts4_deferred { 514 do_test 3.$tn.3 { fts3_zero_long_segments t1 $limit } {1} 515 } 516 517 foreach {tn2 expr def} { 518 1 {a NEAR c} {} 519 2 {a AND c} c 520 3 {"a c"} c 521 4 {"c a"} c 522 5 {"a c" NEAR/1 g} {} 523 6 {"a c" NEAR/0 g} {} 524 } { 525 do_fts3query_test 3.$tn.4.$tn2 -deferred $def t1 $expr 526 } 527 } 528 529 #-------------------------------------------------------------------------- 530 # 531 foreach {tn create} { 532 1 "fts4(x, y)" 533 2 "fts4(x, y, order=DESC)" 534 3 "fts4(x, y, order=DESC, prefix=2)" 535 } { 536 537 execsql [subst { 538 DROP TABLE t1; 539 CREATE VIRTUAL TABLE t1 USING $create; 540 INSERT INTO t1 VALUES('one two five four five', ''); 541 INSERT INTO t1 VALUES('', 'one two five four five'); 542 INSERT INTO t1 VALUES('one two', 'five four five'); 543 }] 544 545 do_fts3query_test 4.$tn.1.1 t1 {one AND five} 546 do_fts3query_test 4.$tn.1.2 t1 {one NEAR five} 547 do_fts3query_test 4.$tn.1.3 t1 {one NEAR/1 five} 548 do_fts3query_test 4.$tn.1.4 t1 {one NEAR/2 five} 549 do_fts3query_test 4.$tn.1.5 t1 {one NEAR/3 five} 550 551 do_test 4.$tn.2 { 552 set limit [fts3_make_deferrable t1 five] 553 execsql { INSERT INTO t1(t1) VALUES('optimize') } 554 ifcapable fts4_deferred { 555 expr {[fts3_zero_long_segments t1 $limit]>0} 556 } else { 557 expr 1 558 } 559 } {1} 560 561 do_fts3query_test 4.$tn.3.1 -deferred five t1 {one AND five} 562 do_fts3query_test 4.$tn.3.2 -deferred five t1 {one NEAR five} 563 do_fts3query_test 4.$tn.3.3 -deferred five t1 {one NEAR/1 five} 564 do_fts3query_test 4.$tn.3.4 -deferred five t1 {one NEAR/2 five} 565 566 do_fts3query_test 4.$tn.3.5 -deferred five t1 {one NEAR/3 five} 567 568 do_fts3query_test 4.$tn.4.1 -deferred fi* t1 {on* AND fi*} 569 do_fts3query_test 4.$tn.4.2 -deferred fi* t1 {on* NEAR fi*} 570 do_fts3query_test 4.$tn.4.3 -deferred fi* t1 {on* NEAR/1 fi*} 571 do_fts3query_test 4.$tn.4.4 -deferred fi* t1 {on* NEAR/2 fi*} 572 do_fts3query_test 4.$tn.4.5 -deferred fi* t1 {on* NEAR/3 fi*} 573 574 ifcapable fts4_deferred { 575 db eval {UPDATE t1_stat SET value=x'' WHERE id=0} 576 do_catchsql_test 4.$tn.4.6 { 577 SELECT docid FROM t1 WHERE t1 MATCH 'on* NEAR/3 fi*' 578 } {1 {database disk image is malformed}} 579 } 580 } 581 582 #-------------------------------------------------------------------------- 583 # The following test cases - fts3auto-5.* - focus on using prefix indexes. 584 # 585 set chunkconfig [fts3_configure_incr_load 1 1] 586 foreach {tn create pending} { 587 1 "fts4(a, b)" 1 588 2 "fts4(a, b, order=ASC, prefix=1)" 1 589 3 "fts4(a, b, order=ASC, prefix=\"1,3\")" 0 590 4 "fts4(a, b, order=DESC, prefix=\"2,4\")" 0 591 5 "fts4(a, b, order=DESC, prefix=\"1\")" 0 592 6 "fts4(a, b, order=ASC, prefix=\"1,3\")" 0 593 } { 594 595 execsql [subst { 596 DROP TABLE IF EXISTS t1; 597 CREATE VIRTUAL TABLE t1 USING $create; 598 }] 599 600 if {$pending} {execsql BEGIN} 601 602 foreach {a b} { 603 "the song of songs which is solomons" 604 "let him kiss me with the kisses of his mouth for thy love is better than wine" 605 "because of the savour of thy good ointments thy name is as ointment poured forth therefore do the virgins love thee" 606 "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" 607 "i am black but comely o ye daughters of jerusalem as the tents of kedar as the curtains of solomon" 608 "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" 609 "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?" 610 "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" 611 "i have compared thee o my love to a company of horses in pharaohs chariots" 612 "thy cheeks are comely with rows of jewels thy neck with chains of gold" 613 "we will make thee borders of gold with studs of silver" 614 "while the king sitteth at his table my spikenard sendeth forth the smell thereof" 615 "a bundle of myrrh is my wellbeloved unto me he shall lie all night betwixt my breasts" 616 "my beloved is unto me as a cluster of camphire in the vineyards of en gedi" 617 "behold thou art fair my love behold thou art fair thou hast doves eyes" 618 "behold thou art fair my beloved yea pleasant also our bed is green" 619 "the beams of our house are cedar and our rafters of fir" 620 } { 621 execsql {INSERT INTO t1(a, b) VALUES($a, $b)} 622 } 623 624 625 do_fts3query_test 5.$tn.1.1 t1 {s*} 626 do_fts3query_test 5.$tn.1.2 t1 {so*} 627 do_fts3query_test 5.$tn.1.3 t1 {"s* o*"} 628 do_fts3query_test 5.$tn.1.4 t1 {b* NEAR/3 a*} 629 do_fts3query_test 5.$tn.1.5 t1 {a*} 630 do_fts3query_test 5.$tn.1.6 t1 {th* NEAR/5 a* NEAR/5 w*} 631 do_fts3query_test 5.$tn.1.7 t1 {"b* th* art* fair*"} 632 633 if {$pending} {execsql COMMIT} 634 } 635 eval fts3_configure_incr_load $chunkconfig 636 637 foreach {tn pending create} { 638 1 0 "fts4(a, b, c, d)" 639 2 1 "fts4(a, b, c, d)" 640 3 0 "fts4(a, b, c, d, order=DESC)" 641 4 1 "fts4(a, b, c, d, order=DESC)" 642 } { 643 execsql [subst { 644 DROP TABLE IF EXISTS t1; 645 CREATE VIRTUAL TABLE t1 USING $create; 646 }] 647 648 649 if {$pending} { execsql BEGIN } 650 651 foreach {a b c d} { 652 "A B C" "D E F" "G H I" "J K L" 653 "B C D" "E F G" "H I J" "K L A" 654 "C D E" "F G H" "I J K" "L A B" 655 "D E F" "G H I" "J K L" "A B C" 656 "E F G" "H I J" "K L A" "B C D" 657 "F G H" "I J K" "L A B" "C D E" 658 } { 659 execsql { INSERT INTO t1 VALUES($a, $b, $c, $d) } 660 } 661 662 do_fts3query_test 6.$tn.1 t1 {b:G} 663 do_fts3query_test 6.$tn.2 t1 {b:G AND c:I} 664 do_fts3query_test 6.$tn.3 t1 {b:G NEAR c:I} 665 do_fts3query_test 6.$tn.4 t1 {a:C OR b:G OR c:K OR d:C} 666 667 do_fts3query_test 6.$tn.5 t1 {a:G OR b:G} 668 669 catchsql { COMMIT } 670 } 671 672 foreach {tn create} { 673 1 "fts4(x)" 674 2 "fts4(x, order=DESC)" 675 } { 676 execsql [subst { 677 DROP TABLE IF EXISTS t1; 678 CREATE VIRTUAL TABLE t1 USING $create; 679 }] 680 681 foreach {x} { 682 "F E N O T K X V A X I E X A P G Q V H U" 683 "R V A E T C V Q N I E L O N U G J K L U" 684 "U Y I G W M V F J L X I D C H F P J Q B" 685 "S G D Z X R P G S S Y B K A S G A I L L" 686 "L S I C H T Z S R Q P R N K J X L F M J" 687 "C C C D P X B Z C M A D A C X S B T X V" 688 "W Y J M D R G V R K B X S A W R I T N C" 689 "P K L W T M S P O Y Y V V O E H Q A I R" 690 "C D Y I C Z F H J C O Y A Q F L S B D K" 691 "P G S C Y C Y V I M B D S Z D D Y W I E" 692 "Z K Z U E E S F Y X T U A L W O U J C Q" 693 "P A T Z S W L P L Q V Y Y I P W U X S S" 694 "I U I H U O F Z F R H R F T N D X A G M" 695 "N A B M S H K X S O Y D T X S B R Y H Z" 696 "L U D A S K I L S V Z J P U B E B Y H M" 697 } { 698 execsql { INSERT INTO t1 VALUES($x) } 699 } 700 701 # Add extra documents to the database such that token "B" will be considered 702 # deferrable if considering the other tokens means that 2 or fewer documents 703 # will be loaded into memory. 704 # 705 fts3_make_deferrable t1 B 2 706 707 # B is not deferred in either of the first two tests below, since filtering 708 # on "M" or "D" returns 10 documents or so. But filtering on "M * D" only 709 # returns 2, so B is deferred in this case. 710 # 711 do_fts3query_test 7.$tn.1 t1 {"M B"} 712 do_fts3query_test 7.$tn.2 t1 {"B D"} 713 do_fts3query_test 7.$tn.3 -deferred B t1 {"M B D"} 714 } 715 716 set sqlite_fts3_enable_parentheses $sfep 717 finish_test