xref: /sqlite-3.40.0/test/like.test (revision 8d889afc)
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
18set testdir [file dirname $argv0]
19source $testdir/tester.tcl
20set testprefix like
21
22# Create some sample data to work with.
23#
24do_test like-1.0 {
25  execsql {
26    CREATE TABLE t1(x TEXT);
27  }
28  foreach str {
29    a
30    ab
31    abc
32    abcd
33
34    acd
35    abd
36    bc
37    bcd
38
39    xyz
40    ABC
41    CDE
42    {ABC abc xyz}
43  } {
44    db eval {INSERT INTO t1 VALUES(:str)}
45  }
46  execsql {
47    SELECT count(*) FROM t1;
48  }
49} {12}
50
51# Test that both case sensitive and insensitive version of LIKE work.
52#
53do_test like-1.1 {
54  execsql {
55    SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
56  }
57} {ABC abc}
58do_test like-1.2 {
59  execsql {
60    SELECT x FROM t1 WHERE x GLOB 'abc' ORDER BY 1;
61  }
62} {abc}
63do_test like-1.3 {
64  execsql {
65    SELECT x FROM t1 WHERE x LIKE 'ABC' ORDER BY 1;
66  }
67} {ABC abc}
68do_test like-1.4 {
69  execsql {
70    SELECT x FROM t1 WHERE x LIKE 'aBc' ORDER BY 1;
71  }
72} {ABC abc}
73do_test like-1.5.1 {
74  # Use sqlite3_exec() to verify fix for ticket [25ee81271091] 2011-06-26
75  sqlite3_exec db {PRAGMA case_sensitive_like=on}
76} {0 {}}
77do_test like-1.5.2 {
78  execsql {
79    SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
80  }
81} {abc}
82do_test like-1.5.3 {
83  execsql {
84    PRAGMA case_sensitive_like; -- no argument; does not change setting
85    SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
86  }
87} {abc}
88do_test like-1.6 {
89  execsql {
90    SELECT x FROM t1 WHERE x GLOB 'abc' ORDER BY 1;
91  }
92} {abc}
93do_test like-1.7 {
94  execsql {
95    SELECT x FROM t1 WHERE x LIKE 'ABC' ORDER BY 1;
96  }
97} {ABC}
98do_test like-1.8 {
99  execsql {
100    SELECT x FROM t1 WHERE x LIKE 'aBc' ORDER BY 1;
101  }
102} {}
103do_test like-1.9 {
104  execsql {
105    PRAGMA case_sensitive_like=off;
106    SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
107  }
108} {ABC abc}
109do_test like-1.10 {
110  execsql {
111    PRAGMA case_sensitive_like;  -- No argument, does not change setting.
112    SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
113  }
114} {ABC abc}
115
116# Tests of the REGEXP operator
117#
118do_test like-2.1 {
119  proc test_regexp {a b} {
120    return [regexp $a $b]
121  }
122  db function regexp -argcount 2 test_regexp
123  execsql {
124    SELECT x FROM t1 WHERE x REGEXP 'abc' ORDER BY 1;
125  }
126} {{ABC abc xyz} abc abcd}
127do_test like-2.2 {
128  execsql {
129    SELECT x FROM t1 WHERE x REGEXP '^abc' ORDER BY 1;
130  }
131} {abc abcd}
132
133# Tests of the MATCH operator
134#
135do_test like-2.3 {
136  proc test_match {a b} {
137    return [string match $a $b]
138  }
139  db function match -argcount 2 test_match
140  execsql {
141    SELECT x FROM t1 WHERE x MATCH '*abc*' ORDER BY 1;
142  }
143} {{ABC abc xyz} abc abcd}
144do_test like-2.4 {
145  execsql {
146    SELECT x FROM t1 WHERE x MATCH 'abc*' ORDER BY 1;
147  }
148} {abc abcd}
149
150# For the remaining tests, we need to have the like optimizations
151# enabled.
152#
153ifcapable !like_opt {
154  finish_test
155  return
156}
157
158# This procedure executes the SQL.  Then it appends to the result the
159# "sort" or "nosort" keyword (as in the cksort procedure above) then
160# it appends the names of the table and index used.
161#
162proc queryplan {sql} {
163  set ::sqlite_sort_count 0
164  db cache flush
165  set data [execsql $sql]
166  if {$::sqlite_sort_count} {set x sort} {set x nosort}
167  lappend data $x
168  set eqp [execsql "EXPLAIN QUERY PLAN $sql"]
169  # puts eqp=$eqp
170  foreach {a b c x} $eqp {
171    if {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING COVERING INDEX (\w+)\y} \
172        $x all ss as tab idx]} {
173      lappend data {} $idx
174    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
175        $x all ss as tab idx]} {
176      lappend data $tab $idx
177    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+)\y} $x all ss as tab]} {
178      lappend data $tab *
179    }
180  }
181  return $data
182}
183
184# Perform tests on the like optimization.
185#
186# With no index on t1.x and with case sensitivity turned off, no optimization
187# is performed.
188#
189do_test like-3.1 {
190  set sqlite_like_count 0
191  queryplan {
192    SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
193  }
194} {ABC {ABC abc xyz} abc abcd sort t1 *}
195do_test like-3.2 {
196  set sqlite_like_count
197} {12}
198
199# With an index on t1.x and case sensitivity on, optimize completely.
200#
201do_test like-3.3.100 {
202  set sqlite_like_count 0
203  execsql {
204    PRAGMA case_sensitive_like=on;
205    CREATE INDEX i1 ON t1(x);
206  }
207  queryplan {
208    SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
209  }
210} {abc abcd nosort {} i1}
211do_test like-3.3.100.cnt {
212  set sqlite_like_count
213} 0
214
215# The like optimization works even when the pattern is a bound parameter
216#
217# Exception: It does not work if sqlite3_prepare() is used instead of
218# sqlite3_prepare_v2(), as in that case the statement cannot be reprepared
219# after the parameter is bound.
220#
221unset -nocomplain ::likepat
222set ::likepat abc%
223if {[permutation]!="prepare"} {
224  do_test like-3.3.102 {
225    set sqlite_like_count 0
226    queryplan {
227      SELECT x FROM t1 WHERE x LIKE $::likepat ORDER BY 1;
228    }
229  } {abc abcd nosort {} i1}
230  do_test like-3.3.103 {
231    set sqlite_like_count
232  } 0
233}
234
235# Except, the like optimization does not work for bound parameters if
236# the query planner stability guarantee is active.
237#
238do_test like-3.3.104 {
239  set sqlite_like_count 0
240  sqlite3_db_config db QPSG 1
241  queryplan {
242    SELECT x FROM t1 WHERE x LIKE $::likepat ORDER BY 1;
243  }
244} {abc abcd nosort {} i1}
245do_test like-3.3.105 {
246  set sqlite_like_count
247} 12
248
249# The query planner stability guarantee does not disrupt explicit patterns
250#
251do_test like-3.3.105 {
252  set sqlite_like_count 0
253  queryplan {
254    SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
255  }
256} {abc abcd nosort {} i1}
257do_test like-3.3.106 {
258  set sqlite_like_count
259} 0
260sqlite3_db_config db QPSG 0
261
262# The LIKE optimization still works when the RHS is a string with no
263# wildcard.  Ticket [e090183531fc2747]
264#
265do_test like-3.4.2 {
266  queryplan {
267    SELECT x FROM t1 WHERE x LIKE 'a' ORDER BY 1;
268  }
269} {a nosort {} i1}
270do_test like-3.4.3 {
271  queryplan {
272    SELECT x FROM t1 WHERE x LIKE 'ab' ORDER BY 1;
273  }
274} {ab nosort {} i1}
275do_test like-3.4.4 {
276  queryplan {
277    SELECT x FROM t1 WHERE x LIKE 'abcd' ORDER BY 1;
278  }
279} {abcd nosort {} i1}
280do_test like-3.4.5 {
281  queryplan {
282    SELECT x FROM t1 WHERE x LIKE 'abcde' ORDER BY 1;
283  }
284} {nosort {} i1}
285
286
287# Partial optimization when the pattern does not end in '%'
288#
289do_test like-3.5 {
290  set sqlite_like_count 0
291  queryplan {
292    SELECT x FROM t1 WHERE x LIKE 'a_c' ORDER BY 1;
293  }
294} {abc nosort {} i1}
295do_test like-3.6 {
296  set sqlite_like_count
297} 6
298do_test like-3.7 {
299  set sqlite_like_count 0
300  queryplan {
301    SELECT x FROM t1 WHERE x LIKE 'ab%d' ORDER BY 1;
302  }
303} {abcd abd nosort {} i1}
304do_test like-3.8 {
305  set sqlite_like_count
306} 4
307do_test like-3.9 {
308  set sqlite_like_count 0
309  queryplan {
310    SELECT x FROM t1 WHERE x LIKE 'a_c%' ORDER BY 1;
311  }
312} {abc abcd nosort {} i1}
313do_test like-3.10 {
314  set sqlite_like_count
315} 6
316
317# No optimization when the pattern begins with a wildcard.
318# Note that the index is still used but only for sorting.
319#
320do_test like-3.11 {
321  set sqlite_like_count 0
322  queryplan {
323    SELECT x FROM t1 WHERE x LIKE '%bcd' ORDER BY 1;
324  }
325} {abcd bcd nosort {} i1}
326do_test like-3.12 {
327  set sqlite_like_count
328} 12
329
330# No optimization for case insensitive LIKE
331#
332do_test like-3.13 {
333  set sqlite_like_count 0
334  db eval {PRAGMA case_sensitive_like=off;}
335  queryplan {
336    SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
337  }
338} {ABC {ABC abc xyz} abc abcd nosort {} i1}
339do_test like-3.14 {
340  set sqlite_like_count
341} 12
342
343# No optimization without an index.
344#
345do_test like-3.15 {
346  set sqlite_like_count 0
347  db eval {
348    PRAGMA case_sensitive_like=on;
349    DROP INDEX i1;
350  }
351  queryplan {
352    SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
353  }
354} {abc abcd sort t1 *}
355do_test like-3.16 {
356  set sqlite_like_count
357} 12
358
359# No GLOB optimization without an index.
360#
361do_test like-3.17 {
362  set sqlite_like_count 0
363  queryplan {
364    SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1;
365  }
366} {abc abcd sort t1 *}
367do_test like-3.18 {
368  set sqlite_like_count
369} 12
370
371# GLOB is optimized regardless of the case_sensitive_like setting.
372#
373do_test like-3.19 {
374  set sqlite_like_count 0
375  db eval {CREATE INDEX i1 ON t1(x);}
376  queryplan {
377    SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1;
378  }
379} {abc abcd nosort {} i1}
380do_test like-3.20 {
381  set sqlite_like_count
382} 0
383do_test like-3.21 {
384  set sqlite_like_count 0
385  db eval {PRAGMA case_sensitive_like=on;}
386  queryplan {
387    SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1;
388  }
389} {abc abcd nosort {} i1}
390do_test like-3.22 {
391  set sqlite_like_count
392} 0
393do_test like-3.23 {
394  set sqlite_like_count 0
395  db eval {PRAGMA case_sensitive_like=off;}
396  queryplan {
397    SELECT x FROM t1 WHERE x GLOB 'a[bc]d' ORDER BY 1;
398  }
399} {abd acd nosort {} i1}
400do_test like-3.24 {
401  set sqlite_like_count
402} 6
403
404# GLOB optimization when there is no wildcard.  Ticket [e090183531fc2747]
405#
406do_test like-3.25 {
407  queryplan {
408    SELECT x FROM t1 WHERE x GLOB 'a' ORDER BY 1;
409  }
410} {a nosort {} i1}
411do_test like-3.26 {
412  queryplan {
413    SELECT x FROM t1 WHERE x GLOB 'abcd' ORDER BY 1;
414  }
415} {abcd nosort {} i1}
416do_test like-3.27 {
417  queryplan {
418    SELECT x FROM t1 WHERE x GLOB 'abcde' ORDER BY 1;
419  }
420} {nosort {} i1}
421
422
423
424# No optimization if the LHS of the LIKE is not a column name or
425# if the RHS is not a string.
426#
427do_test like-4.1 {
428  execsql {PRAGMA case_sensitive_like=on}
429  set sqlite_like_count 0
430  queryplan {
431    SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1
432  }
433} {abc abcd nosort {} i1}
434do_test like-4.2 {
435  set sqlite_like_count
436} 0
437do_test like-4.3 {
438  set sqlite_like_count 0
439  queryplan {
440    SELECT x FROM t1 WHERE +x LIKE 'abc%' ORDER BY 1
441  }
442} {abc abcd nosort {} i1}
443do_test like-4.4 {
444  set sqlite_like_count
445} 12
446do_test like-4.5 {
447  set sqlite_like_count 0
448  queryplan {
449    SELECT x FROM t1 WHERE x LIKE ('ab' || 'c%') ORDER BY 1
450  }
451} {abc abcd nosort {} i1}
452do_test like-4.6 {
453  set sqlite_like_count
454} 12
455
456# Collating sequences on the index disable the LIKE optimization.
457# Or if the NOCASE collating sequence is used, the LIKE optimization
458# is enabled when case_sensitive_like is OFF.
459#
460do_test like-5.1 {
461  execsql {PRAGMA case_sensitive_like=off}
462  set sqlite_like_count 0
463  queryplan {
464    SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1
465  }
466} {ABC {ABC abc xyz} abc abcd nosort {} i1}
467do_test like-5.2 {
468  set sqlite_like_count
469} 12
470do_test like-5.3 {
471  execsql {
472    CREATE TABLE t2(x TEXT COLLATE NOCASE);
473    INSERT INTO t2 SELECT * FROM t1 ORDER BY rowid;
474    CREATE INDEX i2 ON t2(x COLLATE NOCASE);
475  }
476  set sqlite_like_count 0
477  queryplan {
478    SELECT x FROM t2 WHERE x LIKE 'abc%' ORDER BY 1
479  }
480} {abc ABC {ABC abc xyz} abcd nosort {} i2}
481do_test like-5.4 {
482  set sqlite_like_count
483} 0
484do_test like-5.5 {
485  execsql {
486    PRAGMA case_sensitive_like=on;
487  }
488  set sqlite_like_count 0
489  queryplan {
490    SELECT x FROM t2 WHERE x LIKE 'abc%' ORDER BY 1
491  }
492} {abc abcd nosort {} i2}
493do_test like-5.6 {
494  set sqlite_like_count
495} 12
496do_test like-5.7 {
497  execsql {
498    PRAGMA case_sensitive_like=off;
499  }
500  set sqlite_like_count 0
501  queryplan {
502    SELECT x FROM t2 WHERE x GLOB 'abc*' ORDER BY 1
503  }
504} {abc abcd nosort {} i2}
505do_test like-5.8 {
506  set sqlite_like_count
507} 12
508do_test like-5.11 {
509  execsql {PRAGMA case_sensitive_like=off}
510  set sqlite_like_count 0
511  queryplan {
512    SELECT x FROM t1 WHERE x LIKE 'ABC%' ORDER BY 1
513  }
514} {ABC {ABC abc xyz} abc abcd nosort {} i1}
515do_test like-5.12 {
516  set sqlite_like_count
517} 12
518do_test like-5.13 {
519  set sqlite_like_count 0
520  queryplan {
521    SELECT x FROM t2 WHERE x LIKE 'ABC%' ORDER BY 1
522  }
523} {abc ABC {ABC abc xyz} abcd nosort {} i2}
524do_test like-5.14 {
525  set sqlite_like_count
526} 0
527do_test like-5.15 {
528  execsql {
529    PRAGMA case_sensitive_like=on;
530  }
531  set sqlite_like_count 0
532  queryplan {
533    SELECT x FROM t2 WHERE x LIKE 'ABC%' ORDER BY 1
534  }
535} {ABC {ABC abc xyz} nosort {} i2}
536do_test like-5.16 {
537  set sqlite_like_count
538} 12
539do_test like-5.17 {
540  execsql {
541    PRAGMA case_sensitive_like=off;
542  }
543  set sqlite_like_count 0
544  queryplan {
545    SELECT x FROM t2 WHERE x GLOB 'ABC*' ORDER BY 1
546  }
547} {ABC {ABC abc xyz} nosort {} i2}
548do_test like-5.18 {
549  set sqlite_like_count
550} 12
551
552# Boundary case.  The prefix for a LIKE comparison is rounded up
553# when constructing the comparison.  Example:  "ab" becomes "ac".
554# In other words, the last character is increased by one.
555#
556# Make sure this happens correctly when the last character is a
557# "z" and we are doing case-insensitive comparisons.
558#
559# Ticket #2959
560#
561do_test like-5.21 {
562  execsql {
563    PRAGMA case_sensitive_like=off;
564    INSERT INTO t2 VALUES('ZZ-upper-upper');
565    INSERT INTO t2 VALUES('zZ-lower-upper');
566    INSERT INTO t2 VALUES('Zz-upper-lower');
567    INSERT INTO t2 VALUES('zz-lower-lower');
568  }
569  queryplan {
570    SELECT x FROM t2 WHERE x LIKE 'zz%';
571  }
572} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2}
573do_test like-5.22 {
574  queryplan {
575    SELECT x FROM t2 WHERE x LIKE 'zZ%';
576  }
577} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2}
578do_test like-5.23 {
579  queryplan {
580    SELECT x FROM t2 WHERE x LIKE 'Zz%';
581  }
582} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2}
583do_test like-5.24 {
584  queryplan {
585    SELECT x FROM t2 WHERE x LIKE 'ZZ%';
586  }
587} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2}
588do_test like-5.25 {
589  db eval {
590    PRAGMA case_sensitive_like=on;
591    CREATE TABLE t3(x TEXT);
592    CREATE INDEX i3 ON t3(x);
593    INSERT INTO t3 VALUES('ZZ-upper-upper');
594    INSERT INTO t3 VALUES('zZ-lower-upper');
595    INSERT INTO t3 VALUES('Zz-upper-lower');
596    INSERT INTO t3 VALUES('zz-lower-lower');
597  }
598  queryplan {
599    SELECT x FROM t3 WHERE x LIKE 'zz%';
600  }
601} {zz-lower-lower nosort {} i3}
602do_test like-5.26 {
603  queryplan {
604    SELECT x FROM t3 WHERE x LIKE 'zZ%';
605  }
606} {zZ-lower-upper nosort {} i3}
607do_test like-5.27 {
608  queryplan {
609    SELECT x FROM t3 WHERE x LIKE 'Zz%';
610  }
611} {Zz-upper-lower nosort {} i3}
612do_test like-5.28 {
613  queryplan {
614    SELECT x FROM t3 WHERE x LIKE 'ZZ%';
615  }
616} {ZZ-upper-upper nosort {} i3}
617
618
619# ticket #2407
620#
621# Make sure the LIKE prefix optimization does not strip off leading
622# characters of the like pattern that happen to be quote characters.
623#
624do_test like-6.1 {
625  foreach x { 'abc 'bcd 'def 'ax } {
626    set x2 '[string map {' ''} $x]'
627    db eval "INSERT INTO t2 VALUES($x2)"
628  }
629  execsql {
630    SELECT * FROM t2 WHERE x LIKE '''a%'
631  }
632} {'abc 'ax}
633
634do_test like-7.1 {
635  execsql {
636    SELECT rowid, * FROM t1 WHERE rowid GLOB '1*' ORDER BY rowid;
637  }
638} {1 a 10 ABC 11 CDE 12 {ABC abc xyz}}
639
640# ticket #3345.
641#
642# Overloading the LIKE function with -1 for the number of arguments
643# will overload both the 2-argument and the 3-argument LIKE.
644#
645do_test like-8.1 {
646  db eval {
647    CREATE TABLE t8(x);
648    INSERT INTO t8 VALUES('abcdef');
649    INSERT INTO t8 VALUES('ghijkl');
650    INSERT INTO t8 VALUES('mnopqr');
651    SELECT 1, x FROM t8 WHERE x LIKE '%h%';
652    SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
653  }
654} {1 ghijkl 2 ghijkl}
655do_test like-8.2 {
656  proc newlike {args} {return 1} ;# Alternative LIKE is always return TRUE
657  db function like newlike       ;# Uses -1 for nArg in sqlite3_create_function
658  db cache flush
659  db eval {
660    SELECT 1, x FROM t8 WHERE x LIKE '%h%';
661    SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
662  }
663} {1 ghijkl 2 ghijkl}
664do_test like-8.3 {
665  db function like -argcount 2 newlike
666  db eval {
667    SELECT 1, x FROM t8 WHERE x LIKE '%h%';
668    SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
669  }
670} {1 abcdef 1 ghijkl 1 mnopqr 2 ghijkl}
671do_test like-8.4 {
672  db function like -argcount 3 newlike
673  db eval {
674    SELECT 1, x FROM t8 WHERE x LIKE '%h%';
675    SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
676  }
677} {1 abcdef 1 ghijkl 1 mnopqr 2 abcdef 2 ghijkl 2 mnopqr}
678
679
680ifcapable like_opt&&!icu {
681  # Evaluate SQL.  Return the result set followed by the
682  # and the number of full-scan steps.
683  #
684  db close
685  sqlite3 db test.db
686  proc count_steps {sql} {
687    set r [db eval $sql]
688    lappend r scan [db status step] sort [db status sort]
689  }
690  do_test like-9.1 {
691    count_steps {
692       SELECT x FROM t2 WHERE x LIKE 'x%'
693    }
694  } {xyz scan 0 sort 0}
695  do_test like-9.2 {
696    count_steps {
697       SELECT x FROM t2 WHERE x LIKE '_y%'
698    }
699  } {xyz scan 19 sort 0}
700  do_test like-9.3.1 {
701    set res [sqlite3_exec_hex db {
702       SELECT x FROM t2 WHERE x LIKE '%78%25'
703    }]
704  } {0 {x xyz}}
705  ifcapable explain {
706    do_test like-9.3.2 {
707      set res [sqlite3_exec_hex db {
708         EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%78%25'
709      }]
710      regexp {INDEX i2} $res
711    } {1}
712  }
713  do_test like-9.4.1 {
714    sqlite3_exec_hex db {INSERT INTO t2 VALUES('%ffhello')}
715    set res [sqlite3_exec_hex db {
716       SELECT substr(x,2) AS x FROM t2 WHERE +x LIKE '%ff%25'
717    }]
718  } {0 {x hello}}
719  do_test like-9.4.2 {
720    set res [sqlite3_exec_hex db {
721       SELECT substr(x,2) AS x FROM t2 WHERE x LIKE '%ff%25'
722    }]
723  } {0 {x hello}}
724  ifcapable explain {
725    do_test like-9.4.3 {
726      set res [sqlite3_exec_hex db {
727         EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%ff%25'
728      }]
729      regexp {SCAN t2} $res
730    } {1}
731  }
732  do_test like-9.5.1 {
733    set res [sqlite3_exec_hex db {
734       SELECT x FROM t2 WHERE x LIKE '%fe%25'
735    }]
736  } {0 {}}
737  ifcapable explain {
738    do_test like-9.5.2 {
739      set res [sqlite3_exec_hex db {
740         EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%fe%25'
741      }]
742      regexp {INDEX i2} $res
743    } {1}
744  }
745
746  # Do an SQL statement.  Append the search count to the end of the result.
747  #
748  proc count sql {
749    set ::sqlite_search_count 0
750    set ::sqlite_like_count 0
751    return [concat [execsql $sql] scan $::sqlite_search_count \
752             like $::sqlite_like_count]
753  }
754
755  # The LIKE and GLOB optimizations do not work on columns with
756  # affinity other than TEXT.
757  # Ticket #3901
758  #
759  do_test like-10.1 {
760    db close
761    sqlite3 db test.db
762    execsql {
763      CREATE TABLE t10(
764        a INTEGER PRIMARY KEY,
765        b INTEGER COLLATE nocase UNIQUE,
766        c NUMBER COLLATE nocase UNIQUE,
767        d BLOB COLLATE nocase UNIQUE,
768        e COLLATE nocase UNIQUE,
769        f TEXT COLLATE nocase UNIQUE
770      );
771      INSERT INTO t10 VALUES(1,1,1,1,1,1);
772      INSERT INTO t10 VALUES(12,12,12,12,12,12);
773      INSERT INTO t10 VALUES(123,123,123,123,123,123);
774      INSERT INTO t10 VALUES(234,234,234,234,234,234);
775      INSERT INTO t10 VALUES(345,345,345,345,345,345);
776      INSERT INTO t10 VALUES(45,45,45,45,45,45);
777    }
778    count {
779      SELECT a FROM t10 WHERE b LIKE '12%' ORDER BY +a;
780    }
781  } {12 123 scan 5 like 6}
782  do_test like-10.2 {
783    count {
784      SELECT a FROM t10 WHERE c LIKE '12%' ORDER BY +a;
785    }
786  } {12 123 scan 5 like 6}
787  do_test like-10.3 {
788    count {
789      SELECT a FROM t10 WHERE d LIKE '12%' ORDER BY +a;
790    }
791  } {12 123 scan 5 like 6}
792  do_test like-10.4 {
793    count {
794      SELECT a FROM t10 WHERE e LIKE '12%' ORDER BY +a;
795    }
796  } {12 123 scan 5 like 6}
797  ifcapable like_match_blobs {
798    do_test like-10.5a {
799      count {
800        SELECT a FROM t10 WHERE f LIKE '12%' ORDER BY +a;
801      }
802    } {12 123 scan 4 like 0}
803  } else {
804    do_test like-10.5b {
805      count {
806        SELECT a FROM t10 WHERE f LIKE '12%' ORDER BY +a;
807      }
808    } {12 123 scan 3 like 0}
809  }
810  do_test like-10.6 {
811    count {
812      SELECT a FROM t10 WHERE a LIKE '12%' ORDER BY +a;
813    }
814  } {12 123 scan 5 like 6}
815  do_test like-10.10 {
816    execsql {
817      CREATE TABLE t10b(
818        a INTEGER PRIMARY KEY,
819        b INTEGER UNIQUE,
820        c NUMBER UNIQUE,
821        d BLOB UNIQUE,
822        e UNIQUE,
823        f TEXT UNIQUE
824      );
825      INSERT INTO t10b SELECT * FROM t10;
826    }
827    count {
828      SELECT a FROM t10b WHERE b GLOB '12*' ORDER BY +a;
829    }
830  } {12 123 scan 5 like 6}
831  do_test like-10.11 {
832    count {
833      SELECT a FROM t10b WHERE c GLOB '12*' ORDER BY +a;
834    }
835  } {12 123 scan 5 like 6}
836  do_test like-10.12 {
837    count {
838      SELECT a FROM t10b WHERE d GLOB '12*' ORDER BY +a;
839    }
840  } {12 123 scan 5 like 6}
841  do_test like-10.13 {
842    count {
843      SELECT a FROM t10b WHERE e GLOB '12*' ORDER BY +a;
844    }
845  } {12 123 scan 5 like 6}
846  ifcapable like_match_blobs {
847    do_test like-10.14 {
848      count {
849        SELECT a FROM t10b WHERE f GLOB '12*' ORDER BY +a;
850      }
851    } {12 123 scan 4 like 0}
852  } else {
853    do_test like-10.14 {
854      count {
855        SELECT a FROM t10b WHERE f GLOB '12*' ORDER BY +a;
856      }
857    } {12 123 scan 3 like 0}
858  }
859  do_test like-10.15 {
860    count {
861      SELECT a FROM t10b WHERE a GLOB '12*' ORDER BY +a;
862    }
863  } {12 123 scan 5 like 6}
864}
865
866# LIKE and GLOB where the default collating sequence is not appropriate
867# but an index with the appropriate collating sequence exists.
868#
869do_test like-11.0 {
870  execsql {
871    CREATE TABLE t11(
872      a INTEGER PRIMARY KEY,
873      b TEXT COLLATE nocase,
874      c TEXT COLLATE binary
875    );
876    INSERT INTO t11 VALUES(1, 'a','a');
877    INSERT INTO t11 VALUES(2, 'ab','ab');
878    INSERT INTO t11 VALUES(3, 'abc','abc');
879    INSERT INTO t11 VALUES(4, 'abcd','abcd');
880    INSERT INTO t11 VALUES(5, 'A','A');
881    INSERT INTO t11 VALUES(6, 'AB','AB');
882    INSERT INTO t11 VALUES(7, 'ABC','ABC');
883    INSERT INTO t11 VALUES(8, 'ABCD','ABCD');
884    INSERT INTO t11 VALUES(9, 'x','x');
885    INSERT INTO t11 VALUES(10, 'yz','yz');
886    INSERT INTO t11 VALUES(11, 'X','X');
887    INSERT INTO t11 VALUES(12, 'YZ','YZ');
888    SELECT count(*) FROM t11;
889  }
890} {12}
891do_test like-11.1 {
892  db eval {PRAGMA case_sensitive_like=OFF;}
893  queryplan {
894    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
895  }
896} {abc abcd ABC ABCD nosort t11 *}
897do_test like-11.2 {
898  db eval {PRAGMA case_sensitive_like=ON;}
899  queryplan {
900    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
901  }
902} {abc abcd nosort t11 *}
903do_test like-11.3 {
904  db eval {
905    PRAGMA case_sensitive_like=OFF;
906    CREATE INDEX t11b ON t11(b);
907  }
908  queryplan {
909    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a;
910  }
911} {abc abcd ABC ABCD sort {} t11b}
912do_test like-11.4 {
913  db eval {PRAGMA case_sensitive_like=ON;}
914  queryplan {
915    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
916  }
917} {abc abcd nosort t11 *}
918do_test like-11.5 {
919  db eval {
920    PRAGMA case_sensitive_like=OFF;
921    DROP INDEX t11b;
922    CREATE INDEX t11bnc ON t11(b COLLATE nocase);
923  }
924  queryplan {
925    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a;
926  }
927} {abc abcd ABC ABCD sort {} t11bnc}
928do_test like-11.6 {
929  db eval {CREATE INDEX t11bb ON t11(b COLLATE binary);}
930  queryplan {
931    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a;
932  }
933} {abc abcd ABC ABCD sort {} t11bnc}
934do_test like-11.7 {
935  db eval {PRAGMA case_sensitive_like=ON;}
936  queryplan {
937    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a;
938  }
939} {abc abcd sort {} t11bb}
940do_test like-11.8 {
941  db eval {PRAGMA case_sensitive_like=OFF;}
942  queryplan {
943    SELECT b FROM t11 WHERE b GLOB 'abc*' ORDER BY +a;
944  }
945} {abc abcd sort {} t11bb}
946do_test like-11.9 {
947  db eval {
948    CREATE INDEX t11cnc ON t11(c COLLATE nocase);
949    CREATE INDEX t11cb ON t11(c COLLATE binary);
950  }
951  queryplan {
952    SELECT c FROM t11 WHERE c LIKE 'abc%' ORDER BY +a;
953  }
954} {abc abcd ABC ABCD sort {} t11cnc}
955do_test like-11.10 {
956  queryplan {
957    SELECT c FROM t11 WHERE c GLOB 'abc*' ORDER BY +a;
958  }
959} {abc abcd sort {} t11cb}
960
961# A COLLATE clause on the pattern does not change the result of a
962# LIKE operator.
963#
964do_execsql_test like-12.1 {
965  CREATE TABLE t12nc(id INTEGER, x TEXT UNIQUE COLLATE nocase);
966  INSERT INTO t12nc VALUES(1,'abcde'),(2,'uvwxy'),(3,'ABCDEF');
967  CREATE TABLE t12b(id INTEGER, x TEXT UNIQUE COLLATE binary);
968  INSERT INTO t12b VALUES(1,'abcde'),(2,'uvwxy'),(3,'ABCDEF');
969  SELECT id FROM t12nc WHERE x LIKE 'abc%' ORDER BY +id;
970} {1 3}
971do_execsql_test like-12.2 {
972  SELECT id FROM t12b WHERE x LIKE 'abc%' ORDER BY +id;
973} {1 3}
974do_execsql_test like-12.3 {
975  SELECT id FROM t12nc WHERE x LIKE 'abc%' COLLATE binary ORDER BY +id;
976} {1 3}
977do_execsql_test like-12.4 {
978  SELECT id FROM t12b WHERE x LIKE 'abc%' COLLATE binary ORDER BY +id;
979} {1 3}
980do_execsql_test like-12.5 {
981  SELECT id FROM t12nc WHERE x LIKE 'abc%' COLLATE nocase ORDER BY +id;
982} {1 3}
983do_execsql_test like-12.6 {
984  SELECT id FROM t12b WHERE x LIKE 'abc%' COLLATE nocase ORDER BY +id;
985} {1 3}
986
987# Adding a COLLATE clause to the pattern of a LIKE operator does nothing
988# to change the suitability of using an index to satisfy that LIKE
989# operator.
990#
991do_execsql_test like-12.11 {
992  EXPLAIN QUERY PLAN
993  SELECT id FROM t12nc WHERE x LIKE 'abc%' ORDER BY +id;
994} {/SEARCH/}
995do_execsql_test like-12.12 {
996  EXPLAIN QUERY PLAN
997  SELECT id FROM t12b WHERE x LIKE 'abc%' ORDER BY +id;
998} {/SCAN/}
999do_execsql_test like-12.13 {
1000  EXPLAIN QUERY PLAN
1001  SELECT id FROM t12nc WHERE x LIKE 'abc%' COLLATE nocase ORDER BY +id;
1002} {/SEARCH/}
1003do_execsql_test like-12.14 {
1004  EXPLAIN QUERY PLAN
1005  SELECT id FROM t12b WHERE x LIKE 'abc%' COLLATE nocase ORDER BY +id;
1006} {/SCAN/}
1007do_execsql_test like-12.15 {
1008  EXPLAIN QUERY PLAN
1009  SELECT id FROM t12nc WHERE x LIKE 'abc%' COLLATE binary ORDER BY +id;
1010} {/SEARCH/}
1011do_execsql_test like-12.16 {
1012  EXPLAIN QUERY PLAN
1013  SELECT id FROM t12b WHERE x LIKE 'abc%' COLLATE binary ORDER BY +id;
1014} {/SCAN/}
1015
1016# Ticket [https://www.sqlite.org/src/tktview/80369eddd5c94d49f7fbbcf5]
1017# 2016-01-20
1018#
1019do_execsql_test like-13.1 {
1020  SELECT char(0x304d) LIKE char(0x306d);
1021} {0}
1022do_execsql_test like-13.2 {
1023  SELECT char(0x4d) LIKE char(0x306d);
1024} {0}
1025do_execsql_test like-13.3 {
1026  SELECT char(0x304d) LIKE char(0x6d);
1027} {0}
1028do_execsql_test like-13.4 {
1029  SELECT char(0x4d) LIKE char(0x6d);
1030} {1}
1031
1032# Performance testing for patterns with many wildcards.  These LIKE and GLOB
1033# patterns were quite slow with SQLite 3.15.2 and earlier.
1034#
1035do_test like-14.1 {
1036  set x [lindex [time {
1037    db one {SELECT 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz'GLOB'*a*a*a*a*a*a*a*a*y'}
1038  }] 0]
1039  set tlimit [expr {1000 * $::sqlite_options(configslower)}]
1040  puts -nonewline " ($x ms - want less than $tlimit) "
1041  expr {$x<$tlimit}
1042} {1}
1043ifcapable !icu {
1044  do_test like-14.2 {
1045    set x [lindex [time {
1046      db one {SELECT 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz'LIKE'%a%a%a%a%a%a%a%a%y'}
1047    }] 0]
1048  set tlimit [expr {1000 * $::sqlite_options(configslower)}]
1049  puts -nonewline " ($x ms - want less than $tlimit) "
1050  expr {$x<$tlimit}
1051  } {1}
1052}
1053
1054ifcapable !icu {
1055# As of 2017-07-27 (3.21.0) the LIKE optimization works with ESCAPE as
1056# long as the ESCAPE is a single-byte literal.
1057#
1058db close
1059sqlite3 db :memory:
1060do_execsql_test like-15.100 {
1061  CREATE TABLE t15(x TEXT COLLATE nocase, y, PRIMARY KEY(x));
1062  INSERT INTO t15(x,y) VALUES
1063    ('abcde',1), ('ab%de',2), ('a_cde',3),
1064    ('uvwxy',11),('uvwx%',12),('uvwx_',13),
1065    ('_bcde',21),('%bcde',22),
1066    ('abcd_',31),('abcd%',32),
1067    ('ab%xy',41);
1068  SELECT y FROM t15 WHERE x LIKE 'ab/%d%' ESCAPE '/';
1069} {2}
1070do_execsql_test like-15.101 {
1071  EXPLAIN QUERY PLAN
1072  SELECT y FROM t15 WHERE x LIKE 'ab/%d%' ESCAPE '/';
1073} {/SEARCH/}
1074do_execsql_test like-15.102 {
1075  EXPLAIN QUERY PLAN
1076  SELECT y FROM t15 WHERE x LIKE 'ab/%d%' ESCAPE '//';
1077} {/SCAN/}
1078do_execsql_test like-15.103 {
1079  EXPLAIN QUERY PLAN
1080  SELECT y FROM t15 WHERE x LIKE 'ab/%d%' ESCAPE '';
1081} {/SCAN/}
1082do_execsql_test like-15.110 {
1083  SELECT y FROM t15 WHERE x LIKE 'abcdx%%' ESCAPE 'x';
1084} {32}
1085do_execsql_test like-15.111 {
1086  SELECT y FROM t15 WHERE x LIKE 'abx%%' ESCAPE 'x' ORDER BY +y
1087} {2 41}
1088do_execsql_test like-15.112 {
1089  EXPLAIN QUERY PLAN
1090  SELECT y FROM t15 WHERE x LIKE 'abx%%' ESCAPE 'x' ORDER BY +y
1091} {/SEARCH/}
1092do_execsql_test like-15.120 {
1093  SELECT y FROM t15 WHERE x LIKE '/%bc%' ESCAPE '/';
1094} {22}
1095do_execsql_test like-15.121 {
1096  EXPLAIN QUERY PLAN
1097  SELECT y FROM t15 WHERE x LIKE '/%bc%' ESCAPE '/';
1098} {/SEARCH/}
1099}
1100
1101#-------------------------------------------------------------------------
1102# Tests for ticket [b1d8c79314].
1103#
1104reset_db
1105do_execsql_test 16.0 {
1106  CREATE TABLE t1(a INTEGER COLLATE NOCASE);
1107  CREATE INDEX i1 ON t1(a);
1108  INSERT INTO t1 VALUES(' 1x');
1109  INSERT INTO t1 VALUES(' 1-');
1110}
1111do_execsql_test 16.1 {
1112  SELECT * FROM t1 WHERE a LIKE ' 1%';
1113} {{ 1x} { 1-}}
1114do_execsql_test 16.2 {
1115  SELECT * FROM t1 WHERE a LIKE ' 1-';
1116} {{ 1-}}
1117
1118# 2020-03-19
1119# The ESCAPE clause on LIKE takes precedence over wildcards
1120#
1121do_execsql_test 17.0 {
1122  DROP TABLE IF EXISTS t1;
1123  CREATE TABLE t1(id INTEGER PRIMARY KEY, x TEXT);
1124  INSERT INTO t1 VALUES
1125    (1,'abcde'),
1126    (2,'abc_'),
1127    (3,'abc__'),
1128    (4,'abc%'),
1129    (5,'abc%%');
1130  SELECT id FROM t1 WHERE x LIKE 'abc%%' ESCAPE '%';
1131} {4}
1132do_execsql_test 17.1 {
1133  SELECT id FROM t1 WHERE x LIKE 'abc__' ESCAPE '_';
1134} {2}
1135
1136# 2021-02-15 ticket c0aeea67d58ae0fd
1137#
1138do_execsql_test 17.1 {
1139  SELECT 'x' LIKE '%' ESCAPE '_';
1140} {1}
1141
1142
1143finish_test
1144