000001  # 2010 January 07
000002  #
000003  # The author disclaims copyright to this source code.  In place of
000004  # a legal notice, here is a blessing:
000005  #
000006  #    May you do good and not evil.
000007  #    May you find forgiveness for yourself and forgive others.
000008  #    May you share freely, never taking more than you give.
000009  #
000010  #*************************************************************************
000011  #
000012  # The tests in this file test the FTS3 auxillary functions offsets(), 
000013  # snippet() and matchinfo() work. At time of writing, running this file 
000014  # provides full coverage of fts3_snippet.c.
000015  #
000016  
000017  set testdir [file dirname $argv0]
000018  source $testdir/tester.tcl
000019  set testprefix fts3snippet
000020  
000021  # If SQLITE_ENABLE_FTS3 is not defined, omit this file.
000022  ifcapable !fts3 { finish_test ; return }
000023  source $testdir/fts3_common.tcl
000024  
000025  set sqlite_fts3_enable_parentheses 1
000026  set DO_MALLOC_TEST 0
000027  
000028  # Transform the list $L to its "normal" form. So that it can be compared to
000029  # another list with the same set of elements using [string compare].
000030  #
000031  proc normalize {L} {
000032    set ret [list]
000033    foreach l $L {lappend ret $l}
000034    return $ret
000035  }
000036  
000037  proc do_offsets_test {name expr args} {
000038    set result [list]
000039    foreach a $args {
000040      lappend result [normalize $a]
000041    }
000042    do_select_test $name {
000043      SELECT offsets(ft) FROM ft WHERE ft MATCH $expr
000044    } $result
000045  }
000046    
000047  # Document text used by a few tests. Contains the English names of all
000048  # integers between 1 and 300.
000049  #
000050  set numbers [normalize {
000051    one two three four five six seven eight nine ten eleven twelve thirteen
000052    fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone
000053    twentytwo twentythree twentyfour twentyfive twentysix twentyseven
000054    twentyeight twentynine thirty thirtyone thirtytwo thirtythree thirtyfour
000055    thirtyfive thirtysix thirtyseven thirtyeight thirtynine forty fortyone
000056    fortytwo fortythree fortyfour fortyfive fortysix fortyseven fortyeight
000057    fortynine fifty fiftyone fiftytwo fiftythree fiftyfour fiftyfive fiftysix
000058    fiftyseven fiftyeight fiftynine sixty sixtyone sixtytwo sixtythree sixtyfour
000059    sixtyfive sixtysix sixtyseven sixtyeight sixtynine seventy seventyone
000060    seventytwo seventythree seventyfour seventyfive seventysix seventyseven
000061    seventyeight seventynine eighty eightyone eightytwo eightythree eightyfour
000062    eightyfive eightysix eightyseven eightyeight eightynine ninety ninetyone
000063    ninetytwo ninetythree ninetyfour ninetyfive ninetysix ninetyseven
000064    ninetyeight ninetynine onehundred onehundredone onehundredtwo
000065    onehundredthree onehundredfour onehundredfive onehundredsix onehundredseven
000066    onehundredeight onehundrednine onehundredten onehundredeleven
000067    onehundredtwelve onehundredthirteen onehundredfourteen onehundredfifteen
000068    onehundredsixteen onehundredseventeen onehundredeighteen onehundrednineteen
000069    onehundredtwenty onehundredtwentyone onehundredtwentytwo
000070    onehundredtwentythree onehundredtwentyfour onehundredtwentyfive
000071    onehundredtwentysix onehundredtwentyseven onehundredtwentyeight
000072    onehundredtwentynine onehundredthirty onehundredthirtyone
000073    onehundredthirtytwo onehundredthirtythree onehundredthirtyfour
000074    onehundredthirtyfive onehundredthirtysix onehundredthirtyseven
000075    onehundredthirtyeight onehundredthirtynine onehundredforty
000076    onehundredfortyone onehundredfortytwo onehundredfortythree
000077    onehundredfortyfour onehundredfortyfive onehundredfortysix
000078    onehundredfortyseven onehundredfortyeight onehundredfortynine
000079    onehundredfifty onehundredfiftyone onehundredfiftytwo onehundredfiftythree
000080    onehundredfiftyfour onehundredfiftyfive onehundredfiftysix
000081    onehundredfiftyseven onehundredfiftyeight onehundredfiftynine
000082    onehundredsixty onehundredsixtyone onehundredsixtytwo onehundredsixtythree
000083    onehundredsixtyfour onehundredsixtyfive onehundredsixtysix
000084    onehundredsixtyseven onehundredsixtyeight onehundredsixtynine
000085    onehundredseventy onehundredseventyone onehundredseventytwo
000086    onehundredseventythree onehundredseventyfour onehundredseventyfive
000087    onehundredseventysix onehundredseventyseven onehundredseventyeight
000088    onehundredseventynine onehundredeighty onehundredeightyone
000089    onehundredeightytwo onehundredeightythree onehundredeightyfour
000090    onehundredeightyfive onehundredeightysix onehundredeightyseven
000091    onehundredeightyeight onehundredeightynine onehundredninety
000092    onehundredninetyone onehundredninetytwo onehundredninetythree
000093    onehundredninetyfour onehundredninetyfive onehundredninetysix
000094    onehundredninetyseven onehundredninetyeight onehundredninetynine twohundred
000095    twohundredone twohundredtwo twohundredthree twohundredfour twohundredfive
000096    twohundredsix twohundredseven twohundredeight twohundrednine twohundredten
000097    twohundredeleven twohundredtwelve twohundredthirteen twohundredfourteen
000098    twohundredfifteen twohundredsixteen twohundredseventeen twohundredeighteen
000099    twohundrednineteen twohundredtwenty twohundredtwentyone twohundredtwentytwo
000100    twohundredtwentythree twohundredtwentyfour twohundredtwentyfive
000101    twohundredtwentysix twohundredtwentyseven twohundredtwentyeight
000102    twohundredtwentynine twohundredthirty twohundredthirtyone
000103    twohundredthirtytwo twohundredthirtythree twohundredthirtyfour
000104    twohundredthirtyfive twohundredthirtysix twohundredthirtyseven
000105    twohundredthirtyeight twohundredthirtynine twohundredforty
000106    twohundredfortyone twohundredfortytwo twohundredfortythree
000107    twohundredfortyfour twohundredfortyfive twohundredfortysix
000108    twohundredfortyseven twohundredfortyeight twohundredfortynine
000109    twohundredfifty twohundredfiftyone twohundredfiftytwo twohundredfiftythree
000110    twohundredfiftyfour twohundredfiftyfive twohundredfiftysix
000111    twohundredfiftyseven twohundredfiftyeight twohundredfiftynine
000112    twohundredsixty twohundredsixtyone twohundredsixtytwo twohundredsixtythree
000113    twohundredsixtyfour twohundredsixtyfive twohundredsixtysix
000114    twohundredsixtyseven twohundredsixtyeight twohundredsixtynine
000115    twohundredseventy twohundredseventyone twohundredseventytwo
000116    twohundredseventythree twohundredseventyfour twohundredseventyfive
000117    twohundredseventysix twohundredseventyseven twohundredseventyeight
000118    twohundredseventynine twohundredeighty twohundredeightyone
000119    twohundredeightytwo twohundredeightythree twohundredeightyfour
000120    twohundredeightyfive twohundredeightysix twohundredeightyseven
000121    twohundredeightyeight twohundredeightynine twohundredninety
000122    twohundredninetyone twohundredninetytwo twohundredninetythree
000123    twohundredninetyfour twohundredninetyfive twohundredninetysix
000124    twohundredninetyseven twohundredninetyeight twohundredninetynine
000125    threehundred
000126  }]
000127  
000128  foreach {DO_MALLOC_TEST enc} {
000129    0 utf8
000130    1 utf8
000131    1 utf16
000132  } {
000133  
000134    db close
000135    forcedelete test.db
000136    sqlite3 db test.db
000137    sqlite3_db_config_lookaside db 0 0 0
000138    db eval "PRAGMA encoding = \"$enc\""
000139  
000140    # Set variable $T to the test name prefix for this iteration of the loop.
000141    #
000142    set T "fts3snippet-1.$enc"
000143  
000144    ##########################################################################
000145    # Test the offset function.
000146    #
000147    do_test $T.1.1 {
000148      execsql {
000149        CREATE VIRTUAL TABLE ft USING fts3;
000150        INSERT INTO ft VALUES('xxx xxx xxx xxx');
000151      }
000152    } {}
000153    do_offsets_test $T.1.2 {xxx} {0 0 0 3 0 0 4 3 0 0 8 3 0 0 12 3}
000154    do_offsets_test $T.1.3 {"xxx xxx"} {
000155        0 0  0 3     0 0  4 3     0 1  4 3     0 0  8 3 
000156        0 1  8 3     0 1 12 3
000157    }
000158    do_offsets_test $T.1.4 {"xxx xxx" xxx} {
000159        0 0  0 3     0 2  0 3     0 0  4 3     0 1  4 3 
000160        0 2  4 3     0 0  8 3     0 1  8 3     0 2  8 3 
000161        0 1 12 3     0 2 12 3
000162    }
000163    do_offsets_test $T.1.5 {xxx "xxx xxx"} {
000164        0 0  0 3     0 1  0 3     0 0  4 3     0 1  4 3 
000165        0 2  4 3     0 0  8 3     0 1  8 3     0 2  8 3 
000166        0 0 12 3     0 2 12 3
000167    }
000168  
000169    do_test $T.2.1 {
000170      set v1 [lrange $numbers 0 99]
000171      execsql {
000172        DROP TABLE IF EXISTS ft;
000173        CREATE VIRTUAL TABLE ft USING fts3(a, b);
000174        INSERT INTO ft VALUES($v1, $numbers);
000175        INSERT INTO ft VALUES($v1, NULL);
000176      }
000177    } {}
000178  
000179    set off [string first "twohundred " $numbers]
000180    do_offsets_test $T.2.1 {twohundred} [list 1 0 $off 10]
000181  
000182    set off [string first "onehundred " $numbers]
000183    do_offsets_test $T.2.2 {onehundred} \
000184      [list 0 0 $off 10 1 0 $off 10] [list 0 0 $off 10]
000185  
000186    # Test a corruption case:
000187    sqlite3_db_config db DEFENSIVE 0
000188    execsql { UPDATE ft_content SET c1b = 'hello world' WHERE c1b = $numbers }
000189    do_error_test $T.2.3 {
000190      SELECT offsets(ft) FROM ft WHERE ft MATCH 'onehundred'
000191    } {database disk image is malformed}
000192    
000193    ##########################################################################
000194    # Test the snippet function.
000195    #
000196    proc do_snippet_test {name expr iCol nTok args} {
000197      set res [list]
000198      foreach a $args { lappend res [string trim $a] }
000199      do_select_test $name {
000200        SELECT snippet(ft,'{','}','...',$iCol,$nTok) FROM ft WHERE ft MATCH $expr
000201      } $res
000202    }
000203    do_test $T.3.1 {
000204      execsql {
000205        DROP TABLE IF EXISTS ft;
000206        CREATE VIRTUAL TABLE ft USING fts3;
000207        INSERT INTO ft VALUES('one two three four five six seven eight nine ten');
000208      }
000209    } {}
000210    do_snippet_test $T.3.2  one    0 5 "{one} two three four five..."
000211    do_snippet_test $T.3.3  two    0 5 "one {two} three four five..."
000212    do_snippet_test $T.3.4  three  0 5 "one two {three} four five..."
000213    do_snippet_test $T.3.5  four   0 5 "...two three {four} five six..."
000214    do_snippet_test $T.3.6  five   0 5 "...three four {five} six seven..."
000215    do_snippet_test $T.3.7  six    0 5 "...four five {six} seven eight..."
000216    do_snippet_test $T.3.8  seven  0 5 "...five six {seven} eight nine..."
000217    do_snippet_test $T.3.9  eight  0 5 "...six seven {eight} nine ten"
000218    do_snippet_test $T.3.10 nine   0 5 "...six seven eight {nine} ten"
000219    do_snippet_test $T.3.11 ten    0 5 "...six seven eight nine {ten}"
000220    
000221    do_test $T.4.1 {
000222      execsql {
000223        INSERT INTO ft VALUES(
000224             'one two three four five '
000225          || 'six seven eight nine ten '
000226          || 'eleven twelve thirteen fourteen fifteen '
000227          || 'sixteen seventeen eighteen nineteen twenty '
000228          || 'one two three four five '
000229          || 'six seven eight nine ten '
000230          || 'eleven twelve thirteen fourteen fifteen '
000231          || 'sixteen seventeen eighteen nineteen twenty'
000232        );
000233      }
000234    } {}
000235    
000236    do_snippet_test $T.4.2 {one nine} 0 5 {
000237       {one} two three...eight {nine} ten
000238    } {
000239       {one} two three...eight {nine} ten...
000240    }
000241    
000242    do_snippet_test $T.4.3 {one nine} 0 -5 {
000243       {one} two three four five...six seven eight {nine} ten
000244    } {
000245       {one} two three four five...seven eight {nine} ten eleven...
000246    }
000247    do_snippet_test $T.4.3 {one nineteen} 0 -5 {
000248       ...eighteen {nineteen} twenty {one} two...
000249    }
000250    do_snippet_test $T.4.4 {two nineteen} 0 -5 {
000251       ...eighteen {nineteen} twenty one {two}...
000252    }
000253    do_snippet_test $T.4.5 {three nineteen} 0 -5 {
000254       ...{nineteen} twenty one two {three}...
000255    }
000256    
000257    do_snippet_test $T.4.6 {four nineteen} 0 -5 {
000258       ...two three {four} five six...seventeen eighteen {nineteen} twenty one...
000259    }
000260    do_snippet_test $T.4.7 {four NEAR nineteen} 0 -5 {
000261       ...seventeen eighteen {nineteen} twenty one...two three {four} five six...
000262    }
000263    
000264    do_snippet_test $T.4.8 {four nineteen} 0 5 {
000265       ...three {four} five...eighteen {nineteen} twenty...
000266    }
000267    do_snippet_test $T.4.9 {four NEAR nineteen} 0 5 {
000268       ...eighteen {nineteen} twenty...three {four} five...
000269    }
000270    do_snippet_test $T.4.10 {four NEAR nineteen} 0 -5 {
000271       ...seventeen eighteen {nineteen} twenty one...two three {four} five six...
000272    }
000273    do_snippet_test $T.4.11 {four NOT (nineteen twentyone)} 0 5 {
000274       ...two three {four} five six...
000275    } {
000276       ...two three {four} five six...
000277    }
000278    do_snippet_test $T.4.12 {four OR nineteen NEAR twentyone} 0 5 {
000279       ...two three {four} five six...
000280    } {
000281       ...two three {four} five six...
000282    }
000283    
000284    do_test $T.5.1 {
000285      execsql {
000286        DROP TABLE IF EXISTS ft;
000287        CREATE VIRTUAL TABLE ft USING fts3(a, b, c);
000288        INSERT INTO ft VALUES(
000289          'one two three four five', 
000290          'four five six seven eight', 
000291          'seven eight nine ten eleven'
000292        );
000293      }
000294    } {}
000295    
000296    do_snippet_test $T.5.2 {five} -1 3 {...three four {five}}
000297    do_snippet_test $T.5.3 {five}  0 3 {...three four {five}}
000298    do_snippet_test $T.5.4 {five}  1 3 {four {five} six...}
000299    do_snippet_test $T.5.5 {five}  2 3 {seven eight nine...}
000300    
000301    do_test $T.5.6 {
000302      execsql { UPDATE ft SET b = NULL }
000303    } {}
000304    
000305    do_snippet_test $T.5.7  {five} -1 3 {...three four {five}}
000306    do_snippet_test $T.5.8  {five}  0 3 {...three four {five}}
000307    do_snippet_test $T.5.9  {five}  1 3 {}
000308    do_snippet_test $T.5.10 {five}  2 3 {seven eight nine...}
000309    
000310    do_snippet_test $T.5.11 {one "seven eight nine"} -1 -3 {
000311      {one} two three...{seven} {eight} {nine}...
000312    }
000313  
000314    do_test $T.6.1 {
000315      execsql {
000316        DROP TABLE IF EXISTS ft;
000317        CREATE VIRTUAL TABLE ft USING fts3(x);
000318        INSERT INTO ft VALUES($numbers);
000319      }
000320    } {}
000321    do_snippet_test $T.6.2 {
000322      one fifty onehundred onehundredfifty twohundredfifty threehundred
000323    } -1 4 {
000324      {one}...{fifty}...{onehundred}...{onehundredfifty}...
000325    }
000326    do_snippet_test $T.6.3 {
000327      one fifty onehundred onehundredfifty twohundredfifty threehundred
000328    } -1 -4 {
000329      {one} two three four...fortyeight fortynine {fifty} fiftyone...ninetyeight ninetynine {onehundred} onehundredone...onehundredfortyeight onehundredfortynine {onehundredfifty} onehundredfiftyone...
000330    }
000331  
000332    do_test $T.7.1 {
000333      execsql {
000334        BEGIN;
000335          DROP TABLE IF EXISTS ft;
000336          CREATE VIRTUAL TABLE ft USING fts3(x);
000337      }
000338      set testresults [list]
000339      for {set i 1} {$i < 150} {incr i} {
000340        set commas [string repeat , $i]
000341        execsql {INSERT INTO ft VALUES('one' || $commas || 'two')}
000342        lappend testresults "{one}$commas{two}"
000343      }
000344      execsql COMMIT
000345    } {}
000346    eval [list do_snippet_test $T.7.2 {one two} -1 3] $testresults
000347    
000348    ##########################################################################
000349    # Test the matchinfo function.
000350    #
000351    proc mit {blob} {
000352      set scan(littleEndian) i*
000353      set scan(bigEndian) I*
000354      binary scan $blob $scan($::tcl_platform(byteOrder)) r
000355      return $r
000356    }
000357    db func mit mit
000358    proc do_matchinfo_test {name expr args} {
000359      set res [list]
000360      foreach a $args { lappend res [normalize $a] }
000361      do_select_test $name {
000362        SELECT mit(matchinfo(ft)) FROM ft WHERE ft MATCH $expr
000363      } $res
000364    }
000365    do_test $T.8.1 {
000366      set ten {one two three four five six seven eight nine ten}
000367      execsql {
000368        DROP TABLE IF EXISTS ft;
000369        CREATE VIRTUAL TABLE ft USING fts3;
000370        INSERT INTO ft VALUES($ten);
000371        INSERT INTO ft VALUES($ten || ' ' || $ten);
000372      }
000373    } {}
000374    
000375    do_matchinfo_test $T.8.2 "one" {1 1  1 3 2} {1 1  2 3 2}
000376    do_matchinfo_test $T.8.3 "one NEAR/3 ten" {2 1  1 1 1 1 1 1}
000377    do_matchinfo_test $T.8.4 "five NEAR/4 ten" \
000378      {2 1  1 3 2  1 3 2} {2 1  2 3 2  2 3 2}
000379    do_matchinfo_test $T.8.5 "six NEAR/3 ten NEAR/3 two" \
000380      {3 1  1 1 1  1 1 1  1 1 1}
000381    do_matchinfo_test $T.8.6 "five NEAR/4 ten NEAR/3 two" \
000382      {3 1  2 2 1  1 1 1  1 1 1}
000383  
000384    do_test $T.9.1 {
000385      execsql {
000386        DROP TABLE IF EXISTS ft;
000387        CREATE VIRTUAL TABLE ft USING fts3(x, y);
000388      }
000389      foreach n {1 2 3} {
000390        set v1 [lrange $numbers 0 [expr $n*100]]
000391        set v2 [string trim [string repeat "$numbers " $n]]
000392        set docid [expr $n * 1000000]
000393        execsql { INSERT INTO ft(docid, x, y) VALUES($docid, $v1, $v2) }
000394      }
000395    } {}
000396    do_matchinfo_test $T.9.2 {two*}     \
000397      { 1 2    1   105 3   101 606 3}   \
000398      { 1 2    3   105 3   202 606 3}   \
000399      { 1 2    101 105 3   303 606 3}
000400  
000401    do_matchinfo_test $T.9.4 {"one* two*"}  \
000402      { 1 2    1 5 3   2 12 3}              \
000403      { 1 2    2 5 3   4 12 3}              \
000404      { 1 2    2 5 3   6 12 3}
000405  
000406    do_matchinfo_test $T.9.5 {twohundredfifty}  \
000407      { 1 2    0 1 1   1 6 3}                   \
000408      { 1 2    0 1 1   2 6 3}                   \
000409      { 1 2    1 1 1   3 6 3}
000410  
000411    do_matchinfo_test $T.9.6 {"threehundred one"} \
000412      { 1 2    0 0 0   1 3 2}                     \
000413      { 1 2    0 0 0   2 3 2}
000414  
000415    do_matchinfo_test $T.9.7 {one OR fivehundred} \
000416      { 2 2    1 3 3   1 6 3   0 0 0   0 0 0 }    \
000417      { 2 2    1 3 3   2 6 3   0 0 0   0 0 0 }    \
000418      { 2 2    1 3 3   3 6 3   0 0 0   0 0 0 }
000419  
000420    do_matchinfo_test $T.9.8 {two OR "threehundred one"} \
000421      { 2 2    1 3 3   1 6 3   0 0 0   0 3 2 }           \
000422      { 2 2    1 3 3   2 6 3   0 0 0   1 3 2 }           \
000423      { 2 2    1 3 3   3 6 3   0 0 0   2 3 2 }
000424  
000425    do_select_test $T.9.9 {
000426      SELECT mit(matchinfo(ft)), mit(matchinfo(ft))
000427      FROM ft WHERE ft MATCH 'two OR "threehundred one"' 
000428    } [normalize {
000429      {2 2 1 3 3 1 6 3 0 0 0 0 3 2}
000430      {2 2 1 3 3 1 6 3 0 0 0 0 3 2}
000431      {2 2 1 3 3 2 6 3 0 0 0 1 3 2}
000432      {2 2 1 3 3 2 6 3 0 0 0 1 3 2}
000433      {2 2 1 3 3 3 6 3 0 0 0 2 3 2}          
000434      {2 2 1 3 3 3 6 3 0 0 0 2 3 2}
000435    }]
000436  
000437    # EVIDENCE-OF: R-40630-02268 If used within a SELECT that uses the
000438    # "query by rowid" or "linear scan" strategies, then the snippet and
000439    # offsets both return an empty string, and the matchinfo function
000440    # returns a blob value zero bytes in size.
000441    #
000442    set r 1000000                   ;# A rowid that exists in table ft
000443    do_select_test $T.10.0 { SELECT rowid FROM ft WHERE rowid = $r } $r
000444    do_select_test $T.10.1 {
000445      SELECT length(offsets(ft)), typeof(offsets(ft)) FROM ft;
000446    } {0 text 0 text 0 text}
000447    do_select_test $T.10.2 {
000448      SELECT length(offsets(ft)), typeof(offsets(ft)) FROM ft WHERE rowid = $r
000449    } {0 text}
000450    do_select_test $T.10.3 {
000451      SELECT length(snippet(ft)), typeof(snippet(ft)) FROM ft;
000452    } {0 text 0 text 0 text}
000453    do_select_test $T.10.4 {
000454      SELECT length(snippet(ft)), typeof(snippet(ft)) FROM ft WHERE rowid = $r;
000455    } {0 text}
000456    do_select_test $T.10.5 {
000457      SELECT length(matchinfo(ft)), typeof(matchinfo(ft)) FROM ft;
000458    } {0 blob 0 blob 0 blob}
000459    do_select_test $T.10.6 {
000460      SELECT length(matchinfo(ft)), typeof(matchinfo(ft)) FROM ft WHERE rowid = $r
000461    } {0 blob}
000462  }
000463  
000464  #-------------------------------------------------------------------------
000465  # Test an interaction between the snippet() function and OR clauses.
000466  #
000467  do_execsql_test 2.1 {
000468    CREATE VIRTUAL TABLE t2 USING fts4;
000469    INSERT INTO t2 VALUES('one two three four five');
000470    INSERT INTO t2 VALUES('two three four five one');
000471    INSERT INTO t2 VALUES('three four five one two');
000472    INSERT INTO t2 VALUES('four five one two three');
000473    INSERT INTO t2 VALUES('five one two three four');
000474  }
000475  
000476  do_execsql_test 2.2 {
000477    SELECT snippet(t2, '[', ']') FROM t2 WHERE t2 MATCH 'one OR (four AND six)'
000478  } {
000479    {[one] two three [four] five}
000480    {two three [four] five [one]}
000481    {three [four] five [one] two}
000482    {[four] five [one] two three}
000483    {five [one] two three [four]}
000484  }
000485  
000486  do_execsql_test 2.3 {
000487    SELECT snippet(t2, '[', ']') FROM t2 
000488    WHERE t2 MATCH 'one OR (four AND six)' 
000489    ORDER BY docid DESC
000490  } {
000491    {five [one] two three [four]}
000492    {[four] five [one] two three}
000493    {three [four] five [one] two}
000494    {two three [four] five [one]}
000495    {[one] two three [four] five}
000496  }
000497  
000498  do_execsql_test 2.4 {
000499    INSERT INTO t2 VALUES('six');
000500  }
000501  
000502  do_execsql_test 2.5 {
000503    SELECT snippet(t2, '[', ']') FROM t2 WHERE t2 MATCH 'one OR (four AND six)'
000504  } {
000505    {[one] two three [four] five}
000506    {two three [four] five [one]}
000507    {three [four] five [one] two}
000508    {[four] five [one] two three}
000509    {five [one] two three [four]}
000510  }
000511  
000512  do_execsql_test 2.6 {
000513    SELECT snippet(t2, '[', ']') FROM t2 
000514    WHERE t2 MATCH 'one OR (four AND six)' 
000515    ORDER BY docid DESC
000516  } {
000517    {five [one] two three [four]}
000518    {[four] five [one] two three}
000519    {three [four] five [one] two}
000520    {two three [four] five [one]}
000521    {[one] two three [four] five}
000522  }
000523  
000524  #-------------------------------------------------------------------------
000525  do_execsql_test 3 {
000526    CREATE VIRTUAL TABLE t3 USING fts4;
000527    INSERT INTO t3 VALUES('[one two three]');
000528  }
000529  do_execsql_test 3.1 {
000530    SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'one';
000531  } {{[<b>one</b> two three]}}
000532  do_execsql_test 3.2 {
000533    SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'two';
000534  } {{[one <b>two</b> three]}}
000535  do_execsql_test 3.3 {
000536    SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'three';
000537  } {{[one two <b>three</b>]}}
000538  do_execsql_test 3.4 {
000539    SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'one OR two OR three';
000540  } {{[<b>one</b> <b>two</b> <b>three</b>]}}
000541  
000542  #-------------------------------------------------------------------------
000543  # Request a snippet 0 tokens in size. This is always an empty string.
000544  do_execsql_test 4.1 {
000545    CREATE VIRTUAL TABLE t4 USING fts4;
000546    INSERT INTO t4 VALUES('a b c d');
000547    SELECT snippet(t4, '[', ']', '...', 0, 0) FROM t4 WHERE t4 MATCH 'b';
000548  } {{}}
000549  
000550  do_test 4.2 {
000551    set x35 [string trim [string repeat "x " 35]]
000552    execsql "INSERT INTO t4 VALUES('$x35 E $x35 F $x35 G $x35');"
000553    llength [db one {
000554      SELECT snippet(t4, '', '', '', 0, 64) FROM t4 WHERE t4 MATCH 'E'
000555    }]
000556  } {64}
000557  
000558  do_test 4.3 {
000559    llength [db one {
000560      SELECT snippet(t4, '', '', '', 0, 150) FROM t4 WHERE t4 MATCH 'E'
000561    }]
000562  } {64}
000563  
000564  #-------------------------------------------------------------------------
000565  # Request a snippet from a query with more than 64 phrases.
000566  #
000567  do_execsql_test 5.0 {
000568    CREATE VIRTUAL TABLE t5 USING fts3(x);
000569    INSERT INTO t5 VALUES('a1 a2 a3');
000570    INSERT INTO t5 VALUES('a4 a5 a6');
000571    INSERT INTO t5 VALUES('a70 a71 a72');
000572  }
000573  
000574  do_execsql_test 5.1 {
000575    SELECT snippet(t5, '[', ']') FROM t5 WHERE t5 MATCH 
000576    'a1 OR a2 OR a3 OR a4 OR a5 OR a6 OR a7 OR a8 OR a9 OR a10 OR ' ||
000577    'a11 OR a12 OR a13 OR a14 OR a15 OR a16 OR a17 OR a18 OR a19 OR a10 OR ' ||
000578    'a21 OR a22 OR a23 OR a24 OR a25 OR a26 OR a27 OR a28 OR a29 OR a20 OR ' ||
000579    'a31 OR a32 OR a33 OR a34 OR a35 OR a36 OR a37 OR a38 OR a39 OR a30 OR ' ||
000580    'a41 OR a42 OR a43 OR a44 OR a45 OR a46 OR a47 OR a48 OR a49 OR a40 OR ' ||
000581    'a51 OR a52 OR a53 OR a54 OR a55 OR a56 OR a57 OR a58 OR a59 OR a50 OR ' ||
000582    'a61 OR a62 OR a63 OR a64 OR a65 OR a66 OR a67 OR a68 OR a69 OR a60 OR ' ||
000583    'a71 OR a72 OR a73 OR a74 OR a75 OR a76 OR a77 OR a78 OR a79 OR a70'
000584  } {
000585    {[a1] [a2] [a3]}
000586    {[a4] [a5] [a6]}
000587    {[a70] [a71] [a72]}
000588  }
000589  
000590  do_execsql_test 5.2 {
000591    SELECT snippet(t5, '[', ']', -1, 0) FROM t5 WHERE t5 MATCH 'a5'
000592  } {{a4 [a5] a6}}
000593  
000594  set sqlite_fts3_enable_parentheses 0
000595  finish_test