| OLD | NEW | 
|---|
| 1 # 2014 June 17 | 1 # 2014 June 17 | 
| 2 # | 2 # | 
| 3 # The author disclaims copyright to this source code.  In place of | 3 # The author disclaims copyright to this source code.  In place of | 
| 4 # a legal notice, here is a blessing: | 4 # a legal notice, here is a blessing: | 
| 5 # | 5 # | 
| 6 #    May you do good and not evil. | 6 #    May you do good and not evil. | 
| 7 #    May you find forgiveness for yourself and forgive others. | 7 #    May you find forgiveness for yourself and forgive others. | 
| 8 #    May you share freely, never taking more than you give. | 8 #    May you share freely, never taking more than you give. | 
| 9 # | 9 # | 
| 10 #************************************************************************* | 10 #************************************************************************* | 
| 11 # This file implements regression tests for SQLite library.  The | 11 # This file implements regression tests for SQLite library.  The | 
| 12 # focus of this script is testing the FTS5 module. | 12 # focus of this script is testing the FTS5 module. | 
| 13 # | 13 # | 
| 14 # | 14 # | 
| 15 | 15 | 
| 16 source [file join [file dirname [info script]] fts5_common.tcl] | 16 source [file join [file dirname [info script]] fts5_common.tcl] | 
| 17 set testprefix fts5ac | 17 set testprefix fts5ac | 
| 18 | 18 | 
| 19 # If SQLITE_ENABLE_FTS5 is defined, omit this file. | 19 # If SQLITE_ENABLE_FTS5 is defined, omit this file. | 
| 20 ifcapable !fts5 { | 20 ifcapable !fts5 { | 
| 21   finish_test | 21   finish_test | 
| 22   return | 22   return | 
| 23 } | 23 } | 
| 24 | 24 | 
|  | 25 foreach_detail_mode $testprefix { | 
|  | 26 | 
| 25 set data { | 27 set data { | 
| 26     0   {p o q e z k z p n f y u z y n y}   {l o o l v v k} | 28     0   {p o q e z k z p n f y u z y n y}   {l o o l v v k} | 
| 27     1   {p k h h p y l l h i p v n}         {p p l u r i f a j g e r r x w} | 29     1   {p k h h p y l l h i p v n}         {p p l u r i f a j g e r r x w} | 
| 28     2   {l s z j k i m p s}                 {l w e j t j e e i t w r o p o} | 30     2   {l s z j k i m p s}                 {l w e j t j e e i t w r o p o} | 
| 29     3   {x g y m y m h p}                   {k j j b r e y y a k y} | 31     3   {x g y m y m h p}                   {k j j b r e y y a k y} | 
| 30     4   {q m a i y i z}                     {o w a g k x g j m w e u k} | 32     4   {q m a i y i z}                     {o w a g k x g j m w e u k} | 
| 31     5   {k o a w y b s z}                   {s g l m m l m g p} | 33     5   {k o a w y b s z}                   {s g l m m l m g p} | 
| 32     6   {d a q i z h b l c p k j g k}       {p x u j x t v c z} | 34     6   {d a q i z h b l c p k j g k}       {p x u j x t v c z} | 
| 33     7   {f d a g o c t i}                   {w f c x l d r k i j} | 35     7   {f d a g o c t i}                   {w f c x l d r k i j} | 
| 34     8   {y g w u b q p o m j y b p a e k}   {r i d k y w o z q m a t p} | 36     8   {y g w u b q p o m j y b p a e k}   {r i d k y w o z q m a t p} | 
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 118     92  {f y d j o q t c c q m f j s t}     {f h e d y m o k} | 120     92  {f y d j o q t c c q m f j s t}     {f h e d y m o k} | 
| 119     93  {k x j r m a d o i z j}             {r t t t f e b r x i v j v g o} | 121     93  {k x j r m a d o i z j}             {r t t t f e b r x i v j v g o} | 
| 120     94  {s f e a e t i h h d q p z t q}     {b k m k w h c} | 122     94  {s f e a e t i h h d q p z t q}     {b k m k w h c} | 
| 121     95  {h b n j t k i h o q u}             {w n g i t o k c a m y p f l x c p} | 123     95  {h b n j t k i h o q u}             {w n g i t o k c a m y p f l x c p} | 
| 122     96  {f c x p y r b m o l m o a}         {p c a q s u n n x d c f a o} | 124     96  {f c x p y r b m o l m o a}         {p c a q s u n n x d c f a o} | 
| 123     97  {u h h k m n k}                     {u b v n u a o c} | 125     97  {u h h k m n k}                     {u b v n u a o c} | 
| 124     98  {s p e t c z d f n w f}             {l s f j b l c e s h} | 126     98  {s p e t c z d f n w f}             {l s f j b l c e s h} | 
| 125     99  {r c v w i v h a t a c v c r e}     {h h u m g o f b a e o} | 127     99  {r c v w i v h a t a c v c r e}     {h h u m g o f b a e o} | 
| 126 } | 128 } | 
| 127 | 129 | 
| 128 # Argument $expr is an FTS5 match expression designed to be executed against |  | 
| 129 # an FTS5 table with the following schema: |  | 
| 130 # |  | 
| 131 #   CREATE VIRTUAL TABLE xy USING fts5(x, y); |  | 
| 132 # |  | 
| 133 # Assuming the table contains the same records as stored int the global |  | 
| 134 # $::data array (see above), this function returns a list containing one |  | 
| 135 # element for each match in the dataset. The elements are themselves lists |  | 
| 136 # formatted as follows: |  | 
| 137 # |  | 
| 138 #   <rowid> {<phrase 0 matches> <phrase 1 matches>...} |  | 
| 139 # |  | 
| 140 # where each <phrase X matches> element is a list of phrase matches in the |  | 
| 141 # same form as returned by auxiliary scalar function fts5_test(). |  | 
| 142 # |  | 
| 143 proc matchdata {bPos expr {bAsc 1}} { |  | 
| 144 |  | 
| 145   set tclexpr [db one { |  | 
| 146     SELECT fts5_expr_tcl($expr, 'nearset $cols -pc ::pc', 'x', 'y') |  | 
| 147   }] |  | 
| 148   set res [list] |  | 
| 149 |  | 
| 150   #puts $tclexpr |  | 
| 151   foreach {id x y} $::data { |  | 
| 152     set cols [list $x $y] |  | 
| 153     set ::pc 0 |  | 
| 154     #set hits [lsort -command instcompare [eval $tclexpr]] |  | 
| 155     set hits [eval $tclexpr] |  | 
| 156     if {[llength $hits]>0} { |  | 
| 157       if {$bPos} { |  | 
| 158         lappend res [list $id $hits] |  | 
| 159       } else { |  | 
| 160         lappend res $id |  | 
| 161       } |  | 
| 162     } |  | 
| 163   } |  | 
| 164 |  | 
| 165   if {$bAsc} { |  | 
| 166     set res [lsort -integer -increasing -index 0 $res] |  | 
| 167   } else { |  | 
| 168     set res [lsort -integer -decreasing -index 0 $res] |  | 
| 169   } |  | 
| 170 |  | 
| 171   return [concat {*}$res] |  | 
| 172 } |  | 
| 173 |  | 
| 174 # |  | 
| 175 # End of test code |  | 
| 176 #------------------------------------------------------------------------- |  | 
| 177 |  | 
| 178 proc fts5_test_poslist {cmd} { |  | 
| 179   set res [list] |  | 
| 180   for {set i 0} {$i < [$cmd xInstCount]} {incr i} { |  | 
| 181     lappend res [string map {{ } .} [$cmd xInst $i]] |  | 
| 182   } |  | 
| 183   set res |  | 
| 184 } |  | 
| 185 |  | 
| 186 |  | 
| 187 foreach {tn2 sql} { | 130 foreach {tn2 sql} { | 
| 188   1  {} | 131   1  {} | 
| 189   2  {BEGIN} | 132   2  {BEGIN} | 
| 190 } { | 133 } { | 
| 191   reset_db | 134   reset_db | 
| 192   sqlite3_fts5_create_function db fts5_test_poslist fts5_test_poslist | 135   fts5_aux_test_functions db | 
| 193 | 136 | 
| 194   do_execsql_test 1.0 { | 137   do_execsql_test 1.$tn2.0 { | 
| 195     CREATE VIRTUAL TABLE xx USING fts5(x,y); | 138     CREATE VIRTUAL TABLE xx USING fts5(x,y, detail=%DETAIL%); | 
| 196     INSERT INTO xx(xx, rank) VALUES('pgsz', 32); | 139     INSERT INTO xx(xx, rank) VALUES('pgsz', 32); | 
| 197   } | 140   } | 
| 198 | 141 | 
| 199   execsql $sql | 142   execsql $sql | 
| 200 | 143 | 
| 201   do_test $tn2.1.1 { | 144   do_test 1.$tn2.1.1 { | 
| 202     foreach {id x y} $data { | 145     foreach {id x y} $data { | 
| 203       execsql { INSERT INTO xx(rowid, x, y) VALUES($id, $x, $y) } | 146       execsql { INSERT INTO xx(rowid, x, y) VALUES($id, $x, $y) } | 
| 204     } | 147     } | 
| 205     execsql { INSERT INTO xx(xx) VALUES('integrity-check') } | 148     execsql { INSERT INTO xx(xx) VALUES('integrity-check') } | 
| 206   } {} | 149   } {} | 
| 207 | 150 | 
| 208 | 151 | 
| 209   #------------------------------------------------------------------------- | 152   #------------------------------------------------------------------------- | 
| 210   # Test phrase queries. |  | 
| 211   # | 153   # | 
| 212   foreach {tn phrase} { | 154   do_execsql_test 1.$tn2.integrity { | 
| 213     1 "o" | 155     INSERT INTO xx(xx) VALUES('integrity-check'); | 
| 214     2 "b q" |  | 
| 215     3 "e a e" |  | 
| 216     4 "m d g q q b k b w f q q p p" |  | 
| 217     5 "l o o l v v k" |  | 
| 218     6 "a" |  | 
| 219     7 "b" |  | 
| 220     8 "c" |  | 
| 221     9 "no" |  | 
| 222     10 "L O O L V V K" |  | 
| 223   } { |  | 
| 224     set expr "\"$phrase\"" |  | 
| 225     set res [matchdata 1 $expr] |  | 
| 226 |  | 
| 227     do_execsql_test $tn2.1.2.$tn.[llength $res] { |  | 
| 228       SELECT rowid, fts5_test_poslist(xx) FROM xx WHERE xx match $expr |  | 
| 229     } $res |  | 
| 230   } |  | 
| 231 |  | 
| 232   #------------------------------------------------------------------------- |  | 
| 233   # Test some AND and OR queries. |  | 
| 234   # |  | 
| 235   foreach {tn expr} { |  | 
| 236     1.1 "a   AND b" |  | 
| 237     1.2 "a+b AND c" |  | 
| 238     1.3 "d+c AND u" |  | 
| 239     1.4 "d+c AND u+d" |  | 
| 240 |  | 
| 241     2.1 "a   OR b" |  | 
| 242     2.2 "a+b OR c" |  | 
| 243     2.3 "d+c OR u" |  | 
| 244     2.4 "d+c OR u+d" |  | 
| 245 |  | 
| 246     3.1 { a AND b AND c } |  | 
| 247   } { |  | 
| 248     set res [matchdata 1 $expr] |  | 
| 249     do_execsql_test $tn2.2.$tn.[llength $res] { |  | 
| 250       SELECT rowid, fts5_test_poslist(xx) FROM xx WHERE xx match $expr |  | 
| 251     } $res |  | 
| 252   } |  | 
| 253 |  | 
| 254   #------------------------------------------------------------------------- |  | 
| 255   # Queries on a specific column. |  | 
| 256   # |  | 
| 257   foreach {tn expr} { |  | 
| 258     1.1 "x:a" |  | 
| 259     1.2 "y:a" |  | 
| 260     1.3 "x:b" |  | 
| 261     1.4 "y:b" |  | 
| 262     2.1 "{x}:a" |  | 
| 263     2.2 "{y}:a" |  | 
| 264     2.3 "{x}:b" |  | 
| 265     2.4 "{y}:b" |  | 
| 266 |  | 
| 267     3.1 "{x y}:a" |  | 
| 268     3.2 "{y x}:a" |  | 
| 269     3.3 "{x x}:b" |  | 
| 270     3.4 "{y y}:b" |  | 
| 271 |  | 
| 272     4.1 {{"x" "y"}:a} |  | 
| 273     4.2 {{"y" x}:a} |  | 
| 274     4.3 {{x "x"}:b} |  | 
| 275     4.4 {{"y" y}:b} |  | 
| 276   } { |  | 
| 277     set res [matchdata 1 $expr] |  | 
| 278     do_execsql_test $tn2.3.$tn.[llength $res] { |  | 
| 279       SELECT rowid, fts5_test_poslist(xx) FROM xx WHERE xx match $expr |  | 
| 280     } $res |  | 
| 281   } |  | 
| 282 |  | 
| 283   #------------------------------------------------------------------------- |  | 
| 284   # Some NEAR queries. |  | 
| 285   # |  | 
| 286   foreach {tn expr} { |  | 
| 287     1 "NEAR(a b)" |  | 
| 288     2 "NEAR(r c)" |  | 
| 289     2 { NEAR(r c, 5) } |  | 
| 290     3 { NEAR(r c, 3) } |  | 
| 291     4 { NEAR(r c, 2) } |  | 
| 292     5 { NEAR(r c, 0) } |  | 
| 293     6 { NEAR(a b c) } |  | 
| 294     7 { NEAR(a b c, 8) } |  | 
| 295     8  { x : NEAR(r c) } |  | 
| 296     9  { y : NEAR(r c) } |  | 
| 297   } { |  | 
| 298     set res [matchdata 1 $expr] |  | 
| 299     do_execsql_test $tn2.4.1.$tn.[llength $res] { |  | 
| 300       SELECT rowid, fts5_test_poslist(xx) FROM xx WHERE xx match $expr |  | 
| 301     } $res |  | 
| 302   } |  | 
| 303 |  | 
| 304   do_test $tn2.4.1  { nearset {{a b c}} -- a } {0.0.0} |  | 
| 305   do_test $tn2.4.2  { nearset {{a b c}} -- c } {0.0.2} |  | 
| 306 |  | 
| 307   foreach {tn expr tclexpr} { |  | 
| 308     1 {a b} {AND [N $x -- {a}] [N $x -- {b}]} |  | 
| 309   } { |  | 
| 310     do_execsql_test $tn2.5.$tn { |  | 
| 311       SELECT fts5_expr_tcl($expr, 'N $x') |  | 
| 312     } [list $tclexpr] |  | 
| 313   } | 156   } | 
| 314 | 157 | 
| 315   #------------------------------------------------------------------------- | 158   #------------------------------------------------------------------------- | 
| 316   # | 159   # | 
| 317   do_execsql_test $tn2.6.integrity { | 160   foreach {tn expr} { | 
| 318     INSERT INTO xx(xx) VALUES('integrity-check'); | 161     1.1 "a   AND b" | 
| 319   } | 162     1.2 "a   OR b" | 
| 320   #db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM xx_data} {puts $r} | 163     1.3 "o" | 
| 321   foreach {bAsc sql} { | 164     1.4 "b q" | 
| 322     1 {SELECT rowid FROM xx WHERE xx MATCH $expr} | 165     1.5 "e a e" | 
| 323     0 {SELECT rowid FROM xx WHERE xx MATCH $expr ORDER BY rowid DESC} | 166     1.6 "m d g q q b k b w f q q p p" | 
|  | 167     1.7 "l o o l v v k" | 
|  | 168     1.8 "a" | 
|  | 169     1.9 "b" | 
|  | 170     1.10 "c" | 
|  | 171     1.11 "no" | 
|  | 172     1.12 "L O O L V V K" | 
|  | 173     1.13 "a AND b AND c" | 
|  | 174     1.14 "x:a" | 
|  | 175 | 
|  | 176     2.1 "x:a" | 
|  | 177     2.2 "y:a" | 
|  | 178     2.3 "x:b" | 
|  | 179     2.4 "y:b" | 
|  | 180 | 
|  | 181     3.1 "{x}:a" | 
|  | 182     3.2 "{y}:a" | 
|  | 183     3.3 "{x}:b" | 
|  | 184     3.4 "{y}:b" | 
|  | 185 | 
|  | 186     4.1 "{x y}:a" | 
|  | 187     4.2 "{y x}:a" | 
|  | 188     4.3 "{x x}:b" | 
|  | 189     4.4 "{y y}:b" | 
|  | 190 | 
|  | 191     5.1 {{"x" "y"}:a} | 
|  | 192     5.2 {{"y" x}:a} | 
|  | 193     5.3 {{x "x"}:b} | 
|  | 194     5.4 {{"y" y}:b} | 
|  | 195 | 
|  | 196     6.1 "b + q" | 
|  | 197     6.2 "e + a + e" | 
|  | 198     6.3 "m + d + g + q + q + b + k + b + w + f + q + q + p + p" | 
|  | 199     6.4 "l + o + o + l + v + v + k" | 
|  | 200     6.5 "L + O + O + L + V + V + K" | 
|  | 201 | 
|  | 202     7.1 "a+b AND c" | 
|  | 203     7.2 "d+c AND u" | 
|  | 204     7.3 "d+c AND u+d" | 
|  | 205     7.4 "a+b OR c" | 
|  | 206     7.5 "d+c OR u" | 
|  | 207     7.6 "d+c OR u+d" | 
|  | 208 | 
|  | 209     8.1 "NEAR(a b)" | 
|  | 210     8.2 "NEAR(r c)" | 
|  | 211     8.2 { NEAR(r c, 5) } | 
|  | 212     8.3 { NEAR(r c, 3) } | 
|  | 213     8.4 { NEAR(r c, 2) } | 
|  | 214     8.5 { NEAR(r c, 0) } | 
|  | 215     8.6 { NEAR(a b c) } | 
|  | 216     8.7 { NEAR(a b c, 8) } | 
|  | 217     8.8  { x : NEAR(r c) } | 
|  | 218     8.9  { y : NEAR(r c) } | 
|  | 219 | 
|  | 220     9.1 { NEAR(r c) } | 
|  | 221     9.2 { NEAR(r c, 5) } | 
|  | 222     9.3 { NEAR(r c, 3) } | 
|  | 223     9.4 { NEAR(r c, 2) } | 
|  | 224     9.5 { NEAR(r c, 0) } | 
|  | 225     9.6 { NEAR(a b c) } | 
|  | 226     9.7 { NEAR(a b c, 8) } | 
|  | 227     9.8  { x : NEAR(r c) } | 
|  | 228     9.9  { y : NEAR(r c) } | 
|  | 229     9.10 { x : "r c" } | 
|  | 230     9.11 { y : "r c" } | 
|  | 231     9.12 { a AND b } | 
|  | 232     9.13 { a AND b AND c } | 
|  | 233     9.14a { a } | 
|  | 234     9.14b { a OR b } | 
|  | 235     9.15 { a OR b AND c } | 
|  | 236     9.16 { c AND b OR a } | 
|  | 237     9.17 { c AND (b OR a) } | 
|  | 238     9.18 { c NOT (b OR a) } | 
|  | 239     9.19 { (c NOT b) OR (a AND d) } | 
| 324   } { | 240   } { | 
| 325     foreach {tn expr} { | 241 | 
| 326       0.1 x | 242     if {[fts5_expr_ok $expr xx]==0} { | 
| 327       1 { NEAR(r c) } | 243       do_test 1.$tn2.$tn.OMITTED { list } [list] | 
| 328       2 { NEAR(r c, 5) } | 244       continue | 
| 329       3 { NEAR(r c, 3) } |  | 
| 330       4 { NEAR(r c, 2) } |  | 
| 331       5 { NEAR(r c, 0) } |  | 
| 332       6 { NEAR(a b c) } |  | 
| 333       7 { NEAR(a b c, 8) } |  | 
| 334       8  { x : NEAR(r c) } |  | 
| 335       9  { y : NEAR(r c) } |  | 
| 336       10 { x : "r c" } |  | 
| 337       11 { y : "r c" } |  | 
| 338       12 { a AND b } |  | 
| 339       13 { a AND b AND c } |  | 
| 340       14a { a } |  | 
| 341       14b { a OR b } |  | 
| 342       15 { a OR b AND c } |  | 
| 343       16 { c AND b OR a } |  | 
| 344       17 { c AND (b OR a) } |  | 
| 345       18 { c NOT (b OR a) } |  | 
| 346       19 { c NOT b OR a AND d } |  | 
| 347     } { |  | 
| 348       set res [matchdata 0 $expr $bAsc] |  | 
| 349       do_execsql_test $tn2.6.$bAsc.$tn.[llength $res] $sql $res |  | 
| 350     } | 245     } | 
|  | 246 | 
|  | 247     set res [fts5_query_data $expr xx] | 
|  | 248     do_execsql_test 1.$tn2.$tn.[llength $res].asc { | 
|  | 249       SELECT rowid, fts5_test_poslist(xx), fts5_test_collist(xx) | 
|  | 250       FROM xx WHERE xx match $expr | 
|  | 251     } $res | 
|  | 252 | 
|  | 253     set res [fts5_query_data $expr xx DESC] | 
|  | 254     do_execsql_test 1.$tn2.$tn.[llength $res].desc { | 
|  | 255       SELECT rowid, fts5_test_poslist(xx), fts5_test_collist(xx) | 
|  | 256       FROM xx WHERE xx match $expr ORDER BY 1 DESC | 
|  | 257     } $res | 
| 351   } | 258   } | 
| 352 } | 259 } | 
| 353 | 260 | 
| 354 do_execsql_test 3.1 { | 261 } | 
|  | 262 | 
|  | 263 do_execsql_test 2.1 { | 
| 355   SELECT fts5_expr_tcl('a AND b'); | 264   SELECT fts5_expr_tcl('a AND b'); | 
| 356 } {{AND [nearset -- {a}] [nearset -- {b}]}} | 265 } {{AND [nearset -- {a}] [nearset -- {b}]}} | 
| 357 | 266 | 
|  | 267 do_test 2.2.1  { nearset {{a b c}} -- a } {0.0.0} | 
|  | 268 do_test 2.2.2  { nearset {{a b c}} -- c } {0.0.2} | 
|  | 269 | 
|  | 270 foreach {tn expr tclexpr} { | 
|  | 271   1 {a b} {AND [N $x -- {a}] [N $x -- {b}]} | 
|  | 272 } { | 
|  | 273   do_execsql_test 2.3.$tn { | 
|  | 274     SELECT fts5_expr_tcl($expr, 'N $x') | 
|  | 275   } [list $tclexpr] | 
|  | 276 } | 
|  | 277 | 
| 358 finish_test | 278 finish_test | 
| 359 | 279 | 
| OLD | NEW | 
|---|