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    execsql { UPDATE ft_content SET c1b = 'hello world' WHERE c1b = $numbers }
000188    do_error_test $T.2.3 {
000189      SELECT offsets(ft) FROM ft WHERE ft MATCH 'onehundred'
000190    } {database disk image is malformed}
000191    
000192    ##########################################################################
000193    # Test the snippet function.
000194    #
000195    proc do_snippet_test {name expr iCol nTok args} {
000196      set res [list]
000197      foreach a $args { lappend res [string trim $a] }
000198      do_select_test $name {
000199        SELECT snippet(ft,'{','}','...',$iCol,$nTok) FROM ft WHERE ft MATCH $expr
000200      } $res
000201    }
000202    do_test $T.3.1 {
000203      execsql {
000204        DROP TABLE IF EXISTS ft;
000205        CREATE VIRTUAL TABLE ft USING fts3;
000206        INSERT INTO ft VALUES('one two three four five six seven eight nine ten');
000207      }
000208    } {}
000209    do_snippet_test $T.3.2  one    0 5 "{one} two three four five..."
000210    do_snippet_test $T.3.3  two    0 5 "one {two} three four five..."
000211    do_snippet_test $T.3.4  three  0 5 "one two {three} four five..."
000212    do_snippet_test $T.3.5  four   0 5 "...two three {four} five six..."
000213    do_snippet_test $T.3.6  five   0 5 "...three four {five} six seven..."
000214    do_snippet_test $T.3.7  six    0 5 "...four five {six} seven eight..."
000215    do_snippet_test $T.3.8  seven  0 5 "...five six {seven} eight nine..."
000216    do_snippet_test $T.3.9  eight  0 5 "...six seven {eight} nine ten"
000217    do_snippet_test $T.3.10 nine   0 5 "...six seven eight {nine} ten"
000218    do_snippet_test $T.3.11 ten    0 5 "...six seven eight nine {ten}"
000219    
000220    do_test $T.4.1 {
000221      execsql {
000222        INSERT INTO ft VALUES(
000223             'one two three four five '
000224          || 'six seven eight nine ten '
000225          || 'eleven twelve thirteen fourteen fifteen '
000226          || 'sixteen seventeen eighteen nineteen twenty '
000227          || 'one two three four five '
000228          || 'six seven eight nine ten '
000229          || 'eleven twelve thirteen fourteen fifteen '
000230          || 'sixteen seventeen eighteen nineteen twenty'
000231        );
000232      }
000233    } {}
000234    
000235    do_snippet_test $T.4.2 {one nine} 0 5 {
000236       {one} two three...eight {nine} ten
000237    } {
000238       {one} two three...eight {nine} ten...
000239    }
000240    
000241    do_snippet_test $T.4.3 {one nine} 0 -5 {
000242       {one} two three four five...six seven eight {nine} ten
000243    } {
000244       {one} two three four five...seven eight {nine} ten eleven...
000245    }
000246    do_snippet_test $T.4.3 {one nineteen} 0 -5 {
000247       ...eighteen {nineteen} twenty {one} two...
000248    }
000249    do_snippet_test $T.4.4 {two nineteen} 0 -5 {
000250       ...eighteen {nineteen} twenty one {two}...
000251    }
000252    do_snippet_test $T.4.5 {three nineteen} 0 -5 {
000253       ...{nineteen} twenty one two {three}...
000254    }
000255    
000256    do_snippet_test $T.4.6 {four nineteen} 0 -5 {
000257       ...two three {four} five six...seventeen eighteen {nineteen} twenty one...
000258    }
000259    do_snippet_test $T.4.7 {four NEAR nineteen} 0 -5 {
000260       ...seventeen eighteen {nineteen} twenty one...two three {four} five six...
000261    }
000262    
000263    do_snippet_test $T.4.8 {four nineteen} 0 5 {
000264       ...three {four} five...eighteen {nineteen} twenty...
000265    }
000266    do_snippet_test $T.4.9 {four NEAR nineteen} 0 5 {
000267       ...eighteen {nineteen} twenty...three {four} five...
000268    }
000269    do_snippet_test $T.4.10 {four NEAR nineteen} 0 -5 {
000270       ...seventeen eighteen {nineteen} twenty one...two three {four} five six...
000271    }
000272    do_snippet_test $T.4.11 {four NOT (nineteen twentyone)} 0 5 {
000273       ...two three {four} five six...
000274    } {
000275       ...two three {four} five six...
000276    }
000277    do_snippet_test $T.4.12 {four OR nineteen NEAR twentyone} 0 5 {
000278       ...two three {four} five six...
000279    } {
000280       ...two three {four} five six...
000281    }
000282    
000283    do_test $T.5.1 {
000284      execsql {
000285        DROP TABLE IF EXISTS ft;
000286        CREATE VIRTUAL TABLE ft USING fts3(a, b, c);
000287        INSERT INTO ft VALUES(
000288          'one two three four five', 
000289          'four five six seven eight', 
000290          'seven eight nine ten eleven'
000291        );
000292      }
000293    } {}
000294    
000295    do_snippet_test $T.5.2 {five} -1 3 {...three four {five}}
000296    do_snippet_test $T.5.3 {five}  0 3 {...three four {five}}
000297    do_snippet_test $T.5.4 {five}  1 3 {four {five} six...}
000298    do_snippet_test $T.5.5 {five}  2 3 {seven eight nine...}
000299    
000300    do_test $T.5.6 {
000301      execsql { UPDATE ft SET b = NULL }
000302    } {}
000303    
000304    do_snippet_test $T.5.7  {five} -1 3 {...three four {five}}
000305    do_snippet_test $T.5.8  {five}  0 3 {...three four {five}}
000306    do_snippet_test $T.5.9  {five}  1 3 {}
000307    do_snippet_test $T.5.10 {five}  2 3 {seven eight nine...}
000308    
000309    do_snippet_test $T.5.11 {one "seven eight nine"} -1 -3 {
000310      {one} two three...{seven} {eight} {nine}...
000311    }
000312  
000313    do_test $T.6.1 {
000314      execsql {
000315        DROP TABLE IF EXISTS ft;
000316        CREATE VIRTUAL TABLE ft USING fts3(x);
000317        INSERT INTO ft VALUES($numbers);
000318      }
000319    } {}
000320    do_snippet_test $T.6.2 {
000321      one fifty onehundred onehundredfifty twohundredfifty threehundred
000322    } -1 4 {
000323      {one}...{fifty}...{onehundred}...{onehundredfifty}...
000324    }
000325    do_snippet_test $T.6.3 {
000326      one fifty onehundred onehundredfifty twohundredfifty threehundred
000327    } -1 -4 {
000328      {one} two three four...fortyeight fortynine {fifty} fiftyone...ninetyeight ninetynine {onehundred} onehundredone...onehundredfortyeight onehundredfortynine {onehundredfifty} onehundredfiftyone...
000329    }
000330  
000331    do_test $T.7.1 {
000332      execsql {
000333        BEGIN;
000334          DROP TABLE IF EXISTS ft;
000335          CREATE VIRTUAL TABLE ft USING fts3(x);
000336      }
000337      set testresults [list]
000338      for {set i 1} {$i < 150} {incr i} {
000339        set commas [string repeat , $i]
000340        execsql {INSERT INTO ft VALUES('one' || $commas || 'two')}
000341        lappend testresults "{one}$commas{two}"
000342      }
000343      execsql COMMIT
000344    } {}
000345    eval [list do_snippet_test $T.7.2 {one two} -1 3] $testresults
000346    
000347    ##########################################################################
000348    # Test the matchinfo function.
000349    #
000350    proc mit {blob} {
000351      set scan(littleEndian) i*
000352      set scan(bigEndian) I*
000353      binary scan $blob $scan($::tcl_platform(byteOrder)) r
000354      return $r
000355    }
000356    db func mit mit
000357    proc do_matchinfo_test {name expr args} {
000358      set res [list]
000359      foreach a $args { lappend res [normalize $a] }
000360      do_select_test $name {
000361        SELECT mit(matchinfo(ft)) FROM ft WHERE ft MATCH $expr
000362      } $res
000363    }
000364    do_test $T.8.1 {
000365      set ten {one two three four five six seven eight nine ten}
000366      execsql {
000367        DROP TABLE IF EXISTS ft;
000368        CREATE VIRTUAL TABLE ft USING fts3;
000369        INSERT INTO ft VALUES($ten);
000370        INSERT INTO ft VALUES($ten || ' ' || $ten);
000371      }
000372    } {}
000373    
000374    do_matchinfo_test $T.8.2 "one" {1 1  1 3 2} {1 1  2 3 2}
000375    do_matchinfo_test $T.8.3 "one NEAR/3 ten" {2 1  1 1 1 1 1 1}
000376    do_matchinfo_test $T.8.4 "five NEAR/4 ten" \
000377      {2 1  1 3 2  1 3 2} {2 1  2 3 2  2 3 2}
000378    do_matchinfo_test $T.8.5 "six NEAR/3 ten NEAR/3 two" \
000379      {3 1  1 1 1  1 1 1  1 1 1}
000380    do_matchinfo_test $T.8.6 "five NEAR/4 ten NEAR/3 two" \
000381      {3 1  2 2 1  1 1 1  1 1 1}
000382  
000383    do_test $T.9.1 {
000384      execsql {
000385        DROP TABLE IF EXISTS ft;
000386        CREATE VIRTUAL TABLE ft USING fts3(x, y);
000387      }
000388      foreach n {1 2 3} {
000389        set v1 [lrange $numbers 0 [expr $n*100]]
000390        set v2 [string trim [string repeat "$numbers " $n]]
000391        set docid [expr $n * 1000000]
000392        execsql { INSERT INTO ft(docid, x, y) VALUES($docid, $v1, $v2) }
000393      }
000394    } {}
000395    do_matchinfo_test $T.9.2 {two*}     \
000396      { 1 2    1   105 3   101 606 3}   \
000397      { 1 2    3   105 3   202 606 3}   \
000398      { 1 2    101 105 3   303 606 3}
000399  
000400    do_matchinfo_test $T.9.4 {"one* two*"}  \
000401      { 1 2    1 5 3   2 12 3}              \
000402      { 1 2    2 5 3   4 12 3}              \
000403      { 1 2    2 5 3   6 12 3}
000404  
000405    do_matchinfo_test $T.9.5 {twohundredfifty}  \
000406      { 1 2    0 1 1   1 6 3}                   \
000407      { 1 2    0 1 1   2 6 3}                   \
000408      { 1 2    1 1 1   3 6 3}
000409  
000410    do_matchinfo_test $T.9.6 {"threehundred one"} \
000411      { 1 2    0 0 0   1 3 2}                     \
000412      { 1 2    0 0 0   2 3 2}
000413  
000414    do_matchinfo_test $T.9.7 {one OR fivehundred} \
000415      { 2 2    1 3 3   1 6 3   0 0 0   0 0 0 }    \
000416      { 2 2    1 3 3   2 6 3   0 0 0   0 0 0 }    \
000417      { 2 2    1 3 3   3 6 3   0 0 0   0 0 0 }
000418  
000419    do_matchinfo_test $T.9.8 {two OR "threehundred one"} \
000420      { 2 2    1 3 3   1 6 3   0 0 0   0 3 2 }           \
000421      { 2 2    1 3 3   2 6 3   0 0 0   1 3 2 }           \
000422      { 2 2    1 3 3   3 6 3   0 0 0   2 3 2 }
000423  
000424    do_select_test $T.9.9 {
000425      SELECT mit(matchinfo(ft)), mit(matchinfo(ft))
000426      FROM ft WHERE ft MATCH 'two OR "threehundred one"' 
000427    } [normalize {
000428      {2 2 1 3 3 1 6 3 0 0 0 0 3 2}
000429      {2 2 1 3 3 1 6 3 0 0 0 0 3 2}
000430      {2 2 1 3 3 2 6 3 0 0 0 1 3 2}
000431      {2 2 1 3 3 2 6 3 0 0 0 1 3 2}
000432      {2 2 1 3 3 3 6 3 0 0 0 2 3 2}          
000433      {2 2 1 3 3 3 6 3 0 0 0 2 3 2}
000434    }]
000435  
000436    # EVIDENCE-OF: R-40630-02268 If used within a SELECT that uses the
000437    # "query by rowid" or "linear scan" strategies, then the snippet and
000438    # offsets both return an empty string, and the matchinfo function
000439    # returns a blob value zero bytes in size.
000440    #
000441    set r 1000000                   ;# A rowid that exists in table ft
000442    do_select_test $T.10.0 { SELECT rowid FROM ft WHERE rowid = $r } $r
000443    do_select_test $T.10.1 {
000444      SELECT length(offsets(ft)), typeof(offsets(ft)) FROM ft;
000445    } {0 text 0 text 0 text}
000446    do_select_test $T.10.2 {
000447      SELECT length(offsets(ft)), typeof(offsets(ft)) FROM ft WHERE rowid = $r
000448    } {0 text}
000449    do_select_test $T.10.3 {
000450      SELECT length(snippet(ft)), typeof(snippet(ft)) FROM ft;
000451    } {0 text 0 text 0 text}
000452    do_select_test $T.10.4 {
000453      SELECT length(snippet(ft)), typeof(snippet(ft)) FROM ft WHERE rowid = $r;
000454    } {0 text}
000455    do_select_test $T.10.5 {
000456      SELECT length(matchinfo(ft)), typeof(matchinfo(ft)) FROM ft;
000457    } {0 blob 0 blob 0 blob}
000458    do_select_test $T.10.6 {
000459      SELECT length(matchinfo(ft)), typeof(matchinfo(ft)) FROM ft WHERE rowid = $r
000460    } {0 blob}
000461  }
000462  
000463  #-------------------------------------------------------------------------
000464  # Test an interaction between the snippet() function and OR clauses.
000465  #
000466  do_execsql_test 2.1 {
000467    CREATE VIRTUAL TABLE t2 USING fts4;
000468    INSERT INTO t2 VALUES('one two three four five');
000469    INSERT INTO t2 VALUES('two three four five one');
000470    INSERT INTO t2 VALUES('three four five one two');
000471    INSERT INTO t2 VALUES('four five one two three');
000472    INSERT INTO t2 VALUES('five one two three four');
000473  }
000474  
000475  do_execsql_test 2.2 {
000476    SELECT snippet(t2, '[', ']') FROM t2 WHERE t2 MATCH 'one OR (four AND six)'
000477  } {
000478    {[one] two three [four] five}
000479    {two three [four] five [one]}
000480    {three [four] five [one] two}
000481    {[four] five [one] two three}
000482    {five [one] two three [four]}
000483  }
000484  
000485  do_execsql_test 2.3 {
000486    SELECT snippet(t2, '[', ']') FROM t2 
000487    WHERE t2 MATCH 'one OR (four AND six)' 
000488    ORDER BY docid DESC
000489  } {
000490    {five [one] two three [four]}
000491    {[four] five [one] two three}
000492    {three [four] five [one] two}
000493    {two three [four] five [one]}
000494    {[one] two three [four] five}
000495  }
000496  
000497  do_execsql_test 2.4 {
000498    INSERT INTO t2 VALUES('six');
000499  }
000500  
000501  do_execsql_test 2.5 {
000502    SELECT snippet(t2, '[', ']') FROM t2 WHERE t2 MATCH 'one OR (four AND six)'
000503  } {
000504    {[one] two three [four] five}
000505    {two three [four] five [one]}
000506    {three [four] five [one] two}
000507    {[four] five [one] two three}
000508    {five [one] two three [four]}
000509  }
000510  
000511  do_execsql_test 2.6 {
000512    SELECT snippet(t2, '[', ']') FROM t2 
000513    WHERE t2 MATCH 'one OR (four AND six)' 
000514    ORDER BY docid DESC
000515  } {
000516    {five [one] two three [four]}
000517    {[four] five [one] two three}
000518    {three [four] five [one] two}
000519    {two three [four] five [one]}
000520    {[one] two three [four] five}
000521  }
000522  
000523  #-------------------------------------------------------------------------
000524  do_execsql_test 3 {
000525    CREATE VIRTUAL TABLE t3 USING fts4;
000526    INSERT INTO t3 VALUES('[one two three]');
000527  }
000528  do_execsql_test 3.1 {
000529    SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'one';
000530  } {{[<b>one</b> two three]}}
000531  do_execsql_test 3.2 {
000532    SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'two';
000533  } {{[one <b>two</b> three]}}
000534  do_execsql_test 3.3 {
000535    SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'three';
000536  } {{[one two <b>three</b>]}}
000537  do_execsql_test 3.4 {
000538    SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'one OR two OR three';
000539  } {{[<b>one</b> <b>two</b> <b>three</b>]}}
000540  
000541  #-------------------------------------------------------------------------
000542  # Request a snippet 0 tokens in size. This is always an empty string.
000543  do_execsql_test 4.1 {
000544    CREATE VIRTUAL TABLE t4 USING fts4;
000545    INSERT INTO t4 VALUES('a b c d');
000546    SELECT snippet(t4, '[', ']', '...', 0, 0) FROM t4 WHERE t4 MATCH 'b';
000547  } {{}}
000548  
000549  do_test 4.2 {
000550    set x35 [string trim [string repeat "x " 35]]
000551    execsql "INSERT INTO t4 VALUES('$x35 E $x35 F $x35 G $x35');"
000552    llength [db one {
000553      SELECT snippet(t4, '', '', '', 0, 64) FROM t4 WHERE t4 MATCH 'E'
000554    }]
000555  } {64}
000556  
000557  
000558  
000559  
000560  set sqlite_fts3_enable_parentheses 0
000561  finish_test