CoolFace
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
fts3auto.test718 linesDownload Raw Back to test
1# 2011 June 102#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.tcl12 13# If this build does not include FTS3, skip the tests in this file.14#15ifcapable !fts3 { finish_test ; return }16source $testdir/fts3_common.tcl17source $testdir/malloc_common.tcl18 19set testprefix fts3auto20set sfep $sqlite_fts3_enable_parentheses21set sqlite_fts3_enable_parentheses 122 23#--------------------------------------------------------------------------24# Start of Tcl infrastructure used by tests. The entry points are:25#26#   do_fts3query_test27#   fts3_make_deferrable28#   fts3_zero_long_segments 29#30 31#32#    do_fts3query_test TESTNAME ?OPTIONS? TABLE MATCHEXPR33#34# This proc runs several test cases on FTS3/4 table $TABLE using match35# expression $MATCHEXPR. All documents in $TABLE must be formatted so that36# 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 or38# 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 list42# commands are used to tokenize the expression. Any parenthesis must appear43# either as separate list elements, or as the first (for opening) or last44# (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 TOKENLIST50#51# If the "deferred" option is supplied, it is passed a list of tokens that52# are deferred by FTS and result in the relevant matchinfo() stats being an53# approximation. 54#55set sqlite_fts3_enable_parentheses 156proc do_fts3query_test {tn args} {57 58  set nArg [llength $args]59  if {$nArg < 2 || ($nArg % 2)} {60    set cmd do_fts3query_test61    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 aHit79  get_near_results $tbl [string map {AND OR} $match] $deferred aMatchinfo80 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 ASC94  " [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 DESC98  " [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 DESC103  " $matchinfo_desc104 105  do_execsql_test $tn$title.4 "106    SELECT docid, mit(matchinfo($tbl, 'x')) FROM $tbl 107    WHERE $tbl MATCH '$match' ORDER BY docid ASC108  " $matchinfo_asc109}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 $stmt118 119  if {$nRow==0} {120    set nRow [db one "SELECT count(*) FROM $tbl"]121  }122  set pgsz [db one "PRAGMA page_size"]123  execsql BEGIN124  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 COMMIT130 131  return [expr $nRow*$pgsz]132}133 134#    fts3_zero_long_segments TABLE ?LIMIT?135#136proc fts3_zero_long_segments {tbl limit} {137  sqlite3_db_config db DEFENSIVE 0138  execsql " 139    UPDATE ${tbl}_segments 140    SET block = zeroblob(length(block)) 141    WHERE length(block)>$limit142  "143  return [db changes]144}145 146 147proc mit {blob} {148  set scan(littleEndian) i*149  set scan(bigEndian) I*150  binary scan $blob $scan($::tcl_platform(byteOrder)) r151  return $r152}153db func mit mit154 155proc fix_phrase_expr {cols expr colfiltervar} {156  upvar $colfiltervar iColFilter157 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 $iCol167      } elseif {$iColFilter != $iCol} {168        set iColFilter [llength $cols]169      }170    }171    lappend out $t172  }173 174  return $out175}176 177proc fix_near_expr {cols expr colfiltervar} { 178  upvar $colfiltervar iColFilter179 180  set iColFilter -1181 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 $a188    lappend out [fix_phrase_expr $cols $b iColFilter]189  }190  return $out191}192 193proc get_single_near_results {tbl expr deferred arrayvar nullvar} {194  upvar $arrayvar aMatchinfo195  upvar $nullvar nullentry196  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 following204  # 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 expression208  #      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 0217    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) $miss224      }225      incr iCol226    }227  }228  set nPhrase [expr ([llength $expr]+1)/2]229  set nCol $iCol230 231  # This block populates the nHit and nDoc arrays. For each phrase/column232  # 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 for238  #                          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) 0243      set nDoc($iPhrase,$iCol) 0244    }245  }246  foreach key [array names counts] {247    set iCol [lindex [split $key ,] 1]248    set iPhrase 0249    foreach c $counts($key) {250      if {$c>0} { incr nDoc($iPhrase,$iCol) 1 }251      incr nHit($iPhrase,$iCol) $c252      incr iPhrase253    }254  }255 256  if {[llength $deferred] && [llength $expr]==1} {257    set phrase [lindex $expr 0]258    set rewritten [list]259    set partial 0260    foreach tok $phrase {261      if {[lsearch $deferred $tok]>=0} {262        lappend rewritten *263      } else {264        lappend rewritten $tok265        set partial 1266      }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) $tblsize272        set nDoc(0,$iCol) $tblsize273      }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 nullentry282      foreach docid [array names hits] {283        set aMatchinfo($docid) $aRewrite($docid)284      }285      return286    }287  }288 289  # Set up the aMatchinfo array. For each document, set aMatchinfo($docid) to290  # 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) $mi302  }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 315proc matching_brackets {expr} {316  if {[string range $expr 0 0]!="(" || [string range $expr end end] !=")"} { 317    return 0 318  }319 320  set iBracket 1321  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 331proc get_near_results {tbl expr deferred arrayvar {nullvar ""}} {332  upvar $arrayvar aMatchinfo333  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) 1341  set prec(AND) 2342  set prec(OR)  3343 344  set currentprec 0345  set iBracket 0346  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 $i351      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 nullentry364  } 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  nullleft369    get_near_results $tbl $eRight $deferred aRight nullright370 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 $nullleft379      }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#417proc test_fts3_near_match {tn doc expr res} {418  fts3_near_match $doc $expr -phrasecountvar p419  uplevel do_test [list $tn] [list [list set {} $p]] [list $res]420}421 422test_fts3_near_match 1.1.1 {a b c a b} a                   {2}423test_fts3_near_match 1.1.2 {a b c a b} {a 5 b 6 c}         {2 2 1}424test_fts3_near_match 1.1.3 {a b c a b} {"a b"}             {2}425test_fts3_near_match 1.1.4 {a b c a b} {"b c"}             {1}426test_fts3_near_match 1.1.5 {a b c a b} {"c c"}             {0}427 428test_fts3_near_match 1.2.1 "a b c d e f g" {b 2 f}         {0 0}429test_fts3_near_match 1.2.2 "a b c d e f g" {b 3 f}         {1 1}430test_fts3_near_match 1.2.3 "a b c d e f g" {f 2 b}         {0 0}431test_fts3_near_match 1.2.4 "a b c d e f g" {f 3 b}         {1 1}432test_fts3_near_match 1.2.5 "a b c d e f g" {"a b" 2 "f g"} {0 0}433test_fts3_near_match 1.2.6 "a b c d e f g" {"a b" 3 "f g"} {1 1}434 435set 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"436test_fts3_near_match 1.3.1 $A {"c d" 5 "i j" 1 "e f"}      {0 0 0}437test_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#443foreach {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 $expr484  }485}486 487#--------------------------------------------------------------------------488# Some test cases involving deferred tokens.489#490 491foreach {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}             c520    3     {"a c"}               c521    4     {"c a"}               c522    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 $expr526  }527}528 529#--------------------------------------------------------------------------530# 531foreach {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 1558    }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#585set chunkconfig [fts3_configure_incr_load 1 1]586foreach {tn create pending} {587  1    "fts4(a, b)"                                  1588  2    "fts4(a, b, order=ASC, prefix=1)"             1589  3    "fts4(a, b, order=ASC,  prefix=\"1,3\")"      0590  4    "fts4(a, b, order=DESC, prefix=\"2,4\")"      0591  5    "fts4(a, b, order=DESC, prefix=\"1\")"        0592  6    "fts4(a, b, order=ASC,  prefix=\"1,3\")"      0593} {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}635eval fts3_configure_incr_load $chunkconfig636 637foreach {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 672foreach {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 considered702  # deferrable if considering the other tokens means that 2 or fewer documents703  # will be loaded into memory.704  #705  fts3_make_deferrable t1 B 2706 707  # B is not deferred in either of the first two tests below, since filtering708  # on "M" or "D" returns 10 documents or so. But filtering on "M * D" only709  # 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 716set sqlite_fts3_enable_parentheses $sfep717finish_test718