fts2p.test 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. # 2008 June 26
  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 exercises some new testing functions in the FTS2 module,
  12. # and then uses them to do some basic tests that FTS2 is internally
  13. # working as expected.
  14. #
  15. # $Id: fts2p.test,v 1.1 2008/07/22 23:32:28 shess Exp $
  16. #
  17. set testdir [file dirname $argv0]
  18. source $testdir/tester.tcl
  19. # If SQLITE_ENABLE_FTS2 is not defined, omit this file.
  20. ifcapable !fts2 {
  21. finish_test
  22. return
  23. }
  24. #*************************************************************************
  25. # Probe to see if support for these functions is compiled in.
  26. # TODO(shess): Change main.mk to do the right thing and remove this test.
  27. db eval {
  28. DROP TABLE IF EXISTS t1;
  29. CREATE VIRTUAL TABLE t1 USING fts2(c);
  30. INSERT INTO t1 (rowid, c) VALUES (1, 'x');
  31. }
  32. set s {SELECT dump_terms(t1, 1) FROM t1 LIMIT 1}
  33. set r {1 {unable to use function dump_terms in the requested context}}
  34. if {[catchsql $s]==$r} {
  35. finish_test
  36. return
  37. }
  38. #*************************************************************************
  39. # Test that the new functions give appropriate errors.
  40. do_test fts2p-0.0 {
  41. catchsql {
  42. SELECT dump_terms(t1, 1) FROM t1 LIMIT 1;
  43. }
  44. } {1 {dump_terms: incorrect arguments}}
  45. do_test fts2p-0.1 {
  46. catchsql {
  47. SELECT dump_terms(t1, 0, 0, 0) FROM t1 LIMIT 1;
  48. }
  49. } {1 {dump_terms: incorrect arguments}}
  50. do_test fts2p-0.2 {
  51. catchsql {
  52. SELECT dump_terms(1, t1) FROM t1 LIMIT 1;
  53. }
  54. } {1 {unable to use function dump_terms in the requested context}}
  55. do_test fts2p-0.3 {
  56. catchsql {
  57. SELECT dump_terms(t1, 16, 16) FROM t1 LIMIT 1;
  58. }
  59. } {1 {dump_terms: segment not found}}
  60. do_test fts2p-0.4 {
  61. catchsql {
  62. SELECT dump_doclist(t1) FROM t1 LIMIT 1;
  63. }
  64. } {1 {dump_doclist: incorrect arguments}}
  65. do_test fts2p-0.5 {
  66. catchsql {
  67. SELECT dump_doclist(t1, NULL) FROM t1 LIMIT 1;
  68. }
  69. } {1 {dump_doclist: empty second argument}}
  70. do_test fts2p-0.6 {
  71. catchsql {
  72. SELECT dump_doclist(t1, '') FROM t1 LIMIT 1;
  73. }
  74. } {1 {dump_doclist: empty second argument}}
  75. do_test fts2p-0.7 {
  76. catchsql {
  77. SELECT dump_doclist(t1, 'a', 0) FROM t1 LIMIT 1;
  78. }
  79. } {1 {dump_doclist: incorrect arguments}}
  80. do_test fts2p-0.8 {
  81. catchsql {
  82. SELECT dump_doclist(t1, 'a', 0, 0, 0) FROM t1 LIMIT 1;
  83. }
  84. } {1 {dump_doclist: incorrect arguments}}
  85. do_test fts2p-0.9 {
  86. catchsql {
  87. SELECT dump_doclist(t1, 'a', 16, 16) FROM t1 LIMIT 1;
  88. }
  89. } {1 {dump_doclist: segment not found}}
  90. #*************************************************************************
  91. # Utility function to check for the expected terms in the segment
  92. # level/index. _all version does same but for entire index.
  93. proc check_terms {test level index terms} {
  94. # TODO(shess): Figure out why uplevel in do_test can't catch
  95. # $level and $index directly.
  96. set ::level $level
  97. set ::index $index
  98. do_test $test.terms {
  99. execsql {
  100. SELECT dump_terms(t1, $::level, $::index) FROM t1 LIMIT 1;
  101. }
  102. } [list $terms]
  103. }
  104. proc check_terms_all {test terms} {
  105. do_test $test.terms {
  106. execsql {
  107. SELECT dump_terms(t1) FROM t1 LIMIT 1;
  108. }
  109. } [list $terms]
  110. }
  111. # Utility function to check for the expected doclist for the term in
  112. # segment level/index. _all version does same for entire index.
  113. proc check_doclist {test level index term doclist} {
  114. # TODO(shess): Again, why can't the non-:: versions work?
  115. set ::term $term
  116. set ::level $level
  117. set ::index $index
  118. do_test $test {
  119. execsql {
  120. SELECT dump_doclist(t1, $::term, $::level, $::index) FROM t1 LIMIT 1;
  121. }
  122. } [list $doclist]
  123. }
  124. proc check_doclist_all {test term doclist} {
  125. set ::term $term
  126. do_test $test {
  127. execsql {
  128. SELECT dump_doclist(t1, $::term) FROM t1 LIMIT 1;
  129. }
  130. } [list $doclist]
  131. }
  132. #*************************************************************************
  133. # Test the segments resulting from straight-forward inserts.
  134. db eval {
  135. DROP TABLE IF EXISTS t1;
  136. CREATE VIRTUAL TABLE t1 USING fts2(c);
  137. INSERT INTO t1 (rowid, c) VALUES (1, 'This is a test');
  138. INSERT INTO t1 (rowid, c) VALUES (2, 'That was a test');
  139. INSERT INTO t1 (rowid, c) VALUES (3, 'This is a test');
  140. }
  141. # Check for expected segments and expected matches.
  142. do_test fts2p-1.0.segments {
  143. execsql {
  144. SELECT level, idx FROM t1_segdir ORDER BY level, idx;
  145. }
  146. } {0 0 0 1 0 2}
  147. do_test fts2p-1.0.matches {
  148. execsql {
  149. SELECT OFFSETS(t1) FROM t1
  150. WHERE t1 MATCH 'this OR that OR was OR a OR is OR test' ORDER BY rowid;
  151. }
  152. } [list {0 0 0 4 0 4 5 2 0 3 8 1 0 5 10 4} \
  153. {0 1 0 4 0 2 5 3 0 3 9 1 0 5 11 4} \
  154. {0 0 0 4 0 4 5 2 0 3 8 1 0 5 10 4}]
  155. # Check the specifics of the segments constructed.
  156. # Logical view of entire index.
  157. check_terms_all fts2p-1.0.1 {a is test that this was}
  158. check_doclist_all fts2p-1.0.1.1 a {[1 0[2]] [2 0[2]] [3 0[2]]}
  159. check_doclist_all fts2p-1.0.1.2 is {[1 0[1]] [3 0[1]]}
  160. check_doclist_all fts2p-1.0.1.3 test {[1 0[3]] [2 0[3]] [3 0[3]]}
  161. check_doclist_all fts2p-1.0.1.4 that {[2 0[0]]}
  162. check_doclist_all fts2p-1.0.1.5 this {[1 0[0]] [3 0[0]]}
  163. check_doclist_all fts2p-1.0.1.6 was {[2 0[1]]}
  164. # Segment 0,0
  165. check_terms fts2p-1.0.2 0 0 {a is test this}
  166. check_doclist fts2p-1.0.2.1 0 0 a {[1 0[2]]}
  167. check_doclist fts2p-1.0.2.2 0 0 is {[1 0[1]]}
  168. check_doclist fts2p-1.0.2.3 0 0 test {[1 0[3]]}
  169. check_doclist fts2p-1.0.2.4 0 0 this {[1 0[0]]}
  170. # Segment 0,1
  171. check_terms fts2p-1.0.3 0 1 {a test that was}
  172. check_doclist fts2p-1.0.3.1 0 1 a {[2 0[2]]}
  173. check_doclist fts2p-1.0.3.2 0 1 test {[2 0[3]]}
  174. check_doclist fts2p-1.0.3.3 0 1 that {[2 0[0]]}
  175. check_doclist fts2p-1.0.3.4 0 1 was {[2 0[1]]}
  176. # Segment 0,2
  177. check_terms fts2p-1.0.4 0 2 {a is test this}
  178. check_doclist fts2p-1.0.4.1 0 2 a {[3 0[2]]}
  179. check_doclist fts2p-1.0.4.2 0 2 is {[3 0[1]]}
  180. check_doclist fts2p-1.0.4.3 0 2 test {[3 0[3]]}
  181. check_doclist fts2p-1.0.4.4 0 2 this {[3 0[0]]}
  182. #*************************************************************************
  183. # Test the segments resulting from inserts followed by a delete.
  184. db eval {
  185. DROP TABLE IF EXISTS t1;
  186. CREATE VIRTUAL TABLE t1 USING fts2(c);
  187. INSERT INTO t1 (rowid, c) VALUES (1, 'This is a test');
  188. INSERT INTO t1 (rowid, c) VALUES (2, 'That was a test');
  189. INSERT INTO t1 (rowid, c) VALUES (3, 'This is a test');
  190. DELETE FROM t1 WHERE rowid = 1;
  191. }
  192. do_test fts2p-1.1.segments {
  193. execsql {
  194. SELECT level, idx FROM t1_segdir ORDER BY level, idx;
  195. }
  196. } {0 0 0 1 0 2 0 3}
  197. do_test fts2p-1.1.matches {
  198. execsql {
  199. SELECT OFFSETS(t1) FROM t1
  200. WHERE t1 MATCH 'this OR that OR was OR a OR is OR test' ORDER BY rowid;
  201. }
  202. } {{0 1 0 4 0 2 5 3 0 3 9 1 0 5 11 4} {0 0 0 4 0 4 5 2 0 3 8 1 0 5 10 4}}
  203. check_terms_all fts2p-1.1.1 {a is test that this was}
  204. check_doclist_all fts2p-1.1.1.1 a {[2 0[2]] [3 0[2]]}
  205. check_doclist_all fts2p-1.1.1.2 is {[3 0[1]]}
  206. check_doclist_all fts2p-1.1.1.3 test {[2 0[3]] [3 0[3]]}
  207. check_doclist_all fts2p-1.1.1.4 that {[2 0[0]]}
  208. check_doclist_all fts2p-1.1.1.5 this {[3 0[0]]}
  209. check_doclist_all fts2p-1.1.1.6 was {[2 0[1]]}
  210. check_terms fts2p-1.1.2 0 0 {a is test this}
  211. check_doclist fts2p-1.1.2.1 0 0 a {[1 0[2]]}
  212. check_doclist fts2p-1.1.2.2 0 0 is {[1 0[1]]}
  213. check_doclist fts2p-1.1.2.3 0 0 test {[1 0[3]]}
  214. check_doclist fts2p-1.1.2.4 0 0 this {[1 0[0]]}
  215. check_terms fts2p-1.1.3 0 1 {a test that was}
  216. check_doclist fts2p-1.1.3.1 0 1 a {[2 0[2]]}
  217. check_doclist fts2p-1.1.3.2 0 1 test {[2 0[3]]}
  218. check_doclist fts2p-1.1.3.3 0 1 that {[2 0[0]]}
  219. check_doclist fts2p-1.1.3.4 0 1 was {[2 0[1]]}
  220. check_terms fts2p-1.1.4 0 2 {a is test this}
  221. check_doclist fts2p-1.1.4.1 0 2 a {[3 0[2]]}
  222. check_doclist fts2p-1.1.4.2 0 2 is {[3 0[1]]}
  223. check_doclist fts2p-1.1.4.3 0 2 test {[3 0[3]]}
  224. check_doclist fts2p-1.1.4.4 0 2 this {[3 0[0]]}
  225. check_terms fts2p-1.1.5 0 3 {a is test this}
  226. check_doclist fts2p-1.1.5.1 0 3 a {[1]}
  227. check_doclist fts2p-1.1.5.2 0 3 is {[1]}
  228. check_doclist fts2p-1.1.5.3 0 3 test {[1]}
  229. check_doclist fts2p-1.1.5.4 0 3 this {[1]}
  230. #*************************************************************************
  231. # Test results when all references to certain tokens are deleted.
  232. db eval {
  233. DROP TABLE IF EXISTS t1;
  234. CREATE VIRTUAL TABLE t1 USING fts2(c);
  235. INSERT INTO t1 (rowid, c) VALUES (1, 'This is a test');
  236. INSERT INTO t1 (rowid, c) VALUES (2, 'That was a test');
  237. INSERT INTO t1 (rowid, c) VALUES (3, 'This is a test');
  238. DELETE FROM t1 WHERE rowid IN (1,3);
  239. }
  240. # Still 4 segments because 0,3 will contain deletes for rowid 1 and 3.
  241. do_test fts2p-1.2.segments {
  242. execsql {
  243. SELECT level, idx FROM t1_segdir ORDER BY level, idx;
  244. }
  245. } {0 0 0 1 0 2 0 3}
  246. do_test fts2p-1.2.matches {
  247. execsql {
  248. SELECT OFFSETS(t1) FROM t1
  249. WHERE t1 MATCH 'this OR that OR was OR a OR is OR test' ORDER BY rowid;
  250. }
  251. } {{0 1 0 4 0 2 5 3 0 3 9 1 0 5 11 4}}
  252. check_terms_all fts2p-1.2.1 {a is test that this was}
  253. check_doclist_all fts2p-1.2.1.1 a {[2 0[2]]}
  254. check_doclist_all fts2p-1.2.1.2 is {}
  255. check_doclist_all fts2p-1.2.1.3 test {[2 0[3]]}
  256. check_doclist_all fts2p-1.2.1.4 that {[2 0[0]]}
  257. check_doclist_all fts2p-1.2.1.5 this {}
  258. check_doclist_all fts2p-1.2.1.6 was {[2 0[1]]}
  259. check_terms fts2p-1.2.2 0 0 {a is test this}
  260. check_doclist fts2p-1.2.2.1 0 0 a {[1 0[2]]}
  261. check_doclist fts2p-1.2.2.2 0 0 is {[1 0[1]]}
  262. check_doclist fts2p-1.2.2.3 0 0 test {[1 0[3]]}
  263. check_doclist fts2p-1.2.2.4 0 0 this {[1 0[0]]}
  264. check_terms fts2p-1.2.3 0 1 {a test that was}
  265. check_doclist fts2p-1.2.3.1 0 1 a {[2 0[2]]}
  266. check_doclist fts2p-1.2.3.2 0 1 test {[2 0[3]]}
  267. check_doclist fts2p-1.2.3.3 0 1 that {[2 0[0]]}
  268. check_doclist fts2p-1.2.3.4 0 1 was {[2 0[1]]}
  269. check_terms fts2p-1.2.4 0 2 {a is test this}
  270. check_doclist fts2p-1.2.4.1 0 2 a {[3 0[2]]}
  271. check_doclist fts2p-1.2.4.2 0 2 is {[3 0[1]]}
  272. check_doclist fts2p-1.2.4.3 0 2 test {[3 0[3]]}
  273. check_doclist fts2p-1.2.4.4 0 2 this {[3 0[0]]}
  274. check_terms fts2p-1.2.5 0 3 {a is test this}
  275. check_doclist fts2p-1.2.5.1 0 3 a {[1] [3]}
  276. check_doclist fts2p-1.2.5.2 0 3 is {[1] [3]}
  277. check_doclist fts2p-1.2.5.3 0 3 test {[1] [3]}
  278. check_doclist fts2p-1.2.5.4 0 3 this {[1] [3]}
  279. #*************************************************************************
  280. # Test results when everything is optimized manually.
  281. db eval {
  282. DROP TABLE IF EXISTS t1;
  283. CREATE VIRTUAL TABLE t1 USING fts2(c);
  284. INSERT INTO t1 (rowid, c) VALUES (1, 'This is a test');
  285. INSERT INTO t1 (rowid, c) VALUES (2, 'That was a test');
  286. INSERT INTO t1 (rowid, c) VALUES (3, 'This is a test');
  287. DELETE FROM t1 WHERE rowid IN (1,3);
  288. DROP TABLE IF EXISTS t1old;
  289. ALTER TABLE t1 RENAME TO t1old;
  290. CREATE VIRTUAL TABLE t1 USING fts2(c);
  291. INSERT INTO t1 (rowid, c) SELECT rowid, c FROM t1old;
  292. DROP TABLE t1old;
  293. }
  294. # Should be a single optimal segment with the same logical results.
  295. do_test fts2p-1.3.segments {
  296. execsql {
  297. SELECT level, idx FROM t1_segdir ORDER BY level, idx;
  298. }
  299. } {0 0}
  300. do_test fts2p-1.3.matches {
  301. execsql {
  302. SELECT OFFSETS(t1) FROM t1
  303. WHERE t1 MATCH 'this OR that OR was OR a OR is OR test' ORDER BY rowid;
  304. }
  305. } {{0 1 0 4 0 2 5 3 0 3 9 1 0 5 11 4}}
  306. check_terms_all fts2p-1.3.1 {a test that was}
  307. check_doclist_all fts2p-1.3.1.1 a {[2 0[2]]}
  308. check_doclist_all fts2p-1.3.1.2 test {[2 0[3]]}
  309. check_doclist_all fts2p-1.3.1.3 that {[2 0[0]]}
  310. check_doclist_all fts2p-1.3.1.4 was {[2 0[1]]}
  311. check_terms fts2p-1.3.2 0 0 {a test that was}
  312. check_doclist fts2p-1.3.2.1 0 0 a {[2 0[2]]}
  313. check_doclist fts2p-1.3.2.2 0 0 test {[2 0[3]]}
  314. check_doclist fts2p-1.3.2.3 0 0 that {[2 0[0]]}
  315. check_doclist fts2p-1.3.2.4 0 0 was {[2 0[1]]}
  316. finish_test