Annotation of embedaddon/sqlite3/test/e_fts3.test, revision 1.1.1.1
1.1 misho 1: # 2009 November 28
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: # This file implements tests to verify the "testable statements" in the
13: # fts3.in document.
14: #
15:
16: set testdir [file dirname $argv0]
17: source $testdir/tester.tcl
18:
19: # If this build does not include FTS3, skip the tests in this file.
20: #
21: ifcapable !fts3 { finish_test ; return }
22: source $testdir/fts3_common.tcl
23: source $testdir/malloc_common.tcl
24:
25: # Procs used to make the tests in this file easier to read.
26: #
27: proc ddl_test {tn ddl} {
28: uplevel [list do_write_test e_fts3-$tn sqlite_master $ddl]
29: }
30: proc write_test {tn tbl sql} {
31: uplevel [list do_write_test e_fts3-$tn $tbl $sql]
32: }
33: proc read_test {tn sql result} {
34: uplevel [list do_select_test e_fts3-$tn $sql $result]
35: }
36: proc error_test {tn sql result} {
37: uplevel [list do_error_test e_fts3-$tn $sql $result]
38: }
39:
40:
41: #-------------------------------------------------------------------------
42: # The body of the following [foreach] block contains test cases to verify
43: # that the example code in fts3.html works as expected. The tests run three
44: # times, with different values for DO_MALLOC_TEST.
45: #
46: # DO_MALLOC_TEST=0: Run tests with no OOM errors.
47: # DO_MALLOC_TEST=1: Run tests with transient OOM errors.
48: # DO_MALLOC_TEST=2: Run tests with persistent OOM errors.
49: #
50: foreach {DO_MALLOC_TEST enc} {
51: 0 utf-8
52: 1 utf-8
53: 2 utf-8
54: 1 utf-16
55: } {
56:
57: #if {$DO_MALLOC_TEST} break
58:
59: # Reset the database and database connection. If this iteration of the
60: # [foreach] loop is testing with OOM errors, disable the lookaside buffer.
61: #
62: db close
63: forcedelete test.db test.db-journal
64: sqlite3 db test.db
65: if {$DO_MALLOC_TEST} { sqlite3_db_config_lookaside db 0 0 0 }
66: db eval "PRAGMA encoding = '$enc'"
67:
68: proc mit {blob} {
69: set scan(littleEndian) i*
70: set scan(bigEndian) I*
71: binary scan $blob $scan($::tcl_platform(byteOrder)) r
72: return $r
73: }
74: db func mit mit
75:
76: ##########################################################################
77: # Test the example CREATE VIRTUAL TABLE statements in section 1.1
78: # of fts3.in.
79: #
80: ddl_test 1.1.1.1 {CREATE VIRTUAL TABLE data USING fts3()}
81: read_test 1.1.1.2 {PRAGMA table_info(data)} {0 content {} 0 {} 0}
82:
83: ddl_test 1.1.2.1 {
84: CREATE VIRTUAL TABLE pages USING fts3(title, keywords, body)
85: }
86: read_test 1.1.2.2 {
87: PRAGMA table_info(pages)
88: } {0 title {} 0 {} 0 1 keywords {} 0 {} 0 2 body {} 0 {} 0}
89:
90: ddl_test 1.1.3.1 {
91: CREATE VIRTUAL TABLE mail USING fts3(
92: subject VARCHAR(256) NOT NULL,
93: body TEXT CHECK(length(body)<10240)
94: )
95: }
96: read_test 1.1.3.2 {
97: PRAGMA table_info(mail)
98: } {0 subject {} 0 {} 0 1 body {} 0 {} 0}
99:
100: # A very large string. Used to test if the constraint on column "body" of
101: # table "mail" is enforced (it should not be - FTS3 tables do not support
102: # constraints).
103: set largetext [string repeat "the quick brown fox " 5000]
104: write_test 1.1.3.3 mail_content { INSERT INTO mail VALUES(NULL, $largetext) }
105: read_test 1.1.3.4 {
106: SELECT subject IS NULL, length(body) FROM mail
107: } [list 1 100000]
108:
109: ddl_test 1.1.4.1 {
110: CREATE VIRTUAL TABLE papers USING fts3(author, document, tokenize=porter)
111: }
112: read_test 1.1.4.2 {
113: PRAGMA table_info(papers)
114: } {0 author {} 0 {} 0 1 document {} 0 {} 0}
115:
116: ddl_test 1.1.5.1 {
117: CREATE VIRTUAL TABLE simpledata USING fts3(tokenize=simple)
118: }
119: read_test 1.1.5.2 {
120: PRAGMA table_info(simpledata)
121: } {0 content {} 0 {} 0}
122:
123: ifcapable icu {
124: ddl_test 1.1.6.1 {
125: CREATE VIRTUAL TABLE names USING fts3(a, b, tokenize=icu en_AU)
126: }
127: read_test 1.1.6.2 {
128: PRAGMA table_info(names)
129: } {0 a {} 0 {} 0 1 b {} 0 {} 0}
130: }
131:
132: ddl_test 1.1.7.1 {DROP TABLE data}
133: ddl_test 1.1.7.2 {DROP TABLE pages}
134: ddl_test 1.1.7.3 {DROP TABLE mail}
135: ddl_test 1.1.7.4 {DROP TABLE papers}
136: ddl_test 1.1.7.5 {DROP TABLE simpledata}
137: read_test 1.1.7.6 {SELECT * FROM sqlite_master} {}
138:
139: # The following is not one of the examples in section 1.1. It tests
140: # specifying an FTS3 table with no module arguments using a slightly
141: # different syntax.
142: ddl_test 1.1.8.1 {CREATE VIRTUAL TABLE data USING fts3;}
143: read_test 1.1.8.2 {PRAGMA table_info(data)} {0 content {} 0 {} 0}
144: ddl_test 1.1.8.3 {DROP TABLE data}
145:
146: ##########################################################################
147: # Test the examples in section 1.2 (populating fts3 tables)
148: #
149: ddl_test 1.2.1.1 {
150: CREATE VIRTUAL TABLE pages USING fts3(title, body);
151: }
152: write_test 1.2.1.2 pages_content {
153: INSERT INTO pages(docid, title, body)
154: VALUES(53, 'Home Page', 'SQLite is a software...');
155: }
156: read_test 1.2.1.3 {
157: SELECT docid, * FROM pages
158: } {53 {Home Page} {SQLite is a software...}}
159:
160: write_test 1.2.1.4 pages_content {
161: INSERT INTO pages(title, body)
162: VALUES('Download', 'All SQLite source code...');
163: }
164: read_test 1.2.1.5 {
165: SELECT docid, * FROM pages
166: } {53 {Home Page} {SQLite is a software...} 54 Download {All SQLite source code...}}
167:
168: write_test 1.2.1.6 pages_content {
169: UPDATE pages SET title = 'Download SQLite' WHERE rowid = 54
170: }
171: read_test 1.2.1.7 {
172: SELECT docid, * FROM pages
173: } {53 {Home Page} {SQLite is a software...} 54 {Download SQLite} {All SQLite source code...}}
174:
175: write_test 1.2.1.8 pages_content { DELETE FROM pages }
176: read_test 1.2.1.9 { SELECT docid, * FROM pages } {}
177:
178: do_error_test fts3-1.2.1.10 {
179: INSERT INTO pages(rowid, docid, title, body) VALUES(1, 2, 'A title', 'A document body');
180: } {SQL logic error or missing database}
181:
182: # Test the optimize() function example:
183: ddl_test 1.2.2.1 { CREATE VIRTUAL TABLE docs USING fts3 }
184: write_test 1.2.2.2 docs_content {
185: INSERT INTO docs VALUES('Others translate the first clause as');
186: }
187: write_test 1.2.2.3 docs_content {
188: INSERT INTO docs VALUES('"which is for Solomon," meaning that');
189: }
190: write_test 1.2.2.4 docs_content {
191: INSERT INTO docs VALUES('the book is dedicated to Solomon.');
192: }
193: read_test 1.2.2.5 { SELECT count(*) FROM docs_segdir } {3}
194: write_test 1.2.2.6 docs_segdir {
195: INSERT INTO docs(docs) VALUES('optimize');
196: }
197: read_test 1.2.2.7 { SELECT count(*) FROM docs_segdir } {1}
198: ddl_test 1.2.2.8 { DROP TABLE docs }
199:
200: ##########################################################################
201: # Test the examples in section 1.3 (querying FTS3 tables)
202: #
203: ddl_test 1.3.1.1 { CREATE VIRTUAL TABLE mail USING fts3(subject, body) }
204: read_test 1.3.1.2 {
205: SELECT * FROM mail WHERE rowid = 15; -- Fast. Rowid lookup.
206: SELECT * FROM mail WHERE body MATCH 'sqlite'; -- Fast. Full-text query.
207: SELECT * FROM mail WHERE mail MATCH 'search'; -- Fast. Full-text query.
208: SELECT * FROM mail WHERE rowid BETWEEN 15 AND 20; -- Slow. Linear scan.
209: SELECT * FROM mail WHERE subject = 'database'; -- Slow. Linear scan.
210: SELECT * FROM mail WHERE subject MATCH 'database'; -- Fast. Full-text query.
211: } {}
212: ddl_test 1.3.1.3 { DROP TABLE mail }
213:
214: ddl_test 1.3.2.1 { CREATE VIRTUAL TABLE mail USING fts3(subject, body) }
215:
216: write_test 1.3.2.2 mail_content {
217: INSERT INTO mail(docid, subject, body)
218: VALUES(1, 'software feedback', 'found it too slow')
219: }
220: write_test 1.3.2.3 mail_content {
221: INSERT INTO mail(docid, subject, body)
222: VALUES(2, 'software feedback', 'no feedback')
223: }
224: write_test 1.3.2.4 mail_content {
225: INSERT INTO mail(docid, subject, body)
226: VALUES(3, 'slow lunch order', 'was a software problem')
227: }
228: read_test 1.3.2.5 {
229: SELECT * FROM mail WHERE subject MATCH 'software'
230: } {{software feedback} {found it too slow} {software feedback} {no feedback}}
231: read_test 1.3.2.6 {
232: SELECT * FROM mail WHERE body MATCH 'feedback'
233: } {{software feedback} {no feedback}}
234: read_test 1.3.2.7 {
235: SELECT * FROM mail WHERE mail MATCH 'software'
236: } {{software feedback} {found it too slow} {software feedback} {no feedback} {slow lunch order} {was a software problem}}
237: read_test 1.3.2.7 {
238: SELECT * FROM mail WHERE mail MATCH 'slow'
239: } {{software feedback} {found it too slow} {slow lunch order} {was a software problem}}
240: ddl_test 1.3.2.8 { DROP TABLE mail }
241:
242: ddl_test 1.3.3.1 { CREATE VIRTUAL TABLE docs USING fts3(content) }
243: read_test 1.3.3.2 { SELECT * FROM docs WHERE docs MATCH 'sqlite' } {}
244: read_test 1.3.3.3 { SELECT * FROM docs WHERE docs.docs MATCH 'sqlite' } {}
245: read_test 1.3.3.4 { SELECT * FROM docs WHERE main.docs.docs MATCH 'sqlite' } {}
246: do_error_test e_fts3-1.3.3.5 {
247: SELECT * FROM docs WHERE main.docs MATCH 'sqlite'
248: } {no such column: main.docs}
249: ddl_test 1.3.2.8 { DROP TABLE docs }
250:
251: ##########################################################################
252: # Test the examples in section 3 (full-text index queries).
253: #
254: ddl_test 1.4.1.1 { CREATE VIRTUAL TABLE docs USING fts3(title, body) }
255: unset -nocomplain R
256: foreach {tn title body} {
257: 2 "linux driver" "a device"
258: 3 "driver" "linguistic trick"
259: 4 "problems" "linux problems"
260: 5 "linux" "big problems"
261: 6 "linux driver" "a device driver problem"
262: 7 "good times" "applications for linux"
263: 8 "not so good" "linux applications"
264: 9 "alternative" "linoleum appliances"
265: 10 "no L I N" "to be seen"
266: } {
267: write_test 1.4.1.$tn docs_content { INSERT INTO docs VALUES($title,$body) }
268: set R($tn) [list $title $body]
269: }
270:
271: read_test 1.4.1.11 {
272: SELECT * FROM docs WHERE docs MATCH 'linux'
273: } [concat $R(2) $R(4) $R(5) $R(6) $R(7) $R(8)]
274: read_test 1.4.1.12 {
275: SELECT * FROM docs WHERE docs MATCH 'lin*'
276: } [concat $R(2) $R(3) $R(4) $R(5) $R(6) $R(7) $R(8) $R(9)]
277: read_test 1.4.1.13 {
278: SELECT * FROM docs WHERE docs MATCH 'title:linux problems'
279: } [concat $R(5)]
280: read_test 1.4.1.14 {
281: SELECT * FROM docs WHERE body MATCH 'title:linux driver'
282: } [concat $R(6)]
283: read_test 1.4.1.15 {
284: SELECT * FROM docs WHERE docs MATCH '"linux applications"'
285: } [concat $R(8)]
286: read_test 1.4.1.16 {
287: SELECT * FROM docs WHERE docs MATCH '"lin* app*"'
288: } [concat $R(8) $R(9)]
289: ddl_test 1.4.1.17 { DROP TABLE docs }
290: unset R
291:
292: ddl_test 1.4.2.1 { CREATE VIRTUAL TABLE docs USING fts3() }
293: write_test 1.4.2.2 docs_content {
294: INSERT INTO docs VALUES(
295: 'SQLite is an ACID compliant embedded relational database management system')
296: }
297: foreach {tn query hit} {
298: 3 {SELECT * FROM docs WHERE docs MATCH 'sqlite NEAR database'} 1
299: 4 {SELECT * FROM docs WHERE docs MATCH 'database NEAR/6 sqlite'} 1
300: 5 {SELECT * FROM docs WHERE docs MATCH 'database NEAR/5 sqlite'} 0
301: 6 {SELECT * FROM docs WHERE docs MATCH 'database NEAR/2 "ACID compliant"'} 1
302: 7 {SELECT * FROM docs WHERE docs MATCH '"ACID compliant" NEAR/2 sqlite'} 1
303: 8 {SELECT * FROM docs WHERE docs MATCH 'sqlite NEAR/2 acid NEAR/2 relational'} 1
304: 9 {SELECT * FROM docs WHERE docs MATCH 'acid NEAR/2 sqlite NEAR/2 relational'} 0
305: } {
306: set res [db eval {SELECT * FROM docs WHERE $hit}]
307: read_test 1.4.2.$tn $query $res
308: }
309: ddl_test 1.4.2.10 { DROP TABLE docs }
310:
311: ##########################################################################
312: # Test the example in section 3.1 (set operators with enhanced syntax).
313: #
314: set sqlite_fts3_enable_parentheses 1
315: ddl_test 1.5.1.1 { CREATE VIRTUAL TABLE docs USING fts3() }
316: foreach {tn docid content} {
317: 2 1 "a database is a software system"
318: 3 2 "sqlite is a software system"
319: 4 3 "sqlite is a database"
320: } {
321: set R($docid) $content
322: write_test 1.5.1.$tn docs_content {
323: INSERT INTO docs(docid, content) VALUES($docid, $content)
324: }
325: }
326: read_test 1.5.1.4 {
327: SELECT * FROM docs WHERE docs MATCH 'sqlite AND database'
328: } [list $R(3)]
329: read_test 1.5.1.5 {
330: SELECT * FROM docs WHERE docs MATCH 'database sqlite'
331: } [list $R(3)]
332: read_test 1.5.1.6 {
333: SELECT * FROM docs WHERE docs MATCH 'sqlite OR database'
334: } [list $R(1) $R(2) $R(3)]
335: read_test 1.5.1.7 {
336: SELECT * FROM docs WHERE docs MATCH 'database NOT sqlite'
337: } [list $R(1)]
338: read_test 1.5.1.8 {
339: SELECT * FROM docs WHERE docs MATCH 'database and sqlite'
340: } {}
341:
342: write_test 1.5.2.1 docs_content {
343: INSERT INTO docs
344: SELECT 'sqlite is also a library' UNION ALL
345: SELECT 'library software'
346: }
347: read_test 1.5.2.2 {
348: SELECT docid FROM docs WHERE docs MATCH 'sqlite AND database OR library'
349: } {3 4 5}
350: read_test 1.5.2.3 {
351: SELECT docid FROM docs WHERE docs MATCH 'sqlite AND database'
352: UNION
353: SELECT docid FROM docs WHERE docs MATCH 'library'
354: } {3 4 5}
355: write_test 1.5.2.4 docs_content {
356: INSERT INTO docs
357: SELECT 'the sqlite library runs on linux' UNION ALL
358: SELECT 'as does the sqlite database (on linux)' UNION ALL
359: SELECT 'the sqlite database is accessed by the sqlite library'
360: }
361: read_test 1.5.2.2 {
362: SELECT docid FROM docs
363: WHERE docs MATCH '("sqlite database" OR "sqlite library") AND linux';
364: } {6 7}
365: read_test 1.5.2.3 {
366: SELECT docid FROM docs WHERE docs MATCH 'linux'
367: INTERSECT
368: SELECT docid FROM (
369: SELECT docid FROM docs WHERE docs MATCH '"sqlite library"'
370: UNION
371: SELECT docid FROM docs WHERE docs MATCH '"sqlite database"'
372: );
373: } {6 7}
374:
375: ##########################################################################
376: # Test the examples in section 3.2 (set operators with standard syntax).
377: # These tests reuse the table populated by the block above.
378: #
379: set sqlite_fts3_enable_parentheses 0
380: read_test 1.6.1.1 {
381: SELECT * FROM docs WHERE docs MATCH 'sqlite -database'
382: } {{sqlite is a software system} {sqlite is also a library} {the sqlite library runs on linux}}
383: read_test 1.6.1.2 {
384: SELECT * FROM docs WHERE docs MATCH 'sqlite OR database library'
385: } {{sqlite is also a library} {the sqlite library runs on linux} {the sqlite database is accessed by the sqlite library}}
386:
387: set sqlite_fts3_enable_parentheses 1
388: read_test 1.6.1.3 {
389: SELECT * FROM docs WHERE docs MATCH 'sqlite OR database library'
390: } {{sqlite is a software system} {sqlite is a database} {sqlite is also a library} {the sqlite library runs on linux} {as does the sqlite database (on linux)} {the sqlite database is accessed by the sqlite library}}
391: read_test 1.6.1.4 {
392: SELECT * FROM docs WHERE docs MATCH '(sqlite OR database) library'
393: } {{sqlite is also a library} {the sqlite library runs on linux} {the sqlite database is accessed by the sqlite library}}
394: set sqlite_fts3_enable_parentheses 0
395: ddl_test 1.6.1.5 { DROP TABLE docs }
396:
397: ##########################################################################
398: # Test the examples in section 4 (auxillary functions).
399: #
400: ddl_test 1.7.1.1 { CREATE VIRTUAL TABLE mail USING fts3(subject, body) }
401:
402: write_test 1.7.1.2 mail_content {
403: INSERT INTO mail VALUES(
404: 'hello world', 'This message is a hello world message.');
405: }
406: write_test 1.7.1.3 mail_content {
407: INSERT INTO mail VALUES(
408: 'urgent: serious', 'This mail is seen as a more serious mail');
409: }
410:
411: read_test 1.7.1.4 {
412: SELECT offsets(mail) FROM mail WHERE mail MATCH 'world';
413: } {{0 0 6 5 1 0 24 5}}
414: read_test 1.7.1.5 {
415: SELECT offsets(mail) FROM mail WHERE mail MATCH 'message'
416: } {{1 0 5 7 1 0 30 7}}
417: read_test 1.7.1.6 {
418: SELECT offsets(mail) FROM mail WHERE mail MATCH '"serious mail"'
419: } {{1 0 28 7 1 1 36 4}}
420:
421: ddl_test 1.7.2.1 { CREATE VIRTUAL TABLE text USING fts3() }
422:
423: write_test 1.7.2.2 text_content {
424: INSERT INTO text VALUES('
425: During 30 Nov-1 Dec, 2-3oC drops. Cool in the upper portion, minimum temperature 14-16oC and cool elsewhere, minimum temperature 17-20oC. Cold to very cold on mountaintops, minimum temperature 6-12oC. Northeasterly winds 15-30 km/hr. After that, temperature increases. Northeasterly winds 15-30 km/hr.
426: ');
427: }
428:
429: read_test 1.7.2.3 {
430: SELECT snippet(text) FROM text WHERE text MATCH 'cold'
431: } {{<b>...</b>cool elsewhere, minimum temperature 17-20oC. <b>Cold</b> to very <b>cold</b> on mountaintops, minimum temperature 6<b>...</b>}}
432:
433: read_test 1.7.2.4 {
434: SELECT snippet(text, '[', ']', '...') FROM text WHERE text MATCH '"min* tem*"'
435: } {{...the upper portion, [minimum] [temperature] 14-16oC and cool elsewhere, [minimum] [temperature] 17-20oC. Cold...}}
436:
437: ddl_test 1.7.3.1 { DROP TABLE IF EXISTS t1 }
438: ddl_test 1.7.3.2 { CREATE VIRTUAL TABLE t1 USING fts3(a, b) }
439: write_test 1.7.3.3 t1_content {
440: INSERT INTO t1 VALUES(
441: 'transaction default models default', 'Non transaction reads');
442: }
443: write_test 1.7.3.4 t1_content {
444: INSERT INTO t1 VALUES('the default transaction', 'these semantics present');
445: }
446: write_test 1.7.3.5 t1_content {
447: INSERT INTO t1 VALUES('single request', 'default data');
448: }
449: read_test 1.7.3.6 {
450: SELECT mit(matchinfo(t1)) FROM t1
451: WHERE t1 MATCH 'default transaction "these semantics"';
452: } {{3 2 1 3 2 0 1 1 1 2 2 0 1 1 0 0 0 1 1 1}}
453:
454: ##########################################################################
455: # Test the example in section 5 (custom tokenizers).
456: #
457: ddl_test 1.8.1.1 { CREATE VIRTUAL TABLE simple USING fts3(tokenize=simple) }
458: write_test 1.8.1.2 simple_content {
459: INSERT INTO simple VALUES('Right now they''re very frustrated')
460: }
461: read_test 1.8.1.3 {SELECT docid FROM simple WHERE simple MATCH 'Frustrated'} {1}
462: read_test 1.8.1.4 {SELECT docid FROM simple WHERE simple MATCH 'Frustration'} {}
463:
464: ddl_test 1.8.2.1 { CREATE VIRTUAL TABLE porter USING fts3(tokenize=porter) }
465: write_test 1.8.2.2 porter_content {
466: INSERT INTO porter VALUES('Right now they''re very frustrated')
467: }
468: read_test 1.8.2.4 {
469: SELECT docid FROM porter WHERE porter MATCH 'Frustration'
470: } {1}
471:
472: }
473: # End of tests of example code in fts3.html
474: #-------------------------------------------------------------------------
475:
476: #-------------------------------------------------------------------------
477: # Test that errors in the arguments passed to the snippet and offsets
478: # functions are handled correctly.
479: #
480: set DO_MALLOC_TEST 0
481: ddl_test 2.1.0 { DROP TABLE IF EXISTS t1 }
482: ddl_test 2.1.1 { CREATE VIRTUAL TABLE t1 USING fts3(a, b) }
483: write_test 2.1.2 t1_content {
484: INSERT INTO t1 VALUES('one two three', x'A1B2C3D4E5F6');
485: }
486: error_test 2.1.3 {
487: SELECT offsets(a) FROM t1 WHERE a MATCH 'one'
488: } {illegal first argument to offsets}
489: error_test 2.1.4 {
490: SELECT offsets(b) FROM t1 WHERE a MATCH 'one'
491: } {illegal first argument to offsets}
492: error_test 2.1.5 {
493: SELECT optimize(a) FROM t1 LIMIT 1
494: } {illegal first argument to optimize}
495: error_test 2.1.6 {
496: SELECT snippet(a) FROM t1 WHERE a MATCH 'one'
497: } {illegal first argument to snippet}
498: error_test 2.1.7 {
499: SELECT snippet() FROM t1 WHERE a MATCH 'one'
500: } {unable to use function snippet in the requested context}
501: error_test 2.1.8 {
502: SELECT snippet(a, b, 'A', 'B', 'C', 'D', 'E') FROM t1 WHERE a MATCH 'one'
503: } {wrong number of arguments to function snippet()}
504: #-------------------------------------------------------------------------
505:
506: #-------------------------------------------------------------------------
507: # Test the effect of an OOM error while installing the FTS3 module (i.e.
508: # opening a database handle). This case was not tested by the OOM testing
509: # of the document examples above.
510: #
511: do_malloc_test e_fts3-3 -tclbody {
512: if {[catch {sqlite3 db test.db}]} { error "out of memory" }
513: }
514: #-------------------------------------------------------------------------
515:
516: #-------------------------------------------------------------------------
517: # Verify the return values of the optimize() function. If no error occurs,
518: # the returned value should be "Index optimized" if the data structure
519: # was modified, or "Index already optimal" if it were not.
520: #
521: set DO_MALLOC_TEST 0
522: ddl_test 4.1 { CREATE VIRTUAL TABLE t4 USING fts3(a, b) }
523: write_test 4.2 t4_content {
524: INSERT INTO t4 VALUES('In Xanadu', 'did Kubla Khan');
525: }
526: write_test 4.3 t4_content {
527: INSERT INTO t4 VALUES('a stately pleasure', 'dome decree');
528: }
529: do_test e_fts3-4.4 {
530: execsql { SELECT optimize(t4) FROM t4 LIMIT 1 }
531: } {{Index optimized}}
532: do_test e_fts3-4.5 {
533: execsql { SELECT optimize(t4) FROM t4 LIMIT 1 }
534: } {{Index already optimal}}
535: #-------------------------------------------------------------------------
536:
537: #-------------------------------------------------------------------------
538: # Test that the snippet function appears to work correctly with 1, 2, 3
539: # or 4 arguments passed to it.
540: #
541: set DO_MALLOC_TEST 0
542: ddl_test 5.1 { CREATE VIRTUAL TABLE t5 USING fts3(x) }
543: write_test 5.2 t5_content {
544: INSERT INTO t5 VALUES('In Xanadu did Kubla Khan A stately pleasure-dome decree Where Alph, the sacred river, ran Through caverns measureless to man Down to a sunless sea. So twice five miles of fertile ground With walls and towers were girdled round : And there were gardens bright with sinuous rills, Where blossomed many an incense-bearing tree ; And here were forests ancient as the hills, Enfolding sunny spots of greenery.');
545: }
546: read_test 5.3 {
547: SELECT snippet(t5) FROM t5 WHERE t5 MATCH 'miles'
548: } {{<b>...</b>to a sunless sea. So twice five <b>miles</b> of fertile ground With walls and towers<b>...</b>}}
549: read_test 5.4 {
550: SELECT snippet(t5, '<i>') FROM t5 WHERE t5 MATCH 'miles'
551: } {{<b>...</b>to a sunless sea. So twice five <i>miles</b> of fertile ground With walls and towers<b>...</b>}}
552: read_test 5.5 {
553: SELECT snippet(t5, '<i>', '</i>') FROM t5 WHERE t5 MATCH 'miles'
554: } {{<b>...</b>to a sunless sea. So twice five <i>miles</i> of fertile ground With walls and towers<b>...</b>}}
555: read_test 5.6 {
556: SELECT snippet(t5, '<i>', '</i>', 'XXX') FROM t5 WHERE t5 MATCH 'miles'
557: } {{XXXto a sunless sea. So twice five <i>miles</i> of fertile ground With walls and towersXXX}}
558: #-------------------------------------------------------------------------
559:
560: #-------------------------------------------------------------------------
561: # Test that an empty MATCH expression returns an empty result set. As
562: # does passing a NULL value as a MATCH expression.
563: #
564: set DO_MALLOC_TEST 0
565: ddl_test 6.1 { CREATE VIRTUAL TABLE t6 USING fts3(x) }
566: write_test 6.2 t5_content { INSERT INTO t6 VALUES('a'); }
567: write_test 6.3 t5_content { INSERT INTO t6 VALUES('b'); }
568: write_test 6.4 t5_content { INSERT INTO t6 VALUES('c'); }
569: read_test 6.5 { SELECT * FROM t6 WHERE t6 MATCH '' } {}
570: read_test 6.6 { SELECT * FROM t6 WHERE x MATCH '' } {}
571: read_test 6.7 { SELECT * FROM t6 WHERE t6 MATCH NULL } {}
572: read_test 6.8 { SELECT * FROM t6 WHERE x MATCH NULL } {}
573: #-------------------------------------------------------------------------
574:
575: #-------------------------------------------------------------------------
576: # Test a few facets of the FTS3 xFilter() callback implementation:
577: #
578: # 1. That the sqlite3_index_constraint.usable flag is respected.
579: #
580: # 2. That it is an error to use the "docid" or "rowid" column of
581: # an FTS3 table as the LHS of a MATCH operator.
582: #
583: # 3. That it is an error to AND together two MATCH expressions in
584: # that refer to a single FTS3 table in a WHERE clause.
585: #
586: #
587: set DO_MALLOC_TEST 0
588: ddl_test 7.1.1 { CREATE VIRTUAL TABLE t7 USING fts3(a) }
589: ddl_test 7.1.2 { CREATE VIRTUAL TABLE t8 USING fts3(b) }
590: write_test 7.1.3 t7_content { INSERT INTO t7(docid, a) VALUES(4,'number four') }
591: write_test 7.1.4 t7_content { INSERT INTO t7(docid, a) VALUES(5,'number five') }
592: write_test 7.1.5 t8_content { INSERT INTO t8(docid, b) VALUES(4,'letter D') }
593: write_test 7.1.6 t8_content { INSERT INTO t8(docid, b) VALUES(5,'letter E') }
594: read_test 7.1.7 {
595: SELECT a || ':' || b FROM t7 JOIN t8 USING(docid)
596: } {{number four:letter D} {number five:letter E}}
597:
598: error_test 7.2.1 {
599: SELECT * FROM t7 WHERE docid MATCH 'number'
600: } {unable to use function MATCH in the requested context}
601: error_test 7.2.2 {
602: SELECT * FROM t7 WHERE rowid MATCH 'number'
603: } {unable to use function MATCH in the requested context}
604:
605: error_test 7.3.1 {
606: SELECT * FROM t7 WHERE a MATCH 'number' AND a MATCH 'four'
607: } {unable to use function MATCH in the requested context}
608: error_test 7.3.2 {
609: SELECT * FROM t7, t8 WHERE a MATCH 'number' AND a MATCH 'four'
610: } {unable to use function MATCH in the requested context}
611: error_test 7.3.3 {
612: SELECT * FROM t7, t8 WHERE b MATCH 'letter' AND b MATCH 'd'
613: } {unable to use function MATCH in the requested context}
614: read_test 7.3.4 {
615: SELECT * FROM t7, t8 WHERE a MATCH 'number' AND b MATCH 'letter'
616: } {{number four} {letter D} {number four} {letter E} {number five} {letter D} {number five} {letter E}}
617: read_test 7.3.5 {
618: SELECT * FROM t7 WHERE a MATCH 'number' AND docid = 4
619: } {{number four}}
620:
621: #-------------------------------------------------------------------------
622: # Test the quoting of FTS3 table column names. Names may be quoted using
623: # any of "", '', ``` or [].
624: #
625: set DO_MALLOC_TEST 0
626: ddl_test 8.1.1 { CREATE VIRTUAL TABLE t9a USING fts3("c1", [c2]) }
627: ddl_test 8.1.2 { CREATE VIRTUAL TABLE t9b USING fts3('c1', `c2`) }
628: read_test 8.1.3 { PRAGMA table_info(t9a) } {0 c1 {} 0 {} 0 1 c2 {} 0 {} 0}
629: read_test 8.1.4 { PRAGMA table_info(t9b) } {0 c1 {} 0 {} 0 1 c2 {} 0 {} 0}
630: ddl_test 8.2.1 { CREATE VIRTUAL TABLE t9c USING fts3("c""1", 'c''2') }
631: read_test 8.2.2 { PRAGMA table_info(t9c) } {0 c\"1 {} 0 {} 0 1 c'2 {} 0 {} 0}
632: #-------------------------------------------------------------------------
633:
634: #-------------------------------------------------------------------------
635: # Test that FTS3 tables can be renamed using the ALTER RENAME command.
636: # OOM errors are tested during ALTER RENAME commands also.
637: #
638: foreach DO_MALLOC_TEST {0 1 2} {
639: db close
640: forcedelete test.db test.db-journal
641: sqlite3 db test.db
642: if {$DO_MALLOC_TEST} { sqlite3_db_config_lookaside db 0 0 0 }
643:
644: ddl_test 9.1.1 { CREATE VIRTUAL TABLE t10 USING fts3(x) }
645: write_test 9.1.2 t10_content { INSERT INTO t10 VALUES('fts3 tables') }
646: write_test 9.1.3 t10_content { INSERT INTO t10 VALUES('are renameable') }
647:
648: read_test 9.1.4 {
649: SELECT * FROM t10 WHERE t10 MATCH 'table*'
650: } {{fts3 tables}}
651: read_test 9.1.5 {
652: SELECT * FROM t10 WHERE x MATCH 'rename*'
653: } {{are renameable}}
654:
655: ddl_test 9.1.6 { ALTER TABLE t10 RENAME TO t11 }
656:
657: read_test 9.1.7 {
658: SELECT * FROM t11 WHERE t11 MATCH 'table*'
659: } {{fts3 tables}}
660: read_test 9.1.8 {
661: SELECT * FROM t11 WHERE x MATCH 'rename*'
662: } {{are renameable}}
663: }
664: #-------------------------------------------------------------------------
665:
666: #-------------------------------------------------------------------------
667: # Test a couple of cases involving corrupt data structures:
668: #
669: # 1) A case where a document referenced by the full-text index is
670: # not present in the %_content table.
671: #
672: # 2) A badly formatted b-tree segment node.
673: #
674: set DO_MALLOC_TEST 0
675: ddl_test 10.1.1 { CREATE VIRTUAL TABLE ta USING fts3 }
676: write_test 10.1.2 ta_content {
677: INSERT INTO ta VALUES('During a summer vacation in 1790') }
678: write_test 10.1.3 ta_content {
679: INSERT INTO ta VALUES('Wordsworth went on a walking tour') }
680: write_test 10.1.4 ta_content { DELETE FROM ta_content WHERE rowid = 2 }
681: read_test 10.1.5 {
682: SELECT * FROM ta WHERE ta MATCH 'summer'
683: } {{During a summer vacation in 1790}}
684: error_test 10.1.6 {
685: SELECT * FROM ta WHERE ta MATCH 'walking'
686: } {database disk image is malformed}
687:
688: write_test 10.2.1 ta_content { DELETE FROM ta }
689: write_test 10.2.2 ta_content {
690: INSERT INTO ta VALUES('debate demonstrated the rising difficulty') }
691: write_test 10.2.3 ta_content {
692: INSERT INTO ta VALUES('Google released its browser beta') }
693:
694: set blob [db one {SELECT root FROM ta_segdir WHERE rowid = 2}]
695: binary scan $blob "a6 a3 a*" start middle end
696: set middle "\x0E\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x06\x06"
697: set blob [binary format "a6 a* a*" $start $middle $end]
698: write_test 10.2.4 ta_segdir {
699: UPDATE ta_segdir SET root = $blob WHERE rowid = 2
700: }
701: error_test 10.2.5 {
702: SELECT * FROM ta WHERE ta MATCH 'beta'
703: } {database disk image is malformed}
704:
705:
706: finish_test
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>