modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/fts5/test/fts5vocab.test (about) 1 # 2015 Apr 24 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 # The tests in this file focus on testing the fts5vocab module. 13 # 14 15 source [file join [file dirname [info script]] fts5_common.tcl] 16 set testprefix fts5vocab 17 18 # If SQLITE_ENABLE_FTS5 is defined, omit this file. 19 ifcapable !fts5 { 20 finish_test 21 return 22 } 23 24 foreach_detail_mode $testprefix { 25 26 proc null_list_entries {iFirst nInterval L} { 27 for {set i $iFirst} {$i < [llength $L]} {incr i $nInterval} { 28 lset L $i {} 29 } 30 return $L 31 } 32 33 proc star_from_row {L} { 34 if {[detail_is_full]==0} { 35 set L [null_list_entries 2 3 $L] 36 } 37 return $L 38 } 39 40 proc star_from_col {L} { 41 if {[detail_is_col]} { 42 set L [null_list_entries 3 4 $L] 43 } 44 if {[detail_is_none]} { 45 set L [null_list_entries 1 4 $L] 46 set L [null_list_entries 3 4 $L] 47 } 48 return $L 49 } 50 51 proc row_to_col {L} { 52 if {[detail_is_none]==0} { error "this is for detail=none mode" } 53 set ret [list] 54 foreach {a b c} $L { 55 lappend ret $a {} $b {} 56 } 57 set ret 58 } 59 60 if 1 { 61 62 do_execsql_test 1.1.1 { 63 CREATE VIRTUAL TABLE t1 USING fts5(one, prefix=1, detail=%DETAIL%); 64 CREATE VIRTUAL TABLE v1 USING fts5vocab(t1, 'row'); 65 PRAGMA table_info = v1; 66 } { 67 0 term {} 0 {} 0 68 1 doc {} 0 {} 0 69 2 cnt {} 0 {} 0 70 } 71 72 do_execsql_test 1.1.2 { 73 CREATE VIRTUAL TABLE v2 USING fts5vocab(t1, 'col'); 74 PRAGMA table_info = v2; 75 } { 76 0 term {} 0 {} 0 77 1 col {} 0 {} 0 78 2 doc {} 0 {} 0 79 3 cnt {} 0 {} 0 80 } 81 82 do_execsql_test 1.2.1 { SELECT * FROM v1 } { } 83 do_execsql_test 1.2.2 { SELECT * FROM v2 } { } 84 85 do_execsql_test 1.3 { 86 INSERT INTO t1 VALUES('x y z'); 87 INSERT INTO t1 VALUES('x x x'); 88 } 89 90 do_execsql_test 1.4.1 { 91 SELECT * FROM v1; 92 } [star_from_row {x 2 4 y 1 1 z 1 1}] 93 94 do_execsql_test 1.4.2 { 95 SELECT * FROM v2; 96 } [star_from_col {x one 2 4 y one 1 1 z one 1 1}] 97 98 do_execsql_test 1.5.1 { 99 BEGIN; 100 INSERT INTO t1 VALUES('a b c'); 101 SELECT * FROM v1 WHERE term<'d'; 102 } [star_from_row {a 1 1 b 1 1 c 1 1}] 103 104 do_execsql_test 1.5.2 { 105 SELECT * FROM v2 WHERE term<'d'; 106 COMMIT; 107 } [star_from_col {a one 1 1 b one 1 1 c one 1 1}] 108 109 do_execsql_test 1.6 { 110 DELETE FROM t1 WHERE one = 'a b c'; 111 SELECT * FROM v1; 112 } [star_from_row {x 2 4 y 1 1 z 1 1}] 113 114 #------------------------------------------------------------------------- 115 # 116 do_execsql_test 2.0 { 117 CREATE VIRTUAL TABLE tt USING fts5(a, b, detail=%DETAIL%); 118 INSERT INTO tt VALUES('d g b f d f', 'f c e c d a'); 119 INSERT INTO tt VALUES('f a e a a b', 'e d c f d d'); 120 INSERT INTO tt VALUES('b c a a a b', 'f f c c b c'); 121 INSERT INTO tt VALUES('f d c a c e', 'd g d e g d'); 122 INSERT INTO tt VALUES('g d e f a g x', 'f f d a a b'); 123 INSERT INTO tt VALUES('g c f b c g', 'a g f d c b'); 124 INSERT INTO tt VALUES('c e c f g b', 'f e d b g a'); 125 INSERT INTO tt VALUES('g d e f d e', 'a c d b a g'); 126 INSERT INTO tt VALUES('e f a c c b', 'b f e a f d y'); 127 INSERT INTO tt VALUES('c c a a c f', 'd g a e b g'); 128 } 129 130 set res_row [star_from_row { 131 a 10 20 b 9 14 c 9 20 d 9 19 132 e 8 13 f 10 20 g 7 14 x 1 1 133 y 1 1 134 }] 135 set res_col [star_from_col { 136 a a 6 11 a b 7 9 137 b a 6 7 b b 7 7 138 c a 6 12 c b 5 8 139 d a 4 6 d b 9 13 140 e a 6 7 e b 6 6 141 f a 9 10 f b 7 10 142 g a 5 7 g b 5 7 143 x a 1 1 y b 1 1 144 }] 145 if {[detail_is_none]} { 146 set res_col [row_to_col $res_row] 147 } 148 149 foreach {tn tbl resname} { 150 1 "fts5vocab(tt, 'col')" res_col 151 2 "fts5vocab(tt, 'row')" res_row 152 3 "fts5vocab(tt, \"row\")" res_row 153 4 "fts5vocab(tt, [row])" res_row 154 5 "fts5vocab(tt, `row`)" res_row 155 156 6 "fts5vocab('tt', 'row')" res_row 157 7 "fts5vocab(\"tt\", \"row\")" res_row 158 8 "fts5vocab([tt], [row])" res_row 159 9 "fts5vocab(`tt`, `row`)" res_row 160 } { 161 do_execsql_test 2.$tn " 162 DROP TABLE IF EXISTS tv; 163 CREATE VIRTUAL TABLE tv USING $tbl; 164 SELECT * FROM tv; 165 " [set $resname] 166 } 167 168 #------------------------------------------------------------------------- 169 # Test errors in the CREATE VIRTUAL TABLE statement. 170 # 171 foreach {tn sql} { 172 1 { CREATE VIRTUAL TABLE aa USING fts5vocab() } 173 2 { CREATE VIRTUAL TABLE aa USING fts5vocab(x) } 174 3 { CREATE VIRTUAL TABLE aa USING fts5vocab(x,y,z) } 175 4 { CREATE VIRTUAL TABLE temp.aa USING fts5vocab(x,y,z,y) } 176 } { 177 do_catchsql_test 3.$tn $sql {1 {wrong number of vtable arguments}} 178 } 179 180 do_catchsql_test 4.0 { 181 CREATE VIRTUAL TABLE cc USING fts5vocab(tbl, unknown); 182 } {1 {fts5vocab: unknown table type: 'unknown'}} 183 184 do_catchsql_test 4.1 { 185 ATTACH 'test.db' AS aux; 186 CREATE VIRTUAL TABLE aux.cc USING fts5vocab(main, tbl, row); 187 } {1 {wrong number of vtable arguments}} 188 189 #------------------------------------------------------------------------- 190 # Test fts5vocab tables created in the temp schema. 191 # 192 reset_db 193 forcedelete test.db2 194 do_execsql_test 5.0 { 195 ATTACH 'test.db2' AS aux; 196 CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%); 197 CREATE VIRTUAL TABLE temp.t1 USING fts5(x, detail=%DETAIL%); 198 CREATE VIRTUAL TABLE aux.t1 USING fts5(x, detail=%DETAIL%); 199 200 INSERT INTO main.t1 VALUES('a b c'); 201 INSERT INTO main.t1 VALUES('d e f'); 202 INSERT INTO main.t1 VALUES('a e c'); 203 204 INSERT INTO temp.t1 VALUES('1 2 3'); 205 INSERT INTO temp.t1 VALUES('4 5 6'); 206 INSERT INTO temp.t1 VALUES('1 5 3'); 207 208 INSERT INTO aux.t1 VALUES('x y z'); 209 INSERT INTO aux.t1 VALUES('m n o'); 210 INSERT INTO aux.t1 VALUES('x n z'); 211 } 212 213 do_execsql_test 5.1 { 214 CREATE VIRTUAL TABLE temp.vm USING fts5vocab(main, t1, row); 215 CREATE VIRTUAL TABLE temp.vt1 USING fts5vocab(t1, row); 216 CREATE VIRTUAL TABLE temp.vt2 USING fts5vocab(temp, t1, row); 217 CREATE VIRTUAL TABLE temp.va USING fts5vocab(aux, t1, row); 218 } 219 220 do_execsql_test 5.2 { SELECT * FROM vm } [star_from_row { 221 a 2 2 b 1 1 c 2 2 d 1 1 e 2 2 f 1 1 222 }] 223 do_execsql_test 5.3 { SELECT * FROM vt1 } [star_from_row { 224 1 2 2 2 1 1 3 2 2 4 1 1 5 2 2 6 1 1 225 }] 226 do_execsql_test 5.4 { SELECT * FROM vt2 } [star_from_row { 227 1 2 2 2 1 1 3 2 2 4 1 1 5 2 2 6 1 1 228 }] 229 do_execsql_test 5.5 { SELECT * FROM va } [star_from_row { 230 m 1 1 n 2 2 o 1 1 x 2 2 y 1 1 z 2 2 231 }] 232 233 #------------------------------------------------------------------------- 234 # 235 do_execsql_test 6.0 { 236 CREATE TABLE iii(iii); 237 CREATE TABLE jjj(x); 238 } 239 240 do_catchsql_test 6.1 { 241 CREATE VIRTUAL TABLE vocab1 USING fts5vocab(iii, row); 242 SELECT * FROM vocab1; 243 } {1 {no such fts5 table: main.iii}} 244 245 do_catchsql_test 6.2 { 246 CREATE VIRTUAL TABLE vocab2 USING fts5vocab(jjj, row); 247 SELECT * FROM vocab2; 248 } {1 {no such fts5 table: main.jjj}} 249 250 do_catchsql_test 6.2 { 251 CREATE VIRTUAL TABLE vocab3 USING fts5vocab(lll, row); 252 SELECT * FROM vocab3; 253 } {1 {no such fts5 table: main.lll}} 254 255 #------------------------------------------------------------------------- 256 # Test single term queries on fts5vocab tables (i.e. those with term=? 257 # constraints in the WHERE clause). 258 # 259 do_execsql_test 7.0 { 260 CREATE VIRTUAL TABLE tx USING fts5(one, two, detail=%DETAIL%); 261 INSERT INTO tx VALUES('g a ggg g a b eee', 'cc d aa ff g ee'); 262 INSERT INTO tx VALUES('dd fff i a i jjj', 'f fff hh jj e f'); 263 INSERT INTO tx VALUES('ggg a f f fff dd aa', 'd ggg f f j gg ddd'); 264 INSERT INTO tx VALUES('e bb h jjj ii gg', 'e aa e f c fff'); 265 INSERT INTO tx VALUES('j ff aa a h', 'h a j bbb bb'); 266 INSERT INTO tx VALUES('cc i ff c d f', 'dd ii fff f c cc d'); 267 INSERT INTO tx VALUES('jjj g i bb cc eee', 'hhh iii aaa b bbb aaa'); 268 INSERT INTO tx VALUES('hhh hhh hhh bb fff f', 'fff gg aa ii h a'); 269 INSERT INTO tx VALUES('b c cc aaa iii ggg f', 'iii ff ee a ff c cc'); 270 INSERT INTO tx VALUES('hhh b hhh aaa j i i', 'dd ee ee aa bbb iii'); 271 INSERT INTO tx VALUES('hh dd h b g ff i', 'ccc bb cc ccc f a d'); 272 INSERT INTO tx VALUES('g d b ggg jj', 'fff jj ff jj g gg ee'); 273 INSERT INTO tx VALUES('g ee ggg ggg cc bb eee', 'aa j jjj bbb dd eee ff'); 274 INSERT INTO tx VALUES('c jjj hh ddd dd h', 'e aaa h jjj gg'); 275 276 CREATE VIRTUAL TABLE txr USING fts5vocab(tx, row); 277 CREATE VIRTUAL TABLE txc USING fts5vocab(tx, col); 278 } 279 280 proc cont {L elem} { 281 set n 0 282 foreach e $L { if {$elem==$e} {incr n} } 283 set n 284 } 285 db func cont cont 286 287 foreach {term} { 288 a aa aaa 289 b bb bbb 290 c cc ccc 291 d dd ddd 292 e ee eee 293 f ff fff 294 g gg ggg 295 h hh hhh 296 i ii iii 297 j jj jjj 298 } { 299 set resr [db eval { 300 SELECT $term, 301 sum(cont(one || ' ' || two, $term) > 0), 302 sum(cont(one || ' ' || two, $term)) 303 FROM tx 304 }] 305 if {[lindex $resr 1]==0} {set resr [list]} 306 307 set r1 [db eval { 308 SELECT $term, 'one', sum(cont(one, $term)>0), sum(cont(one, $term)) FROM tx 309 }] 310 if {[lindex $r1 2]==0} {set r1 [list]} 311 312 set r2 [db eval { 313 SELECT $term, 'two', sum(cont(two, $term)>0), sum(cont(two, $term)) FROM tx 314 }] 315 if {[lindex $r2 2]==0} {set r2 [list]} 316 317 set resc [concat $r1 $r2] 318 319 set resc [star_from_col $resc] 320 set resr [star_from_row $resr] 321 if {[detail_is_none]} { set resc [row_to_col $resr] } 322 do_execsql_test 7.$term.1 {SELECT * FROM txc WHERE term=$term} $resc 323 do_execsql_test 7.$term.2 {SELECT * FROM txr WHERE term=$term} $resr 324 } 325 326 do_execsql_test 7.1 { 327 CREATE TABLE txr_c AS SELECT * FROM txr; 328 CREATE TABLE txc_c AS SELECT * FROM txc; 329 } 330 331 # Test range queries on the fts5vocab tables created above. 332 # 333 foreach {tn a b} { 334 1 a jjj 335 2 bb j 336 3 ccc ddd 337 4 dd xyz 338 5 xzy dd 339 6 h hh 340 } { 341 do_execsql_test 7.2.$tn.1 { 342 SELECT * FROM txr WHERE term>=$a 343 } [db eval {SELECT * FROM txr_c WHERE term>=$a}] 344 do_execsql_test 7.2.$tn.2 { 345 SELECT * FROM txr WHERE term<=$b 346 } [db eval {SELECT * FROM txr_c WHERE term <=$b}] 347 do_execsql_test 7.2.$tn.3 { 348 SELECT * FROM txr WHERE term>=$a AND term<=$b 349 } [db eval {SELECT * FROM txr_c WHERE term>=$a AND term <=$b}] 350 351 do_execsql_test 7.2.$tn.4 { 352 SELECT * FROM txc WHERE term>=$a 353 } [db eval {SELECT * FROM txc_c WHERE term>=$a}] 354 do_execsql_test 7.2.$tn.5 { 355 SELECT * FROM txc WHERE term<=$b 356 } [db eval {SELECT * FROM txc_c WHERE term <=$b}] 357 do_execsql_test 7.2.$tn.6 { 358 SELECT * FROM txc WHERE term>=$a AND term<=$b 359 } [db eval {SELECT * FROM txc_c WHERE term>=$a AND term <=$b}] 360 361 do_execsql_test 7.2.$tn.7 { 362 SELECT * FROM txr WHERE term>$a 363 } [db eval {SELECT * FROM txr_c WHERE term>$a}] 364 do_execsql_test 7.2.$tn.8 { 365 SELECT * FROM txr WHERE term<$b 366 } [db eval {SELECT * FROM txr_c WHERE term<$b}] 367 do_execsql_test 7.2.$tn.9 { 368 SELECT * FROM txr WHERE term>$a AND term<$b 369 } [db eval {SELECT * FROM txr_c WHERE term>$a AND term <$b}] 370 371 do_execsql_test 7.2.$tn.10 { 372 SELECT * FROM txc WHERE term>$a 373 } [db eval {SELECT * FROM txc_c WHERE term>$a}] 374 do_execsql_test 7.2.$tn.11 { 375 SELECT * FROM txc WHERE term<$b 376 } [db eval {SELECT * FROM txc_c WHERE term<$b}] 377 do_execsql_test 7.2.$tn.12 { 378 SELECT * FROM txc WHERE term>$a AND term<$b 379 } [db eval {SELECT * FROM txc_c WHERE term>$a AND term <$b}] 380 } 381 382 do_execsql_test 7.3.1 { 383 SELECT count(*) FROM txr, txr_c WHERE txr.term = txr_c.term; 384 } {30} 385 386 if {![detail_is_none]} { 387 do_execsql_test 7.3.2 { 388 SELECT count(*) FROM txc, txc_c 389 WHERE txc.term = txc_c.term AND txc.col=txc_c.col; 390 } {57} 391 } 392 393 } 394 395 #------------------------------------------------------------------------- 396 # Test the fts5vocab tables response to a specific types of corruption: 397 # where the fts5 index contains hits for columns that do not exist. 398 # 399 do_execsql_test 8.0 { 400 CREATE VIRTUAL TABLE x1 USING fts5(a, b, c, detail=%DETAIL%); 401 INSERT INTO x1 VALUES('a b c', 'd e f', 'g h i'); 402 INSERT INTO x1 VALUES('g h i', 'a b c', 'd e f'); 403 INSERT INTO x1 VALUES('d e f', 'g h i', 'a b c'); 404 CREATE VIRTUAL TABLE x1_r USING fts5vocab(x1, row); 405 CREATE VIRTUAL TABLE x1_c USING fts5vocab(x1, col); 406 } 407 408 set resr [star_from_row {a 3 3 b 3 3 c 3 3 d 3 3 e 3 3 f 3 3 g 3 3 h 3 3 i 3 3}] 409 set resc [star_from_col { 410 a a 1 1 a b 1 1 a c 1 1 b a 1 1 411 b b 1 1 b c 1 1 c a 1 1 c b 1 1 412 c c 1 1 d a 1 1 d b 1 1 d c 1 1 413 e a 1 1 e b 1 1 e c 1 1 f a 1 1 414 f b 1 1 f c 1 1 g a 1 1 g b 1 1 415 g c 1 1 h a 1 1 h b 1 1 h c 1 1 416 i a 1 1 i b 1 1 i c 1 1 417 }] 418 if {[detail_is_none]} { set resc [row_to_col $resr] } 419 420 do_execsql_test 8.1.1 { SELECT * FROM x1_r; } $resr 421 do_execsql_test 8.1.2 { SELECT * FROM x1_c } $resc 422 423 do_execsql_test 8.2 { 424 PRAGMA writable_schema = 1; 425 UPDATE sqlite_master 426 SET sql = 'CREATE VIRTUAL TABLE x1 USING fts5(a, detail=%DETAIL%)' 427 WHERE name = 'x1'; 428 } 429 db close 430 sqlite3 db test.db 431 sqlite3_fts5_may_be_corrupt 1 432 433 do_execsql_test 8.2.1 { SELECT * FROM x1_r } $resr 434 435 if {[detail_is_none]} { 436 do_execsql_test 8.2.2 { SELECT * FROM x1_c } $resc 437 } else { 438 do_catchsql_test 8.2.2 { 439 SELECT * FROM x1_c 440 } {1 {database disk image is malformed}} 441 } 442 443 sqlite3_fts5_may_be_corrupt 0 444 } 445 446 #------------------------------------------------------------------------- 447 # Test that both "ORDER BY term" and "ORDER BY term DESC" work. 448 # 449 reset_db 450 do_execsql_test 9.1 { 451 CREATE VIRTUAL TABLE x1 USING fts5(x); 452 INSERT INTO x1 VALUES('def ABC ghi'); 453 INSERT INTO x1 VALUES('DEF abc GHI'); 454 } 455 456 do_execsql_test 9.2 { 457 CREATE VIRTUAL TABLE rrr USING fts5vocab(x1, row); 458 SELECT * FROM rrr 459 } { 460 abc 2 2 def 2 2 ghi 2 2 461 } 462 do_execsql_test 9.3 { 463 SELECT * FROM rrr ORDER BY term ASC 464 } { 465 abc 2 2 def 2 2 ghi 2 2 466 } 467 do_execsql_test 9.4 { 468 SELECT * FROM rrr ORDER BY term DESC 469 } { 470 ghi 2 2 def 2 2 abc 2 2 471 } 472 do_test 9.5 { 473 set e2 [db eval { EXPLAIN SELECT * FROM rrr ORDER BY term ASC }] 474 expr [lsearch $e2 SorterSort]<0 475 } 1 476 do_test 9.6 { 477 set e2 [db eval { EXPLAIN SELECT * FROM rrr ORDER BY term DESC }] 478 expr [lsearch $e2 SorterSort]<0 479 } 0 480 481 482 483 finish_test 484