fts5contentless.test 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. # 2014 Dec 20
  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 contains tests for the content= and content_rowid= options.
  13. #
  14. source [file join [file dirname [info script]] fts5_common.tcl]
  15. set testprefix fts5contentless
  16. # If SQLITE_ENABLE_FTS5 is not defined, omit this file.
  17. ifcapable !fts5 {
  18. finish_test
  19. return
  20. }
  21. # Check that it is not possible to specify "contentless_delete=1" for
  22. # anything other than a contentless table.
  23. #
  24. set res(0) {0 {}}
  25. set res(1) {1 {contentless_delete=1 requires a contentless table}}
  26. foreach {tn sql bError} {
  27. 1 "(a, b, contentless_delete=1)" 1
  28. 2 "(a, b, contentless_delete=1, content=abc)" 1
  29. 3 "(a, b, contentless_delete=1, content=)" 0
  30. 4 "(content=, contentless_delete=1, a)" 0
  31. 5 "(content='', contentless_delete=1, hello)" 0
  32. } {
  33. execsql { BEGIN }
  34. do_catchsql_test 1.$tn "CREATE VIRTUAL TABLE t1 USING fts5 $sql" $res($bError)
  35. execsql { ROLLBACK }
  36. }
  37. # Check that it is not possible to specify "contentless_delete=1"
  38. # along with columnsize=1.
  39. #
  40. set res(0) {0 {}}
  41. set res(1) {1 {contentless_delete=1 is incompatible with columnsize=0}}
  42. foreach {tn sql bError} {
  43. 2 "(a, b, content='', contentless_delete=1, columnsize=0)" 1
  44. } {
  45. execsql { BEGIN }
  46. do_catchsql_test 1.$tn "CREATE VIRTUAL TABLE t1 USING fts5 $sql" $res($bError)
  47. execsql { ROLLBACK }
  48. }
  49. # Check that if contentless_delete=1 is specified, then the "origin"
  50. # column is added to the %_docsize table.
  51. reset_db
  52. do_execsql_test 3.0 {
  53. CREATE VIRTUAL TABLE x1 USING fts5(c, content='');
  54. CREATE VIRTUAL TABLE x2 USING fts5(c, content='', contentless_delete=1);
  55. }
  56. do_execsql_test 3.1 {
  57. SELECT sql FROM sqlite_schema WHERE name IN ('x1_docsize', 'x2_docsize');
  58. } {
  59. {CREATE TABLE 'x1_docsize'(id INTEGER PRIMARY KEY, sz BLOB)}
  60. {CREATE TABLE 'x2_docsize'(id INTEGER PRIMARY KEY, sz BLOB, origin INTEGER)}
  61. }
  62. do_execsql_test 3.2.1 {
  63. SELECT hex(block) FROM x1_data WHERE id=10
  64. } {00000000000000}
  65. do_execsql_test 3.2.2 {
  66. SELECT hex(block) FROM x2_data WHERE id=10
  67. } {00000000FF000001000000}
  68. do_execsql_test 3.3 {
  69. INSERT INTO x2 VALUES('first text');
  70. INSERT INTO x2 VALUES('second text');
  71. }
  72. do_execsql_test 3.4 {
  73. SELECT id, origin FROM x2_docsize
  74. } {1 1 2 2}
  75. do_execsql_test 3.5 {
  76. SELECT level, segment, loc1, loc2 FROM fts5_structure(
  77. (SELECT block FROM x2_data WHERE id=10)
  78. )
  79. } {
  80. 0 0 1 1
  81. 0 1 2 2
  82. }
  83. do_execsql_test 3.6 {
  84. INSERT INTO x2(x2) VALUES('optimize');
  85. }
  86. do_execsql_test 3.7 {
  87. SELECT level, segment, loc1, loc2 FROM fts5_structure(
  88. (SELECT block FROM x2_data WHERE id=10)
  89. )
  90. } {
  91. 1 0 1 2
  92. }
  93. do_execsql_test 3.8 {
  94. DELETE FROM x2 WHERE rowid=2;
  95. }
  96. do_execsql_test 3.9 {
  97. SELECT rowid FROM x2('text')
  98. } {1}
  99. #--------------------------------------------------------------------------
  100. reset_db
  101. proc document {n} {
  102. set vocab [list A B C D E F G H I J K L M N O P Q R S T U V W X Y Z]
  103. set ret [list]
  104. for {set ii 0} {$ii < $n} {incr ii} {
  105. lappend ret [lindex $vocab [expr int(rand()*[llength $vocab])]]
  106. }
  107. set ret
  108. }
  109. set nRow 1000
  110. do_execsql_test 4.0 {
  111. CREATE TABLE t1(x);
  112. CREATE VIRTUAL TABLE ft USING fts5(x, content='', contentless_delete=1);
  113. INSERT INTO ft(ft, rank) VALUES('pgsz', 100);
  114. }
  115. do_test 4.1 {
  116. for {set ii 0} {$ii < $nRow} {incr ii} {
  117. set doc [document 6]
  118. execsql {
  119. INSERT INTO t1 VALUES($doc);
  120. INSERT INTO ft VALUES($doc);
  121. }
  122. }
  123. } {}
  124. foreach v {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} {
  125. set L1 [execsql {SELECT rowid FROM t1 WHERE x LIKE '%'||$v||'%'}]
  126. set L2 [execsql {SELECT rowid FROM ft($v)}]
  127. do_test 4.2.$v { set L1 } $L2
  128. }
  129. do_test 4.3 {
  130. for {set ii 1} {$ii < $nRow} {incr ii 2} {
  131. execsql {
  132. DELETE FROM ft WHERE rowid=$ii;
  133. DELETE FROM t1 WHERE rowid=$ii;
  134. }
  135. }
  136. } {}
  137. foreach v {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} {
  138. set L1 [execsql {SELECT rowid FROM t1 WHERE x LIKE '%'||$v||'%'}]
  139. set L2 [execsql {SELECT rowid FROM ft($v)}]
  140. do_test 4.4.$v { set L1 } $L2
  141. }
  142. do_execsql_test 4.5 {
  143. INSERT INTO ft(ft) VALUES('optimize');
  144. } {}
  145. foreach v {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} {
  146. set L1 [execsql {SELECT rowid FROM t1 WHERE x LIKE '%'||$v||'%'}]
  147. set L2 [execsql {SELECT rowid FROM ft($v)}]
  148. do_test 4.6.$v { set L1 } $L2
  149. }
  150. #execsql_pp { SELECT fts5_decode(id, block) FROM ft_data }
  151. #-------------------------------------------------------------------------
  152. reset_db
  153. do_execsql_test 5.0 {
  154. CREATE VIRTUAL TABLE ft USING fts5(x, content='', contentless_delete=1);
  155. INSERT INTO ft(rowid, x) VALUES(1, 'one two three');
  156. INSERT INTO ft(rowid, x) VALUES(2, 'one two four');
  157. INSERT INTO ft(rowid, x) VALUES(3, 'one two five');
  158. INSERT INTO ft(rowid, x) VALUES(4, 'one two seven');
  159. INSERT INTO ft(rowid, x) VALUES(5, 'one two eight');
  160. }
  161. do_execsql_test 5.1 {
  162. DELETE FROM ft WHERE rowid=2
  163. }
  164. do_execsql_test 5.2 {
  165. SELECT rowid FROM ft
  166. } {1 3 4 5}
  167. do_catchsql_test 5.3 {
  168. UPDATE ft SET x='four six' WHERE rowid=3
  169. } {0 {}}
  170. do_execsql_test 5.4 {
  171. SELECT rowid FROM ft('one');
  172. } {1 4 5}
  173. do_execsql_test 5.5 {
  174. REPLACE INTO ft(rowid, x) VALUES(3, 'four six');
  175. SELECT rowid FROM ft('one');
  176. } {1 4 5}
  177. do_execsql_test 5.6 {
  178. REPLACE INTO ft(rowid, x) VALUES(6, 'one two eleven');
  179. SELECT rowid FROM ft('one');
  180. } {1 4 5 6}
  181. #-------------------------------------------------------------------------
  182. reset_db
  183. do_execsql_test 6.0 {
  184. CREATE VIRTUAL TABLE ft USING fts5(x, content='', contentless_delete=1);
  185. INSERT INTO ft(rowid, x) VALUES(1, 'one two three');
  186. INSERT INTO ft(rowid, x) VALUES(2, 'one two four');
  187. }
  188. do_test 6.1 {
  189. db eval { SELECT rowid FROM ft('one two') } {
  190. if {$rowid==1} {
  191. db eval { INSERT INTO ft(rowid, x) VALUES(3, 'one two four') }
  192. }
  193. }
  194. } {}
  195. #-------------------------------------------------------------------------
  196. reset_db
  197. do_execsql_test 7.0 {
  198. CREATE VIRTUAL TABLE ft USING fts5(x, content='', contentless_delete=1);
  199. }
  200. set lRowid [list -450 0 1 2 42]
  201. do_test 7.1 {
  202. execsql BEGIN
  203. foreach r $lRowid {
  204. execsql { INSERT INTO ft(rowid, x) VALUES($r, 'one one one'); }
  205. }
  206. execsql COMMIT
  207. } {}
  208. do_test 7.2 {
  209. execsql BEGIN
  210. foreach r $lRowid {
  211. execsql { REPLACE INTO ft(rowid, x) VALUES($r, 'two two two'); }
  212. }
  213. execsql COMMIT
  214. } {}
  215. do_execsql_test 7.3 { SELECT rowid FROM ft('one'); } {}
  216. do_execsql_test 7.4 { SELECT rowid FROM ft('two'); } $lRowid
  217. #-------------------------------------------------------------------------
  218. reset_db
  219. do_execsql_test 8.0 {
  220. CREATE VIRTUAL TABLE ft USING fts5(x, content='', contentless_delete=1);
  221. INSERT INTO ft VALUES('hello world');
  222. INSERT INTO ft VALUES('one two three');
  223. }
  224. do_catchsql_test 8.1 {
  225. INSERT INTO ft(ft, rowid, x) VALUES('delete', 1, 'hello world');
  226. } {1 {'delete' may not be used with a contentless_delete=1 table}}
  227. do_execsql_test 8.2 {
  228. BEGIN;
  229. INSERT INTO ft(rowid, x) VALUES(3, 'four four four');
  230. DELETE FROM ft WHERE rowid=3;
  231. COMMIT;
  232. SELECT rowid FROM ft('four');
  233. } {}
  234. #-------------------------------------------------------------------------
  235. reset_db
  236. do_execsql_test 9.0 {
  237. CREATE VIRTUAL TABLE ft USING fts5(x, content='', contentless_delete=0);
  238. INSERT INTO ft VALUES('hello world');
  239. INSERT INTO ft VALUES('one two three');
  240. }
  241. do_catchsql_test 9.1 {
  242. INSERT INTO ft(ft, rowid, x) VALUES('delete', 1, 'hello world');
  243. } {0 {}}
  244. do_catchsql_test 9.2 {
  245. CREATE VIRTUAL TABLE ft2 USING fts5(x, content='', contentless_delete=2);
  246. } {1 {malformed contentless_delete=... directive}}
  247. do_catchsql_test 9.3 {
  248. CREATE VIRTUAL TABLE ft2 USING fts5(x, content='', contentless_delete=11);
  249. } {1 {malformed contentless_delete=... directive}}
  250. finish_test