1# 2010 January 07
2#
3# The author disclaims copyright to this source code.  In place of
4# a legal notice, here is a blessing:
5#
6#    May you do good and not evil.
7#    May you find forgiveness for yourself and forgive others.
8#    May you share freely, never taking more than you give.
9#
10#*************************************************************************
11#
12# The tests in this file test the FTS3 auxillary functions offsets(),
13# snippet() and matchinfo() work. At time of writing, running this file
14# provides full coverage of fts3_snippet.c.
15#
16
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
19set testprefix fts3snippet
20
21# If SQLITE_ENABLE_FTS3 is not defined, omit this file.
22ifcapable !fts3 { finish_test ; return }
23source $testdir/fts3_common.tcl
24
25set sqlite_fts3_enable_parentheses 1
26set DO_MALLOC_TEST 0
27
28# Transform the list $L to its "normal" form. So that it can be compared to
29# another list with the same set of elements using [string compare].
30#
31proc normalize {L} {
32  set ret [list]
33  foreach l $L {lappend ret $l}
34  return $ret
35}
36
37proc do_offsets_test {name expr args} {
38  set result [list]
39  foreach a $args {
40    lappend result [normalize $a]
41  }
42  do_select_test $name {
43    SELECT offsets(ft) FROM ft WHERE ft MATCH $expr
44  } $result
45}
46
47# Document text used by a few tests. Contains the English names of all
48# integers between 1 and 300.
49#
50set numbers [normalize {
51  one two three four five six seven eight nine ten eleven twelve thirteen
52  fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone
53  twentytwo twentythree twentyfour twentyfive twentysix twentyseven
54  twentyeight twentynine thirty thirtyone thirtytwo thirtythree thirtyfour
55  thirtyfive thirtysix thirtyseven thirtyeight thirtynine forty fortyone
56  fortytwo fortythree fortyfour fortyfive fortysix fortyseven fortyeight
57  fortynine fifty fiftyone fiftytwo fiftythree fiftyfour fiftyfive fiftysix
58  fiftyseven fiftyeight fiftynine sixty sixtyone sixtytwo sixtythree sixtyfour
59  sixtyfive sixtysix sixtyseven sixtyeight sixtynine seventy seventyone
60  seventytwo seventythree seventyfour seventyfive seventysix seventyseven
61  seventyeight seventynine eighty eightyone eightytwo eightythree eightyfour
62  eightyfive eightysix eightyseven eightyeight eightynine ninety ninetyone
63  ninetytwo ninetythree ninetyfour ninetyfive ninetysix ninetyseven
64  ninetyeight ninetynine onehundred onehundredone onehundredtwo
65  onehundredthree onehundredfour onehundredfive onehundredsix onehundredseven
66  onehundredeight onehundrednine onehundredten onehundredeleven
67  onehundredtwelve onehundredthirteen onehundredfourteen onehundredfifteen
68  onehundredsixteen onehundredseventeen onehundredeighteen onehundrednineteen
69  onehundredtwenty onehundredtwentyone onehundredtwentytwo
70  onehundredtwentythree onehundredtwentyfour onehundredtwentyfive
71  onehundredtwentysix onehundredtwentyseven onehundredtwentyeight
72  onehundredtwentynine onehundredthirty onehundredthirtyone
73  onehundredthirtytwo onehundredthirtythree onehundredthirtyfour
74  onehundredthirtyfive onehundredthirtysix onehundredthirtyseven
75  onehundredthirtyeight onehundredthirtynine onehundredforty
76  onehundredfortyone onehundredfortytwo onehundredfortythree
77  onehundredfortyfour onehundredfortyfive onehundredfortysix
78  onehundredfortyseven onehundredfortyeight onehundredfortynine
79  onehundredfifty onehundredfiftyone onehundredfiftytwo onehundredfiftythree
80  onehundredfiftyfour onehundredfiftyfive onehundredfiftysix
81  onehundredfiftyseven onehundredfiftyeight onehundredfiftynine
82  onehundredsixty onehundredsixtyone onehundredsixtytwo onehundredsixtythree
83  onehundredsixtyfour onehundredsixtyfive onehundredsixtysix
84  onehundredsixtyseven onehundredsixtyeight onehundredsixtynine
85  onehundredseventy onehundredseventyone onehundredseventytwo
86  onehundredseventythree onehundredseventyfour onehundredseventyfive
87  onehundredseventysix onehundredseventyseven onehundredseventyeight
88  onehundredseventynine onehundredeighty onehundredeightyone
89  onehundredeightytwo onehundredeightythree onehundredeightyfour
90  onehundredeightyfive onehundredeightysix onehundredeightyseven
91  onehundredeightyeight onehundredeightynine onehundredninety
92  onehundredninetyone onehundredninetytwo onehundredninetythree
93  onehundredninetyfour onehundredninetyfive onehundredninetysix
94  onehundredninetyseven onehundredninetyeight onehundredninetynine twohundred
95  twohundredone twohundredtwo twohundredthree twohundredfour twohundredfive
96  twohundredsix twohundredseven twohundredeight twohundrednine twohundredten
97  twohundredeleven twohundredtwelve twohundredthirteen twohundredfourteen
98  twohundredfifteen twohundredsixteen twohundredseventeen twohundredeighteen
99  twohundrednineteen twohundredtwenty twohundredtwentyone twohundredtwentytwo
100  twohundredtwentythree twohundredtwentyfour twohundredtwentyfive
101  twohundredtwentysix twohundredtwentyseven twohundredtwentyeight
102  twohundredtwentynine twohundredthirty twohundredthirtyone
103  twohundredthirtytwo twohundredthirtythree twohundredthirtyfour
104  twohundredthirtyfive twohundredthirtysix twohundredthirtyseven
105  twohundredthirtyeight twohundredthirtynine twohundredforty
106  twohundredfortyone twohundredfortytwo twohundredfortythree
107  twohundredfortyfour twohundredfortyfive twohundredfortysix
108  twohundredfortyseven twohundredfortyeight twohundredfortynine
109  twohundredfifty twohundredfiftyone twohundredfiftytwo twohundredfiftythree
110  twohundredfiftyfour twohundredfiftyfive twohundredfiftysix
111  twohundredfiftyseven twohundredfiftyeight twohundredfiftynine
112  twohundredsixty twohundredsixtyone twohundredsixtytwo twohundredsixtythree
113  twohundredsixtyfour twohundredsixtyfive twohundredsixtysix
114  twohundredsixtyseven twohundredsixtyeight twohundredsixtynine
115  twohundredseventy twohundredseventyone twohundredseventytwo
116  twohundredseventythree twohundredseventyfour twohundredseventyfive
117  twohundredseventysix twohundredseventyseven twohundredseventyeight
118  twohundredseventynine twohundredeighty twohundredeightyone
119  twohundredeightytwo twohundredeightythree twohundredeightyfour
120  twohundredeightyfive twohundredeightysix twohundredeightyseven
121  twohundredeightyeight twohundredeightynine twohundredninety
122  twohundredninetyone twohundredninetytwo twohundredninetythree
123  twohundredninetyfour twohundredninetyfive twohundredninetysix
124  twohundredninetyseven twohundredninetyeight twohundredninetynine
125  threehundred
126}]
127
128foreach {DO_MALLOC_TEST enc} {
129  0 utf8
130  1 utf8
131  1 utf16
132} {
133
134  db close
135  forcedelete test.db
136  sqlite3 db test.db
137  sqlite3_db_config_lookaside db 0 0 0
138  db eval "PRAGMA encoding = \"$enc\""
139
140  # Set variable $T to the test name prefix for this iteration of the loop.
141  #
142  set T "fts3snippet-1.$enc"
143
144  ##########################################################################
145  # Test the offset function.
146  #
147  do_test $T.1.1 {
148    execsql {
149      CREATE VIRTUAL TABLE ft USING fts3;
150      INSERT INTO ft VALUES('xxx xxx xxx xxx');
151    }
152  } {}
153  do_offsets_test $T.1.2 {xxx} {0 0 0 3 0 0 4 3 0 0 8 3 0 0 12 3}
154  do_offsets_test $T.1.3 {"xxx xxx"} {
155      0 0  0 3     0 0  4 3     0 1  4 3     0 0  8 3
156      0 1  8 3     0 1 12 3
157  }
158  do_offsets_test $T.1.4 {"xxx xxx" xxx} {
159      0 0  0 3     0 2  0 3     0 0  4 3     0 1  4 3
160      0 2  4 3     0 0  8 3     0 1  8 3     0 2  8 3
161      0 1 12 3     0 2 12 3
162  }
163  do_offsets_test $T.1.5 {xxx "xxx xxx"} {
164      0 0  0 3     0 1  0 3     0 0  4 3     0 1  4 3
165      0 2  4 3     0 0  8 3     0 1  8 3     0 2  8 3
166      0 0 12 3     0 2 12 3
167  }
168
169  do_test $T.2.1 {
170    set v1 [lrange $numbers 0 99]
171    execsql {
172      DROP TABLE IF EXISTS ft;
173      CREATE VIRTUAL TABLE ft USING fts3(a, b);
174      INSERT INTO ft VALUES($v1, $numbers);
175      INSERT INTO ft VALUES($v1, NULL);
176    }
177  } {}
178
179  set off [string first "twohundred " $numbers]
180  do_offsets_test $T.2.1 {twohundred} [list 1 0 $off 10]
181
182  set off [string first "onehundred " $numbers]
183  do_offsets_test $T.2.2 {onehundred} \
184    [list 0 0 $off 10 1 0 $off 10] [list 0 0 $off 10]
185
186  # Test a corruption case:
187  sqlite3_db_config db DEFENSIVE 0
188  execsql { UPDATE ft_content SET c1b = 'hello world' WHERE c1b = $numbers }
189  do_error_test $T.2.3 {
190    SELECT offsets(ft) FROM ft WHERE ft MATCH 'onehundred'
191  } {database disk image is malformed}
192
193  ##########################################################################
194  # Test the snippet function.
195  #
196  proc do_snippet_test {name expr iCol nTok args} {
197    set res [list]
198    foreach a $args { lappend res [string trim $a] }
199    do_select_test $name {
200      SELECT snippet(ft,'{','}','...',$iCol,$nTok) FROM ft WHERE ft MATCH $expr
201    } $res
202  }
203  do_test $T.3.1 {
204    execsql {
205      DROP TABLE IF EXISTS ft;
206      CREATE VIRTUAL TABLE ft USING fts3;
207      INSERT INTO ft VALUES('one two three four five six seven eight nine ten');
208    }
209  } {}
210  do_snippet_test $T.3.2  one    0 5 "{one} two three four five..."
211  do_snippet_test $T.3.3  two    0 5 "one {two} three four five..."
212  do_snippet_test $T.3.4  three  0 5 "one two {three} four five..."
213  do_snippet_test $T.3.5  four   0 5 "...two three {four} five six..."
214  do_snippet_test $T.3.6  five   0 5 "...three four {five} six seven..."
215  do_snippet_test $T.3.7  six    0 5 "...four five {six} seven eight..."
216  do_snippet_test $T.3.8  seven  0 5 "...five six {seven} eight nine..."
217  do_snippet_test $T.3.9  eight  0 5 "...six seven {eight} nine ten"
218  do_snippet_test $T.3.10 nine   0 5 "...six seven eight {nine} ten"
219  do_snippet_test $T.3.11 ten    0 5 "...six seven eight nine {ten}"
220
221  do_test $T.4.1 {
222    execsql {
223      INSERT INTO ft VALUES(
224           'one two three four five '
225        || 'six seven eight nine ten '
226        || 'eleven twelve thirteen fourteen fifteen '
227        || 'sixteen seventeen eighteen nineteen twenty '
228        || 'one two three four five '
229        || 'six seven eight nine ten '
230        || 'eleven twelve thirteen fourteen fifteen '
231        || 'sixteen seventeen eighteen nineteen twenty'
232      );
233    }
234  } {}
235
236  do_snippet_test $T.4.2 {one nine} 0 5 {
237     {one} two three...eight {nine} ten
238  } {
239     {one} two three...eight {nine} ten...
240  }
241
242  do_snippet_test $T.4.3 {one nine} 0 -5 {
243     {one} two three four five...six seven eight {nine} ten
244  } {
245     {one} two three four five...seven eight {nine} ten eleven...
246  }
247  do_snippet_test $T.4.3 {one nineteen} 0 -5 {
248     ...eighteen {nineteen} twenty {one} two...
249  }
250  do_snippet_test $T.4.4 {two nineteen} 0 -5 {
251     ...eighteen {nineteen} twenty one {two}...
252  }
253  do_snippet_test $T.4.5 {three nineteen} 0 -5 {
254     ...{nineteen} twenty one two {three}...
255  }
256
257  do_snippet_test $T.4.6 {four nineteen} 0 -5 {
258     ...two three {four} five six...seventeen eighteen {nineteen} twenty one...
259  }
260  do_snippet_test $T.4.7 {four NEAR nineteen} 0 -5 {
261     ...seventeen eighteen {nineteen} twenty one...two three {four} five six...
262  }
263
264  do_snippet_test $T.4.8 {four nineteen} 0 5 {
265     ...three {four} five...eighteen {nineteen} twenty...
266  }
267  do_snippet_test $T.4.9 {four NEAR nineteen} 0 5 {
268     ...eighteen {nineteen} twenty...three {four} five...
269  }
270  do_snippet_test $T.4.10 {four NEAR nineteen} 0 -5 {
271     ...seventeen eighteen {nineteen} twenty one...two three {four} five six...
272  }
273  do_snippet_test $T.4.11 {four NOT (nineteen twentyone)} 0 5 {
274     ...two three {four} five six...
275  } {
276     ...two three {four} five six...
277  }
278  do_snippet_test $T.4.12 {four OR nineteen NEAR twentyone} 0 5 {
279     ...two three {four} five six...
280  } {
281     ...two three {four} five six...
282  }
283
284  do_test $T.5.1 {
285    execsql {
286      DROP TABLE IF EXISTS ft;
287      CREATE VIRTUAL TABLE ft USING fts3(a, b, c);
288      INSERT INTO ft VALUES(
289        'one two three four five',
290        'four five six seven eight',
291        'seven eight nine ten eleven'
292      );
293    }
294  } {}
295
296  do_snippet_test $T.5.2 {five} -1 3 {...three four {five}}
297  do_snippet_test $T.5.3 {five}  0 3 {...three four {five}}
298  do_snippet_test $T.5.4 {five}  1 3 {four {five} six...}
299  do_snippet_test $T.5.5 {five}  2 3 {seven eight nine...}
300
301  do_test $T.5.6 {
302    execsql { UPDATE ft SET b = NULL }
303  } {}
304
305  do_snippet_test $T.5.7  {five} -1 3 {...three four {five}}
306  do_snippet_test $T.5.8  {five}  0 3 {...three four {five}}
307  do_snippet_test $T.5.9  {five}  1 3 {}
308  do_snippet_test $T.5.10 {five}  2 3 {seven eight nine...}
309
310  do_snippet_test $T.5.11 {one "seven eight nine"} -1 -3 {
311    {one} two three...{seven} {eight} {nine}...
312  }
313
314  do_test $T.6.1 {
315    execsql {
316      DROP TABLE IF EXISTS ft;
317      CREATE VIRTUAL TABLE ft USING fts3(x);
318      INSERT INTO ft VALUES($numbers);
319    }
320  } {}
321  do_snippet_test $T.6.2 {
322    one fifty onehundred onehundredfifty twohundredfifty threehundred
323  } -1 4 {
324    {one}...{fifty}...{onehundred}...{onehundredfifty}...
325  }
326  do_snippet_test $T.6.3 {
327    one fifty onehundred onehundredfifty twohundredfifty threehundred
328  } -1 -4 {
329    {one} two three four...fortyeight fortynine {fifty} fiftyone...ninetyeight ninetynine {onehundred} onehundredone...onehundredfortyeight onehundredfortynine {onehundredfifty} onehundredfiftyone...
330  }
331
332  do_test $T.7.1 {
333    execsql {
334      BEGIN;
335        DROP TABLE IF EXISTS ft;
336        CREATE VIRTUAL TABLE ft USING fts3(x);
337    }
338    set testresults [list]
339    for {set i 1} {$i < 150} {incr i} {
340      set commas [string repeat , $i]
341      execsql {INSERT INTO ft VALUES('one' || $commas || 'two')}
342      lappend testresults "{one}$commas{two}"
343    }
344    execsql COMMIT
345  } {}
346  eval [list do_snippet_test $T.7.2 {one two} -1 3] $testresults
347
348  ##########################################################################
349  # Test the matchinfo function.
350  #
351  proc mit {blob} {
352    set scan(littleEndian) i*
353    set scan(bigEndian) I*
354    binary scan $blob $scan($::tcl_platform(byteOrder)) r
355    return $r
356  }
357  db func mit mit
358  proc do_matchinfo_test {name expr args} {
359    set res [list]
360    foreach a $args { lappend res [normalize $a] }
361    do_select_test $name {
362      SELECT mit(matchinfo(ft)) FROM ft WHERE ft MATCH $expr
363    } $res
364  }
365  do_test $T.8.1 {
366    set ten {one two three four five six seven eight nine ten}
367    execsql {
368      DROP TABLE IF EXISTS ft;
369      CREATE VIRTUAL TABLE ft USING fts3;
370      INSERT INTO ft VALUES($ten);
371      INSERT INTO ft VALUES($ten || ' ' || $ten);
372    }
373  } {}
374
375  do_matchinfo_test $T.8.2 "one" {1 1  1 3 2} {1 1  2 3 2}
376  do_matchinfo_test $T.8.3 "one NEAR/3 ten" {2 1  1 1 1 1 1 1}
377  do_matchinfo_test $T.8.4 "five NEAR/4 ten" \
378    {2 1  1 3 2  1 3 2} {2 1  2 3 2  2 3 2}
379  do_matchinfo_test $T.8.5 "six NEAR/3 ten NEAR/3 two" \
380    {3 1  1 1 1  1 1 1  1 1 1}
381  do_matchinfo_test $T.8.6 "five NEAR/4 ten NEAR/3 two" \
382    {3 1  2 2 1  1 1 1  1 1 1}
383
384  do_test $T.9.1 {
385    execsql {
386      DROP TABLE IF EXISTS ft;
387      CREATE VIRTUAL TABLE ft USING fts3(x, y);
388    }
389    foreach n {1 2 3} {
390      set v1 [lrange $numbers 0 [expr $n*100]]
391      set v2 [string trim [string repeat "$numbers " $n]]
392      set docid [expr $n * 1000000]
393      execsql { INSERT INTO ft(docid, x, y) VALUES($docid, $v1, $v2) }
394    }
395  } {}
396  do_matchinfo_test $T.9.2 {two*}     \
397    { 1 2    1   105 3   101 606 3}   \
398    { 1 2    3   105 3   202 606 3}   \
399    { 1 2    101 105 3   303 606 3}
400
401  do_matchinfo_test $T.9.4 {"one* two*"}  \
402    { 1 2    1 5 3   2 12 3}              \
403    { 1 2    2 5 3   4 12 3}              \
404    { 1 2    2 5 3   6 12 3}
405
406  do_matchinfo_test $T.9.5 {twohundredfifty}  \
407    { 1 2    0 1 1   1 6 3}                   \
408    { 1 2    0 1 1   2 6 3}                   \
409    { 1 2    1 1 1   3 6 3}
410
411  do_matchinfo_test $T.9.6 {"threehundred one"} \
412    { 1 2    0 0 0   1 3 2}                     \
413    { 1 2    0 0 0   2 3 2}
414
415  do_matchinfo_test $T.9.7 {one OR fivehundred} \
416    { 2 2    1 3 3   1 6 3   0 0 0   0 0 0 }    \
417    { 2 2    1 3 3   2 6 3   0 0 0   0 0 0 }    \
418    { 2 2    1 3 3   3 6 3   0 0 0   0 0 0 }
419
420  do_matchinfo_test $T.9.8 {two OR "threehundred one"} \
421    { 2 2    1 3 3   1 6 3   0 0 0   0 3 2 }           \
422    { 2 2    1 3 3   2 6 3   0 0 0   1 3 2 }           \
423    { 2 2    1 3 3   3 6 3   0 0 0   2 3 2 }
424
425  do_select_test $T.9.9 {
426    SELECT mit(matchinfo(ft)), mit(matchinfo(ft))
427    FROM ft WHERE ft MATCH 'two OR "threehundred one"'
428  } [normalize {
429    {2 2 1 3 3 1 6 3 0 0 0 0 3 2}
430    {2 2 1 3 3 1 6 3 0 0 0 0 3 2}
431    {2 2 1 3 3 2 6 3 0 0 0 1 3 2}
432    {2 2 1 3 3 2 6 3 0 0 0 1 3 2}
433    {2 2 1 3 3 3 6 3 0 0 0 2 3 2}
434    {2 2 1 3 3 3 6 3 0 0 0 2 3 2}
435  }]
436
437  # EVIDENCE-OF: R-40630-02268 If used within a SELECT that uses the
438  # "query by rowid" or "linear scan" strategies, then the snippet and
439  # offsets both return an empty string, and the matchinfo function
440  # returns a blob value zero bytes in size.
441  #
442  set r 1000000                   ;# A rowid that exists in table ft
443  do_select_test $T.10.0 { SELECT rowid FROM ft WHERE rowid = $r } $r
444  do_select_test $T.10.1 {
445    SELECT length(offsets(ft)), typeof(offsets(ft)) FROM ft;
446  } {0 text 0 text 0 text}
447  do_select_test $T.10.2 {
448    SELECT length(offsets(ft)), typeof(offsets(ft)) FROM ft WHERE rowid = $r
449  } {0 text}
450  do_select_test $T.10.3 {
451    SELECT length(snippet(ft)), typeof(snippet(ft)) FROM ft;
452  } {0 text 0 text 0 text}
453  do_select_test $T.10.4 {
454    SELECT length(snippet(ft)), typeof(snippet(ft)) FROM ft WHERE rowid = $r;
455  } {0 text}
456  do_select_test $T.10.5 {
457    SELECT length(matchinfo(ft)), typeof(matchinfo(ft)) FROM ft;
458  } {0 blob 0 blob 0 blob}
459  do_select_test $T.10.6 {
460    SELECT length(matchinfo(ft)), typeof(matchinfo(ft)) FROM ft WHERE rowid = $r
461  } {0 blob}
462}
463
464#-------------------------------------------------------------------------
465# Test an interaction between the snippet() function and OR clauses.
466#
467do_execsql_test 2.1 {
468  CREATE VIRTUAL TABLE t2 USING fts4;
469  INSERT INTO t2 VALUES('one two three four five');
470  INSERT INTO t2 VALUES('two three four five one');
471  INSERT INTO t2 VALUES('three four five one two');
472  INSERT INTO t2 VALUES('four five one two three');
473  INSERT INTO t2 VALUES('five one two three four');
474}
475
476do_execsql_test 2.2 {
477  SELECT snippet(t2, '[', ']') FROM t2 WHERE t2 MATCH 'one OR (four AND six)'
478} {
479  {[one] two three [four] five}
480  {two three [four] five [one]}
481  {three [four] five [one] two}
482  {[four] five [one] two three}
483  {five [one] two three [four]}
484}
485
486do_execsql_test 2.3 {
487  SELECT snippet(t2, '[', ']') FROM t2
488  WHERE t2 MATCH 'one OR (four AND six)'
489  ORDER BY docid DESC
490} {
491  {five [one] two three [four]}
492  {[four] five [one] two three}
493  {three [four] five [one] two}
494  {two three [four] five [one]}
495  {[one] two three [four] five}
496}
497
498do_execsql_test 2.4 {
499  INSERT INTO t2 VALUES('six');
500}
501
502do_execsql_test 2.5 {
503  SELECT snippet(t2, '[', ']') FROM t2 WHERE t2 MATCH 'one OR (four AND six)'
504} {
505  {[one] two three [four] five}
506  {two three [four] five [one]}
507  {three [four] five [one] two}
508  {[four] five [one] two three}
509  {five [one] two three [four]}
510}
511
512do_execsql_test 2.6 {
513  SELECT snippet(t2, '[', ']') FROM t2
514  WHERE t2 MATCH 'one OR (four AND six)'
515  ORDER BY docid DESC
516} {
517  {five [one] two three [four]}
518  {[four] five [one] two three}
519  {three [four] five [one] two}
520  {two three [four] five [one]}
521  {[one] two three [four] five}
522}
523
524#-------------------------------------------------------------------------
525do_execsql_test 3 {
526  CREATE VIRTUAL TABLE t3 USING fts4;
527  INSERT INTO t3 VALUES('[one two three]');
528}
529do_execsql_test 3.1 {
530  SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'one';
531} {{[<b>one</b> two three]}}
532do_execsql_test 3.2 {
533  SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'two';
534} {{[one <b>two</b> three]}}
535do_execsql_test 3.3 {
536  SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'three';
537} {{[one two <b>three</b>]}}
538do_execsql_test 3.4 {
539  SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'one OR two OR three';
540} {{[<b>one</b> <b>two</b> <b>three</b>]}}
541
542#-------------------------------------------------------------------------
543# Request a snippet 0 tokens in size. This is always an empty string.
544do_execsql_test 4.1 {
545  CREATE VIRTUAL TABLE t4 USING fts4;
546  INSERT INTO t4 VALUES('a b c d');
547  SELECT snippet(t4, '[', ']', '...', 0, 0) FROM t4 WHERE t4 MATCH 'b';
548} {{}}
549
550do_test 4.2 {
551  set x35 [string trim [string repeat "x " 35]]
552  execsql "INSERT INTO t4 VALUES('$x35 E $x35 F $x35 G $x35');"
553  llength [db one {
554    SELECT snippet(t4, '', '', '', 0, 64) FROM t4 WHERE t4 MATCH 'E'
555  }]
556} {64}
557
558do_test 4.3 {
559  llength [db one {
560    SELECT snippet(t4, '', '', '', 0, 150) FROM t4 WHERE t4 MATCH 'E'
561  }]
562} {64}
563
564
565#-------------------------------------------------------------------------
566# Request a snippet from a query with more than 64 phrases.
567#
568do_execsql_test 5.0 {
569  CREATE VIRTUAL TABLE t5 USING fts3(x);
570  INSERT INTO t5 VALUES('a1 a2 a3');
571  INSERT INTO t5 VALUES('a4 a5 a6');
572  INSERT INTO t5 VALUES('a70 a71 a72');
573}
574
575do_execsql_test 5.1 {
576  SELECT snippet(t5, '[', ']') FROM t5 WHERE t5 MATCH
577  'a1 OR a2 OR a3 OR a4 OR a5 OR a6 OR a7 OR a8 OR a9 OR a10 OR ' ||
578  'a11 OR a12 OR a13 OR a14 OR a15 OR a16 OR a17 OR a18 OR a19 OR a10 OR ' ||
579  'a21 OR a22 OR a23 OR a24 OR a25 OR a26 OR a27 OR a28 OR a29 OR a20 OR ' ||
580  'a31 OR a32 OR a33 OR a34 OR a35 OR a36 OR a37 OR a38 OR a39 OR a30 OR ' ||
581  'a41 OR a42 OR a43 OR a44 OR a45 OR a46 OR a47 OR a48 OR a49 OR a40 OR ' ||
582  'a51 OR a52 OR a53 OR a54 OR a55 OR a56 OR a57 OR a58 OR a59 OR a50 OR ' ||
583  'a61 OR a62 OR a63 OR a64 OR a65 OR a66 OR a67 OR a68 OR a69 OR a60 OR ' ||
584  'a71 OR a72 OR a73 OR a74 OR a75 OR a76 OR a77 OR a78 OR a79 OR a70'
585} {
586  {[a1] [a2] [a3]}
587  {[a4] [a5] [a6]}
588  {[a70] [a71] [a72]}
589}
590
591set sqlite_fts3_enable_parentheses 0
592finish_test
593