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 { 704dc3d73dSdan ifcapable fts4_deferred { set deferred $v } 712cf1a1deSdan } 722cf1a1deSdan default { 732cf1a1deSdan error "bad option \"$k\": must be -deferred" 742cf1a1deSdan } 752cf1a1deSdan } 762cf1a1deSdan } 772cf1a1deSdan 785cfed52dSdan get_near_results $tbl $match $deferred aHit 795cfed52dSdan get_near_results $tbl [string map {AND OR} $match] $deferred aMatchinfo 80653265d9Sdan 81653265d9Sdan set matchinfo_asc [list] 825cfed52dSdan foreach docid [lsort -integer -incr [array names aHit]] { 83653265d9Sdan lappend matchinfo_asc $docid $aMatchinfo($docid) 84653265d9Sdan } 85653265d9Sdan set matchinfo_desc [list] 865cfed52dSdan foreach docid [lsort -integer -decr [array names aHit]] { 87653265d9Sdan lappend matchinfo_desc $docid $aMatchinfo($docid) 88653265d9Sdan } 89653265d9Sdan 905cfed52dSdan set title "(\"$match\" -> [llength [array names aHit]] rows)" 91653265d9Sdan 92653265d9Sdan do_execsql_test $tn$title.1 " 93653265d9Sdan SELECT docid FROM $tbl WHERE $tbl MATCH '$match' ORDER BY docid ASC 945cfed52dSdan " [lsort -integer -incr [array names aHit]] 95653265d9Sdan 96653265d9Sdan do_execsql_test $tn$title.2 " 97653265d9Sdan SELECT docid FROM $tbl WHERE $tbl MATCH '$match' ORDER BY docid DESC 985cfed52dSdan " [lsort -integer -decr [array names aHit]] 99653265d9Sdan 100653265d9Sdan do_execsql_test $tn$title.3 " 101653265d9Sdan SELECT docid, mit(matchinfo($tbl, 'x')) FROM $tbl 102653265d9Sdan WHERE $tbl MATCH '$match' ORDER BY docid DESC 103653265d9Sdan " $matchinfo_desc 104653265d9Sdan 105653265d9Sdan do_execsql_test $tn$title.4 " 106653265d9Sdan SELECT docid, mit(matchinfo($tbl, 'x')) FROM $tbl 107653265d9Sdan WHERE $tbl MATCH '$match' ORDER BY docid ASC 108653265d9Sdan " $matchinfo_asc 109653265d9Sdan} 110653265d9Sdan 111da7b4561Sdan# fts3_make_deferrable TABLE TOKEN ?NROW? 112db27fc07Sdan# 113da7b4561Sdanproc fts3_make_deferrable {tbl token {nRow 0}} { 114db27fc07Sdan 115db27fc07Sdan set stmt [sqlite3_prepare db "SELECT * FROM $tbl" -1 dummy] 116db27fc07Sdan set name [sqlite3_column_name $stmt 0] 117db27fc07Sdan sqlite3_finalize $stmt 118db27fc07Sdan 119da7b4561Sdan if {$nRow==0} { 120db27fc07Sdan set nRow [db one "SELECT count(*) FROM $tbl"] 121da7b4561Sdan } 122db27fc07Sdan set pgsz [db one "PRAGMA page_size"] 123db27fc07Sdan execsql BEGIN 124db27fc07Sdan for {set i 0} {$i < ($nRow * $pgsz * 1.2)/100} {incr i} { 125db27fc07Sdan set doc [string repeat "$token " 100] 126db27fc07Sdan execsql "INSERT INTO $tbl ($name) VALUES(\$doc)" 127db27fc07Sdan } 128db27fc07Sdan execsql "INSERT INTO $tbl ($name) VALUES('aaaaaaa ${token}aaaaa')" 129db27fc07Sdan execsql COMMIT 130db27fc07Sdan 131db27fc07Sdan return [expr $nRow*$pgsz] 132db27fc07Sdan} 133db27fc07Sdan 134db27fc07Sdan# fts3_zero_long_segments TABLE ?LIMIT? 135db27fc07Sdan# 136db27fc07Sdanproc fts3_zero_long_segments {tbl limit} { 137*0f0d3ddfSdrh sqlite3_db_config db DEFENSIVE 0 138db27fc07Sdan execsql " 139db27fc07Sdan UPDATE ${tbl}_segments 140db27fc07Sdan SET block = zeroblob(length(block)) 141db27fc07Sdan WHERE length(block)>$limit 142db27fc07Sdan " 143*0f0d3ddfSdrh sqlite3_db_config db DEFENSIVE 1 144db27fc07Sdan return [db changes] 145db27fc07Sdan} 146db27fc07Sdan 147653265d9Sdan 14899ebad90Sdanproc mit {blob} { 14999ebad90Sdan set scan(littleEndian) i* 15099ebad90Sdan set scan(bigEndian) I* 15199ebad90Sdan binary scan $blob $scan($::tcl_platform(byteOrder)) r 15299ebad90Sdan return $r 15399ebad90Sdan} 15499ebad90Sdandb func mit mit 15599ebad90Sdan 156b727d679Sdanproc fix_phrase_expr {cols expr colfiltervar} { 157b727d679Sdan upvar $colfiltervar iColFilter 158b727d679Sdan 15999ebad90Sdan set out [list] 160b727d679Sdan foreach t $expr { 161b727d679Sdan if {[string match *:* $t]} { 162b727d679Sdan set col [lindex [split $t :] 0] 163b727d679Sdan set t [lindex [split $t :] 1] 164b727d679Sdan set iCol [lsearch $cols $col] 165b727d679Sdan if {$iCol<0} { error "unknown column: $col" } 166b727d679Sdan if {$iColFilter < 0} { 167b727d679Sdan set iColFilter $iCol 168b727d679Sdan } elseif {$iColFilter != $iCol} { 169b727d679Sdan set iColFilter [llength $cols] 170b727d679Sdan } 171b727d679Sdan } 172b727d679Sdan lappend out $t 173b727d679Sdan } 174b727d679Sdan 175b727d679Sdan return $out 176b727d679Sdan} 177b727d679Sdan 178b727d679Sdanproc fix_near_expr {cols expr colfiltervar} { 179b727d679Sdan upvar $colfiltervar iColFilter 180b727d679Sdan 181b727d679Sdan set iColFilter -1 182b727d679Sdan 183b727d679Sdan set out [list] 184b727d679Sdan lappend out [fix_phrase_expr $cols [lindex $expr 0] iColFilter] 18599ebad90Sdan foreach {a b} [lrange $expr 1 end] { 18699ebad90Sdan if {[string match -nocase near $a]} { set a 10 } 18799ebad90Sdan if {[string match -nocase near/* $a]} { set a [string range $a 5 end] } 18899ebad90Sdan lappend out $a 189b727d679Sdan lappend out [fix_phrase_expr $cols $b iColFilter] 19099ebad90Sdan } 19199ebad90Sdan return $out 19299ebad90Sdan} 19399ebad90Sdan 1942cf1a1deSdanproc get_single_near_results {tbl expr deferred arrayvar nullvar} { 1953fd65192Sdan upvar $arrayvar aMatchinfo 1963fd65192Sdan upvar $nullvar nullentry 1973fd65192Sdan catch {array unset aMatchinfo} 19899ebad90Sdan 199b727d679Sdan set cols [list] 200b727d679Sdan set miss [list] 201b727d679Sdan db eval "PRAGMA table_info($tbl)" A { lappend cols $A(name) ; lappend miss 0 } 202b727d679Sdan set expr [fix_near_expr $cols $expr iColFilter] 20399ebad90Sdan 20499ebad90Sdan # Calculate the expected results using [fts3_near_match]. The following 20599ebad90Sdan # loop populates the "hits" and "counts" arrays as follows: 20699ebad90Sdan # 20799ebad90Sdan # 1. For each document in the table that matches the NEAR expression, 20899ebad90Sdan # hits($docid) is set to 1. The set of docids that match the expression 20999ebad90Sdan # can therefore be found using [array names hits]. 21099ebad90Sdan # 21199ebad90Sdan # 2. For each column of each document in the table, counts($docid,$iCol) 21299ebad90Sdan # is set to the -phrasecountvar output. 21399ebad90Sdan # 21499ebad90Sdan set res [list] 21599ebad90Sdan catch { array unset hits } 21699ebad90Sdan db eval "SELECT docid, * FROM $tbl" d { 21799ebad90Sdan set iCol 0 21899ebad90Sdan foreach col [lrange $d(*) 1 end] { 21999ebad90Sdan set docid $d(docid) 220b727d679Sdan if {$iColFilter<0 || $iCol==$iColFilter} { 22199ebad90Sdan set hit [fts3_near_match $d($col) $expr -p counts($docid,$iCol)] 22299ebad90Sdan if {$hit} { set hits($docid) 1 } 223b727d679Sdan } else { 224b727d679Sdan set counts($docid,$iCol) $miss 225b727d679Sdan } 22699ebad90Sdan incr iCol 22799ebad90Sdan } 22899ebad90Sdan } 22999ebad90Sdan set nPhrase [expr ([llength $expr]+1)/2] 23099ebad90Sdan set nCol $iCol 23199ebad90Sdan 23299ebad90Sdan # This block populates the nHit and nDoc arrays. For each phrase/column 23399ebad90Sdan # in the query/table, array elements are set as follows: 23499ebad90Sdan # 23599ebad90Sdan # nHit($iPhrase,$iCol) - Total number of hits for phrase $iPhrase in 23699ebad90Sdan # column $iCol. 23799ebad90Sdan # 23899ebad90Sdan # nDoc($iPhrase,$iCol) - Number of documents with at least one hit for 23999ebad90Sdan # phrase $iPhrase in column $iCol. 24099ebad90Sdan # 24199ebad90Sdan for {set iPhrase 0} {$iPhrase < $nPhrase} {incr iPhrase} { 24299ebad90Sdan for {set iCol 0} {$iCol < $nCol} {incr iCol} { 24399ebad90Sdan set nHit($iPhrase,$iCol) 0 24499ebad90Sdan set nDoc($iPhrase,$iCol) 0 24599ebad90Sdan } 24699ebad90Sdan } 24799ebad90Sdan foreach key [array names counts] { 24899ebad90Sdan set iCol [lindex [split $key ,] 1] 24999ebad90Sdan set iPhrase 0 25099ebad90Sdan foreach c $counts($key) { 2512f779343Sdan if {$c>0} { incr nDoc($iPhrase,$iCol) 1 } 2522f779343Sdan incr nHit($iPhrase,$iCol) $c 25399ebad90Sdan incr iPhrase 25499ebad90Sdan } 25599ebad90Sdan } 25699ebad90Sdan 2572cf1a1deSdan if {[llength $deferred] && [llength $expr]==1} { 2582f779343Sdan set phrase [lindex $expr 0] 2592f779343Sdan set rewritten [list] 2602f779343Sdan set partial 0 2612f779343Sdan foreach tok $phrase { 2622cf1a1deSdan if {[lsearch $deferred $tok]>=0} { 2632f779343Sdan lappend rewritten * 2642f779343Sdan } else { 2652f779343Sdan lappend rewritten $tok 2662f779343Sdan set partial 1 2672f779343Sdan } 2682f779343Sdan } 2692f779343Sdan if {$partial==0} { 2702f779343Sdan set tblsize [db one "SELECT count(*) FROM $tbl"] 2712f779343Sdan for {set iCol 0} {$iCol < $nCol} {incr iCol} { 2722f779343Sdan set nHit(0,$iCol) $tblsize 2732f779343Sdan set nDoc(0,$iCol) $tblsize 2742f779343Sdan } 2752f779343Sdan } elseif {$rewritten != $phrase} { 2762f779343Sdan while {[lindex $rewritten end] == "*"} { 2772f779343Sdan set rewritten [lrange $rewritten 0 end-1] 2782f779343Sdan } 2792f779343Sdan while {[lindex $rewritten 0] == "*"} { 2802f779343Sdan set rewritten [lrange $rewritten 1 end] 2812f779343Sdan } 2822cf1a1deSdan get_single_near_results $tbl [list $rewritten] {} aRewrite nullentry 2832f779343Sdan foreach docid [array names hits] { 2842f779343Sdan set aMatchinfo($docid) $aRewrite($docid) 2852f779343Sdan } 2862f779343Sdan return 2872f779343Sdan } 2882f779343Sdan } 2892f779343Sdan 29099ebad90Sdan # Set up the aMatchinfo array. For each document, set aMatchinfo($docid) to 29199ebad90Sdan # contain the output of matchinfo('x') for the document. 29299ebad90Sdan # 29399ebad90Sdan foreach docid [array names hits] { 29499ebad90Sdan set mi [list] 29599ebad90Sdan for {set iPhrase 0} {$iPhrase<$nPhrase} {incr iPhrase} { 29699ebad90Sdan for {set iCol 0} {$iCol<$nCol} {incr iCol} { 29799ebad90Sdan lappend mi [lindex $counts($docid,$iCol) $iPhrase] 29899ebad90Sdan lappend mi $nHit($iPhrase,$iCol) 2992f779343Sdan lappend mi $nDoc($iPhrase,$iCol) 30099ebad90Sdan } 30199ebad90Sdan } 30299ebad90Sdan set aMatchinfo($docid) $mi 30399ebad90Sdan } 30499ebad90Sdan 3053fd65192Sdan # Set up the nullentry output. 3063fd65192Sdan # 3073fd65192Sdan set nullentry [list] 3083fd65192Sdan for {set iPhrase 0} {$iPhrase<$nPhrase} {incr iPhrase} { 3093fd65192Sdan for {set iCol 0} {$iCol<$nCol} {incr iCol} { 3102f779343Sdan lappend nullentry 0 $nHit($iPhrase,$iCol) $nDoc($iPhrase,$iCol) 3113fd65192Sdan } 3123fd65192Sdan } 3133fd65192Sdan} 3143fd65192Sdan 3153fd65192Sdan 3163fd65192Sdanproc matching_brackets {expr} { 3173fd65192Sdan if {[string range $expr 0 0]!="(" || [string range $expr end end] !=")"} { 3183fd65192Sdan return 0 3193fd65192Sdan } 3203fd65192Sdan 3213fd65192Sdan set iBracket 1 3223fd65192Sdan set nExpr [string length $expr] 3233fd65192Sdan for {set i 1} {$iBracket && $i < $nExpr} {incr i} { 3243fd65192Sdan set c [string range $expr $i $i] 3253fd65192Sdan if {$c == "("} {incr iBracket} 3263fd65192Sdan if {$c == ")"} {incr iBracket -1} 3273fd65192Sdan } 3283fd65192Sdan 3293fd65192Sdan return [expr ($iBracket==0 && $i==$nExpr)] 3303fd65192Sdan} 3313fd65192Sdan 3322cf1a1deSdanproc get_near_results {tbl expr deferred arrayvar {nullvar ""}} { 3333fd65192Sdan upvar $arrayvar aMatchinfo 3343fd65192Sdan if {$nullvar != ""} { upvar $nullvar nullentry } 3353fd65192Sdan 3363fd65192Sdan set expr [string trim $expr] 3373fd65192Sdan while { [matching_brackets $expr] } { 3383fd65192Sdan set expr [string trim [string range $expr 1 end-1]] 3393fd65192Sdan } 3403fd65192Sdan 3413fd65192Sdan set prec(NOT) 1 3423fd65192Sdan set prec(AND) 2 3433fd65192Sdan set prec(OR) 3 3443fd65192Sdan 3453fd65192Sdan set currentprec 0 3463fd65192Sdan set iBracket 0 3473fd65192Sdan set expr_length [llength $expr] 3483fd65192Sdan for {set i 0} {$i < $expr_length} {incr i} { 3493fd65192Sdan set op [lindex $expr $i] 3503fd65192Sdan if {$iBracket==0 && [info exists prec($op)] && $prec($op)>=$currentprec } { 3513fd65192Sdan set opidx $i 3523fd65192Sdan set currentprec $prec($op) 3533fd65192Sdan } else { 3543fd65192Sdan for {set j 0} {$j < [string length $op]} {incr j} { 3553fd65192Sdan set c [string range $op $j $j] 3563fd65192Sdan if {$c == "("} { incr iBracket +1 } 3573fd65192Sdan if {$c == ")"} { incr iBracket -1 } 3583fd65192Sdan } 3593fd65192Sdan } 3603fd65192Sdan } 3613fd65192Sdan if {$iBracket!=0} { error "mismatched brackets in: $expr" } 3623fd65192Sdan 3633fd65192Sdan if {[info exists opidx]==0} { 3642cf1a1deSdan get_single_near_results $tbl $expr $deferred aMatchinfo nullentry 3653fd65192Sdan } else { 3663fd65192Sdan set eLeft [lrange $expr 0 [expr $opidx-1]] 3673fd65192Sdan set eRight [lrange $expr [expr $opidx+1] end] 3683fd65192Sdan 3692cf1a1deSdan get_near_results $tbl $eLeft $deferred aLeft nullleft 3702cf1a1deSdan get_near_results $tbl $eRight $deferred aRight nullright 3713fd65192Sdan 3723fd65192Sdan switch -- [lindex $expr $opidx] { 3733fd65192Sdan "NOT" { 3743fd65192Sdan foreach hit [array names aLeft] { 3753fd65192Sdan if {0==[info exists aRight($hit)]} { 3763fd65192Sdan set aMatchinfo($hit) $aLeft($hit) 3773fd65192Sdan } 3783fd65192Sdan } 3793fd65192Sdan set nullentry $nullleft 3803fd65192Sdan } 3813fd65192Sdan 3823fd65192Sdan "AND" { 3833fd65192Sdan foreach hit [array names aLeft] { 3843fd65192Sdan if {[info exists aRight($hit)]} { 3853fd65192Sdan set aMatchinfo($hit) [concat $aLeft($hit) $aRight($hit)] 3863fd65192Sdan } 3873fd65192Sdan } 3883fd65192Sdan set nullentry [concat $nullleft $nullright] 3893fd65192Sdan } 3903fd65192Sdan 3913fd65192Sdan "OR" { 3923fd65192Sdan foreach hit [array names aLeft] { 3933fd65192Sdan if {[info exists aRight($hit)]} { 3943fd65192Sdan set aMatchinfo($hit) [concat $aLeft($hit) $aRight($hit)] 3953fd65192Sdan unset aRight($hit) 3963fd65192Sdan } else { 3973fd65192Sdan set aMatchinfo($hit) [concat $aLeft($hit) $nullright] 3983fd65192Sdan } 3993fd65192Sdan } 4003fd65192Sdan foreach hit [array names aRight] { 4013fd65192Sdan set aMatchinfo($hit) [concat $nullleft $aRight($hit)] 4023fd65192Sdan } 4033fd65192Sdan 4043fd65192Sdan set nullentry [concat $nullleft $nullright] 4053fd65192Sdan } 4063fd65192Sdan } 4073fd65192Sdan } 4083fd65192Sdan} 4093fd65192Sdan 4103fd65192Sdan 4113fd65192Sdan# End of test procs. Actual tests are below this line. 4123fd65192Sdan#-------------------------------------------------------------------------- 4133fd65192Sdan 4143fd65192Sdan#-------------------------------------------------------------------------- 4153fd65192Sdan# The following test cases - fts3auto-1.* - focus on testing the Tcl 4163fd65192Sdan# command [fts3_near_match], which is used by other tests in this file. 4173fd65192Sdan# 4183fd65192Sdanproc test_fts3_near_match {tn doc expr res} { 4193fd65192Sdan fts3_near_match $doc $expr -phrasecountvar p 4203fd65192Sdan uplevel do_test [list $tn] [list [list set {} $p]] [list $res] 4213fd65192Sdan} 4223fd65192Sdan 4233fd65192Sdantest_fts3_near_match 1.1.1 {a b c a b} a {2} 4243fd65192Sdantest_fts3_near_match 1.1.2 {a b c a b} {a 5 b 6 c} {2 2 1} 4253fd65192Sdantest_fts3_near_match 1.1.3 {a b c a b} {"a b"} {2} 4263fd65192Sdantest_fts3_near_match 1.1.4 {a b c a b} {"b c"} {1} 4273fd65192Sdantest_fts3_near_match 1.1.5 {a b c a b} {"c c"} {0} 4283fd65192Sdan 4293fd65192Sdantest_fts3_near_match 1.2.1 "a b c d e f g" {b 2 f} {0 0} 4303fd65192Sdantest_fts3_near_match 1.2.2 "a b c d e f g" {b 3 f} {1 1} 4313fd65192Sdantest_fts3_near_match 1.2.3 "a b c d e f g" {f 2 b} {0 0} 4323fd65192Sdantest_fts3_near_match 1.2.4 "a b c d e f g" {f 3 b} {1 1} 4333fd65192Sdantest_fts3_near_match 1.2.5 "a b c d e f g" {"a b" 2 "f g"} {0 0} 4343fd65192Sdantest_fts3_near_match 1.2.6 "a b c d e f g" {"a b" 3 "f g"} {1 1} 4353fd65192Sdan 4363fd65192Sdanset 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" 4373fd65192Sdantest_fts3_near_match 1.3.1 $A {"c d" 5 "i j" 1 "e f"} {0 0 0} 4383fd65192Sdantest_fts3_near_match 1.3.2 $A {"c d" 5 "i j" 2 "e f"} {1 1 1} 4393fd65192Sdan 4403fd65192Sdan#-------------------------------------------------------------------------- 4413fd65192Sdan# Test cases fts3auto-2.* run some simple tests using the 4422f779343Sdan# [do_fts3query_test] proc. 4433fd65192Sdan# 4443fd65192Sdanforeach {tn create} { 4452f779343Sdan 1 "fts4(a, b)" 4462f779343Sdan 2 "fts4(a, b, order=DESC)" 4472f779343Sdan 3 "fts4(a, b, order=ASC)" 4482f779343Sdan 4 "fts4(a, b, prefix=1)" 4492f779343Sdan 5 "fts4(a, b, order=DESC, prefix=1)" 4502f779343Sdan 6 "fts4(a, b, order=ASC, prefix=1)" 4513fd65192Sdan} { 4523fd65192Sdan do_test 2.$tn.1 { 4533fd65192Sdan catchsql { DROP TABLE t1 } 4542f779343Sdan execsql "CREATE VIRTUAL TABLE t1 USING $create" 45599ebad90Sdan for {set i 0} {$i<32} {incr i} { 45699ebad90Sdan set doc [list] 45799ebad90Sdan if {$i&0x01} {lappend doc one} 45899ebad90Sdan if {$i&0x02} {lappend doc two} 45999ebad90Sdan if {$i&0x04} {lappend doc three} 46099ebad90Sdan if {$i&0x08} {lappend doc four} 46199ebad90Sdan if {$i&0x10} {lappend doc five} 46299ebad90Sdan execsql { INSERT INTO t1 VALUES($doc, null) } 46399ebad90Sdan } 46499ebad90Sdan } {} 4652f779343Sdan 4663fd65192Sdan foreach {tn2 expr} { 46799ebad90Sdan 1 {one} 46899ebad90Sdan 2 {one NEAR/1 five} 46999ebad90Sdan 3 {t*} 47099ebad90Sdan 4 {t* NEAR/0 five} 47199ebad90Sdan 5 {o* NEAR/1 f*} 47299ebad90Sdan 6 {one NEAR five NEAR two NEAR four NEAR three} 4733fd65192Sdan 7 {one NEAR xyz} 4743fd65192Sdan 8 {one OR two} 4753fd65192Sdan 9 {one AND two} 4763fd65192Sdan 10 {one NOT two} 4773fd65192Sdan 11 {one AND two OR three} 4783fd65192Sdan 12 {three OR one AND two} 4793fd65192Sdan 13 {(three OR one) AND two} 4803fd65192Sdan 14 {(three OR one) AND two NOT (five NOT four)} 4813fd65192Sdan 15 {"one two"} 4823fd65192Sdan 16 {"one two" NOT "three four"} 48399ebad90Sdan } { 4842f779343Sdan do_fts3query_test 2.$tn.2.$tn2 t1 $expr 4852f779343Sdan } 4862f779343Sdan} 4872f779343Sdan 4882f779343Sdan#-------------------------------------------------------------------------- 4892f779343Sdan# Some test cases involving deferred tokens. 4902f779343Sdan# 4912f779343Sdan 4922f779343Sdanforeach {tn create} { 4932f779343Sdan 1 "fts4(x)" 4942f779343Sdan 2 "fts4(x, order=DESC)" 4952f779343Sdan} { 4962f779343Sdan catchsql { DROP TABLE t1 } 4972f779343Sdan execsql "CREATE VIRTUAL TABLE t1 USING $create" 4982f779343Sdan do_execsql_test 3.$tn.1 { 499653265d9Sdan INSERT INTO t1(docid, x) VALUES(-2, 'a b c d e f g h i j k'); 500653265d9Sdan INSERT INTO t1(docid, x) VALUES(-1, 'b c d e f g h i j k a'); 501653265d9Sdan INSERT INTO t1(docid, x) VALUES(0, 'c d e f g h i j k a b'); 502653265d9Sdan INSERT INTO t1(docid, x) VALUES(1, 'd e f g h i j k a b c'); 503653265d9Sdan INSERT INTO t1(docid, x) VALUES(2, 'e f g h i j k a b c d'); 504653265d9Sdan INSERT INTO t1(docid, x) VALUES(3, 'f g h i j k a b c d e'); 505653265d9Sdan INSERT INTO t1(docid, x) VALUES(4, 'a c e g i k'); 506653265d9Sdan INSERT INTO t1(docid, x) VALUES(5, 'a d g j'); 507653265d9Sdan INSERT INTO t1(docid, x) VALUES(6, 'c a b'); 5082f779343Sdan } 5092f779343Sdan 510db27fc07Sdan set limit [fts3_make_deferrable t1 c] 5112f779343Sdan 512db27fc07Sdan do_fts3query_test 3.$tn.2.1 t1 {a OR c} 5132f779343Sdan 5144dc3d73dSdan ifcapable fts4_deferred { 5154dc3d73dSdan do_test 3.$tn.3 { fts3_zero_long_segments t1 $limit } {1} 5164dc3d73dSdan } 517db27fc07Sdan 5182cf1a1deSdan foreach {tn2 expr def} { 5192cf1a1deSdan 1 {a NEAR c} {} 5202cf1a1deSdan 2 {a AND c} c 5212cf1a1deSdan 3 {"a c"} c 5222cf1a1deSdan 4 {"c a"} c 5232cf1a1deSdan 5 {"a c" NEAR/1 g} {} 5242cf1a1deSdan 6 {"a c" NEAR/0 g} {} 5252f779343Sdan } { 526db27fc07Sdan do_fts3query_test 3.$tn.4.$tn2 -deferred $def t1 $expr 5272cf1a1deSdan } 5282cf1a1deSdan} 5292cf1a1deSdan 5302cf1a1deSdan#-------------------------------------------------------------------------- 5312cf1a1deSdan# 5322cf1a1deSdanforeach {tn create} { 5332cf1a1deSdan 1 "fts4(x, y)" 5342cf1a1deSdan 2 "fts4(x, y, order=DESC)" 535db27fc07Sdan 3 "fts4(x, y, order=DESC, prefix=2)" 5362cf1a1deSdan} { 5372cf1a1deSdan 538db27fc07Sdan execsql [subst { 539db27fc07Sdan DROP TABLE t1; 540db27fc07Sdan CREATE VIRTUAL TABLE t1 USING $create; 541db27fc07Sdan INSERT INTO t1 VALUES('one two five four five', ''); 542db27fc07Sdan INSERT INTO t1 VALUES('', 'one two five four five'); 543db27fc07Sdan INSERT INTO t1 VALUES('one two', 'five four five'); 544db27fc07Sdan }] 5452cf1a1deSdan 546db27fc07Sdan do_fts3query_test 4.$tn.1.1 t1 {one AND five} 547db27fc07Sdan do_fts3query_test 4.$tn.1.2 t1 {one NEAR five} 548db27fc07Sdan do_fts3query_test 4.$tn.1.3 t1 {one NEAR/1 five} 549db27fc07Sdan do_fts3query_test 4.$tn.1.4 t1 {one NEAR/2 five} 550db27fc07Sdan do_fts3query_test 4.$tn.1.5 t1 {one NEAR/3 five} 551db27fc07Sdan 552db27fc07Sdan do_test 4.$tn.2 { 553db27fc07Sdan set limit [fts3_make_deferrable t1 five] 554db27fc07Sdan execsql { INSERT INTO t1(t1) VALUES('optimize') } 5554dc3d73dSdan ifcapable fts4_deferred { 556db27fc07Sdan expr {[fts3_zero_long_segments t1 $limit]>0} 5574dc3d73dSdan } else { 5584dc3d73dSdan expr 1 5594dc3d73dSdan } 560db27fc07Sdan } {1} 561db27fc07Sdan 562db27fc07Sdan do_fts3query_test 4.$tn.3.1 -deferred five t1 {one AND five} 563db27fc07Sdan do_fts3query_test 4.$tn.3.2 -deferred five t1 {one NEAR five} 564db27fc07Sdan do_fts3query_test 4.$tn.3.3 -deferred five t1 {one NEAR/1 five} 565db27fc07Sdan do_fts3query_test 4.$tn.3.4 -deferred five t1 {one NEAR/2 five} 566d4d21feaSdan 567db27fc07Sdan do_fts3query_test 4.$tn.3.5 -deferred five t1 {one NEAR/3 five} 568db27fc07Sdan 569db27fc07Sdan do_fts3query_test 4.$tn.4.1 -deferred fi* t1 {on* AND fi*} 570db27fc07Sdan do_fts3query_test 4.$tn.4.2 -deferred fi* t1 {on* NEAR fi*} 571db27fc07Sdan do_fts3query_test 4.$tn.4.3 -deferred fi* t1 {on* NEAR/1 fi*} 572db27fc07Sdan do_fts3query_test 4.$tn.4.4 -deferred fi* t1 {on* NEAR/2 fi*} 573db27fc07Sdan do_fts3query_test 4.$tn.4.5 -deferred fi* t1 {on* NEAR/3 fi*} 57499ebad90Sdan} 57599ebad90Sdan 576376d1e5cSdan#-------------------------------------------------------------------------- 577376d1e5cSdan# The following test cases - fts3auto-5.* - focus on using prefix indexes. 578376d1e5cSdan# 579376d1e5cSdanset chunkconfig [fts3_configure_incr_load 1 1] 580d4d21feaSdanforeach {tn create pending} { 581d4d21feaSdan 1 "fts4(a, b)" 1 582b727d679Sdan 2 "fts4(a, b, order=ASC, prefix=1)" 1 583585db0e2Sdan 3 "fts4(a, b, order=ASC, prefix=\"1,3\")" 0 584585db0e2Sdan 4 "fts4(a, b, order=DESC, prefix=\"2,4\")" 0 585585db0e2Sdan 5 "fts4(a, b, order=DESC, prefix=\"1\")" 0 586585db0e2Sdan 6 "fts4(a, b, order=ASC, prefix=\"1,3\")" 0 587376d1e5cSdan} { 588376d1e5cSdan 589376d1e5cSdan execsql [subst { 590d4d21feaSdan DROP TABLE IF EXISTS t1; 591376d1e5cSdan CREATE VIRTUAL TABLE t1 USING $create; 592376d1e5cSdan }] 593376d1e5cSdan 594d4d21feaSdan if {$pending} {execsql BEGIN} 595d4d21feaSdan 596376d1e5cSdan foreach {a b} { 597376d1e5cSdan "the song of songs which is solomons" 598376d1e5cSdan "let him kiss me with the kisses of his mouth for thy love is better than wine" 599376d1e5cSdan "because of the savour of thy good ointments thy name is as ointment poured forth therefore do the virgins love thee" 600376d1e5cSdan "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" 601376d1e5cSdan "i am black but comely o ye daughters of jerusalem as the tents of kedar as the curtains of solomon" 602376d1e5cSdan "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" 603376d1e5cSdan "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?" 604376d1e5cSdan "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" 605376d1e5cSdan "i have compared thee o my love to a company of horses in pharaohs chariots" 606376d1e5cSdan "thy cheeks are comely with rows of jewels thy neck with chains of gold" 607376d1e5cSdan "we will make thee borders of gold with studs of silver" 608376d1e5cSdan "while the king sitteth at his table my spikenard sendeth forth the smell thereof" 609376d1e5cSdan "a bundle of myrrh is my wellbeloved unto me he shall lie all night betwixt my breasts" 610376d1e5cSdan "my beloved is unto me as a cluster of camphire in the vineyards of en gedi" 611376d1e5cSdan "behold thou art fair my love behold thou art fair thou hast doves eyes" 612376d1e5cSdan "behold thou art fair my beloved yea pleasant also our bed is green" 613376d1e5cSdan "the beams of our house are cedar and our rafters of fir" 614376d1e5cSdan } { 615376d1e5cSdan execsql {INSERT INTO t1(a, b) VALUES($a, $b)} 616376d1e5cSdan } 617376d1e5cSdan 618d4d21feaSdan 619376d1e5cSdan do_fts3query_test 5.$tn.1.1 t1 {s*} 620376d1e5cSdan do_fts3query_test 5.$tn.1.2 t1 {so*} 621376d1e5cSdan do_fts3query_test 5.$tn.1.3 t1 {"s* o*"} 622376d1e5cSdan do_fts3query_test 5.$tn.1.4 t1 {b* NEAR/3 a*} 623d4d21feaSdan do_fts3query_test 5.$tn.1.5 t1 {a*} 624d4d21feaSdan do_fts3query_test 5.$tn.1.6 t1 {th* NEAR/5 a* NEAR/5 w*} 625d4d21feaSdan do_fts3query_test 5.$tn.1.7 t1 {"b* th* art* fair*"} 626d4d21feaSdan 627d4d21feaSdan if {$pending} {execsql COMMIT} 628376d1e5cSdan} 629376d1e5cSdaneval fts3_configure_incr_load $chunkconfig 630376d1e5cSdan 631b727d679Sdanforeach {tn pending create} { 632b727d679Sdan 1 0 "fts4(a, b, c, d)" 633b727d679Sdan 2 1 "fts4(a, b, c, d)" 634b727d679Sdan 3 0 "fts4(a, b, c, d, order=DESC)" 635b727d679Sdan 4 1 "fts4(a, b, c, d, order=DESC)" 636b727d679Sdan} { 637b727d679Sdan execsql [subst { 638b727d679Sdan DROP TABLE IF EXISTS t1; 639b727d679Sdan CREATE VIRTUAL TABLE t1 USING $create; 640b727d679Sdan }] 641b727d679Sdan 642b727d679Sdan 643b727d679Sdan if {$pending} { execsql BEGIN } 644b727d679Sdan 645b727d679Sdan foreach {a b c d} { 646b727d679Sdan "A B C" "D E F" "G H I" "J K L" 647b727d679Sdan "B C D" "E F G" "H I J" "K L A" 648b727d679Sdan "C D E" "F G H" "I J K" "L A B" 649b727d679Sdan "D E F" "G H I" "J K L" "A B C" 650b727d679Sdan "E F G" "H I J" "K L A" "B C D" 651b727d679Sdan "F G H" "I J K" "L A B" "C D E" 652b727d679Sdan } { 653b727d679Sdan execsql { INSERT INTO t1 VALUES($a, $b, $c, $d) } 654b727d679Sdan } 655b727d679Sdan 656b727d679Sdan do_fts3query_test 6.$tn.1 t1 {b:G} 657b727d679Sdan do_fts3query_test 6.$tn.2 t1 {b:G AND c:I} 658b727d679Sdan do_fts3query_test 6.$tn.3 t1 {b:G NEAR c:I} 659b727d679Sdan do_fts3query_test 6.$tn.4 t1 {a:C OR b:G OR c:K OR d:C} 6605cfed52dSdan 661b727d679Sdan do_fts3query_test 6.$tn.5 t1 {a:G OR b:G} 662b727d679Sdan 663b727d679Sdan catchsql { COMMIT } 664b727d679Sdan} 665b727d679Sdan 666da7b4561Sdanforeach {tn create} { 667da7b4561Sdan 1 "fts4(x)" 668da7b4561Sdan 2 "fts4(x, order=DESC)" 669da7b4561Sdan} { 670da7b4561Sdan execsql [subst { 671da7b4561Sdan DROP TABLE IF EXISTS t1; 672da7b4561Sdan CREATE VIRTUAL TABLE t1 USING $create; 673da7b4561Sdan }] 674da7b4561Sdan 675da7b4561Sdan foreach {x} { 676da7b4561Sdan "F E N O T K X V A X I E X A P G Q V H U" 677da7b4561Sdan "R V A E T C V Q N I E L O N U G J K L U" 678da7b4561Sdan "U Y I G W M V F J L X I D C H F P J Q B" 679da7b4561Sdan "S G D Z X R P G S S Y B K A S G A I L L" 680da7b4561Sdan "L S I C H T Z S R Q P R N K J X L F M J" 681da7b4561Sdan "C C C D P X B Z C M A D A C X S B T X V" 682da7b4561Sdan "W Y J M D R G V R K B X S A W R I T N C" 683da7b4561Sdan "P K L W T M S P O Y Y V V O E H Q A I R" 684da7b4561Sdan "C D Y I C Z F H J C O Y A Q F L S B D K" 685da7b4561Sdan "P G S C Y C Y V I M B D S Z D D Y W I E" 686da7b4561Sdan "Z K Z U E E S F Y X T U A L W O U J C Q" 687da7b4561Sdan "P A T Z S W L P L Q V Y Y I P W U X S S" 688da7b4561Sdan "I U I H U O F Z F R H R F T N D X A G M" 689da7b4561Sdan "N A B M S H K X S O Y D T X S B R Y H Z" 690da7b4561Sdan "L U D A S K I L S V Z J P U B E B Y H M" 691da7b4561Sdan } { 692da7b4561Sdan execsql { INSERT INTO t1 VALUES($x) } 693da7b4561Sdan } 694da7b4561Sdan 695da7b4561Sdan # Add extra documents to the database such that token "B" will be considered 696da7b4561Sdan # deferrable if considering the other tokens means that 2 or fewer documents 697da7b4561Sdan # will be loaded into memory. 698da7b4561Sdan # 699da7b4561Sdan fts3_make_deferrable t1 B 2 700da7b4561Sdan 701da7b4561Sdan # B is not deferred in either of the first two tests below, since filtering 702da7b4561Sdan # on "M" or "D" returns 10 documents or so. But filtering on "M * D" only 703da7b4561Sdan # returns 2, so B is deferred in this case. 704da7b4561Sdan # 705da7b4561Sdan do_fts3query_test 7.$tn.1 t1 {"M B"} 706da7b4561Sdan do_fts3query_test 7.$tn.2 t1 {"B D"} 707da7b4561Sdan do_fts3query_test 7.$tn.3 -deferred B t1 {"M B D"} 708da7b4561Sdan} 709da7b4561Sdan 7103fd65192Sdanset sqlite_fts3_enable_parentheses $sfep 71199ebad90Sdanfinish_test 712