xref: /sqlite-3.40.0/ext/fts5/test/fts5ab.test (revision a690ff36)
1# 2014 June 17
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# This file implements regression tests for SQLite library.  The
12# focus of this script is testing the FTS5 module.
13#
14#
15
16source [file join [file dirname [info script]] fts5_common.tcl]
17set testprefix fts5ab
18
19# If SQLITE_ENABLE_FTS5 is defined, omit this file.
20ifcapable !fts5 {
21  finish_test
22  return
23}
24
25foreach_detail_mode $testprefix {
26
27do_execsql_test 1.0 {
28  CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL%);
29  INSERT INTO t1 VALUES('hello', 'world');
30  INSERT INTO t1 VALUES('one two', 'three four');
31  INSERT INTO t1(rowid, a, b) VALUES(45, 'forty', 'five');
32}
33
34do_execsql_test 1.1 {
35  SELECT * FROM t1 ORDER BY rowid DESC;
36} { forty five {one two} {three four} hello world }
37
38do_execsql_test 1.2 {
39  SELECT rowid FROM t1 ORDER BY rowid DESC;
40} {45 2 1}
41
42do_execsql_test 1.3 {
43  SELECT rowid FROM t1 ORDER BY rowid ASC;
44} {1 2 45}
45
46do_execsql_test 1.4 {
47  SELECT * FROM t1 WHERE rowid=2;
48} {{one two} {three four}}
49
50do_execsql_test 1.5 {
51  SELECT * FROM t1 WHERE rowid=2.01;
52} {}
53
54do_execsql_test 1.6 {
55  SELECT * FROM t1 WHERE rowid=1.99;
56} {}
57
58#-------------------------------------------------------------------------
59
60reset_db
61do_execsql_test 2.1 {
62  CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%);
63  INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
64  INSERT INTO t1 VALUES('one');
65  INSERT INTO t1 VALUES('two');
66  INSERT INTO t1 VALUES('three');
67}
68
69do_catchsql_test 2.2 {
70  SELECT rowid, * FROM t1 WHERE t1 MATCH 'AND AND'
71} {1 {fts5: syntax error near "AND"}}
72
73do_execsql_test 2.3 { SELECT rowid, * FROM t1 WHERE t1 MATCH 'two' } {2 two}
74do_execsql_test 2.4 { SELECT rowid, * FROM t1 WHERE t1 MATCH 'three' } {3 three}
75do_execsql_test 2.5 { SELECT rowid, * FROM t1 WHERE t1 MATCH 'one' } {1 one}
76
77do_execsql_test 2.6 {
78  INSERT INTO t1 VALUES('a b c d e f g');
79  INSERT INTO t1 VALUES('b d e a a a i');
80  INSERT INTO t1 VALUES('x y z b c c c');
81}
82
83foreach {tn expr res} {
84  1  a    {5 4}
85  2  b    {6 5 4}
86  3  c    {6 4}
87  4  d    {5 4}
88  5  e    {5 4}
89  6  f    {4}
90  7  g    {4}
91  8  x    {6}
92  9  y    {6}
93  10 z    {6}
94} {
95  do_execsql_test 2.7.$tn.1 {
96    SELECT rowid FROM t1 WHERE t1 MATCH $expr ORDER BY rowid DESC
97  } $res
98  do_execsql_test 2.7.$tn.2 {
99    SELECT rowid FROM t1 WHERE t1 MATCH $expr ORDER BY rowid ASC
100  } [lsort -integer $res]
101}
102
103#-------------------------------------------------------------------------
104#
105reset_db
106do_execsql_test 3.0 {
107  CREATE VIRTUAL TABLE t1 USING fts5(a,b);
108  INSERT INTO t1(t1, rank) VALUES('pgsz', 32);
109}
110
111foreach {tn a b} {
112   1 {abashed abandons abase abash abaft} {abases abased}
113   2 {abasing abases abaft abated abandons} {abases abandoned}
114   3 {abatement abash abash abated abase} {abasements abashing}
115   4 {abaft abasements abase abasement abasing} {abasement abases}
116   5 {abaft abashing abatement abash abasements} {abandons abandoning}
117   6 {aback abate abasements abashes abandoned} {abasement abased}
118   7 {abandons abated abased aback abandoning} {abases abandoned}
119   8 {abashing abases abasement abaft abashing} {abashed abate}
120   9 {abash abase abate abashing abashed} {abandon abandoned}
121   10 {abate abandoning abandons abasement aback} {abandon abandoning}
122} {
123  do_execsql_test 3.1.$tn.1 { INSERT INTO t1 VALUES($a, $b) }
124  do_execsql_test 3.1.$tn.2 { INSERT INTO t1(t1) VALUES('integrity-check') }
125}
126
127foreach {tn expr res} {
128  1 {abash} {9 5 3 1}
129  2 {abase} {9 4 3 1}
130  3 {abase + abash} {1}
131  4 {abash + abase} {9}
132  5 {abaft + abashing} {8 5}
133  6 {abandon + abandoning} {10}
134  7 {"abashing abases abasement abaft abashing"} {8}
135} {
136  do_execsql_test 3.2.$tn {
137    SELECT rowid FROM t1 WHERE t1 MATCH $expr ORDER BY rowid DESC
138  } $res
139}
140
141do_execsql_test 3.3 {
142  SELECT rowid FROM t1 WHERE t1 MATCH 'NEAR(aback abate, 2)'
143} {6}
144
145foreach {tn expr res} {
146  1 {abash} {1 3 5 9}
147  2 {abase} {1 3 4 9}
148  3 {abase + abash} {1}
149  4 {abash + abase} {9}
150  5 {abaft + abashing} {5 8}
151  6 {abandon + abandoning} {10}
152  7 {"abashing abases abasement abaft abashing"} {8}
153} {
154  do_execsql_test 3.4.$tn {
155    SELECT rowid FROM t1 WHERE t1 MATCH $expr
156  } $res
157}
158
159#-------------------------------------------------------------------------
160# Documents with more than 2M tokens.
161#
162
163do_execsql_test 4.0 {
164  CREATE VIRTUAL TABLE s1 USING fts5(x, detail=%DETAIL%);
165}
166foreach {tn doc} [list \
167  1 [string repeat {a x } 1500000]       \
168  2 "[string repeat {a a } 1500000] x"   \
169] {
170  do_execsql_test 4.$tn { INSERT INTO s1 VALUES($doc) }
171}
172
173do_execsql_test 4.3 {
174  SELECT rowid FROM s1 WHERE s1 MATCH 'x'
175} {1 2}
176
177if {[detail_is_full]} {
178  do_execsql_test 4.4 {
179    SELECT rowid FROM s1 WHERE s1 MATCH '"a x"'
180  } {1 2}
181}
182
183do_execsql_test 4.5 {
184  SELECT rowid FROM s1 WHERE s1 MATCH 'a x'
185} {1 2}
186
187#-------------------------------------------------------------------------
188# Check that a special case of segment promotion works. The case is where
189# a new segment is written to level L, but the oldest segment within level
190# (L-2) is larger than it.
191#
192do_execsql_test 5.0 {
193  CREATE VIRTUAL TABLE s2 USING fts5(x, detail=%DETAIL%);
194  INSERT INTO s2(s2, rank) VALUES('pgsz', 32);
195  INSERT INTO s2(s2, rank) VALUES('automerge', 0);
196}
197
198proc rnddoc {n} {
199  set map [list 0 a  1 b  2 c  3 d  4 e  5 f  6 g  7 h  8 i  9 j]
200  set doc [list]
201  for {set i 0} {$i < $n} {incr i} {
202    lappend doc [string map $map [format %.3d [expr int(rand()*1000)]]]
203  }
204  set doc
205}
206db func rnddoc rnddoc
207
208do_test 5.1 {
209  for {set i 1} {$i <= 65} {incr i} {
210    execsql { INSERT INTO s2 VALUES(rnddoc(10)) }
211  }
212  for {set i 1} {$i <= 63} {incr i} {
213    execsql { DELETE FROM s2 WHERE rowid = $i }
214  }
215  fts5_level_segs s2
216} {0 8}
217
218do_test 5.2 {
219  execsql {
220    INSERT INTO s2(s2, rank) VALUES('automerge', 8);
221  }
222  for {set i 0} {$i < 7} {incr i} {
223    execsql { INSERT INTO s2 VALUES(rnddoc(50)) }
224  }
225  fts5_level_segs s2
226} {8 0 0}
227
228# Test also the other type of segment promotion - when a new segment is written
229# that is larger than segments immediately following it.
230do_test 5.3 {
231  execsql {
232    DROP TABLE s2;
233    CREATE VIRTUAL TABLE s2 USING fts5(x, detail=%DETAIL%);
234    INSERT INTO s2(s2, rank) VALUES('pgsz', 32);
235    INSERT INTO s2(s2, rank) VALUES('automerge', 0);
236  }
237
238  for {set i 1} {$i <= 16} {incr i} {
239    execsql { INSERT INTO s2 VALUES(rnddoc(5)) }
240  }
241  fts5_level_segs s2
242} {0 1}
243
244do_test 5.4 {
245  execsql { INSERT INTO s2 VALUES(rnddoc(160)) }
246  fts5_level_segs s2
247} {2 0}
248
249#-------------------------------------------------------------------------
250#
251do_execsql_test 6.0 {
252  CREATE VIRTUAL TABLE s3 USING fts5(x, detail=%DETAIL%);
253  BEGIN;
254    INSERT INTO s3 VALUES('a b c');
255    INSERT INTO s3 VALUES('A B C');
256}
257
258do_execsql_test 6.1.1 {
259  SELECT rowid FROM s3 WHERE s3 MATCH 'a'
260} {1 2}
261
262do_execsql_test 6.1.2 {
263  SELECT rowid FROM s3 WHERE s3 MATCH 'a' ORDER BY rowid DESC
264} {2 1}
265
266do_execsql_test 6.2 {
267  COMMIT;
268}
269
270do_execsql_test 6.3 {
271  SELECT rowid FROM s3 WHERE s3 MATCH 'a'
272} {1 2}
273
274do_test 6.4 {
275  db close
276  sqlite3 db test.db
277  execsql {
278    BEGIN;
279      INSERT INTO s3(s3) VALUES('optimize');
280    ROLLBACK;
281  }
282} {}
283
284#-------------------------------------------------------------------------
285#
286set doc [string repeat "a b c " 500]
287do_execsql_test 7.0 {
288  CREATE VIRTUAL TABLE x1 USING fts5(x, detail=%DETAIL%);
289  INSERT INTO x1(x1, rank) VALUES('pgsz', 32);
290  INSERT INTO x1 VALUES($doc);
291}
292
293} ;# foreach_detail_mode...
294
295
296finish_test
297