fts5ab.test 7.6 KB

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