blob: 4a0a811b464a8d609715220365cbbb769088957c [file] [log] [blame]
danielk197733e89032008-12-17 15:18:17 +00001# 2006 September 9
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 FTS3 module.
13#
drhb39187a2009-01-01 12:34:45 +000014# $Id: fts3expr.test,v 1.5 2009/01/01 12:34:46 drh Exp $
danielk197733e89032008-12-17 15:18:17 +000015#
16
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
19
20# If SQLITE_ENABLE_FTS3 is defined, omit this file.
21ifcapable !fts3 {
22 finish_test
23 return
24}
25
26set sqlite_fts3_enable_parentheses 1
27
28proc test_fts3expr {expr} {
29 db one {SELECT fts3_exprtest('simple', $expr, 'a', 'b', 'c')}
30}
31do_test fts3expr-1.0 {
32 test_fts3expr "abcd"
33} {PHRASE 3 0 abcd}
34do_test fts3expr-1.1 {
35 test_fts3expr " tag "
36} {PHRASE 3 0 tag}
37
38do_test fts3expr-1.2 {
39 test_fts3expr "ab AND cd"
40} {AND {PHRASE 3 0 ab} {PHRASE 3 0 cd}}
drhb39187a2009-01-01 12:34:45 +000041do_test fts3expr-1.2.1 {
42 test_fts3expr "ab cd"
43} {AND {PHRASE 3 0 ab} {PHRASE 3 0 cd}}
danielk197733e89032008-12-17 15:18:17 +000044do_test fts3expr-1.3 {
45 test_fts3expr "ab OR cd"
46} {OR {PHRASE 3 0 ab} {PHRASE 3 0 cd}}
47do_test fts3expr-1.4 {
48 test_fts3expr "ab NOT cd"
49} {NOT {PHRASE 3 0 ab} {PHRASE 3 0 cd}}
50do_test fts3expr-1.5 {
51 test_fts3expr "ab NEAR cd"
52} {NEAR/10 {PHRASE 3 0 ab} {PHRASE 3 0 cd}}
drhb39187a2009-01-01 12:34:45 +000053do_test fts3expr-1.6.1 {
danielk197733e89032008-12-17 15:18:17 +000054 test_fts3expr "ab NEAR/5 cd"
55} {NEAR/5 {PHRASE 3 0 ab} {PHRASE 3 0 cd}}
drhb39187a2009-01-01 12:34:45 +000056do_test fts3expr-1.6.2 {
57 test_fts3expr "ab NEAR/87654321 cd"
58} {NEAR/87654321 {PHRASE 3 0 ab} {PHRASE 3 0 cd}}
59do_test fts3expr-1.6.3 {
60 test_fts3expr "ab NEAR/7654321 cd"
61} {NEAR/7654321 {PHRASE 3 0 ab} {PHRASE 3 0 cd}}
62do_test fts3expr-1.6.4 {
63 test_fts3expr "ab NEAR/654321 cd"
64} {NEAR/654321 {PHRASE 3 0 ab} {PHRASE 3 0 cd}}
65do_test fts3expr-1.6.5 {
66 test_fts3expr "ab NEAR/54321 cd"
67} {NEAR/54321 {PHRASE 3 0 ab} {PHRASE 3 0 cd}}
68do_test fts3expr-1.6.6 {
69 test_fts3expr "ab NEAR/4321 cd"
70} {NEAR/4321 {PHRASE 3 0 ab} {PHRASE 3 0 cd}}
71do_test fts3expr-1.6.7 {
72 test_fts3expr "ab NEAR/321 cd"
73} {NEAR/321 {PHRASE 3 0 ab} {PHRASE 3 0 cd}}
74do_test fts3expr-1.6.8 {
75 test_fts3expr "ab NEAR/21 cd"
76} {NEAR/21 {PHRASE 3 0 ab} {PHRASE 3 0 cd}}
danielk197733e89032008-12-17 15:18:17 +000077
78do_test fts3expr-1.7 {
79 test_fts3expr {"one two three"}
80} {PHRASE 3 0 one two three}
drhb39187a2009-01-01 12:34:45 +000081do_test fts3expr-1.8.1 {
danielk197733e89032008-12-17 15:18:17 +000082 test_fts3expr {zero "one two three" four}
83} {AND {AND {PHRASE 3 0 zero} {PHRASE 3 0 one two three}} {PHRASE 3 0 four}}
drhb39187a2009-01-01 12:34:45 +000084do_test fts3expr-1.8.2 {
85 test_fts3expr {zero AND "one two three" four}
86} {AND {AND {PHRASE 3 0 zero} {PHRASE 3 0 one two three}} {PHRASE 3 0 four}}
87do_test fts3expr-1.8.3 {
88 test_fts3expr {zero "one two three" AND four}
89} {AND {AND {PHRASE 3 0 zero} {PHRASE 3 0 one two three}} {PHRASE 3 0 four}}
90do_test fts3expr-1.8.4 {
91 test_fts3expr {zero AND "one two three" AND four}
92} {AND {AND {PHRASE 3 0 zero} {PHRASE 3 0 one two three}} {PHRASE 3 0 four}}
93do_test fts3expr-1.9.1 {
94 test_fts3expr {"one* two three"}
95} {PHRASE 3 0 one+ two three}
96do_test fts3expr-1.9.2 {
97 test_fts3expr {"one two* three"}
98} {PHRASE 3 0 one two+ three}
99do_test fts3expr-1.9.3 {
100 test_fts3expr {"one* two* three"}
101} {PHRASE 3 0 one+ two+ three}
102do_test fts3expr-1.9.4 {
103 test_fts3expr {"one two three*"}
104} {PHRASE 3 0 one two three+}
105do_test fts3expr-1.9.5 {
danielk197733e89032008-12-17 15:18:17 +0000106 test_fts3expr {"one* two three*"}
107} {PHRASE 3 0 one+ two three+}
drhb39187a2009-01-01 12:34:45 +0000108do_test fts3expr-1.9.6 {
109 test_fts3expr {"one two* three*"}
110} {PHRASE 3 0 one two+ three+}
111do_test fts3expr-1.9.7 {
112 test_fts3expr {"one* two* three*"}
113} {PHRASE 3 0 one+ two+ three+}
danielk197733e89032008-12-17 15:18:17 +0000114
115do_test fts3expr-1.10 {
116 test_fts3expr {one* two}
117} {AND {PHRASE 3 0 one+} {PHRASE 3 0 two}}
118do_test fts3expr-1.11 {
119 test_fts3expr {one two*}
120} {AND {PHRASE 3 0 one} {PHRASE 3 0 two+}}
121
122do_test fts3expr-1.14 {
123 test_fts3expr {a:one two}
124} {AND {PHRASE 0 0 one} {PHRASE 3 0 two}}
125do_test fts3expr-1.15 {
126 test_fts3expr {one b:two}
127} {AND {PHRASE 3 0 one} {PHRASE 1 0 two}}
128
drhb39187a2009-01-01 12:34:45 +0000129do_test fts3expr-1.16 {
130 test_fts3expr {one AND two AND three AND four AND five}
131} [list AND \
132 [list AND \
133 [list AND \
134 [list AND {PHRASE 3 0 one} {PHRASE 3 0 two}] \
135 {PHRASE 3 0 three} \
136 ] \
137 {PHRASE 3 0 four} \
138 ] \
139 {PHRASE 3 0 five} \
140 ]
141do_test fts3expr-1.17 {
142 test_fts3expr {(one AND two) AND ((three AND four) AND five)}
143} [list AND \
144 [list AND {PHRASE 3 0 one} {PHRASE 3 0 two}] \
145 [list AND \
146 [list AND {PHRASE 3 0 three} {PHRASE 3 0 four}] \
147 {PHRASE 3 0 five} \
148 ] \
149 ]
150do_test fts3expr-1.18 {
151 test_fts3expr {(one AND two) OR ((three AND four) AND five)}
152} [list OR \
153 [list AND {PHRASE 3 0 one} {PHRASE 3 0 two}] \
154 [list AND \
155 [list AND {PHRASE 3 0 three} {PHRASE 3 0 four}] \
156 {PHRASE 3 0 five} \
157 ] \
158 ]
159do_test fts3expr-1.19 {
160 test_fts3expr {(one AND two) AND ((three AND four) OR five)}
161} [list AND \
162 [list AND {PHRASE 3 0 one} {PHRASE 3 0 two}] \
163 [list OR \
164 [list AND {PHRASE 3 0 three} {PHRASE 3 0 four}] \
165 {PHRASE 3 0 five} \
166 ] \
167 ]
168do_test fts3expr-1.20 {
169 test_fts3expr {(one OR two) AND ((three OR four) AND five)}
170} [list AND \
171 [list OR {PHRASE 3 0 one} {PHRASE 3 0 two}] \
172 [list AND \
173 [list OR {PHRASE 3 0 three} {PHRASE 3 0 four}] \
174 {PHRASE 3 0 five} \
175 ] \
176 ]
177do_test fts3expr-1.21 {
178 test_fts3expr {(one OR two) AND ((three NOT four) AND five)}
179} [list AND \
180 [list OR {PHRASE 3 0 one} {PHRASE 3 0 two}] \
181 [list AND \
182 [list NOT {PHRASE 3 0 three} {PHRASE 3 0 four}] \
183 {PHRASE 3 0 five} \
184 ] \
185 ]
186do_test fts3expr-1.22 {
187 test_fts3expr {(one OR two) NOT ((three OR four) AND five)}
188} [list NOT \
189 [list OR {PHRASE 3 0 one} {PHRASE 3 0 two}] \
190 [list AND \
191 [list OR {PHRASE 3 0 three} {PHRASE 3 0 four}] \
192 {PHRASE 3 0 five} \
193 ] \
194 ]
195do_test fts3expr-1.23 {
196 test_fts3expr {(((((one OR two))))) NOT (((((three OR four))) AND five))}
197} [list NOT \
198 [list OR {PHRASE 3 0 one} {PHRASE 3 0 two}] \
199 [list AND \
200 [list OR {PHRASE 3 0 three} {PHRASE 3 0 four}] \
201 {PHRASE 3 0 five} \
202 ] \
203 ]
204do_test fts3expr-1.24 {
205 test_fts3expr {one NEAR two}
206} [list NEAR/10 {PHRASE 3 0 one} {PHRASE 3 0 two}]
207do_test fts3expr-1.25 {
208 test_fts3expr {(one NEAR two)}
209} [list NEAR/10 {PHRASE 3 0 one} {PHRASE 3 0 two}]
210do_test fts3expr-1.26 {
211 test_fts3expr {((((((one NEAR two))))))}
212} [list NEAR/10 {PHRASE 3 0 one} {PHRASE 3 0 two}]
213do_test fts3expr-1.27 {
214 test_fts3expr {(one NEAR two) OR ((three OR four) AND five)}
215} [list OR \
216 [list NEAR/10 {PHRASE 3 0 one} {PHRASE 3 0 two}] \
217 [list AND \
218 [list OR {PHRASE 3 0 three} {PHRASE 3 0 four}] \
219 {PHRASE 3 0 five} \
220 ] \
221 ]
222do_test fts3expr-1.28 {
223 test_fts3expr {(one NEAR/321 two) OR ((three OR four) AND five)}
224} [list OR \
225 [list NEAR/321 {PHRASE 3 0 one} {PHRASE 3 0 two}] \
226 [list AND \
227 [list OR {PHRASE 3 0 three} {PHRASE 3 0 four}] \
228 {PHRASE 3 0 five} \
229 ] \
230 ]
231
danielk197733e89032008-12-17 15:18:17 +0000232proc strip_phrase_data {L} {
233 if {[lindex $L 0] eq "PHRASE"} {
234 return [lrange $L 3 end]
235 }
236 return [list \
237 [lindex $L 0] \
238 [strip_phrase_data [lindex $L 1]] \
239 [strip_phrase_data [lindex $L 2]] \
240 ]
241}
242proc test_fts3expr2 {expr} {
243 strip_phrase_data [
244 db one {SELECT fts3_exprtest('simple', $expr, 'a', 'b', 'c')}
245 ]
246}
247do_test fts3expr-2.1 {
248 test_fts3expr2 "ab OR cd AND ef"
249} {OR ab {AND cd ef}}
250do_test fts3expr-2.2 {
251 test_fts3expr2 "cd AND ef OR ab"
252} {OR {AND cd ef} ab}
253do_test fts3expr-2.3 {
254 test_fts3expr2 "ab AND cd AND ef OR gh"
255} {OR {AND {AND ab cd} ef} gh}
256do_test fts3expr-2.4 {
257 test_fts3expr2 "ab AND cd OR ef AND gh"
258} {OR {AND ab cd} {AND ef gh}}
259do_test fts3expr-2.5 {
260 test_fts3expr2 "ab cd"
261} {AND ab cd}
262
263do_test fts3expr-3.1 {
264 test_fts3expr2 "(ab OR cd) AND ef"
265} {AND {OR ab cd} ef}
266do_test fts3expr-3.2 {
267 test_fts3expr2 "ef AND (ab OR cd)"
268} {AND ef {OR ab cd}}
269do_test fts3expr-3.3 {
270 test_fts3expr2 "(ab OR cd)"
271} {OR ab cd}
272do_test fts3expr-3.4 {
273 test_fts3expr2 "(((ab OR cd)))"
274} {OR ab cd}
275
danielk197749b4b4d2009-01-01 04:19:51 +0000276do_test fts3expr-3.5 {
277 test_fts3expr2 "one AND (two NEAR three)"
278} {AND one {NEAR/10 two three}}
danielk19775973e6a2009-01-01 07:08:54 +0000279do_test fts3expr-3.6 {
280 test_fts3expr2 "one (two NEAR three)"
281} {AND one {NEAR/10 two three}}
282do_test fts3expr-3.7 {
283 test_fts3expr2 "(two NEAR three) one"
284} {AND {NEAR/10 two three} one}
285do_test fts3expr-3.8 {
286 test_fts3expr2 "(two NEAR three) AND one"
287} {AND {NEAR/10 two three} one}
288do_test fts3expr-3.9 {
289 test_fts3expr2 "(two NEAR three) (four five)"
290} {AND {NEAR/10 two three} {AND four five}}
291do_test fts3expr-3.10 {
292 test_fts3expr2 "(two NEAR three) AND (four five)"
293} {AND {NEAR/10 two three} {AND four five}}
294do_test fts3expr-3.11 {
295 test_fts3expr2 "(two NEAR three) (four NEAR five)"
296} {AND {NEAR/10 two three} {NEAR/10 four five}}
297do_test fts3expr-3.12 {
298 test_fts3expr2 "(two NEAR three) OR (four NEAR five)"
299} {OR {NEAR/10 two three} {NEAR/10 four five}}
300
danielk1977758bc072009-01-01 07:42:49 +0000301do_test fts3expr-3.13 {
302 test_fts3expr2 "(two NEAR/1a three)"
303} {AND {AND {AND two near} 1a} three}
304
305do_test fts3expr-3.14 {
306 test_fts3expr2 "(two NEAR// three)"
307} {AND {AND two near} three}
308do_test fts3expr-3.15 {
309 test_fts3expr2 "(two NEAR/: three)"
310} {AND {AND two near} three}
311
312do_test fts3expr-3.16 {
313 test_fts3expr2 "(two NEAR three)OR(four NEAR five)"
314} {OR {NEAR/10 two three} {NEAR/10 four five}}
315do_test fts3expr-3.17 {
316 test_fts3expr2 "(two NEAR three)OR\"four five\""
317} {OR {NEAR/10 two three} {four five}}
318do_test fts3expr-3.18 {
319 test_fts3expr2 "one \u0080wo"
320} "AND one \u0080wo"
321
322
danielk197749b4b4d2009-01-01 04:19:51 +0000323
danielk197733e89032008-12-17 15:18:17 +0000324#------------------------------------------------------------------------
325# The following tests, fts3expr-4.*, test the parsers response to syntax
326# errors in query expressions. This is done using a real fts3 table and
327# MATCH clauses, not the parser test interface.
328#
329do_test fts3expr-4.1 {
330 execsql { CREATE VIRTUAL TABLE t1 USING fts3(a, b, c) }
331} {}
332
333# Mismatched parenthesis:
334do_test fts3expr-4.2.1 {
335 catchsql { SELECT * FROM t1 WHERE t1 MATCH 'example AND (hello OR world))' }
336} {1 {SQL logic error or missing database}}
337do_test fts3expr-4.2.2 {
338 catchsql { SELECT * FROM t1 WHERE t1 MATCH 'example AND (hello OR world' }
339} {1 {SQL logic error or missing database}}
340
341# Unterminated quotation marks:
342do_test fts3expr-4.3.1 {
343 catchsql { SELECT * FROM t1 WHERE t1 MATCH 'example OR "hello world' }
344} {1 {SQL logic error or missing database}}
345do_test fts3expr-4.3.2 {
346 catchsql { SELECT * FROM t1 WHERE t1 MATCH 'example OR hello world"' }
347} {1 {SQL logic error or missing database}}
348
349# Binary operators without the required operands.
350do_test fts3expr-4.4.1 {
351 catchsql { SELECT * FROM t1 WHERE t1 MATCH 'OR hello world' }
352} {1 {SQL logic error or missing database}}
353do_test fts3expr-4.4.2 {
354 catchsql { SELECT * FROM t1 WHERE t1 MATCH 'hello world OR' }
355} {1 {SQL logic error or missing database}}
356do_test fts3expr-4.4.3 {
357 catchsql { SELECT * FROM t1 WHERE t1 MATCH 'one (hello world OR) two' }
358} {1 {SQL logic error or missing database}}
359do_test fts3expr-4.4.4 {
360 catchsql { SELECT * FROM t1 WHERE t1 MATCH 'one (OR hello world) two' }
361} {1 {SQL logic error or missing database}}
362
363# NEAR operators with something other than phrases as arguments.
364do_test fts3expr-4.5.1 {
365 catchsql { SELECT * FROM t1 WHERE t1 MATCH '(hello OR world) NEAR one' }
366} {1 {SQL logic error or missing database}}
367do_test fts3expr-4.5.2 {
368 catchsql { SELECT * FROM t1 WHERE t1 MATCH 'one NEAR (hello OR world)' }
369} {1 {SQL logic error or missing database}}
370
371#------------------------------------------------------------------------
372# The following OOM tests are designed to cover cases in fts3_expr.c.
373#
374source $testdir/malloc_common.tcl
375do_malloc_test fts3expr-malloc-1 -sqlbody {
376 SELECT fts3_exprtest('simple', 'a b c "d e f"', 'a', 'b', 'c')
377}
378do_malloc_test fts3expr-malloc-2 -tclprep {
379 set sqlite_fts3_enable_parentheses 0
380} -sqlbody {
381 SELECT fts3_exprtest('simple', 'a -b', 'a', 'b', 'c')
382} -cleanup {
383 set sqlite_fts3_enable_parentheses 1
384}
385
386#------------------------------------------------------------------------
387# The following tests are not very important. They cover error handling
388# cases in the test code, which makes test coverage easier to measure.
389#
390do_test fts3expr-5.1 {
391 catchsql { SELECT fts3_exprtest('simple', 'a b') }
392} {1 {Usage: fts3_exprtest(tokenizer, expr, col1, ...}}
393do_test fts3expr-5.2 {
394 catchsql { SELECT fts3_exprtest('doesnotexist', 'a b', 'c') }
395} {1 {No such tokenizer module}}
396do_test fts3expr-5.3 {
397 catchsql { SELECT fts3_exprtest('simple', 'a b OR', 'c') }
398} {1 {Error parsing expression}}
399
400#------------------------------------------------------------------------
401# The next set of tests verifies that things actually work as they are
402# supposed to when using the new syntax.
403#
404do_test fts3expr-6.1 {
405 execsql {
406 CREATE VIRTUAL TABLE t1 USING fts3(a);
407 }
408 for {set ii 1} {$ii < 32} {incr ii} {
409 set v [list]
410 if {$ii & 1} { lappend v one }
411 if {$ii & 2} { lappend v two }
412 if {$ii & 4} { lappend v three }
413 if {$ii & 8} { lappend v four }
414 if {$ii & 16} { lappend v five }
415 execsql { INSERT INTO t1 VALUES($v) }
416 }
417
418 execsql {SELECT rowid FROM t1 WHERE t1 MATCH 'five four one' ORDER BY rowid}
419} {25 27 29 31}
420
421foreach {id expr res} {
422
423 2 "five four NOT one" {24 26 28 30}
424
425 3 "five AND four OR one"
426 {1 3 5 7 9 11 13 15 17 19 21 23 24 25 26 27 28 29 30 31}
427
428 4 "five AND (four OR one)" {17 19 21 23 24 25 26 27 28 29 30 31}
429
430 5 "five NOT (four OR one)" {16 18 20 22}
431
432 6 "(five NOT (four OR one)) OR (five AND (four OR one))"
433 {16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31}
434
435 7 "(five OR one) AND two AND three" {7 15 22 23 30 31}
436
437 8 "five OR one AND two AND three"
438 {7 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31}
439
440 9 "five OR one two three"
441 {7 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31}
442
443 10 "five OR \"one two three\""
444 {7 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31}
445
446 11 "one two OR four five NOT three" {3 7 11 15 19 23 24 25 26 27 31}
447
448 12 "(one two OR four five) NOT three" {3 11 19 24 25 26 27}
449
450 13 "((((((one two OR four five)))))) NOT three" {3 11 19 24 25 26 27}
451
452} {
453 do_test fts3expr-6.$id {
454 execsql { SELECT rowid FROM t1 WHERE t1 MATCH $expr ORDER BY rowid }
455 } $res
456}
457
458set sqlite_fts3_enable_parentheses 0
459finish_test