OLD | NEW |
(Empty) | |
| 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 file delete -force 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 sou
rce 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 docume
nt 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} {sl
ow 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 pr
oblem}} |
| 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 dat
abase 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 librar
y} {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 dat
abase 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 tempera
ture 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. Af
ter 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, [m
inimum] [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 g
irdled round : And there were gardens bright with sinuous rills, Where blossomed
many an incense-bearing tree ; And here were forests ancient as the hills, Enfo
lding 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 Wi
th 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 Wi
th 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 Wi
th 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 wall
s 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} {n
umber 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 file delete -force 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 |
OLD | NEW |