| OLD | NEW | 
 | (Empty) | 
|    1 # 2005 August 13 |  | 
|    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 file is testing the LIKE and GLOB operators and |  | 
|   13 # in particular the optimizations that occur to help those operators |  | 
|   14 # run faster. |  | 
|   15 # |  | 
|   16 # $Id: like.test,v 1.13 2009/06/07 23:45:11 drh Exp $ |  | 
|   17  |  | 
|   18 set testdir [file dirname $argv0] |  | 
|   19 source $testdir/tester.tcl |  | 
|   20  |  | 
|   21 # Create some sample data to work with. |  | 
|   22 # |  | 
|   23 do_test like-1.0 { |  | 
|   24   execsql { |  | 
|   25     CREATE TABLE t1(x TEXT); |  | 
|   26   } |  | 
|   27   foreach str { |  | 
|   28     a |  | 
|   29     ab |  | 
|   30     abc |  | 
|   31     abcd |  | 
|   32  |  | 
|   33     acd |  | 
|   34     abd |  | 
|   35     bc |  | 
|   36     bcd |  | 
|   37  |  | 
|   38     xyz |  | 
|   39     ABC |  | 
|   40     CDE |  | 
|   41     {ABC abc xyz} |  | 
|   42   } { |  | 
|   43     db eval {INSERT INTO t1 VALUES(:str)} |  | 
|   44   } |  | 
|   45   execsql { |  | 
|   46     SELECT count(*) FROM t1; |  | 
|   47   } |  | 
|   48 } {12} |  | 
|   49  |  | 
|   50 # Test that both case sensitive and insensitive version of LIKE work. |  | 
|   51 # |  | 
|   52 do_test like-1.1 { |  | 
|   53   execsql { |  | 
|   54     SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1; |  | 
|   55   } |  | 
|   56 } {ABC abc} |  | 
|   57 do_test like-1.2 { |  | 
|   58   execsql { |  | 
|   59     SELECT x FROM t1 WHERE x GLOB 'abc' ORDER BY 1; |  | 
|   60   } |  | 
|   61 } {abc} |  | 
|   62 do_test like-1.3 { |  | 
|   63   execsql { |  | 
|   64     SELECT x FROM t1 WHERE x LIKE 'ABC' ORDER BY 1; |  | 
|   65   } |  | 
|   66 } {ABC abc} |  | 
|   67 do_test like-1.4 { |  | 
|   68   execsql { |  | 
|   69     SELECT x FROM t1 WHERE x LIKE 'aBc' ORDER BY 1; |  | 
|   70   } |  | 
|   71 } {ABC abc} |  | 
|   72 do_test like-1.5.1 { |  | 
|   73   execsql { |  | 
|   74     PRAGMA case_sensitive_like=on; |  | 
|   75     SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1; |  | 
|   76   } |  | 
|   77 } {abc} |  | 
|   78 do_test like-1.5.2 { |  | 
|   79   execsql { |  | 
|   80     PRAGMA case_sensitive_like; -- no argument; does not change setting |  | 
|   81     SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1; |  | 
|   82   } |  | 
|   83 } {abc} |  | 
|   84 do_test like-1.6 { |  | 
|   85   execsql { |  | 
|   86     SELECT x FROM t1 WHERE x GLOB 'abc' ORDER BY 1; |  | 
|   87   } |  | 
|   88 } {abc} |  | 
|   89 do_test like-1.7 { |  | 
|   90   execsql { |  | 
|   91     SELECT x FROM t1 WHERE x LIKE 'ABC' ORDER BY 1; |  | 
|   92   } |  | 
|   93 } {ABC} |  | 
|   94 do_test like-1.8 { |  | 
|   95   execsql { |  | 
|   96     SELECT x FROM t1 WHERE x LIKE 'aBc' ORDER BY 1; |  | 
|   97   } |  | 
|   98 } {} |  | 
|   99 do_test like-1.9 { |  | 
|  100   execsql { |  | 
|  101     PRAGMA case_sensitive_like=off; |  | 
|  102     SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1; |  | 
|  103   } |  | 
|  104 } {ABC abc} |  | 
|  105 do_test like-1.10 { |  | 
|  106   execsql { |  | 
|  107     PRAGMA case_sensitive_like;  -- No argument, does not change setting. |  | 
|  108     SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1; |  | 
|  109   } |  | 
|  110 } {ABC abc} |  | 
|  111  |  | 
|  112 # Tests of the REGEXP operator |  | 
|  113 # |  | 
|  114 do_test like-2.1 { |  | 
|  115   proc test_regexp {a b} { |  | 
|  116     return [regexp $a $b] |  | 
|  117   } |  | 
|  118   db function regexp test_regexp |  | 
|  119   execsql { |  | 
|  120     SELECT x FROM t1 WHERE x REGEXP 'abc' ORDER BY 1; |  | 
|  121   } |  | 
|  122 } {{ABC abc xyz} abc abcd} |  | 
|  123 do_test like-2.2 { |  | 
|  124   execsql { |  | 
|  125     SELECT x FROM t1 WHERE x REGEXP '^abc' ORDER BY 1; |  | 
|  126   } |  | 
|  127 } {abc abcd} |  | 
|  128  |  | 
|  129 # Tests of the MATCH operator |  | 
|  130 # |  | 
|  131 do_test like-2.3 { |  | 
|  132   proc test_match {a b} { |  | 
|  133     return [string match $a $b] |  | 
|  134   } |  | 
|  135   db function match -argcount 2 test_match |  | 
|  136   execsql { |  | 
|  137     SELECT x FROM t1 WHERE x MATCH '*abc*' ORDER BY 1; |  | 
|  138   } |  | 
|  139 } {{ABC abc xyz} abc abcd} |  | 
|  140 do_test like-2.4 { |  | 
|  141   execsql { |  | 
|  142     SELECT x FROM t1 WHERE x MATCH 'abc*' ORDER BY 1; |  | 
|  143   } |  | 
|  144 } {abc abcd} |  | 
|  145  |  | 
|  146 # For the remaining tests, we need to have the like optimizations |  | 
|  147 # enabled. |  | 
|  148 # |  | 
|  149 ifcapable !like_opt { |  | 
|  150   finish_test |  | 
|  151   return |  | 
|  152 }  |  | 
|  153  |  | 
|  154 # This procedure executes the SQL.  Then it appends to the result the |  | 
|  155 # "sort" or "nosort" keyword (as in the cksort procedure above) then |  | 
|  156 # it appends the ::sqlite_query_plan variable. |  | 
|  157 # |  | 
|  158 proc queryplan {sql} { |  | 
|  159   set ::sqlite_sort_count 0 |  | 
|  160   set data [execsql $sql] |  | 
|  161   if {$::sqlite_sort_count} {set x sort} {set x nosort} |  | 
|  162   lappend data $x |  | 
|  163   return [concat $data $::sqlite_query_plan] |  | 
|  164 } |  | 
|  165  |  | 
|  166 # Perform tests on the like optimization. |  | 
|  167 # |  | 
|  168 # With no index on t1.x and with case sensitivity turned off, no optimization |  | 
|  169 # is performed. |  | 
|  170 # |  | 
|  171 do_test like-3.1 { |  | 
|  172   set sqlite_like_count 0 |  | 
|  173   queryplan { |  | 
|  174     SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1; |  | 
|  175   } |  | 
|  176 } {ABC {ABC abc xyz} abc abcd sort t1 {}} |  | 
|  177 do_test like-3.2 { |  | 
|  178   set sqlite_like_count |  | 
|  179 } {12} |  | 
|  180  |  | 
|  181 # With an index on t1.x and case sensitivity on, optimize completely. |  | 
|  182 # |  | 
|  183 do_test like-3.3 { |  | 
|  184   set sqlite_like_count 0 |  | 
|  185   execsql { |  | 
|  186     PRAGMA case_sensitive_like=on; |  | 
|  187     CREATE INDEX i1 ON t1(x); |  | 
|  188   } |  | 
|  189   queryplan { |  | 
|  190     SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1; |  | 
|  191   } |  | 
|  192 } {abc abcd nosort {} i1} |  | 
|  193 do_test like-3.4 { |  | 
|  194   set sqlite_like_count |  | 
|  195 } 0 |  | 
|  196  |  | 
|  197 # Partial optimization when the pattern does not end in '%' |  | 
|  198 # |  | 
|  199 do_test like-3.5 { |  | 
|  200   set sqlite_like_count 0 |  | 
|  201   queryplan { |  | 
|  202     SELECT x FROM t1 WHERE x LIKE 'a_c' ORDER BY 1; |  | 
|  203   } |  | 
|  204 } {abc nosort {} i1} |  | 
|  205 do_test like-3.6 { |  | 
|  206   set sqlite_like_count |  | 
|  207 } 6 |  | 
|  208 do_test like-3.7 { |  | 
|  209   set sqlite_like_count 0 |  | 
|  210   queryplan { |  | 
|  211     SELECT x FROM t1 WHERE x LIKE 'ab%d' ORDER BY 1; |  | 
|  212   } |  | 
|  213 } {abcd abd nosort {} i1} |  | 
|  214 do_test like-3.8 { |  | 
|  215   set sqlite_like_count |  | 
|  216 } 4 |  | 
|  217 do_test like-3.9 { |  | 
|  218   set sqlite_like_count 0 |  | 
|  219   queryplan { |  | 
|  220     SELECT x FROM t1 WHERE x LIKE 'a_c%' ORDER BY 1; |  | 
|  221   } |  | 
|  222 } {abc abcd nosort {} i1} |  | 
|  223 do_test like-3.10 { |  | 
|  224   set sqlite_like_count |  | 
|  225 } 6 |  | 
|  226  |  | 
|  227 # No optimization when the pattern begins with a wildcard. |  | 
|  228 # Note that the index is still used but only for sorting. |  | 
|  229 # |  | 
|  230 do_test like-3.11 { |  | 
|  231   set sqlite_like_count 0 |  | 
|  232   queryplan { |  | 
|  233     SELECT x FROM t1 WHERE x LIKE '%bcd' ORDER BY 1; |  | 
|  234   } |  | 
|  235 } {abcd bcd nosort {} i1} |  | 
|  236 do_test like-3.12 { |  | 
|  237   set sqlite_like_count |  | 
|  238 } 12 |  | 
|  239  |  | 
|  240 # No optimization for case insensitive LIKE |  | 
|  241 # |  | 
|  242 do_test like-3.13 { |  | 
|  243   set sqlite_like_count 0 |  | 
|  244   queryplan { |  | 
|  245     PRAGMA case_sensitive_like=off; |  | 
|  246     SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1; |  | 
|  247   } |  | 
|  248 } {ABC {ABC abc xyz} abc abcd nosort {} i1} |  | 
|  249 do_test like-3.14 { |  | 
|  250   set sqlite_like_count |  | 
|  251 } 12 |  | 
|  252  |  | 
|  253 # No optimization without an index. |  | 
|  254 # |  | 
|  255 do_test like-3.15 { |  | 
|  256   set sqlite_like_count 0 |  | 
|  257   queryplan { |  | 
|  258     PRAGMA case_sensitive_like=on; |  | 
|  259     DROP INDEX i1; |  | 
|  260     SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1; |  | 
|  261   } |  | 
|  262 } {abc abcd sort t1 {}} |  | 
|  263 do_test like-3.16 { |  | 
|  264   set sqlite_like_count |  | 
|  265 } 12 |  | 
|  266  |  | 
|  267 # No GLOB optimization without an index. |  | 
|  268 # |  | 
|  269 do_test like-3.17 { |  | 
|  270   set sqlite_like_count 0 |  | 
|  271   queryplan { |  | 
|  272     SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1; |  | 
|  273   } |  | 
|  274 } {abc abcd sort t1 {}} |  | 
|  275 do_test like-3.18 { |  | 
|  276   set sqlite_like_count |  | 
|  277 } 12 |  | 
|  278  |  | 
|  279 # GLOB is optimized regardless of the case_sensitive_like setting. |  | 
|  280 # |  | 
|  281 do_test like-3.19 { |  | 
|  282   set sqlite_like_count 0 |  | 
|  283   queryplan { |  | 
|  284     CREATE INDEX i1 ON t1(x); |  | 
|  285     SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1; |  | 
|  286   } |  | 
|  287 } {abc abcd nosort {} i1} |  | 
|  288 do_test like-3.20 { |  | 
|  289   set sqlite_like_count |  | 
|  290 } 0 |  | 
|  291 do_test like-3.21 { |  | 
|  292   set sqlite_like_count 0 |  | 
|  293   queryplan { |  | 
|  294     PRAGMA case_sensitive_like=on; |  | 
|  295     SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1; |  | 
|  296   } |  | 
|  297 } {abc abcd nosort {} i1} |  | 
|  298 do_test like-3.22 { |  | 
|  299   set sqlite_like_count |  | 
|  300 } 0 |  | 
|  301 do_test like-3.23 { |  | 
|  302   set sqlite_like_count 0 |  | 
|  303   queryplan { |  | 
|  304     PRAGMA case_sensitive_like=off; |  | 
|  305     SELECT x FROM t1 WHERE x GLOB 'a[bc]d' ORDER BY 1; |  | 
|  306   } |  | 
|  307 } {abd acd nosort {} i1} |  | 
|  308 do_test like-3.24 { |  | 
|  309   set sqlite_like_count |  | 
|  310 } 6 |  | 
|  311  |  | 
|  312 # No optimization if the LHS of the LIKE is not a column name or |  | 
|  313 # if the RHS is not a string. |  | 
|  314 # |  | 
|  315 do_test like-4.1 { |  | 
|  316   execsql {PRAGMA case_sensitive_like=on} |  | 
|  317   set sqlite_like_count 0 |  | 
|  318   queryplan { |  | 
|  319     SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1 |  | 
|  320   } |  | 
|  321 } {abc abcd nosort {} i1} |  | 
|  322 do_test like-4.2 { |  | 
|  323   set sqlite_like_count |  | 
|  324 } 0 |  | 
|  325 do_test like-4.3 { |  | 
|  326   set sqlite_like_count 0 |  | 
|  327   queryplan { |  | 
|  328     SELECT x FROM t1 WHERE +x LIKE 'abc%' ORDER BY 1 |  | 
|  329   } |  | 
|  330 } {abc abcd nosort {} i1} |  | 
|  331 do_test like-4.4 { |  | 
|  332   set sqlite_like_count |  | 
|  333 } 12 |  | 
|  334 do_test like-4.5 { |  | 
|  335   set sqlite_like_count 0 |  | 
|  336   queryplan { |  | 
|  337     SELECT x FROM t1 WHERE x LIKE ('ab' || 'c%') ORDER BY 1 |  | 
|  338   } |  | 
|  339 } {abc abcd nosort {} i1} |  | 
|  340 do_test like-4.6 { |  | 
|  341   set sqlite_like_count |  | 
|  342 } 12 |  | 
|  343  |  | 
|  344 # Collating sequences on the index disable the LIKE optimization. |  | 
|  345 # Or if the NOCASE collating sequence is used, the LIKE optimization |  | 
|  346 # is enabled when case_sensitive_like is OFF. |  | 
|  347 # |  | 
|  348 do_test like-5.1 { |  | 
|  349   execsql {PRAGMA case_sensitive_like=off} |  | 
|  350   set sqlite_like_count 0 |  | 
|  351   queryplan { |  | 
|  352     SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1 |  | 
|  353   } |  | 
|  354 } {ABC {ABC abc xyz} abc abcd nosort {} i1} |  | 
|  355 do_test like-5.2 { |  | 
|  356   set sqlite_like_count |  | 
|  357 } 12 |  | 
|  358 do_test like-5.3 { |  | 
|  359   execsql { |  | 
|  360     CREATE TABLE t2(x TEXT COLLATE NOCASE); |  | 
|  361     INSERT INTO t2 SELECT * FROM t1; |  | 
|  362     CREATE INDEX i2 ON t2(x COLLATE NOCASE); |  | 
|  363   } |  | 
|  364   set sqlite_like_count 0 |  | 
|  365   queryplan { |  | 
|  366     SELECT x FROM t2 WHERE x LIKE 'abc%' ORDER BY 1 |  | 
|  367   } |  | 
|  368 } {abc ABC {ABC abc xyz} abcd nosort {} i2} |  | 
|  369 do_test like-5.4 { |  | 
|  370   set sqlite_like_count |  | 
|  371 } 0 |  | 
|  372 do_test like-5.5 { |  | 
|  373   execsql { |  | 
|  374     PRAGMA case_sensitive_like=on; |  | 
|  375   } |  | 
|  376   set sqlite_like_count 0 |  | 
|  377   queryplan { |  | 
|  378     SELECT x FROM t2 WHERE x LIKE 'abc%' ORDER BY 1 |  | 
|  379   } |  | 
|  380 } {abc abcd nosort {} i2} |  | 
|  381 do_test like-5.6 { |  | 
|  382   set sqlite_like_count |  | 
|  383 } 12 |  | 
|  384 do_test like-5.7 { |  | 
|  385   execsql { |  | 
|  386     PRAGMA case_sensitive_like=off; |  | 
|  387   } |  | 
|  388   set sqlite_like_count 0 |  | 
|  389   queryplan { |  | 
|  390     SELECT x FROM t2 WHERE x GLOB 'abc*' ORDER BY 1 |  | 
|  391   } |  | 
|  392 } {abc abcd nosort {} i2} |  | 
|  393 do_test like-5.8 { |  | 
|  394   set sqlite_like_count |  | 
|  395 } 12 |  | 
|  396 do_test like-5.11 { |  | 
|  397   execsql {PRAGMA case_sensitive_like=off} |  | 
|  398   set sqlite_like_count 0 |  | 
|  399   queryplan { |  | 
|  400     SELECT x FROM t1 WHERE x LIKE 'ABC%' ORDER BY 1 |  | 
|  401   } |  | 
|  402 } {ABC {ABC abc xyz} abc abcd nosort {} i1} |  | 
|  403 do_test like-5.12 { |  | 
|  404   set sqlite_like_count |  | 
|  405 } 12 |  | 
|  406 do_test like-5.13 { |  | 
|  407   set sqlite_like_count 0 |  | 
|  408   queryplan { |  | 
|  409     SELECT x FROM t2 WHERE x LIKE 'ABC%' ORDER BY 1 |  | 
|  410   } |  | 
|  411 } {abc ABC {ABC abc xyz} abcd nosort {} i2} |  | 
|  412 do_test like-5.14 { |  | 
|  413   set sqlite_like_count |  | 
|  414 } 0 |  | 
|  415 do_test like-5.15 { |  | 
|  416   execsql { |  | 
|  417     PRAGMA case_sensitive_like=on; |  | 
|  418   } |  | 
|  419   set sqlite_like_count 0 |  | 
|  420   queryplan { |  | 
|  421     SELECT x FROM t2 WHERE x LIKE 'ABC%' ORDER BY 1 |  | 
|  422   } |  | 
|  423 } {ABC {ABC abc xyz} nosort {} i2} |  | 
|  424 do_test like-5.16 { |  | 
|  425   set sqlite_like_count |  | 
|  426 } 12 |  | 
|  427 do_test like-5.17 { |  | 
|  428   execsql { |  | 
|  429     PRAGMA case_sensitive_like=off; |  | 
|  430   } |  | 
|  431   set sqlite_like_count 0 |  | 
|  432   queryplan { |  | 
|  433     SELECT x FROM t2 WHERE x GLOB 'ABC*' ORDER BY 1 |  | 
|  434   } |  | 
|  435 } {ABC {ABC abc xyz} nosort {} i2} |  | 
|  436 do_test like-5.18 { |  | 
|  437   set sqlite_like_count |  | 
|  438 } 12 |  | 
|  439  |  | 
|  440 # Boundary case.  The prefix for a LIKE comparison is rounded up |  | 
|  441 # when constructing the comparison.  Example:  "ab" becomes "ac". |  | 
|  442 # In other words, the last character is increased by one. |  | 
|  443 # |  | 
|  444 # Make sure this happens correctly when the last character is a  |  | 
|  445 # "z" and we are doing case-insensitive comparisons. |  | 
|  446 # |  | 
|  447 # Ticket #2959 |  | 
|  448 # |  | 
|  449 do_test like-5.21 { |  | 
|  450   execsql { |  | 
|  451     PRAGMA case_sensitive_like=off; |  | 
|  452     INSERT INTO t2 VALUES('ZZ-upper-upper'); |  | 
|  453     INSERT INTO t2 VALUES('zZ-lower-upper'); |  | 
|  454     INSERT INTO t2 VALUES('Zz-upper-lower'); |  | 
|  455     INSERT INTO t2 VALUES('zz-lower-lower'); |  | 
|  456   } |  | 
|  457   queryplan { |  | 
|  458     SELECT x FROM t2 WHERE x LIKE 'zz%'; |  | 
|  459   } |  | 
|  460 } {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2} |  | 
|  461 do_test like-5.22 { |  | 
|  462   queryplan { |  | 
|  463     SELECT x FROM t2 WHERE x LIKE 'zZ%'; |  | 
|  464   } |  | 
|  465 } {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2} |  | 
|  466 do_test like-5.23 { |  | 
|  467   queryplan { |  | 
|  468     SELECT x FROM t2 WHERE x LIKE 'Zz%'; |  | 
|  469   } |  | 
|  470 } {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2} |  | 
|  471 do_test like-5.24 { |  | 
|  472   queryplan { |  | 
|  473     SELECT x FROM t2 WHERE x LIKE 'ZZ%'; |  | 
|  474   } |  | 
|  475 } {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2} |  | 
|  476 do_test like-5.25 { |  | 
|  477   queryplan { |  | 
|  478     PRAGMA case_sensitive_like=on; |  | 
|  479     CREATE TABLE t3(x TEXT); |  | 
|  480     CREATE INDEX i3 ON t3(x); |  | 
|  481     INSERT INTO t3 VALUES('ZZ-upper-upper'); |  | 
|  482     INSERT INTO t3 VALUES('zZ-lower-upper'); |  | 
|  483     INSERT INTO t3 VALUES('Zz-upper-lower'); |  | 
|  484     INSERT INTO t3 VALUES('zz-lower-lower'); |  | 
|  485     SELECT x FROM t3 WHERE x LIKE 'zz%'; |  | 
|  486   } |  | 
|  487 } {zz-lower-lower nosort {} i3} |  | 
|  488 do_test like-5.26 { |  | 
|  489   queryplan { |  | 
|  490     SELECT x FROM t3 WHERE x LIKE 'zZ%'; |  | 
|  491   } |  | 
|  492 } {zZ-lower-upper nosort {} i3} |  | 
|  493 do_test like-5.27 { |  | 
|  494   queryplan { |  | 
|  495     SELECT x FROM t3 WHERE x LIKE 'Zz%'; |  | 
|  496   } |  | 
|  497 } {Zz-upper-lower nosort {} i3} |  | 
|  498 do_test like-5.28 { |  | 
|  499   queryplan { |  | 
|  500     SELECT x FROM t3 WHERE x LIKE 'ZZ%'; |  | 
|  501   } |  | 
|  502 } {ZZ-upper-upper nosort {} i3} |  | 
|  503  |  | 
|  504  |  | 
|  505 # ticket #2407 |  | 
|  506 # |  | 
|  507 # Make sure the LIKE prefix optimization does not strip off leading |  | 
|  508 # characters of the like pattern that happen to be quote characters. |  | 
|  509 # |  | 
|  510 do_test like-6.1 { |  | 
|  511   foreach x { 'abc 'bcd 'def 'ax } { |  | 
|  512     set x2 '[string map {' ''} $x]' |  | 
|  513     db eval "INSERT INTO t2 VALUES($x2)" |  | 
|  514   } |  | 
|  515   execsql { |  | 
|  516     SELECT * FROM t2 WHERE x LIKE '''a%' |  | 
|  517   } |  | 
|  518 } {'abc 'ax} |  | 
|  519  |  | 
|  520 do_test like-7.1 { |  | 
|  521   execsql { |  | 
|  522     SELECT rowid, * FROM t1 WHERE rowid GLOB '1*' ORDER BY rowid; |  | 
|  523   } |  | 
|  524 } {1 a 10 ABC 11 CDE 12 {ABC abc xyz}} |  | 
|  525  |  | 
|  526 # ticket #3345. |  | 
|  527 # |  | 
|  528 # Overloading the LIKE function with -1 for the number of arguments |  | 
|  529 # will overload both the 2-argument and the 3-argument LIKE. |  | 
|  530 # |  | 
|  531 do_test like-8.1 { |  | 
|  532   db eval { |  | 
|  533     CREATE TABLE t8(x); |  | 
|  534     INSERT INTO t8 VALUES('abcdef'); |  | 
|  535     INSERT INTO t8 VALUES('ghijkl'); |  | 
|  536     INSERT INTO t8 VALUES('mnopqr'); |  | 
|  537     SELECT 1, x FROM t8 WHERE x LIKE '%h%'; |  | 
|  538     SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x'; |  | 
|  539   } |  | 
|  540 } {1 ghijkl 2 ghijkl} |  | 
|  541 do_test like-8.2 { |  | 
|  542   proc newlike {args} {return 1} ;# Alternative LIKE is always return TRUE |  | 
|  543   db function like newlike       ;# Uses -1 for nArg in sqlite3_create_function |  | 
|  544   db cache flush |  | 
|  545   db eval { |  | 
|  546     SELECT 1, x FROM t8 WHERE x LIKE '%h%'; |  | 
|  547     SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x'; |  | 
|  548   } |  | 
|  549 } {1 ghijkl 2 ghijkl} |  | 
|  550 do_test like-8.3 { |  | 
|  551   db function like -argcount 2 newlike |  | 
|  552   db eval { |  | 
|  553     SELECT 1, x FROM t8 WHERE x LIKE '%h%'; |  | 
|  554     SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x'; |  | 
|  555   } |  | 
|  556 } {1 abcdef 1 ghijkl 1 mnopqr 2 ghijkl} |  | 
|  557 do_test like-8.4 { |  | 
|  558   db function like -argcount 3 newlike |  | 
|  559   db eval { |  | 
|  560     SELECT 1, x FROM t8 WHERE x LIKE '%h%'; |  | 
|  561     SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x'; |  | 
|  562   } |  | 
|  563 } {1 abcdef 1 ghijkl 1 mnopqr 2 abcdef 2 ghijkl 2 mnopqr} |  | 
|  564  |  | 
|  565  |  | 
|  566 ifcapable like_opt { |  | 
|  567   # Evaluate SQL.  Return the result set followed by the |  | 
|  568   # and the number of full-scan steps. |  | 
|  569   # |  | 
|  570   db close |  | 
|  571   sqlite3 db test.db |  | 
|  572   proc count_steps {sql} { |  | 
|  573     set r [db eval $sql] |  | 
|  574     lappend r scan [db status step] sort [db status sort] |  | 
|  575   } |  | 
|  576   do_test like-9.1 { |  | 
|  577     count_steps { |  | 
|  578        SELECT x FROM t2 WHERE x LIKE 'x%' |  | 
|  579     } |  | 
|  580   } {xyz scan 0 sort 0} |  | 
|  581   do_test like-9.2 { |  | 
|  582     count_steps { |  | 
|  583        SELECT x FROM t2 WHERE x LIKE '_y%' |  | 
|  584     } |  | 
|  585   } {xyz scan 19 sort 0} |  | 
|  586   do_test like-9.3.1 { |  | 
|  587     set res [sqlite3_exec_hex db { |  | 
|  588        SELECT x FROM t2 WHERE x LIKE '%78%25' |  | 
|  589     }] |  | 
|  590   } {0 {x xyz}} |  | 
|  591   ifcapable explain { |  | 
|  592     do_test like-9.3.2 { |  | 
|  593       set res [sqlite3_exec_hex db { |  | 
|  594          EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%78%25' |  | 
|  595       }] |  | 
|  596       regexp {INDEX i2} $res |  | 
|  597     } {1} |  | 
|  598   } |  | 
|  599   do_test like-9.4.1 { |  | 
|  600     sqlite3_exec_hex db {INSERT INTO t2 VALUES('%ffhello')} |  | 
|  601     set res [sqlite3_exec_hex db { |  | 
|  602        SELECT substr(x,2) AS x FROM t2 WHERE +x LIKE '%ff%25' |  | 
|  603     }] |  | 
|  604   } {0 {x hello}} |  | 
|  605   do_test like-9.4.2 { |  | 
|  606     set res [sqlite3_exec_hex db { |  | 
|  607        SELECT substr(x,2) AS x FROM t2 WHERE x LIKE '%ff%25' |  | 
|  608     }] |  | 
|  609   } {0 {x hello}} |  | 
|  610   ifcapable explain { |  | 
|  611     do_test like-9.4.3 { |  | 
|  612       set res [sqlite3_exec_hex db { |  | 
|  613          EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%ff%25' |  | 
|  614       }] |  | 
|  615       regexp {INDEX i2} $res |  | 
|  616     } {0} |  | 
|  617   } |  | 
|  618   do_test like-9.5.1 { |  | 
|  619     set res [sqlite3_exec_hex db { |  | 
|  620        SELECT x FROM t2 WHERE x LIKE '%fe%25' |  | 
|  621     }] |  | 
|  622   } {0 {}} |  | 
|  623   ifcapable explain { |  | 
|  624     do_test like-9.5.2 { |  | 
|  625       set res [sqlite3_exec_hex db { |  | 
|  626          EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%fe%25' |  | 
|  627       }] |  | 
|  628       regexp {INDEX i2} $res |  | 
|  629     } {1} |  | 
|  630   } |  | 
|  631 } |  | 
|  632  |  | 
|  633 # Do an SQL statement.  Append the search count to the end of the result. |  | 
|  634 # |  | 
|  635 proc count sql { |  | 
|  636   set ::sqlite_search_count 0 |  | 
|  637   set ::sqlite_like_count 0 |  | 
|  638   return [concat [execsql $sql] scan $::sqlite_search_count \ |  | 
|  639            like $::sqlite_like_count] |  | 
|  640 } |  | 
|  641  |  | 
|  642 # The LIKE and GLOB optimizations do not work on columns with |  | 
|  643 # affinity other than TEXT. |  | 
|  644 # Ticket #3901 |  | 
|  645 # |  | 
|  646 do_test like-10.1 { |  | 
|  647   db close |  | 
|  648   sqlite3 db test.db |  | 
|  649   execsql { |  | 
|  650     CREATE TABLE t10( |  | 
|  651       a INTEGER PRIMARY KEY, |  | 
|  652       b INTEGER COLLATE nocase UNIQUE, |  | 
|  653       c NUMBER COLLATE nocase UNIQUE, |  | 
|  654       d BLOB COLLATE nocase UNIQUE, |  | 
|  655       e COLLATE nocase UNIQUE, |  | 
|  656       f TEXT COLLATE nocase UNIQUE |  | 
|  657     ); |  | 
|  658     INSERT INTO t10 VALUES(1,1,1,1,1,1); |  | 
|  659     INSERT INTO t10 VALUES(12,12,12,12,12,12); |  | 
|  660     INSERT INTO t10 VALUES(123,123,123,123,123,123); |  | 
|  661     INSERT INTO t10 VALUES(234,234,234,234,234,234); |  | 
|  662     INSERT INTO t10 VALUES(345,345,345,345,345,345); |  | 
|  663     INSERT INTO t10 VALUES(45,45,45,45,45,45); |  | 
|  664   } |  | 
|  665   count { |  | 
|  666     SELECT a FROM t10 WHERE b LIKE '12%' ORDER BY a; |  | 
|  667   } |  | 
|  668 } {12 123 scan 5 like 6} |  | 
|  669 do_test like-10.2 { |  | 
|  670   count { |  | 
|  671     SELECT a FROM t10 WHERE c LIKE '12%' ORDER BY a; |  | 
|  672   } |  | 
|  673 } {12 123 scan 5 like 6} |  | 
|  674 do_test like-10.3 { |  | 
|  675   count { |  | 
|  676     SELECT a FROM t10 WHERE d LIKE '12%' ORDER BY a; |  | 
|  677   } |  | 
|  678 } {12 123 scan 5 like 6} |  | 
|  679 do_test like-10.4 { |  | 
|  680   count { |  | 
|  681     SELECT a FROM t10 WHERE e LIKE '12%' ORDER BY a; |  | 
|  682   } |  | 
|  683 } {12 123 scan 5 like 6} |  | 
|  684 do_test like-10.5 { |  | 
|  685   count { |  | 
|  686     SELECT a FROM t10 WHERE f LIKE '12%' ORDER BY a; |  | 
|  687   } |  | 
|  688 } {12 123 scan 3 like 0} |  | 
|  689 do_test like-10.6 { |  | 
|  690   count { |  | 
|  691     SELECT a FROM t10 WHERE a LIKE '12%' ORDER BY a; |  | 
|  692   } |  | 
|  693 } {12 123 scan 5 like 6} |  | 
|  694 do_test like-10.10 { |  | 
|  695   execsql { |  | 
|  696     CREATE TABLE t10b( |  | 
|  697       a INTEGER PRIMARY KEY, |  | 
|  698       b INTEGER UNIQUE, |  | 
|  699       c NUMBER UNIQUE, |  | 
|  700       d BLOB UNIQUE, |  | 
|  701       e UNIQUE, |  | 
|  702       f TEXT UNIQUE |  | 
|  703     ); |  | 
|  704     INSERT INTO t10b SELECT * FROM t10; |  | 
|  705   } |  | 
|  706   count { |  | 
|  707     SELECT a FROM t10b WHERE b GLOB '12*' ORDER BY a; |  | 
|  708   } |  | 
|  709 } {12 123 scan 5 like 6} |  | 
|  710 do_test like-10.11 { |  | 
|  711   count { |  | 
|  712     SELECT a FROM t10b WHERE c GLOB '12*' ORDER BY a; |  | 
|  713   } |  | 
|  714 } {12 123 scan 5 like 6} |  | 
|  715 do_test like-10.12 { |  | 
|  716   count { |  | 
|  717     SELECT a FROM t10b WHERE d GLOB '12*' ORDER BY a; |  | 
|  718   } |  | 
|  719 } {12 123 scan 5 like 6} |  | 
|  720 do_test like-10.13 { |  | 
|  721   count { |  | 
|  722     SELECT a FROM t10b WHERE e GLOB '12*' ORDER BY a; |  | 
|  723   } |  | 
|  724 } {12 123 scan 5 like 6} |  | 
|  725 do_test like-10.14 { |  | 
|  726   count { |  | 
|  727     SELECT a FROM t10b WHERE f GLOB '12*' ORDER BY a; |  | 
|  728   } |  | 
|  729 } {12 123 scan 3 like 0} |  | 
|  730 do_test like-10.15 { |  | 
|  731   count { |  | 
|  732     SELECT a FROM t10b WHERE a GLOB '12*' ORDER BY a; |  | 
|  733   } |  | 
|  734 } {12 123 scan 5 like 6} |  | 
|  735  |  | 
|  736  |  | 
|  737 finish_test |  | 
| OLD | NEW |