fts3prefix.test 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. # 2011 May 04
  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 FTS3 module.
  13. #
  14. set testdir [file dirname $argv0]
  15. source $testdir/tester.tcl
  16. set testprefix fts3prefix
  17. ifcapable !fts3 {
  18. finish_test
  19. return
  20. }
  21. # This proc tests that the prefixes index appears to represent the same content
  22. # as the terms index.
  23. #
  24. proc fts3_terms_and_prefixes {db tbl prefixlengths} {
  25. set iIndex 0
  26. foreach len $prefixlengths {
  27. incr iIndex
  28. $db eval {
  29. DROP TABLE IF EXISTS fts3check1;
  30. DROP TABLE IF EXISTS fts3check2;
  31. }
  32. $db eval "CREATE VIRTUAL TABLE fts3check1 USING fts4term($tbl, 0);"
  33. $db eval "CREATE VIRTUAL TABLE fts3check2 USING fts4term($tbl, $iIndex);"
  34. $db eval {
  35. DROP TABLE IF EXISTS temp.terms;
  36. DROP TABLE IF EXISTS temp.prefixes;
  37. CREATE TEMP TABLE terms AS SELECT * FROM fts3check1;
  38. CREATE TEMP TABLE prefixes AS SELECT * FROM fts3check2;
  39. CREATE INDEX temp.idx ON prefixes(term);
  40. DROP TABLE fts3check1;
  41. DROP TABLE fts3check2;
  42. }
  43. set nExpect 0
  44. $db eval { SELECT term, docid, col, pos FROM temp.terms } a {
  45. if {[string length $a(term)]<$len} continue
  46. incr nExpect
  47. set prefix [string range $a(term) 0 [expr $len-1]]
  48. set r [$db one {
  49. SELECT count(*) FROM temp.prefixes WHERE
  50. term = $prefix AND docid = $a(docid) AND col = $a(col) AND pos = $a(pos)
  51. }]
  52. if {$r != 1} {
  53. error "$t, $a(docid), $a(col), $a(pos)"
  54. }
  55. }
  56. set nCount [$db one {SELECT count(*) FROM temp.prefixes}]
  57. if {$nCount != $nExpect} {
  58. error "prefixes.count(*) is $nCount expected $nExpect"
  59. }
  60. execsql { DROP TABLE temp.prefixes }
  61. execsql { DROP TABLE temp.terms }
  62. set list [list]
  63. $db eval "
  64. SELECT sum( 1 << (16*(level%1024)) ) AS total, (level/1024) AS tree
  65. FROM ${tbl}_segdir GROUP BY tree
  66. " {
  67. lappend list [list $total $tree]
  68. }
  69. if { [lsort -integer -index 0 $list] != [lsort -integer -index 1 $list] } {
  70. error "inconsistent tree structures: $list"
  71. }
  72. }
  73. return ""
  74. }
  75. proc fts3_tap_test {tn db tbl lens} {
  76. uplevel [list do_test $tn [list fts3_terms_and_prefixes $db $tbl $lens] ""]
  77. }
  78. #-------------------------------------------------------------------------
  79. # Test cases 1.* are a sanity check. They test that the prefixes index is
  80. # being constructed correctly for the simplest possible case.
  81. #
  82. do_execsql_test 1.1 {
  83. CREATE VIRTUAL TABLE t1 USING fts4(prefix='1,3,6');
  84. CREATE VIRTUAL TABLE p1 USING fts4term(t1, 1);
  85. CREATE VIRTUAL TABLE p2 USING fts4term(t1, 2);
  86. CREATE VIRTUAL TABLE p3 USING fts4term(t1, 3);
  87. CREATE VIRTUAL TABLE terms USING fts4term(t1);
  88. }
  89. do_execsql_test 1.2 {
  90. INSERT INTO t1 VALUES('sqlite mysql firebird');
  91. }
  92. do_execsql_test 1.3.1 { SELECT term FROM p1 } {f m s}
  93. do_execsql_test 1.3.2 { SELECT term FROM p2 } {fir mys sql}
  94. do_execsql_test 1.3.3 { SELECT term FROM p3 } {firebi sqlite}
  95. do_execsql_test 1.4 {
  96. SELECT term FROM terms;
  97. } {firebird mysql sqlite}
  98. fts3_tap_test 1.5 db t1 {1 3 6}
  99. #-------------------------------------------------------------------------
  100. # A slightly more complicated dataset. This test also verifies that DELETE
  101. # operations do not corrupt the prefixes index.
  102. #
  103. do_execsql_test 2.1 {
  104. INSERT INTO t1 VALUES('FTS3 and FTS4 are an SQLite virtual table modules');
  105. INSERT INTO t1 VALUES('that allows users to perform full-text searches on');
  106. INSERT INTO t1 VALUES('a set of documents. The most common (and');
  107. INSERT INTO t1 VALUES('effective) way to describe full-text searches is');
  108. INSERT INTO t1 VALUES('"what Google, Yahoo and Altavista do with');
  109. INSERT INTO t1 VALUES('documents placed on the World Wide Web". Users');
  110. INSERT INTO t1 VALUES('input a term, or series of terms, perhaps');
  111. INSERT INTO t1 VALUES('connected by a binary operator or grouped together');
  112. INSERT INTO t1 VALUES('into a phrase, and the full-text query system');
  113. INSERT INTO t1 VALUES('finds the set of documents that best matches those');
  114. INSERT INTO t1 VALUES('terms considering the operators and groupings the');
  115. INSERT INTO t1 VALUES('user has specified. This article describes the');
  116. INSERT INTO t1 VALUES('deployment and usage of FTS3 and FTS4.');
  117. INSERT INTO t1 VALUES('FTS1 and FTS2 are obsolete full-text search');
  118. INSERT INTO t1 VALUES('modules for SQLite. There are known issues with');
  119. INSERT INTO t1 VALUES('these older modules and their use should be');
  120. INSERT INTO t1 VALUES('avoided. Portions of the original FTS3 code were');
  121. INSERT INTO t1 VALUES('contributed to the SQLite project by Scott Hess of');
  122. INSERT INTO t1 VALUES('Google. It is now developed and maintained as part');
  123. INSERT INTO t1 VALUES('of SQLite. ');
  124. }
  125. fts3_tap_test 2.2 db t1 {1 3 6}
  126. do_execsql_test 2.3 { DELETE FROM t1 WHERE docid%2; }
  127. fts3_tap_test 2.4 db t1 {1 3 6}
  128. do_execsql_test 2.5 { INSERT INTO t1(t1) VALUES('optimize') }
  129. fts3_tap_test 2.6 db t1 {1 3 6}
  130. do_execsql_test 3.1 {
  131. CREATE VIRTUAL TABLE t2 USING fts4(prefix='1,2,3');
  132. INSERT INTO t2 VALUES('On 12 September the wind direction turned and');
  133. INSERT INTO t2 VALUES('William''s fleet sailed. A storm blew up and the');
  134. INSERT INTO t2 VALUES('fleet was forced to take shelter at');
  135. INSERT INTO t2 VALUES('Saint-Valery-sur-Somme and again wait for the wind');
  136. INSERT INTO t2 VALUES('to change. On 27 September the Norman fleet');
  137. INSERT INTO t2 VALUES('finally set sail, landing in England at Pevensey');
  138. INSERT INTO t2 VALUES('Bay (Sussex) on 28 September. William then moved');
  139. INSERT INTO t2 VALUES('to Hastings, a few miles to the east, where he');
  140. INSERT INTO t2 VALUES('built a prefabricated wooden castle for a base of');
  141. INSERT INTO t2 VALUES('operations. From there, he ravaged the hinterland');
  142. INSERT INTO t2 VALUES('and waited for Harold''s return from the north.');
  143. INSERT INTO t2 VALUES('On 12 September the wind direction turned and');
  144. INSERT INTO t2 VALUES('William''s fleet sailed. A storm blew up and the');
  145. INSERT INTO t2 VALUES('fleet was forced to take shelter at');
  146. INSERT INTO t2 VALUES('Saint-Valery-sur-Somme and again wait for the wind');
  147. INSERT INTO t2 VALUES('to change. On 27 September the Norman fleet');
  148. INSERT INTO t2 VALUES('finally set sail, landing in England at Pevensey');
  149. INSERT INTO t2 VALUES('Bay (Sussex) on 28 September. William then moved');
  150. INSERT INTO t2 VALUES('to Hastings, a few miles to the east, where he');
  151. INSERT INTO t2 VALUES('built a prefabricated wooden castle for a base of');
  152. INSERT INTO t2 VALUES('operations. From there, he ravaged the hinterland');
  153. INSERT INTO t2 VALUES('and waited for Harold''s return from the north.');
  154. }
  155. fts3_tap_test 3.2 db t2 {1 2 3}
  156. do_execsql_test 3.3 { SELECT optimize(t2) FROM t2 LIMIT 1 } {{Index optimized}}
  157. fts3_tap_test 3.4 db t2 {1 2 3}
  158. #-------------------------------------------------------------------------
  159. # Simple tests for reading the prefix-index.
  160. #
  161. do_execsql_test 4.1 {
  162. CREATE VIRTUAL TABLE t3 USING fts4(prefix="1,4");
  163. INSERT INTO t3 VALUES('one two three');
  164. INSERT INTO t3 VALUES('four five six');
  165. INSERT INTO t3 VALUES('seven eight nine');
  166. }
  167. do_execsql_test 4.2 {
  168. SELECT * FROM t3 WHERE t3 MATCH 'f*'
  169. } {{four five six}}
  170. do_execsql_test 4.3 {
  171. SELECT * FROM t3 WHERE t3 MATCH 'four*'
  172. } {{four five six}}
  173. do_execsql_test 4.4 {
  174. SELECT * FROM t3 WHERE t3 MATCH 's*'
  175. } {{four five six} {seven eight nine}}
  176. do_execsql_test 4.5 {
  177. SELECT * FROM t3 WHERE t3 MATCH 'sev*'
  178. } {{seven eight nine}}
  179. do_execsql_test 4.6 {
  180. SELECT * FROM t3 WHERE t3 MATCH 'one*'
  181. } {{one two three}}
  182. #-------------------------------------------------------------------------
  183. # Syntax tests.
  184. #
  185. do_catchsql_test 5.1 {
  186. CREATE VIRTUAL TABLE t4 USING fts4(prefix="abc");
  187. } {1 {error parsing prefix parameter: abc}}
  188. do_catchsql_test 5.2 {
  189. CREATE VIRTUAL TABLE t4 USING fts4(prefix="");
  190. } {0 {}}
  191. finish_test