xref: /sqlite-3.40.0/test/fts2n.test (revision 85b623f2)
1290283feSshess# 2007 April 26
2290283feSshess#
3290283feSshess# The author disclaims copyright to this source code.
4290283feSshess#
5290283feSshess#*************************************************************************
6290283feSshess# This file implements tests for prefix-searching in the fts2
7290283feSshess# component of the SQLite library.
8290283feSshess#
9*85b623f2Sdrh# $Id: fts2n.test,v 1.2 2007/12/13 21:54:11 drh Exp $
10290283feSshess#
11290283feSshess
12290283feSshessset testdir [file dirname $argv0]
13290283feSshesssource $testdir/tester.tcl
14290283feSshess
15290283feSshess# If SQLITE_ENABLE_FTS2 is defined, omit this file.
16290283feSshessifcapable !fts2 {
17290283feSshess  finish_test
18290283feSshess  return
19290283feSshess}
20290283feSshess
21290283feSshess# A large string to prime the pump with.
22290283feSshessset text {
23290283feSshess  Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas
24290283feSshess  iaculis mollis ipsum. Praesent rhoncus placerat justo. Duis non quam
25290283feSshess  sed turpis posuere placerat. Curabitur et lorem in lorem porttitor
26290283feSshess  aliquet. Pellentesque bibendum tincidunt diam. Vestibulum blandit
27290283feSshess  ante nec elit. In sapien diam, facilisis eget, dictum sed, viverra
28290283feSshess  at, felis. Vestibulum magna. Sed magna dolor, vestibulum rhoncus,
29290283feSshess  ornare vel, vulputate sit amet, felis. Integer malesuada, tellus at
30290283feSshess  luctus gravida, diam nunc porta nibh, nec imperdiet massa metus eu
31290283feSshess  lectus. Aliquam nisi. Nunc fringilla nulla at lectus. Suspendisse
32290283feSshess  potenti. Cum sociis natoque penatibus et magnis dis parturient
33290283feSshess  montes, nascetur ridiculus mus. Pellentesque odio nulla, feugiat eu,
34290283feSshess  suscipit nec, consequat quis, risus.
35290283feSshess}
36290283feSshess
37290283feSshessdb eval {
38290283feSshess  CREATE VIRTUAL TABLE t1 USING fts2(c);
39290283feSshess
40290283feSshess  INSERT INTO t1(rowid, c) VALUES(1, $text);
41290283feSshess  INSERT INTO t1(rowid, c) VALUES(2, 'Another lovely row');
42290283feSshess}
43290283feSshess
44290283feSshess# Exact match
45290283feSshessdo_test fts2n-1.1 {
46290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lorem'"
47290283feSshess} {1}
48290283feSshess
49290283feSshess# And a prefix
50290283feSshessdo_test fts2n-1.2 {
51290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lore*'"
52290283feSshess} {1}
53290283feSshess
54290283feSshess# Prefix includes exact match
55290283feSshessdo_test fts2n-1.3 {
56290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lorem*'"
57290283feSshess} {1}
58290283feSshess
59290283feSshess# Make certain everything isn't considered a prefix!
60290283feSshessdo_test fts2n-1.4 {
61290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lore'"
62290283feSshess} {}
63290283feSshess
64290283feSshess# Prefix across multiple rows.
65290283feSshessdo_test fts2n-1.5 {
66290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lo*'"
67290283feSshess} {1 2}
68290283feSshess
69290283feSshess# Likewise, with multiple hits in one document.
70290283feSshessdo_test fts2n-1.6 {
71290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'l*'"
72290283feSshess} {1 2}
73290283feSshess
74290283feSshess# Prefix which should only hit one document.
75290283feSshessdo_test fts2n-1.7 {
76290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lov*'"
77290283feSshess} {2}
78290283feSshess
79290283feSshess# * not at end is dropped.
80290283feSshessdo_test fts2n-1.8 {
81290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lo *'"
82290283feSshess} {}
83290283feSshess
84290283feSshess# Stand-alone * is dropped.
85290283feSshessdo_test fts2n-1.9 {
86290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH '*'"
87290283feSshess} {}
88290283feSshess
89290283feSshess# Phrase-query prefix.
90290283feSshessdo_test fts2n-1.10 {
91290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH '\"lovely r*\"'"
92290283feSshess} {2}
93290283feSshessdo_test fts2n-1.11 {
94290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH '\"lovely r\"'"
95290283feSshess} {}
96290283feSshess
97290283feSshess# Phrase query with multiple prefix matches.
98290283feSshessdo_test fts2n-1.12 {
99290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH '\"a* l*\"'"
100290283feSshess} {1 2}
101290283feSshess
102290283feSshess# Phrase query with multiple prefix matches.
103290283feSshessdo_test fts2n-1.13 {
104290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH '\"a* l* row\"'"
105290283feSshess} {2}
106290283feSshess
107290283feSshess
108290283feSshess
109290283feSshess
110290283feSshess# Test across updates (and, by implication, deletes).
111290283feSshess
112290283feSshess# Version of text without "lorem".
113290283feSshessregsub -all {[Ll]orem} $text '' ntext
114290283feSshess
115290283feSshessdb eval {
116290283feSshess  CREATE VIRTUAL TABLE t2 USING fts2(c);
117290283feSshess
118290283feSshess  INSERT INTO t2(rowid, c) VALUES(1, $text);
119290283feSshess  INSERT INTO t2(rowid, c) VALUES(2, 'Another lovely row');
120290283feSshess  UPDATE t2 SET c = $ntext WHERE rowid = 1;
121290283feSshess}
122290283feSshess
123290283feSshess# Can't see lorem as an exact match.
124290283feSshessdo_test fts2n-2.1 {
125290283feSshess  execsql "SELECT rowid FROM t2 WHERE t2 MATCH 'lorem'"
126290283feSshess} {}
127290283feSshess
128290283feSshess# Can't see a prefix of lorem, either.
129290283feSshessdo_test fts2n-2.2 {
130290283feSshess  execsql "SELECT rowid FROM t2 WHERE t2 MATCH 'lore*'"
131290283feSshess} {}
132290283feSshess
133290283feSshess# Can see lovely in the other document.
134290283feSshessdo_test fts2n-2.3 {
135290283feSshess  execsql "SELECT rowid FROM t2 WHERE t2 MATCH 'lo*'"
136290283feSshess} {2}
137290283feSshess
138290283feSshess# Can still see other hits.
139290283feSshessdo_test fts2n-2.4 {
140290283feSshess  execsql "SELECT rowid FROM t2 WHERE t2 MATCH 'l*'"
141290283feSshess} {1 2}
142290283feSshess
143290283feSshess# Prefix which should only hit one document.
144290283feSshessdo_test fts2n-2.5 {
145290283feSshess  execsql "SELECT rowid FROM t2 WHERE t2 MATCH 'lov*'"
146290283feSshess} {2}
147290283feSshess
148290283feSshess
149290283feSshess
150290283feSshess# Test with a segment which will have multiple levels in the tree.
151290283feSshess
152290283feSshess# Build a big document with lots of unique terms.
153290283feSshessset bigtext $text
154290283feSshessforeach c {a b c d e} {
155290283feSshess  regsub -all {[A-Za-z]+} $bigtext "&$c" t
156290283feSshess  append bigtext $t
157290283feSshess}
158290283feSshess
159290283feSshess# Populate a table with many copies of the big document, so that we
160290283feSshess# can test the number of hits found.  Populate $ret with the expected
161290283feSshess# hit counts for each row.  offsets() returns 4 elements for every
162290283feSshess# hit.  We'll have 6 hits for row 1, 1 for row 2, and 6*(2^5)==192 for
163290283feSshess# $bigtext.
164290283feSshessset ret {6 1}
165290283feSshessdb eval {
166290283feSshess  BEGIN;
167290283feSshess  CREATE VIRTUAL TABLE t3 USING fts2(c);
168290283feSshess
169290283feSshess  INSERT INTO t3(rowid, c) VALUES(1, $text);
170290283feSshess  INSERT INTO t3(rowid, c) VALUES(2, 'Another lovely row');
171290283feSshess}
172290283feSshessfor {set i 0} {$i<100} {incr i} {
173290283feSshess  db eval {INSERT INTO t3(rowid, c) VALUES(3+$i, $bigtext)}
174290283feSshess  lappend ret 192
175290283feSshess}
176290283feSshessdb eval {COMMIT;}
177290283feSshess
178290283feSshess# Test that we get the expected number of hits.
179290283feSshessdo_test fts2n-3.1 {
180290283feSshess  set t {}
181290283feSshess  db eval {SELECT offsets(t3) as o FROM t3 WHERE t3 MATCH 'l*'} {
182290283feSshess    set l [llength $o]
183290283feSshess    lappend t [expr {$l/4}]
184290283feSshess  }
185290283feSshess  set t
186290283feSshess} $ret
187290283feSshess
188290283feSshess# TODO(shess) It would be useful to test a couple edge cases, but I
189290283feSshess# don't know if we have the precision to manage it from here at this
190290283feSshess# time.  Prefix hits can cross leaves, which the code above _should_
191290283feSshess# hit by virtue of size.  There are two variations on this.  If the
192290283feSshess# tree is 2 levels high, the code will find the leaf-node extent
193*85b623f2Sdrh# directly, but if its higher, the code will have to follow two
194290283feSshess# separate interior branches down the tree.  Both should be tested.
195290283feSshess
196290283feSshessfinish_test
197