fts5al.test 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. # 2014 November 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. # This file implements regression tests for SQLite library. The
  12. # focus of this script is testing the FTS5 module.
  13. #
  14. # Specifically, this function tests the %_config table.
  15. #
  16. source [file join [file dirname [info script]] fts5_common.tcl]
  17. set testprefix fts5al
  18. # If SQLITE_ENABLE_FTS5 is not defined, omit this file.
  19. ifcapable !fts5 {
  20. finish_test
  21. return
  22. }
  23. foreach_detail_mode $testprefix {
  24. do_execsql_test 1.1 {
  25. CREATE VIRTUAL TABLE ft1 USING fts5(x, detail=%DETAIL%);
  26. SELECT * FROM ft1_config;
  27. } {version 4}
  28. do_execsql_test 1.2 {
  29. INSERT INTO ft1(ft1, rank) VALUES('pgsz', 32);
  30. SELECT * FROM ft1_config;
  31. } {pgsz 32 version 4}
  32. do_execsql_test 1.3 {
  33. INSERT INTO ft1(ft1, rank) VALUES('pgsz', 64);
  34. SELECT * FROM ft1_config;
  35. } {pgsz 64 version 4}
  36. #--------------------------------------------------------------------------
  37. # Test the logic for parsing the rank() function definition.
  38. #
  39. foreach {tn defn} {
  40. 1 "fname()"
  41. 2 "fname(1)"
  42. 3 "fname(1,2)"
  43. 4 "fname(null,NULL,nUlL)"
  44. 5 " fname ( null , NULL , nUlL ) "
  45. 6 "fname('abc')"
  46. 7 "fname('a''bc')"
  47. 8 "fname('''abc')"
  48. 9 "fname('abc''')"
  49. 7 "fname( 'a''bc' )"
  50. 8 "fname('''abc' )"
  51. 9 "fname( 'abc''' )"
  52. 10 "fname(X'1234ab')"
  53. 11 "myfunc(1.2)"
  54. 12 "myfunc(-1.0)"
  55. 13 "myfunc(.01,'abc')"
  56. } {
  57. do_execsql_test 2.1.$tn {
  58. INSERT INTO ft1(ft1, rank) VALUES('rank', $defn);
  59. }
  60. }
  61. foreach {tn defn} {
  62. 1 ""
  63. 2 "fname"
  64. 3 "fname(X'234ab')"
  65. 4 "myfunc(-1.,'abc')"
  66. } {
  67. do_test 2.2.$tn {
  68. catchsql { INSERT INTO ft1(ft1, rank) VALUES('rank', $defn) }
  69. } {1 {SQL logic error}}
  70. }
  71. #-------------------------------------------------------------------------
  72. # Assorted tests of the tcl interface for creating extension functions.
  73. #
  74. do_execsql_test 3.1 {
  75. CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%);
  76. INSERT INTO t1 VALUES('q w e r t y');
  77. INSERT INTO t1 VALUES('y t r e w q');
  78. }
  79. proc argtest {cmd args} { return $args }
  80. sqlite3_fts5_create_function db argtest argtest
  81. do_execsql_test 3.2.1 {
  82. SELECT argtest(t1, 123) FROM t1 WHERE t1 MATCH 'q'
  83. } {123 123}
  84. do_execsql_test 3.2.2 {
  85. SELECT argtest(t1, 123, 456) FROM t1 WHERE t1 MATCH 'q'
  86. } {{123 456} {123 456}}
  87. proc rowidtest {cmd} { $cmd xRowid }
  88. sqlite3_fts5_create_function db rowidtest rowidtest
  89. do_execsql_test 3.3.1 {
  90. SELECT rowidtest(t1) FROM t1 WHERE t1 MATCH 'q'
  91. } {1 2}
  92. proc insttest {cmd} {
  93. set res [list]
  94. for {set i 0} {$i < [$cmd xInstCount]} {incr i} {
  95. lappend res [$cmd xInst $i]
  96. }
  97. set res
  98. }
  99. sqlite3_fts5_create_function db insttest insttest
  100. do_execsql_test 3.4.1 {
  101. SELECT insttest(t1) FROM t1 WHERE t1 MATCH 'q'
  102. } {
  103. {{0 0 0}}
  104. {{0 0 5}}
  105. }
  106. if {[detail_is_full]} {
  107. do_execsql_test 3.4.2 {
  108. SELECT insttest(t1) FROM t1 WHERE t1 MATCH 'r+e OR w'
  109. } {
  110. {{1 0 1}}
  111. {{0 0 2} {1 0 4}}
  112. }
  113. }
  114. proc coltest {cmd} {
  115. list [$cmd xColumnSize 0] [$cmd xColumnText 0]
  116. }
  117. sqlite3_fts5_create_function db coltest coltest
  118. do_execsql_test 3.5.1 {
  119. SELECT coltest(t1) FROM t1 WHERE t1 MATCH 'q'
  120. } {
  121. {6 {q w e r t y}}
  122. {6 {y t r e w q}}
  123. }
  124. #-------------------------------------------------------------------------
  125. # Tests for remapping the "rank" column.
  126. #
  127. # 4.1.*: Mapped to a function with no arguments.
  128. # 4.2.*: Mapped to a function with one or more arguments.
  129. #
  130. do_execsql_test 4.0 {
  131. CREATE VIRTUAL TABLE t2 USING fts5(a, b, detail=%DETAIL%);
  132. INSERT INTO t2 VALUES('a s h g s b j m r h', 's b p a d b b a o e');
  133. INSERT INTO t2 VALUES('r h n t a g r d d i', 'l d n j r c f t o q');
  134. INSERT INTO t2 VALUES('q k n i k c a a e m', 'c h n j p g s c i t');
  135. INSERT INTO t2 VALUES('h j g t r e l s g s', 'k q k c i i c k n s');
  136. INSERT INTO t2 VALUES('b l k h d n n n m i', 'p t i a r b t q o l');
  137. INSERT INTO t2 VALUES('k r i l j b g i p a', 't q c h a i m g n l');
  138. INSERT INTO t2 VALUES('a e c q n m o m d g', 'l c t g i s q g q e');
  139. INSERT INTO t2 VALUES('b o j h f o g b p e', 'r t l h s b g i c p');
  140. INSERT INTO t2 VALUES('s q k f q b j g h f', 'n m a o p e i e k t');
  141. INSERT INTO t2 VALUES('o q g g q c o k a b', 'r t k p t f t h p c');
  142. }
  143. proc firstinst {cmd} {
  144. foreach {p c o} [$cmd xInst 0] {}
  145. expr $c*100 + $o
  146. }
  147. sqlite3_fts5_create_function db firstinst firstinst
  148. do_execsql_test 4.1.1 {
  149. SELECT rowid, firstinst(t2) FROM t2 WHERE t2 MATCH 'a' ORDER BY rowid ASC
  150. } {
  151. 1 0 2 4 3 6 5 103
  152. 6 9 7 0 9 102 10 8
  153. }
  154. do_execsql_test 4.1.2 {
  155. SELECT rowid, rank FROM t2
  156. WHERE t2 MATCH 'a' AND rank MATCH 'firstinst()'
  157. ORDER BY rowid ASC
  158. } {
  159. 1 0 2 4 3 6 5 103
  160. 6 9 7 0 9 102 10 8
  161. }
  162. do_execsql_test 4.1.3 {
  163. SELECT rowid, rank FROM t2
  164. WHERE t2 MATCH 'a' AND rank MATCH 'firstinst()'
  165. ORDER BY rank DESC
  166. } {
  167. 5 103 9 102 6 9 10 8 3 6 2 4 1 0 7 0
  168. }
  169. do_execsql_test 4.1.4 {
  170. INSERT INTO t2(t2, rank) VALUES('rank', 'firstinst()');
  171. SELECT rowid, rank FROM t2 WHERE t2 MATCH 'a' ORDER BY rowid ASC
  172. } {
  173. 1 0 2 4 3 6 5 103
  174. 6 9 7 0 9 102 10 8
  175. }
  176. do_execsql_test 4.1.5 {
  177. SELECT rowid, rank FROM t2 WHERE t2 MATCH 'a' ORDER BY rank DESC
  178. } {
  179. 5 103 9 102 6 9 10 8 3 6 2 4 1 0 7 0
  180. }
  181. do_execsql_test 4.1.6 {
  182. INSERT INTO t2(t2, rank) VALUES('rank', 'firstinst ( ) ');
  183. SELECT rowid, rank FROM t2 WHERE t2 MATCH 'a' ORDER BY rank DESC
  184. } {
  185. 5 103 9 102 6 9 10 8 3 6 2 4 1 0 7 0
  186. }
  187. proc rowidplus {cmd ival} {
  188. expr [$cmd xRowid] + $ival
  189. }
  190. sqlite3_fts5_create_function db rowidplus rowidplus
  191. if {[detail_is_full]} {
  192. do_execsql_test 4.2.1 {
  193. INSERT INTO t2(t2, rank) VALUES('rank', 'rowidplus(100) ');
  194. SELECT rowid, rank FROM t2 WHERE t2 MATCH 'o + q + g'
  195. } {
  196. 10 110
  197. }
  198. do_execsql_test 4.2.2 {
  199. INSERT INTO t2(t2, rank) VALUES('rank', 'rowidplus(111) ');
  200. SELECT rowid, rank FROM t2 WHERE t2 MATCH 'o + q + g'
  201. } {
  202. 10 121
  203. }
  204. do_execsql_test 4.2.3 {
  205. SELECT rowid, rank FROM t2
  206. WHERE t2 MATCH 'o + q + g' AND rank MATCH 'rowidplus(112)'
  207. } {
  208. 10 122
  209. }
  210. }
  211. proc rowidmod {cmd imod} {
  212. expr [$cmd xRowid] % $imod
  213. }
  214. sqlite3_fts5_create_function db rowidmod rowidmod
  215. do_execsql_test 4.3.1 {
  216. CREATE VIRTUAL TABLE t3 USING fts5(x, detail=%DETAIL%);
  217. INSERT INTO t3 VALUES('a one');
  218. INSERT INTO t3 VALUES('a two');
  219. INSERT INTO t3 VALUES('a three');
  220. INSERT INTO t3 VALUES('a four');
  221. INSERT INTO t3 VALUES('a five');
  222. INSERT INTO t3(t3, rank) VALUES('rank', 'bm25()');
  223. }
  224. do_execsql_test 4.3.2 {
  225. SELECT * FROM t3
  226. WHERE t3 MATCH 'a' AND rank MATCH 'rowidmod(4)'
  227. ORDER BY rank ASC
  228. } {
  229. {a four} {a one} {a five} {a two} {a three}
  230. }
  231. do_execsql_test 4.3.3 {
  232. SELECT *, rank FROM t3
  233. WHERE t3 MATCH 'a' AND rank MATCH 'rowidmod(3)'
  234. ORDER BY rank ASC
  235. } {
  236. {a three} 0 {a one} 1 {a four} 1 {a two} 2 {a five} 2
  237. }
  238. do_execsql_test 4.3.4 {
  239. SELECT * FROM t3('a', 'rowidmod(4)') ORDER BY rank ASC;
  240. } {
  241. {a four} {a one} {a five} {a two} {a three}
  242. }
  243. do_execsql_test 4.3.5 {
  244. SELECT *, rank FROM t3('a', 'rowidmod(3)') ORDER BY rank ASC
  245. } {
  246. {a three} 0 {a one} 1 {a four} 1 {a two} 2 {a five} 2
  247. }
  248. do_catchsql_test 4.4.3 {
  249. SELECT *, rank FROM t3 WHERE t3 MATCH 'a' AND rank MATCH 'xyz(3)'
  250. } {1 {no such function: xyz}}
  251. do_catchsql_test 4.4.4 {
  252. SELECT *, rank FROM t3 WHERE t3 MATCH 'a' AND rank MATCH NULL
  253. } {1 {parse error in rank function: }}
  254. # Check that the second and subsequent rank= constraints are ignored.
  255. #
  256. do_catchsql_test 4.3.3 {
  257. SELECT *, rank FROM t3
  258. WHERE t3 MATCH 'a' AND
  259. rank MATCH 'nosuch()' AND
  260. rank MATCH 'rowidmod(3)'
  261. ORDER BY rank ASC
  262. } {1 {unable to use function MATCH in the requested context}}
  263. } ;# foreach_detail_mode
  264. finish_test