xref: /sqlite-3.40.0/test/fts3auto.test (revision d4d21fea)
199ebad90Sdan# 2011 June 10
299ebad90Sdan#
399ebad90Sdan#    May you do good and not evil.
499ebad90Sdan#    May you find forgiveness for yourself and forgive others.
599ebad90Sdan#    May you share freely, never taking more than you give.
699ebad90Sdan#
799ebad90Sdan#***********************************************************************
899ebad90Sdan#
999ebad90Sdan
1099ebad90Sdanset testdir [file dirname $argv0]
1199ebad90Sdansource $testdir/tester.tcl
1299ebad90Sdan
1399ebad90Sdan# If this build does not include FTS3, skip the tests in this file.
1499ebad90Sdan#
1599ebad90Sdanifcapable !fts3 { finish_test ; return }
1699ebad90Sdansource $testdir/fts3_common.tcl
1799ebad90Sdansource $testdir/malloc_common.tcl
1899ebad90Sdan
193fd65192Sdanset testprefix fts3auto
203fd65192Sdanset sfep $sqlite_fts3_enable_parentheses
213fd65192Sdanset sqlite_fts3_enable_parentheses 1
2299ebad90Sdan
233fd65192Sdan#--------------------------------------------------------------------------
24db27fc07Sdan# Start of Tcl infrastructure used by tests. The entry points are:
25db27fc07Sdan#
26db27fc07Sdan#   do_fts3query_test
27db27fc07Sdan#   fts3_make_deferrable
28db27fc07Sdan#   fts3_zero_long_segments
2999ebad90Sdan#
30653265d9Sdan
31db27fc07Sdan#
32653265d9Sdan#    do_fts3query_test TESTNAME ?OPTIONS? TABLE MATCHEXPR
33653265d9Sdan#
34653265d9Sdan# This proc runs several test cases on FTS3/4 table $TABLE using match
35653265d9Sdan# expression $MATCHEXPR. All documents in $TABLE must be formatted so that
36653265d9Sdan# they can be "tokenized" using the Tcl list commands (llength, lindex etc.).
37653265d9Sdan# The name and column names used by $TABLE must not require any quoting or
38653265d9Sdan# escaping when used in SQL statements.
39653265d9Sdan#
40653265d9Sdan# $MATCHINFO may be any expression accepted by the FTS4 MATCH operator,
41653265d9Sdan# except that the "<column-name>:token" syntax is not supported. Tcl list
42653265d9Sdan# commands are used to tokenize the expression. Any parenthesis must appear
43653265d9Sdan# either as separate list elements, or as the first (for opening) or last
44653265d9Sdan# (for closing) character of a list element. i.e. the expression "(a OR b)c"
45653265d9Sdan# will not be parsed correctly, but "( a OR b) c" will.
46653265d9Sdan#
472cf1a1deSdan# Available OPTIONS are:
482cf1a1deSdan#
492cf1a1deSdan#     -deferred TOKENLIST
502cf1a1deSdan#
512cf1a1deSdan# If the "deferred" option is supplied, it is passed a list of tokens that
522cf1a1deSdan# are deferred by FTS and result in the relevant matchinfo() stats being an
532cf1a1deSdan# approximation.
542cf1a1deSdan#
55653265d9Sdanset sqlite_fts3_enable_parentheses 1
562cf1a1deSdanproc do_fts3query_test {tn args} {
57653265d9Sdan
582cf1a1deSdan  set nArg [llength $args]
592cf1a1deSdan  if {$nArg < 2 || ($nArg % 2)} {
602cf1a1deSdan    set cmd do_fts3query_test
612cf1a1deSdan    error "wrong # args: should be \"$cmd ?-deferred LIST? TABLE MATCHEXPR\""
622cf1a1deSdan  }
632cf1a1deSdan  set tbl   [lindex $args [expr $nArg-2]]
642cf1a1deSdan  set match [lindex $args [expr $nArg-1]]
652cf1a1deSdan  set deferred [list]
662cf1a1deSdan
672cf1a1deSdan  foreach {k v} [lrange $args 0 [expr $nArg-3]] {
682cf1a1deSdan    switch -- $k {
692cf1a1deSdan      -deferred {
702cf1a1deSdan        set deferred $v
712cf1a1deSdan      }
722cf1a1deSdan      default {
732cf1a1deSdan        error "bad option \"$k\": must be -deferred"
742cf1a1deSdan      }
752cf1a1deSdan    }
762cf1a1deSdan  }
772cf1a1deSdan
782cf1a1deSdan  get_near_results $tbl $match $deferred aMatchinfo
79653265d9Sdan
80653265d9Sdan  set matchinfo_asc [list]
81653265d9Sdan  foreach docid [lsort -integer -incr [array names aMatchinfo]] {
82653265d9Sdan    lappend matchinfo_asc $docid $aMatchinfo($docid)
83653265d9Sdan  }
84653265d9Sdan  set matchinfo_desc [list]
85653265d9Sdan  foreach docid [lsort -integer -decr [array names aMatchinfo]] {
86653265d9Sdan    lappend matchinfo_desc $docid $aMatchinfo($docid)
87653265d9Sdan  }
88653265d9Sdan
89653265d9Sdan  set title "(\"$match\" -> [llength [array names aMatchinfo]] rows)"
90653265d9Sdan
91653265d9Sdan  do_execsql_test $tn$title.1 "
92653265d9Sdan    SELECT docid FROM $tbl WHERE $tbl MATCH '$match' ORDER BY docid ASC
93653265d9Sdan  " [lsort -integer -incr [array names aMatchinfo]]
94653265d9Sdan
95653265d9Sdan  do_execsql_test $tn$title.2 "
96653265d9Sdan    SELECT docid FROM $tbl WHERE $tbl MATCH '$match' ORDER BY docid DESC
97653265d9Sdan  " [lsort -integer -decr [array names aMatchinfo]]
98653265d9Sdan
99653265d9Sdan  do_execsql_test $tn$title.3 "
100653265d9Sdan    SELECT docid, mit(matchinfo($tbl, 'x')) FROM $tbl
101653265d9Sdan    WHERE $tbl MATCH '$match' ORDER BY docid DESC
102653265d9Sdan  " $matchinfo_desc
103653265d9Sdan
104653265d9Sdan  do_execsql_test $tn$title.4 "
105653265d9Sdan    SELECT docid, mit(matchinfo($tbl, 'x')) FROM $tbl
106653265d9Sdan    WHERE $tbl MATCH '$match' ORDER BY docid ASC
107653265d9Sdan  " $matchinfo_asc
108653265d9Sdan}
109653265d9Sdan
110db27fc07Sdan#    fts3_make_deferrable TABLE TOKEN
111db27fc07Sdan#
112db27fc07Sdanproc fts3_make_deferrable {tbl token} {
113db27fc07Sdan
114db27fc07Sdan  set stmt [sqlite3_prepare db "SELECT * FROM $tbl" -1 dummy]
115db27fc07Sdan  set name [sqlite3_column_name $stmt 0]
116db27fc07Sdan  sqlite3_finalize $stmt
117db27fc07Sdan
118db27fc07Sdan  set nRow [db one "SELECT count(*) FROM $tbl"]
119db27fc07Sdan  set pgsz [db one "PRAGMA page_size"]
120db27fc07Sdan  execsql BEGIN
121db27fc07Sdan  for {set i 0} {$i < ($nRow * $pgsz * 1.2)/100} {incr i} {
122db27fc07Sdan    set doc [string repeat "$token " 100]
123db27fc07Sdan    execsql "INSERT INTO $tbl ($name) VALUES(\$doc)"
124db27fc07Sdan  }
125db27fc07Sdan  execsql "INSERT INTO $tbl ($name) VALUES('aaaaaaa ${token}aaaaa')"
126db27fc07Sdan  execsql COMMIT
127db27fc07Sdan
128db27fc07Sdan  return [expr $nRow*$pgsz]
129db27fc07Sdan}
130db27fc07Sdan
131db27fc07Sdan#    fts3_zero_long_segments TABLE ?LIMIT?
132db27fc07Sdan#
133db27fc07Sdanproc fts3_zero_long_segments {tbl limit} {
134db27fc07Sdan  execsql "
135db27fc07Sdan    UPDATE ${tbl}_segments
136db27fc07Sdan    SET block = zeroblob(length(block))
137db27fc07Sdan    WHERE length(block)>$limit
138db27fc07Sdan  "
139db27fc07Sdan  return [db changes]
140db27fc07Sdan}
141db27fc07Sdan
142653265d9Sdan
14399ebad90Sdanproc mit {blob} {
14499ebad90Sdan  set scan(littleEndian) i*
14599ebad90Sdan  set scan(bigEndian) I*
14699ebad90Sdan  binary scan $blob $scan($::tcl_platform(byteOrder)) r
14799ebad90Sdan  return $r
14899ebad90Sdan}
14999ebad90Sdandb func mit mit
15099ebad90Sdan
15199ebad90Sdanproc fix_near_expr {expr} {
15299ebad90Sdan  set out [list]
15399ebad90Sdan  lappend out [lindex $expr 0]
15499ebad90Sdan  foreach {a b} [lrange $expr 1 end] {
15599ebad90Sdan    if {[string match -nocase near $a]}   { set a 10 }
15699ebad90Sdan    if {[string match -nocase near/* $a]} { set a [string range $a 5 end] }
15799ebad90Sdan    lappend out $a
15899ebad90Sdan    lappend out $b
15999ebad90Sdan  }
16099ebad90Sdan  return $out
16199ebad90Sdan}
16299ebad90Sdan
1632cf1a1deSdanproc get_single_near_results {tbl expr deferred arrayvar nullvar} {
1643fd65192Sdan  upvar $arrayvar aMatchinfo
1653fd65192Sdan  upvar $nullvar nullentry
1663fd65192Sdan  catch {array unset aMatchinfo}
16799ebad90Sdan
16899ebad90Sdan  set expr [fix_near_expr $expr]
16999ebad90Sdan
17099ebad90Sdan  # Calculate the expected results using [fts3_near_match]. The following
17199ebad90Sdan  # loop populates the "hits" and "counts" arrays as follows:
17299ebad90Sdan  #
17399ebad90Sdan  #   1. For each document in the table that matches the NEAR expression,
17499ebad90Sdan  #      hits($docid) is set to 1. The set of docids that match the expression
17599ebad90Sdan  #      can therefore be found using [array names hits].
17699ebad90Sdan  #
17799ebad90Sdan  #   2. For each column of each document in the table, counts($docid,$iCol)
17899ebad90Sdan  #      is set to the -phrasecountvar output.
17999ebad90Sdan  #
18099ebad90Sdan  set res [list]
18199ebad90Sdan  catch { array unset hits }
18299ebad90Sdan  db eval "SELECT docid, * FROM $tbl" d {
18399ebad90Sdan    set iCol 0
18499ebad90Sdan    foreach col [lrange $d(*) 1 end] {
18599ebad90Sdan      set docid $d(docid)
18699ebad90Sdan      set hit [fts3_near_match $d($col) $expr -p counts($docid,$iCol)]
18799ebad90Sdan      if {$hit} { set hits($docid) 1 }
18899ebad90Sdan      incr iCol
18999ebad90Sdan    }
19099ebad90Sdan  }
19199ebad90Sdan  set nPhrase [expr ([llength $expr]+1)/2]
19299ebad90Sdan  set nCol $iCol
19399ebad90Sdan
19499ebad90Sdan  # This block populates the nHit and nDoc arrays. For each phrase/column
19599ebad90Sdan  # in the query/table, array elements are set as follows:
19699ebad90Sdan  #
19799ebad90Sdan  #   nHit($iPhrase,$iCol) - Total number of hits for phrase $iPhrase in
19899ebad90Sdan  #                          column $iCol.
19999ebad90Sdan  #
20099ebad90Sdan  #   nDoc($iPhrase,$iCol) - Number of documents with at least one hit for
20199ebad90Sdan  #                          phrase $iPhrase in column $iCol.
20299ebad90Sdan  #
20399ebad90Sdan  for {set iPhrase 0} {$iPhrase < $nPhrase} {incr iPhrase} {
20499ebad90Sdan    for {set iCol 0} {$iCol < $nCol} {incr iCol} {
20599ebad90Sdan      set nHit($iPhrase,$iCol) 0
20699ebad90Sdan      set nDoc($iPhrase,$iCol) 0
20799ebad90Sdan    }
20899ebad90Sdan  }
20999ebad90Sdan  foreach key [array names counts] {
21099ebad90Sdan    set iCol [lindex [split $key ,] 1]
21199ebad90Sdan    set iPhrase 0
21299ebad90Sdan    foreach c $counts($key) {
2132f779343Sdan      if {$c>0} { incr nDoc($iPhrase,$iCol) 1 }
2142f779343Sdan      incr nHit($iPhrase,$iCol) $c
21599ebad90Sdan      incr iPhrase
21699ebad90Sdan    }
21799ebad90Sdan  }
21899ebad90Sdan
2192cf1a1deSdan  if {[llength $deferred] && [llength $expr]==1} {
2202f779343Sdan    set phrase [lindex $expr 0]
2212f779343Sdan    set rewritten [list]
2222f779343Sdan    set partial 0
2232f779343Sdan    foreach tok $phrase {
2242cf1a1deSdan      if {[lsearch $deferred $tok]>=0} {
2252f779343Sdan        lappend rewritten *
2262f779343Sdan      } else {
2272f779343Sdan        lappend rewritten $tok
2282f779343Sdan        set partial 1
2292f779343Sdan      }
2302f779343Sdan    }
2312f779343Sdan    if {$partial==0} {
2322f779343Sdan      set tblsize [db one "SELECT count(*) FROM $tbl"]
2332f779343Sdan      for {set iCol 0} {$iCol < $nCol} {incr iCol} {
2342f779343Sdan        set nHit(0,$iCol) $tblsize
2352f779343Sdan        set nDoc(0,$iCol) $tblsize
2362f779343Sdan      }
2372f779343Sdan    } elseif {$rewritten != $phrase} {
2382f779343Sdan      while {[lindex $rewritten end] == "*"} {
2392f779343Sdan        set rewritten [lrange $rewritten 0 end-1]
2402f779343Sdan      }
2412f779343Sdan      while {[lindex $rewritten 0] == "*"} {
2422f779343Sdan        set rewritten [lrange $rewritten 1 end]
2432f779343Sdan      }
2442cf1a1deSdan      get_single_near_results $tbl [list $rewritten] {} aRewrite nullentry
2452f779343Sdan      foreach docid [array names hits] {
2462f779343Sdan        set aMatchinfo($docid) $aRewrite($docid)
2472f779343Sdan      }
2482f779343Sdan      return
2492f779343Sdan    }
2502f779343Sdan  }
2512f779343Sdan
25299ebad90Sdan  # Set up the aMatchinfo array. For each document, set aMatchinfo($docid) to
25399ebad90Sdan  # contain the output of matchinfo('x') for the document.
25499ebad90Sdan  #
25599ebad90Sdan  foreach docid [array names hits] {
25699ebad90Sdan    set mi [list]
25799ebad90Sdan    for {set iPhrase 0} {$iPhrase<$nPhrase} {incr iPhrase} {
25899ebad90Sdan      for {set iCol 0} {$iCol<$nCol} {incr iCol} {
25999ebad90Sdan        lappend mi [lindex $counts($docid,$iCol) $iPhrase]
26099ebad90Sdan        lappend mi $nHit($iPhrase,$iCol)
2612f779343Sdan        lappend mi $nDoc($iPhrase,$iCol)
26299ebad90Sdan      }
26399ebad90Sdan    }
26499ebad90Sdan    set aMatchinfo($docid) $mi
26599ebad90Sdan  }
26699ebad90Sdan
2673fd65192Sdan  # Set up the nullentry output.
2683fd65192Sdan  #
2693fd65192Sdan  set nullentry [list]
2703fd65192Sdan  for {set iPhrase 0} {$iPhrase<$nPhrase} {incr iPhrase} {
2713fd65192Sdan    for {set iCol 0} {$iCol<$nCol} {incr iCol} {
2722f779343Sdan      lappend nullentry 0 $nHit($iPhrase,$iCol) $nDoc($iPhrase,$iCol)
2733fd65192Sdan    }
2743fd65192Sdan  }
2753fd65192Sdan}
2763fd65192Sdan
2773fd65192Sdan
2783fd65192Sdanproc matching_brackets {expr} {
2793fd65192Sdan  if {[string range $expr 0 0]!="(" || [string range $expr end end] !=")"} {
2803fd65192Sdan    return 0
2813fd65192Sdan  }
2823fd65192Sdan
2833fd65192Sdan  set iBracket 1
2843fd65192Sdan  set nExpr [string length $expr]
2853fd65192Sdan  for {set i 1} {$iBracket && $i < $nExpr} {incr i} {
2863fd65192Sdan    set c [string range $expr $i $i]
2873fd65192Sdan    if {$c == "("} {incr iBracket}
2883fd65192Sdan    if {$c == ")"} {incr iBracket -1}
2893fd65192Sdan  }
2903fd65192Sdan
2913fd65192Sdan  return [expr ($iBracket==0 && $i==$nExpr)]
2923fd65192Sdan}
2933fd65192Sdan
2942cf1a1deSdanproc get_near_results {tbl expr deferred arrayvar {nullvar ""}} {
2953fd65192Sdan  upvar $arrayvar aMatchinfo
2963fd65192Sdan  if {$nullvar != ""} { upvar $nullvar nullentry }
2973fd65192Sdan
2983fd65192Sdan  set expr [string trim $expr]
2993fd65192Sdan  while { [matching_brackets $expr] } {
3003fd65192Sdan    set expr [string trim [string range $expr 1 end-1]]
3013fd65192Sdan  }
3023fd65192Sdan
3033fd65192Sdan  set prec(NOT) 1
3043fd65192Sdan  set prec(AND) 2
3053fd65192Sdan  set prec(OR)  3
3063fd65192Sdan
3073fd65192Sdan  set currentprec 0
3083fd65192Sdan  set iBracket 0
3093fd65192Sdan  set expr_length [llength $expr]
3103fd65192Sdan  for {set i 0} {$i < $expr_length} {incr i} {
3113fd65192Sdan    set op [lindex $expr $i]
3123fd65192Sdan    if {$iBracket==0 && [info exists prec($op)] && $prec($op)>=$currentprec } {
3133fd65192Sdan      set opidx $i
3143fd65192Sdan      set currentprec $prec($op)
3153fd65192Sdan    } else {
3163fd65192Sdan      for {set j 0} {$j < [string length $op]} {incr j} {
3173fd65192Sdan        set c [string range $op $j $j]
3183fd65192Sdan        if {$c == "("} { incr iBracket +1 }
3193fd65192Sdan        if {$c == ")"} { incr iBracket -1 }
3203fd65192Sdan      }
3213fd65192Sdan    }
3223fd65192Sdan  }
3233fd65192Sdan  if {$iBracket!=0} { error "mismatched brackets in: $expr" }
3243fd65192Sdan
3253fd65192Sdan  if {[info exists opidx]==0} {
3262cf1a1deSdan    get_single_near_results $tbl $expr $deferred aMatchinfo nullentry
3273fd65192Sdan  } else {
3283fd65192Sdan    set eLeft  [lrange $expr 0 [expr $opidx-1]]
3293fd65192Sdan    set eRight [lrange $expr [expr $opidx+1] end]
3303fd65192Sdan
3312cf1a1deSdan    get_near_results $tbl $eLeft  $deferred aLeft  nullleft
3322cf1a1deSdan    get_near_results $tbl $eRight $deferred aRight nullright
3333fd65192Sdan
3343fd65192Sdan    switch -- [lindex $expr $opidx] {
3353fd65192Sdan      "NOT" {
3363fd65192Sdan        foreach hit [array names aLeft] {
3373fd65192Sdan          if {0==[info exists aRight($hit)]} {
3383fd65192Sdan            set aMatchinfo($hit) $aLeft($hit)
3393fd65192Sdan          }
3403fd65192Sdan        }
3413fd65192Sdan        set nullentry $nullleft
3423fd65192Sdan      }
3433fd65192Sdan
3443fd65192Sdan      "AND" {
3453fd65192Sdan        foreach hit [array names aLeft] {
3463fd65192Sdan          if {[info exists aRight($hit)]} {
3473fd65192Sdan            set aMatchinfo($hit) [concat $aLeft($hit) $aRight($hit)]
3483fd65192Sdan          }
3493fd65192Sdan        }
3503fd65192Sdan        set nullentry [concat $nullleft $nullright]
3513fd65192Sdan      }
3523fd65192Sdan
3533fd65192Sdan      "OR" {
3543fd65192Sdan        foreach hit [array names aLeft] {
3553fd65192Sdan          if {[info exists aRight($hit)]} {
3563fd65192Sdan            set aMatchinfo($hit) [concat $aLeft($hit) $aRight($hit)]
3573fd65192Sdan            unset aRight($hit)
3583fd65192Sdan          } else {
3593fd65192Sdan            set aMatchinfo($hit) [concat $aLeft($hit) $nullright]
3603fd65192Sdan          }
3613fd65192Sdan        }
3623fd65192Sdan        foreach hit [array names aRight] {
3633fd65192Sdan          set aMatchinfo($hit) [concat $nullleft $aRight($hit)]
3643fd65192Sdan        }
3653fd65192Sdan
3663fd65192Sdan        set nullentry [concat $nullleft $nullright]
3673fd65192Sdan      }
3683fd65192Sdan    }
3693fd65192Sdan  }
3703fd65192Sdan}
3713fd65192Sdan
3723fd65192Sdan
3733fd65192Sdan# End of test procs. Actual tests are below this line.
3743fd65192Sdan#--------------------------------------------------------------------------
3753fd65192Sdan
3763fd65192Sdan#--------------------------------------------------------------------------
3773fd65192Sdan# The following test cases - fts3auto-1.* - focus on testing the Tcl
3783fd65192Sdan# command [fts3_near_match], which is used by other tests in this file.
3793fd65192Sdan#
3803fd65192Sdanproc test_fts3_near_match {tn doc expr res} {
3813fd65192Sdan  fts3_near_match $doc $expr -phrasecountvar p
3823fd65192Sdan  uplevel do_test [list $tn] [list [list set {} $p]] [list $res]
3833fd65192Sdan}
3843fd65192Sdan
3853fd65192Sdantest_fts3_near_match 1.1.1 {a b c a b} a                   {2}
3863fd65192Sdantest_fts3_near_match 1.1.2 {a b c a b} {a 5 b 6 c}         {2 2 1}
3873fd65192Sdantest_fts3_near_match 1.1.3 {a b c a b} {"a b"}             {2}
3883fd65192Sdantest_fts3_near_match 1.1.4 {a b c a b} {"b c"}             {1}
3893fd65192Sdantest_fts3_near_match 1.1.5 {a b c a b} {"c c"}             {0}
3903fd65192Sdan
3913fd65192Sdantest_fts3_near_match 1.2.1 "a b c d e f g" {b 2 f}         {0 0}
3923fd65192Sdantest_fts3_near_match 1.2.2 "a b c d e f g" {b 3 f}         {1 1}
3933fd65192Sdantest_fts3_near_match 1.2.3 "a b c d e f g" {f 2 b}         {0 0}
3943fd65192Sdantest_fts3_near_match 1.2.4 "a b c d e f g" {f 3 b}         {1 1}
3953fd65192Sdantest_fts3_near_match 1.2.5 "a b c d e f g" {"a b" 2 "f g"} {0 0}
3963fd65192Sdantest_fts3_near_match 1.2.6 "a b c d e f g" {"a b" 3 "f g"} {1 1}
3973fd65192Sdan
3983fd65192Sdanset 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"
3993fd65192Sdantest_fts3_near_match 1.3.1 $A {"c d" 5 "i j" 1 "e f"}      {0 0 0}
4003fd65192Sdantest_fts3_near_match 1.3.2 $A {"c d" 5 "i j" 2 "e f"}      {1 1 1}
4013fd65192Sdan
4023fd65192Sdan#--------------------------------------------------------------------------
4033fd65192Sdan# Test cases fts3auto-2.* run some simple tests using the
4042f779343Sdan# [do_fts3query_test] proc.
4053fd65192Sdan#
4063fd65192Sdanforeach {tn create} {
4072f779343Sdan  1    "fts4(a, b)"
4082f779343Sdan  2    "fts4(a, b, order=DESC)"
4092f779343Sdan  3    "fts4(a, b, order=ASC)"
4102f779343Sdan  4    "fts4(a, b, prefix=1)"
4112f779343Sdan  5    "fts4(a, b, order=DESC, prefix=1)"
4122f779343Sdan  6    "fts4(a, b, order=ASC, prefix=1)"
4133fd65192Sdan} {
4143fd65192Sdan  do_test 2.$tn.1 {
4153fd65192Sdan    catchsql { DROP TABLE t1 }
4162f779343Sdan    execsql  "CREATE VIRTUAL TABLE t1 USING $create"
41799ebad90Sdan    for {set i 0} {$i<32} {incr i} {
41899ebad90Sdan      set doc [list]
41999ebad90Sdan      if {$i&0x01} {lappend doc one}
42099ebad90Sdan      if {$i&0x02} {lappend doc two}
42199ebad90Sdan      if {$i&0x04} {lappend doc three}
42299ebad90Sdan      if {$i&0x08} {lappend doc four}
42399ebad90Sdan      if {$i&0x10} {lappend doc five}
42499ebad90Sdan      execsql { INSERT INTO t1 VALUES($doc, null) }
42599ebad90Sdan    }
42699ebad90Sdan  } {}
4272f779343Sdan
4283fd65192Sdan  foreach {tn2 expr} {
42999ebad90Sdan    1     {one}
43099ebad90Sdan    2     {one NEAR/1 five}
43199ebad90Sdan    3     {t*}
43299ebad90Sdan    4     {t* NEAR/0 five}
43399ebad90Sdan    5     {o* NEAR/1 f*}
43499ebad90Sdan    6     {one NEAR five NEAR two NEAR four NEAR three}
4353fd65192Sdan    7     {one NEAR xyz}
4363fd65192Sdan    8     {one OR two}
4373fd65192Sdan    9     {one AND two}
4383fd65192Sdan    10    {one NOT two}
4393fd65192Sdan    11    {one AND two OR three}
4403fd65192Sdan    12    {three OR one AND two}
4413fd65192Sdan    13    {(three OR one) AND two}
4423fd65192Sdan    14    {(three OR one) AND two NOT (five NOT four)}
4433fd65192Sdan    15    {"one two"}
4443fd65192Sdan    16    {"one two" NOT "three four"}
44599ebad90Sdan  } {
4462f779343Sdan    do_fts3query_test 2.$tn.2.$tn2 t1 $expr
4472f779343Sdan  }
4482f779343Sdan}
4492f779343Sdan
4502f779343Sdan#--------------------------------------------------------------------------
4512f779343Sdan# Some test cases involving deferred tokens.
4522f779343Sdan#
4532f779343Sdan
4542f779343Sdanforeach {tn create} {
4552f779343Sdan  1    "fts4(x)"
4562f779343Sdan  2    "fts4(x, order=DESC)"
4572f779343Sdan} {
4582f779343Sdan  catchsql { DROP TABLE t1 }
4592f779343Sdan  execsql  "CREATE VIRTUAL TABLE t1 USING $create"
4602f779343Sdan  do_execsql_test 3.$tn.1 {
461653265d9Sdan    INSERT INTO t1(docid, x) VALUES(-2, 'a b c d e f g h i j k');
462653265d9Sdan    INSERT INTO t1(docid, x) VALUES(-1, 'b c d e f g h i j k a');
463653265d9Sdan    INSERT INTO t1(docid, x) VALUES(0, 'c d e f g h i j k a b');
464653265d9Sdan    INSERT INTO t1(docid, x) VALUES(1, 'd e f g h i j k a b c');
465653265d9Sdan    INSERT INTO t1(docid, x) VALUES(2, 'e f g h i j k a b c d');
466653265d9Sdan    INSERT INTO t1(docid, x) VALUES(3, 'f g h i j k a b c d e');
467653265d9Sdan    INSERT INTO t1(docid, x) VALUES(4, 'a c e g i k');
468653265d9Sdan    INSERT INTO t1(docid, x) VALUES(5, 'a d g j');
469653265d9Sdan    INSERT INTO t1(docid, x) VALUES(6, 'c a b');
4702f779343Sdan  }
4712f779343Sdan
472db27fc07Sdan  set limit [fts3_make_deferrable t1 c]
4732f779343Sdan
474db27fc07Sdan  do_fts3query_test 3.$tn.2.1 t1 {a OR c}
4752f779343Sdan
476db27fc07Sdan  do_test 3.$tn.3 {
477db27fc07Sdan    fts3_zero_long_segments t1 $limit
478db27fc07Sdan  } {1}
479db27fc07Sdan
4802cf1a1deSdan  foreach {tn2 expr def} {
4812cf1a1deSdan    1     {a NEAR c}            {}
4822cf1a1deSdan    2     {a AND c}             c
4832cf1a1deSdan    3     {"a c"}               c
4842cf1a1deSdan    4     {"c a"}               c
4852cf1a1deSdan    5     {"a c" NEAR/1 g}      {}
4862cf1a1deSdan    6     {"a c" NEAR/0 g}      {}
4872f779343Sdan  } {
488db27fc07Sdan    do_fts3query_test 3.$tn.4.$tn2 -deferred $def t1 $expr
4892cf1a1deSdan  }
4902cf1a1deSdan}
4912cf1a1deSdan
4922cf1a1deSdan#--------------------------------------------------------------------------
4932cf1a1deSdan#
4942cf1a1deSdanforeach {tn create} {
4952cf1a1deSdan  1    "fts4(x, y)"
4962cf1a1deSdan  2    "fts4(x, y, order=DESC)"
497db27fc07Sdan  3    "fts4(x, y, order=DESC, prefix=2)"
4982cf1a1deSdan} {
4992cf1a1deSdan
500db27fc07Sdan  execsql [subst {
501db27fc07Sdan    DROP TABLE t1;
502db27fc07Sdan    CREATE VIRTUAL TABLE t1 USING $create;
503db27fc07Sdan    INSERT INTO t1 VALUES('one two five four five', '');
504db27fc07Sdan    INSERT INTO t1 VALUES('', 'one two five four five');
505db27fc07Sdan    INSERT INTO t1 VALUES('one two', 'five four five');
506db27fc07Sdan  }]
5072cf1a1deSdan
508db27fc07Sdan  do_fts3query_test 4.$tn.1.1 t1 {one AND five}
509db27fc07Sdan  do_fts3query_test 4.$tn.1.2 t1 {one NEAR five}
510db27fc07Sdan  do_fts3query_test 4.$tn.1.3 t1 {one NEAR/1 five}
511db27fc07Sdan  do_fts3query_test 4.$tn.1.4 t1 {one NEAR/2 five}
512db27fc07Sdan  do_fts3query_test 4.$tn.1.5 t1 {one NEAR/3 five}
513db27fc07Sdan
514db27fc07Sdan  do_test 4.$tn.2 {
515db27fc07Sdan    set limit [fts3_make_deferrable t1 five]
516db27fc07Sdan    execsql { INSERT INTO t1(t1) VALUES('optimize') }
517db27fc07Sdan    expr {[fts3_zero_long_segments t1 $limit]>0}
518db27fc07Sdan  } {1}
519db27fc07Sdan
520db27fc07Sdan  do_fts3query_test 4.$tn.3.1 -deferred five t1 {one AND five}
521db27fc07Sdan  do_fts3query_test 4.$tn.3.2 -deferred five t1 {one NEAR five}
522db27fc07Sdan  do_fts3query_test 4.$tn.3.3 -deferred five t1 {one NEAR/1 five}
523db27fc07Sdan  do_fts3query_test 4.$tn.3.4 -deferred five t1 {one NEAR/2 five}
524*d4d21feaSdan
525db27fc07Sdan  do_fts3query_test 4.$tn.3.5 -deferred five t1 {one NEAR/3 five}
526db27fc07Sdan
527db27fc07Sdan  do_fts3query_test 4.$tn.4.1 -deferred fi* t1 {on* AND fi*}
528db27fc07Sdan  do_fts3query_test 4.$tn.4.2 -deferred fi* t1 {on* NEAR fi*}
529db27fc07Sdan  do_fts3query_test 4.$tn.4.3 -deferred fi* t1 {on* NEAR/1 fi*}
530db27fc07Sdan  do_fts3query_test 4.$tn.4.4 -deferred fi* t1 {on* NEAR/2 fi*}
531db27fc07Sdan  do_fts3query_test 4.$tn.4.5 -deferred fi* t1 {on* NEAR/3 fi*}
53299ebad90Sdan}
53399ebad90Sdan
534376d1e5cSdan#--------------------------------------------------------------------------
535376d1e5cSdan# The following test cases - fts3auto-5.* - focus on using prefix indexes.
536376d1e5cSdan#
537376d1e5cSdanset chunkconfig [fts3_configure_incr_load 1 1]
538*d4d21feaSdanforeach {tn create pending} {
539*d4d21feaSdan  2    "fts4(a, b, order=ASC, prefix=1)"             1
540*d4d21feaSdan
541*d4d21feaSdan  1    "fts4(a, b)"                                  1
542*d4d21feaSdan  3    "fts4(a, b, order=ASC,  prefix=1,3)"          0
543*d4d21feaSdan  4    "fts4(a, b, order=DESC, prefix=2,4)"          0
544*d4d21feaSdan  5    "fts4(a, b, order=DESC, prefix=1)"            0
545*d4d21feaSdan  6    "fts4(a, b, order=ASC,  prefix=1,3)"          0
546376d1e5cSdan} {
547376d1e5cSdan
548376d1e5cSdan  execsql [subst {
549*d4d21feaSdan    DROP TABLE IF EXISTS t1;
550376d1e5cSdan    CREATE VIRTUAL TABLE t1 USING $create;
551376d1e5cSdan  }]
552376d1e5cSdan
553*d4d21feaSdan  if {$pending} {execsql BEGIN}
554*d4d21feaSdan
555376d1e5cSdan  foreach {a b} {
556376d1e5cSdan    "the song of songs which is solomons"
557376d1e5cSdan    "let him kiss me with the kisses of his mouth for thy love is better than wine"
558376d1e5cSdan    "because of the savour of thy good ointments thy name is as ointment poured forth therefore do the virgins love thee"
559376d1e5cSdan    "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"
560376d1e5cSdan    "i am black but comely o ye daughters of jerusalem as the tents of kedar as the curtains of solomon"
561376d1e5cSdan    "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"
562376d1e5cSdan    "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?"
563376d1e5cSdan    "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"
564376d1e5cSdan    "i have compared thee o my love to a company of horses in pharaohs chariots"
565376d1e5cSdan    "thy cheeks are comely with rows of jewels thy neck with chains of gold"
566376d1e5cSdan    "we will make thee borders of gold with studs of silver"
567376d1e5cSdan    "while the king sitteth at his table my spikenard sendeth forth the smell thereof"
568376d1e5cSdan    "a bundle of myrrh is my wellbeloved unto me he shall lie all night betwixt my breasts"
569376d1e5cSdan    "my beloved is unto me as a cluster of camphire in the vineyards of en gedi"
570376d1e5cSdan    "behold thou art fair my love behold thou art fair thou hast doves eyes"
571376d1e5cSdan    "behold thou art fair my beloved yea pleasant also our bed is green"
572376d1e5cSdan    "the beams of our house are cedar and our rafters of fir"
573376d1e5cSdan  } {
574376d1e5cSdan    execsql {INSERT INTO t1(a, b) VALUES($a, $b)}
575376d1e5cSdan  }
576376d1e5cSdan
577*d4d21feaSdan
578376d1e5cSdan  do_fts3query_test 5.$tn.1.1 t1 {s*}
579376d1e5cSdan  do_fts3query_test 5.$tn.1.2 t1 {so*}
580376d1e5cSdan  do_fts3query_test 5.$tn.1.3 t1 {"s* o*"}
581376d1e5cSdan  do_fts3query_test 5.$tn.1.4 t1 {b* NEAR/3 a*}
582*d4d21feaSdan  do_fts3query_test 5.$tn.1.5 t1 {a*}
583*d4d21feaSdan  do_fts3query_test 5.$tn.1.6 t1 {th* NEAR/5 a* NEAR/5 w*}
584*d4d21feaSdan  do_fts3query_test 5.$tn.1.7 t1 {"b* th* art* fair*"}
585*d4d21feaSdan
586*d4d21feaSdan  if {$pending} {execsql COMMIT}
587376d1e5cSdan}
588376d1e5cSdaneval fts3_configure_incr_load $chunkconfig
589376d1e5cSdan
5903fd65192Sdanset sqlite_fts3_enable_parentheses $sfep
59199ebad90Sdanfinish_test
59299ebad90Sdan
593