xref: /sqlite-3.40.0/test/fts2n.test (revision 290283fe)
1*290283feSshess# 2007 April 26
2*290283feSshess#
3*290283feSshess# The author disclaims copyright to this source code.
4*290283feSshess#
5*290283feSshess#*************************************************************************
6*290283feSshess# This file implements tests for prefix-searching in the fts2
7*290283feSshess# component of the SQLite library.
8*290283feSshess#
9*290283feSshess# $Id: fts2n.test,v 1.1 2007/05/01 18:25:53 shess Exp $
10*290283feSshess#
11*290283feSshess
12*290283feSshessset testdir [file dirname $argv0]
13*290283feSshesssource $testdir/tester.tcl
14*290283feSshess
15*290283feSshess# If SQLITE_ENABLE_FTS2 is defined, omit this file.
16*290283feSshessifcapable !fts2 {
17*290283feSshess  finish_test
18*290283feSshess  return
19*290283feSshess}
20*290283feSshess
21*290283feSshess# A large string to prime the pump with.
22*290283feSshessset text {
23*290283feSshess  Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas
24*290283feSshess  iaculis mollis ipsum. Praesent rhoncus placerat justo. Duis non quam
25*290283feSshess  sed turpis posuere placerat. Curabitur et lorem in lorem porttitor
26*290283feSshess  aliquet. Pellentesque bibendum tincidunt diam. Vestibulum blandit
27*290283feSshess  ante nec elit. In sapien diam, facilisis eget, dictum sed, viverra
28*290283feSshess  at, felis. Vestibulum magna. Sed magna dolor, vestibulum rhoncus,
29*290283feSshess  ornare vel, vulputate sit amet, felis. Integer malesuada, tellus at
30*290283feSshess  luctus gravida, diam nunc porta nibh, nec imperdiet massa metus eu
31*290283feSshess  lectus. Aliquam nisi. Nunc fringilla nulla at lectus. Suspendisse
32*290283feSshess  potenti. Cum sociis natoque penatibus et magnis dis parturient
33*290283feSshess  montes, nascetur ridiculus mus. Pellentesque odio nulla, feugiat eu,
34*290283feSshess  suscipit nec, consequat quis, risus.
35*290283feSshess}
36*290283feSshess
37*290283feSshessdb eval {
38*290283feSshess  CREATE VIRTUAL TABLE t1 USING fts2(c);
39*290283feSshess
40*290283feSshess  INSERT INTO t1(rowid, c) VALUES(1, $text);
41*290283feSshess  INSERT INTO t1(rowid, c) VALUES(2, 'Another lovely row');
42*290283feSshess}
43*290283feSshess
44*290283feSshess# Exact match
45*290283feSshessdo_test fts2n-1.1 {
46*290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lorem'"
47*290283feSshess} {1}
48*290283feSshess
49*290283feSshess# And a prefix
50*290283feSshessdo_test fts2n-1.2 {
51*290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lore*'"
52*290283feSshess} {1}
53*290283feSshess
54*290283feSshess# Prefix includes exact match
55*290283feSshessdo_test fts2n-1.3 {
56*290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lorem*'"
57*290283feSshess} {1}
58*290283feSshess
59*290283feSshess# Make certain everything isn't considered a prefix!
60*290283feSshessdo_test fts2n-1.4 {
61*290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lore'"
62*290283feSshess} {}
63*290283feSshess
64*290283feSshess# Prefix across multiple rows.
65*290283feSshessdo_test fts2n-1.5 {
66*290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lo*'"
67*290283feSshess} {1 2}
68*290283feSshess
69*290283feSshess# Likewise, with multiple hits in one document.
70*290283feSshessdo_test fts2n-1.6 {
71*290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'l*'"
72*290283feSshess} {1 2}
73*290283feSshess
74*290283feSshess# Prefix which should only hit one document.
75*290283feSshessdo_test fts2n-1.7 {
76*290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lov*'"
77*290283feSshess} {2}
78*290283feSshess
79*290283feSshess# * not at end is dropped.
80*290283feSshessdo_test fts2n-1.8 {
81*290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH 'lo *'"
82*290283feSshess} {}
83*290283feSshess
84*290283feSshess# Stand-alone * is dropped.
85*290283feSshessdo_test fts2n-1.9 {
86*290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH '*'"
87*290283feSshess} {}
88*290283feSshess
89*290283feSshess# Phrase-query prefix.
90*290283feSshessdo_test fts2n-1.10 {
91*290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH '\"lovely r*\"'"
92*290283feSshess} {2}
93*290283feSshessdo_test fts2n-1.11 {
94*290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH '\"lovely r\"'"
95*290283feSshess} {}
96*290283feSshess
97*290283feSshess# Phrase query with multiple prefix matches.
98*290283feSshessdo_test fts2n-1.12 {
99*290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH '\"a* l*\"'"
100*290283feSshess} {1 2}
101*290283feSshess
102*290283feSshess# Phrase query with multiple prefix matches.
103*290283feSshessdo_test fts2n-1.13 {
104*290283feSshess  execsql "SELECT rowid FROM t1 WHERE t1 MATCH '\"a* l* row\"'"
105*290283feSshess} {2}
106*290283feSshess
107*290283feSshess
108*290283feSshess
109*290283feSshess
110*290283feSshess# Test across updates (and, by implication, deletes).
111*290283feSshess
112*290283feSshess# Version of text without "lorem".
113*290283feSshessregsub -all {[Ll]orem} $text '' ntext
114*290283feSshess
115*290283feSshessdb eval {
116*290283feSshess  CREATE VIRTUAL TABLE t2 USING fts2(c);
117*290283feSshess
118*290283feSshess  INSERT INTO t2(rowid, c) VALUES(1, $text);
119*290283feSshess  INSERT INTO t2(rowid, c) VALUES(2, 'Another lovely row');
120*290283feSshess  UPDATE t2 SET c = $ntext WHERE rowid = 1;
121*290283feSshess}
122*290283feSshess
123*290283feSshess# Can't see lorem as an exact match.
124*290283feSshessdo_test fts2n-2.1 {
125*290283feSshess  execsql "SELECT rowid FROM t2 WHERE t2 MATCH 'lorem'"
126*290283feSshess} {}
127*290283feSshess
128*290283feSshess# Can't see a prefix of lorem, either.
129*290283feSshessdo_test fts2n-2.2 {
130*290283feSshess  execsql "SELECT rowid FROM t2 WHERE t2 MATCH 'lore*'"
131*290283feSshess} {}
132*290283feSshess
133*290283feSshess# Can see lovely in the other document.
134*290283feSshessdo_test fts2n-2.3 {
135*290283feSshess  execsql "SELECT rowid FROM t2 WHERE t2 MATCH 'lo*'"
136*290283feSshess} {2}
137*290283feSshess
138*290283feSshess# Can still see other hits.
139*290283feSshessdo_test fts2n-2.4 {
140*290283feSshess  execsql "SELECT rowid FROM t2 WHERE t2 MATCH 'l*'"
141*290283feSshess} {1 2}
142*290283feSshess
143*290283feSshess# Prefix which should only hit one document.
144*290283feSshessdo_test fts2n-2.5 {
145*290283feSshess  execsql "SELECT rowid FROM t2 WHERE t2 MATCH 'lov*'"
146*290283feSshess} {2}
147*290283feSshess
148*290283feSshess
149*290283feSshess
150*290283feSshess# Test with a segment which will have multiple levels in the tree.
151*290283feSshess
152*290283feSshess# Build a big document with lots of unique terms.
153*290283feSshessset bigtext $text
154*290283feSshessforeach c {a b c d e} {
155*290283feSshess  regsub -all {[A-Za-z]+} $bigtext "&$c" t
156*290283feSshess  append bigtext $t
157*290283feSshess}
158*290283feSshess
159*290283feSshess# Populate a table with many copies of the big document, so that we
160*290283feSshess# can test the number of hits found.  Populate $ret with the expected
161*290283feSshess# hit counts for each row.  offsets() returns 4 elements for every
162*290283feSshess# hit.  We'll have 6 hits for row 1, 1 for row 2, and 6*(2^5)==192 for
163*290283feSshess# $bigtext.
164*290283feSshessset ret {6 1}
165*290283feSshessdb eval {
166*290283feSshess  BEGIN;
167*290283feSshess  CREATE VIRTUAL TABLE t3 USING fts2(c);
168*290283feSshess
169*290283feSshess  INSERT INTO t3(rowid, c) VALUES(1, $text);
170*290283feSshess  INSERT INTO t3(rowid, c) VALUES(2, 'Another lovely row');
171*290283feSshess}
172*290283feSshessfor {set i 0} {$i<100} {incr i} {
173*290283feSshess  db eval {INSERT INTO t3(rowid, c) VALUES(3+$i, $bigtext)}
174*290283feSshess  lappend ret 192
175*290283feSshess}
176*290283feSshessdb eval {COMMIT;}
177*290283feSshess
178*290283feSshess# Test that we get the expected number of hits.
179*290283feSshessdo_test fts2n-3.1 {
180*290283feSshess  set t {}
181*290283feSshess  db eval {SELECT offsets(t3) as o FROM t3 WHERE t3 MATCH 'l*'} {
182*290283feSshess    set l [llength $o]
183*290283feSshess    lappend t [expr {$l/4}]
184*290283feSshess  }
185*290283feSshess  set t
186*290283feSshess} $ret
187*290283feSshess
188*290283feSshess# TODO(shess) It would be useful to test a couple edge cases, but I
189*290283feSshess# don't know if we have the precision to manage it from here at this
190*290283feSshess# time.  Prefix hits can cross leaves, which the code above _should_
191*290283feSshess# hit by virtue of size.  There are two variations on this.  If the
192*290283feSshess# tree is 2 levels high, the code will find the leaf-node extent
193*290283feSshess# directly, but if it's higher, the code will have to follow two
194*290283feSshess# separate interior branches down the tree.  Both should be tested.
195*290283feSshess
196*290283feSshessfinish_test
197