xref: /sqlite-3.40.0/test/like.test (revision f5576936)
155ef4d97Sdrh# 2005 August 13
255ef4d97Sdrh#
355ef4d97Sdrh# The author disclaims copyright to this source code.  In place of
455ef4d97Sdrh# a legal notice, here is a blessing:
555ef4d97Sdrh#
655ef4d97Sdrh#    May you do good and not evil.
755ef4d97Sdrh#    May you find forgiveness for yourself and forgive others.
855ef4d97Sdrh#    May you share freely, never taking more than you give.
955ef4d97Sdrh#
1055ef4d97Sdrh#***********************************************************************
1155ef4d97Sdrh# This file implements regression tests for SQLite library.  The
1255ef4d97Sdrh# focus of this file is testing the LIKE and GLOB operators and
1355ef4d97Sdrh# in particular the optimizations that occur to help those operators
1455ef4d97Sdrh# run faster.
1555ef4d97Sdrh#
16c4ac22e9Sdrh# $Id: like.test,v 1.13 2009/06/07 23:45:11 drh Exp $
1755ef4d97Sdrh
1855ef4d97Sdrhset testdir [file dirname $argv0]
1955ef4d97Sdrhsource $testdir/tester.tcl
2032d0f64eSdanset testprefix like
2155ef4d97Sdrh
2255ef4d97Sdrh# Create some sample data to work with.
2355ef4d97Sdrh#
2455ef4d97Sdrhdo_test like-1.0 {
2555ef4d97Sdrh  execsql {
2655ef4d97Sdrh    CREATE TABLE t1(x TEXT);
2755ef4d97Sdrh  }
2855ef4d97Sdrh  foreach str {
2955ef4d97Sdrh    a
3055ef4d97Sdrh    ab
3155ef4d97Sdrh    abc
3255ef4d97Sdrh    abcd
3355ef4d97Sdrh
3455ef4d97Sdrh    acd
3555ef4d97Sdrh    abd
3655ef4d97Sdrh    bc
3755ef4d97Sdrh    bcd
3855ef4d97Sdrh
3955ef4d97Sdrh    xyz
4055ef4d97Sdrh    ABC
4155ef4d97Sdrh    CDE
4255ef4d97Sdrh    {ABC abc xyz}
4355ef4d97Sdrh  } {
443bdca9c9Sdanielk1977    db eval {INSERT INTO t1 VALUES(:str)}
4555ef4d97Sdrh  }
4655ef4d97Sdrh  execsql {
4755ef4d97Sdrh    SELECT count(*) FROM t1;
4855ef4d97Sdrh  }
4955ef4d97Sdrh} {12}
5055ef4d97Sdrh
5155ef4d97Sdrh# Test that both case sensitive and insensitive version of LIKE work.
5255ef4d97Sdrh#
5355ef4d97Sdrhdo_test like-1.1 {
5455ef4d97Sdrh  execsql {
5555ef4d97Sdrh    SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
5655ef4d97Sdrh  }
5755ef4d97Sdrh} {ABC abc}
5855ef4d97Sdrhdo_test like-1.2 {
5955ef4d97Sdrh  execsql {
6055ef4d97Sdrh    SELECT x FROM t1 WHERE x GLOB 'abc' ORDER BY 1;
6155ef4d97Sdrh  }
6255ef4d97Sdrh} {abc}
6355ef4d97Sdrhdo_test like-1.3 {
6455ef4d97Sdrh  execsql {
6555ef4d97Sdrh    SELECT x FROM t1 WHERE x LIKE 'ABC' ORDER BY 1;
6655ef4d97Sdrh  }
6755ef4d97Sdrh} {ABC abc}
6855ef4d97Sdrhdo_test like-1.4 {
6955ef4d97Sdrh  execsql {
7055ef4d97Sdrh    SELECT x FROM t1 WHERE x LIKE 'aBc' ORDER BY 1;
7155ef4d97Sdrh  }
7255ef4d97Sdrh} {ABC abc}
73d2cb50b7Sdrhdo_test like-1.5.1 {
74c7060c4dSdrh  # Use sqlite3_exec() to verify fix for ticket [25ee81271091] 2011-06-26
75c7060c4dSdrh  sqlite3_exec db {PRAGMA case_sensitive_like=on}
76c7060c4dSdrh} {0 {}}
77c7060c4dSdrhdo_test like-1.5.2 {
7855ef4d97Sdrh  execsql {
7955ef4d97Sdrh    SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
8055ef4d97Sdrh  }
8155ef4d97Sdrh} {abc}
82c7060c4dSdrhdo_test like-1.5.3 {
83d2cb50b7Sdrh  execsql {
84d2cb50b7Sdrh    PRAGMA case_sensitive_like; -- no argument; does not change setting
85d2cb50b7Sdrh    SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
86d2cb50b7Sdrh  }
87d2cb50b7Sdrh} {abc}
8855ef4d97Sdrhdo_test like-1.6 {
8955ef4d97Sdrh  execsql {
9055ef4d97Sdrh    SELECT x FROM t1 WHERE x GLOB 'abc' ORDER BY 1;
9155ef4d97Sdrh  }
9255ef4d97Sdrh} {abc}
9355ef4d97Sdrhdo_test like-1.7 {
9455ef4d97Sdrh  execsql {
9555ef4d97Sdrh    SELECT x FROM t1 WHERE x LIKE 'ABC' ORDER BY 1;
9655ef4d97Sdrh  }
9755ef4d97Sdrh} {ABC}
9855ef4d97Sdrhdo_test like-1.8 {
9955ef4d97Sdrh  execsql {
10055ef4d97Sdrh    SELECT x FROM t1 WHERE x LIKE 'aBc' ORDER BY 1;
10155ef4d97Sdrh  }
10255ef4d97Sdrh} {}
10355ef4d97Sdrhdo_test like-1.9 {
10455ef4d97Sdrh  execsql {
10555ef4d97Sdrh    PRAGMA case_sensitive_like=off;
10655ef4d97Sdrh    SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
10755ef4d97Sdrh  }
10855ef4d97Sdrh} {ABC abc}
109d2cb50b7Sdrhdo_test like-1.10 {
110d2cb50b7Sdrh  execsql {
111d2cb50b7Sdrh    PRAGMA case_sensitive_like;  -- No argument, does not change setting.
112d2cb50b7Sdrh    SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
113d2cb50b7Sdrh  }
114d2cb50b7Sdrh} {ABC abc}
11555ef4d97Sdrh
11655ef4d97Sdrh# Tests of the REGEXP operator
11755ef4d97Sdrh#
11855ef4d97Sdrhdo_test like-2.1 {
11955ef4d97Sdrh  proc test_regexp {a b} {
12055ef4d97Sdrh    return [regexp $a $b]
12155ef4d97Sdrh  }
1226bd2c735Sdan  db function regexp -argcount 2 test_regexp
12355ef4d97Sdrh  execsql {
12455ef4d97Sdrh    SELECT x FROM t1 WHERE x REGEXP 'abc' ORDER BY 1;
12555ef4d97Sdrh  }
12655ef4d97Sdrh} {{ABC abc xyz} abc abcd}
12755ef4d97Sdrhdo_test like-2.2 {
12855ef4d97Sdrh  execsql {
12955ef4d97Sdrh    SELECT x FROM t1 WHERE x REGEXP '^abc' ORDER BY 1;
13055ef4d97Sdrh  }
13155ef4d97Sdrh} {abc abcd}
13255ef4d97Sdrh
133619a3693Sdanielk1977# Tests of the MATCH operator
134619a3693Sdanielk1977#
135619a3693Sdanielk1977do_test like-2.3 {
136619a3693Sdanielk1977  proc test_match {a b} {
137619a3693Sdanielk1977    return [string match $a $b]
138619a3693Sdanielk1977  }
139e3602be8Sdrh  db function match -argcount 2 test_match
140619a3693Sdanielk1977  execsql {
141619a3693Sdanielk1977    SELECT x FROM t1 WHERE x MATCH '*abc*' ORDER BY 1;
142619a3693Sdanielk1977  }
143619a3693Sdanielk1977} {{ABC abc xyz} abc abcd}
144619a3693Sdanielk1977do_test like-2.4 {
145619a3693Sdanielk1977  execsql {
146619a3693Sdanielk1977    SELECT x FROM t1 WHERE x MATCH 'abc*' ORDER BY 1;
147619a3693Sdanielk1977  }
148619a3693Sdanielk1977} {abc abcd}
149619a3693Sdanielk1977
15055ef4d97Sdrh# For the remaining tests, we need to have the like optimizations
15155ef4d97Sdrh# enabled.
15255ef4d97Sdrh#
15355ef4d97Sdrhifcapable !like_opt {
15455ef4d97Sdrh  finish_test
15555ef4d97Sdrh  return
15655ef4d97Sdrh}
15755ef4d97Sdrh
15855ef4d97Sdrh# This procedure executes the SQL.  Then it appends to the result the
15955ef4d97Sdrh# "sort" or "nosort" keyword (as in the cksort procedure above) then
1607c171098Sdrh# it appends the names of the table and index used.
16155ef4d97Sdrh#
16255ef4d97Sdrhproc queryplan {sql} {
16355ef4d97Sdrh  set ::sqlite_sort_count 0
164169dd928Sdrh  db cache flush
16555ef4d97Sdrh  set data [execsql $sql]
16655ef4d97Sdrh  if {$::sqlite_sort_count} {set x sort} {set x nosort}
16755ef4d97Sdrh  lappend data $x
1687c171098Sdrh  set eqp [execsql "EXPLAIN QUERY PLAN $sql"]
1697c171098Sdrh  # puts eqp=$eqp
1707c171098Sdrh  foreach {a b c x} $eqp {
1718210233cSdrh    if {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING COVERING INDEX (\w+)\y} \
1728210233cSdrh        $x all ss as tab idx]} {
1737c171098Sdrh      lappend data {} $idx
1748210233cSdrh    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
1758210233cSdrh        $x all ss as tab idx]} {
1767c171098Sdrh      lappend data $tab $idx
1778210233cSdrh    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+)\y} $x all ss as tab]} {
1787c171098Sdrh      lappend data $tab *
1797c171098Sdrh    }
1807c171098Sdrh  }
1817c171098Sdrh  return $data
18255ef4d97Sdrh}
18355ef4d97Sdrh
18455ef4d97Sdrh# Perform tests on the like optimization.
18555ef4d97Sdrh#
18655ef4d97Sdrh# With no index on t1.x and with case sensitivity turned off, no optimization
18755ef4d97Sdrh# is performed.
18855ef4d97Sdrh#
18955ef4d97Sdrhdo_test like-3.1 {
19055ef4d97Sdrh  set sqlite_like_count 0
19155ef4d97Sdrh  queryplan {
19255ef4d97Sdrh    SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
19355ef4d97Sdrh  }
1947c171098Sdrh} {ABC {ABC abc xyz} abc abcd sort t1 *}
19555ef4d97Sdrhdo_test like-3.2 {
19655ef4d97Sdrh  set sqlite_like_count
19755ef4d97Sdrh} {12}
19855ef4d97Sdrh
19955ef4d97Sdrh# With an index on t1.x and case sensitivity on, optimize completely.
20055ef4d97Sdrh#
201169dd928Sdrhdo_test like-3.3.100 {
20255ef4d97Sdrh  set sqlite_like_count 0
20355ef4d97Sdrh  execsql {
20455ef4d97Sdrh    PRAGMA case_sensitive_like=on;
20555ef4d97Sdrh    CREATE INDEX i1 ON t1(x);
20655ef4d97Sdrh  }
20755ef4d97Sdrh  queryplan {
20855ef4d97Sdrh    SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
20955ef4d97Sdrh  }
21055ef4d97Sdrh} {abc abcd nosort {} i1}
2111d42ea71Sdrhdo_test like-3.3.100.cnt {
21255ef4d97Sdrh  set sqlite_like_count
21355ef4d97Sdrh} 0
21455ef4d97Sdrh
215169dd928Sdrh# The like optimization works even when the pattern is a bound parameter
216169dd928Sdrh#
217a50b3091Sdan# Exception: It does not work if sqlite3_prepare() is used instead of
218a50b3091Sdan# sqlite3_prepare_v2(), as in that case the statement cannot be reprepared
219a50b3091Sdan# after the parameter is bound.
220a50b3091Sdan#
221cb0d3ba8Sdanunset -nocomplain ::likepat
222a50b3091Sdanset ::likepat abc%
223a50b3091Sdanif {[permutation]!="prepare"} {
224169dd928Sdrh  do_test like-3.3.102 {
225169dd928Sdrh    set sqlite_like_count 0
226169dd928Sdrh    queryplan {
227169dd928Sdrh      SELECT x FROM t1 WHERE x LIKE $::likepat ORDER BY 1;
228169dd928Sdrh    }
229169dd928Sdrh  } {abc abcd nosort {} i1}
230169dd928Sdrh  do_test like-3.3.103 {
231169dd928Sdrh    set sqlite_like_count
232169dd928Sdrh  } 0
233a50b3091Sdan}
234169dd928Sdrh
235169dd928Sdrh# Except, the like optimization does not work for bound parameters if
236169dd928Sdrh# the query planner stability guarantee is active.
237169dd928Sdrh#
238169dd928Sdrhdo_test like-3.3.104 {
239169dd928Sdrh  set sqlite_like_count 0
240169dd928Sdrh  sqlite3_db_config db QPSG 1
241169dd928Sdrh  queryplan {
242169dd928Sdrh    SELECT x FROM t1 WHERE x LIKE $::likepat ORDER BY 1;
243169dd928Sdrh  }
244169dd928Sdrh} {abc abcd nosort {} i1}
245169dd928Sdrhdo_test like-3.3.105 {
246169dd928Sdrh  set sqlite_like_count
247169dd928Sdrh} 12
248169dd928Sdrh
249169dd928Sdrh# The query planner stability guarantee does not disrupt explicit patterns
250169dd928Sdrh#
251169dd928Sdrhdo_test like-3.3.105 {
252169dd928Sdrh  set sqlite_like_count 0
253169dd928Sdrh  queryplan {
254169dd928Sdrh    SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
255169dd928Sdrh  }
256169dd928Sdrh} {abc abcd nosort {} i1}
257169dd928Sdrhdo_test like-3.3.106 {
258169dd928Sdrh  set sqlite_like_count
259169dd928Sdrh} 0
260169dd928Sdrhsqlite3_db_config db QPSG 0
261169dd928Sdrh
26293ee23ccSdrh# The LIKE optimization still works when the RHS is a string with no
26393ee23ccSdrh# wildcard.  Ticket [e090183531fc2747]
26493ee23ccSdrh#
26593ee23ccSdrhdo_test like-3.4.2 {
26693ee23ccSdrh  queryplan {
26793ee23ccSdrh    SELECT x FROM t1 WHERE x LIKE 'a' ORDER BY 1;
26893ee23ccSdrh  }
26993ee23ccSdrh} {a nosort {} i1}
27093ee23ccSdrhdo_test like-3.4.3 {
27193ee23ccSdrh  queryplan {
27293ee23ccSdrh    SELECT x FROM t1 WHERE x LIKE 'ab' ORDER BY 1;
27393ee23ccSdrh  }
27493ee23ccSdrh} {ab nosort {} i1}
27593ee23ccSdrhdo_test like-3.4.4 {
27693ee23ccSdrh  queryplan {
27793ee23ccSdrh    SELECT x FROM t1 WHERE x LIKE 'abcd' ORDER BY 1;
27893ee23ccSdrh  }
27993ee23ccSdrh} {abcd nosort {} i1}
28093ee23ccSdrhdo_test like-3.4.5 {
28193ee23ccSdrh  queryplan {
28293ee23ccSdrh    SELECT x FROM t1 WHERE x LIKE 'abcde' ORDER BY 1;
28393ee23ccSdrh  }
28493ee23ccSdrh} {nosort {} i1}
28593ee23ccSdrh
28693ee23ccSdrh
28755ef4d97Sdrh# Partial optimization when the pattern does not end in '%'
28855ef4d97Sdrh#
28955ef4d97Sdrhdo_test like-3.5 {
29055ef4d97Sdrh  set sqlite_like_count 0
29155ef4d97Sdrh  queryplan {
29255ef4d97Sdrh    SELECT x FROM t1 WHERE x LIKE 'a_c' ORDER BY 1;
29355ef4d97Sdrh  }
29455ef4d97Sdrh} {abc nosort {} i1}
29555ef4d97Sdrhdo_test like-3.6 {
29655ef4d97Sdrh  set sqlite_like_count
29755ef4d97Sdrh} 6
29855ef4d97Sdrhdo_test like-3.7 {
29955ef4d97Sdrh  set sqlite_like_count 0
30055ef4d97Sdrh  queryplan {
30155ef4d97Sdrh    SELECT x FROM t1 WHERE x LIKE 'ab%d' ORDER BY 1;
30255ef4d97Sdrh  }
30355ef4d97Sdrh} {abcd abd nosort {} i1}
30455ef4d97Sdrhdo_test like-3.8 {
30555ef4d97Sdrh  set sqlite_like_count
30655ef4d97Sdrh} 4
30755ef4d97Sdrhdo_test like-3.9 {
30855ef4d97Sdrh  set sqlite_like_count 0
30955ef4d97Sdrh  queryplan {
31055ef4d97Sdrh    SELECT x FROM t1 WHERE x LIKE 'a_c%' ORDER BY 1;
31155ef4d97Sdrh  }
31255ef4d97Sdrh} {abc abcd nosort {} i1}
31355ef4d97Sdrhdo_test like-3.10 {
31455ef4d97Sdrh  set sqlite_like_count
31555ef4d97Sdrh} 6
31655ef4d97Sdrh
31755ef4d97Sdrh# No optimization when the pattern begins with a wildcard.
31855ef4d97Sdrh# Note that the index is still used but only for sorting.
31955ef4d97Sdrh#
32055ef4d97Sdrhdo_test like-3.11 {
32155ef4d97Sdrh  set sqlite_like_count 0
32255ef4d97Sdrh  queryplan {
32355ef4d97Sdrh    SELECT x FROM t1 WHERE x LIKE '%bcd' ORDER BY 1;
32455ef4d97Sdrh  }
32555ef4d97Sdrh} {abcd bcd nosort {} i1}
32655ef4d97Sdrhdo_test like-3.12 {
32755ef4d97Sdrh  set sqlite_like_count
32855ef4d97Sdrh} 12
32955ef4d97Sdrh
33055ef4d97Sdrh# No optimization for case insensitive LIKE
33155ef4d97Sdrh#
33255ef4d97Sdrhdo_test like-3.13 {
33355ef4d97Sdrh  set sqlite_like_count 0
3347c171098Sdrh  db eval {PRAGMA case_sensitive_like=off;}
33555ef4d97Sdrh  queryplan {
33655ef4d97Sdrh    SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
33755ef4d97Sdrh  }
33855ef4d97Sdrh} {ABC {ABC abc xyz} abc abcd nosort {} i1}
33955ef4d97Sdrhdo_test like-3.14 {
34055ef4d97Sdrh  set sqlite_like_count
34155ef4d97Sdrh} 12
34255ef4d97Sdrh
34355ef4d97Sdrh# No optimization without an index.
34455ef4d97Sdrh#
34555ef4d97Sdrhdo_test like-3.15 {
34655ef4d97Sdrh  set sqlite_like_count 0
3477c171098Sdrh  db eval {
34855ef4d97Sdrh    PRAGMA case_sensitive_like=on;
34955ef4d97Sdrh    DROP INDEX i1;
3507c171098Sdrh  }
3517c171098Sdrh  queryplan {
35255ef4d97Sdrh    SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
35355ef4d97Sdrh  }
3547c171098Sdrh} {abc abcd sort t1 *}
35555ef4d97Sdrhdo_test like-3.16 {
35655ef4d97Sdrh  set sqlite_like_count
35755ef4d97Sdrh} 12
35855ef4d97Sdrh
35955ef4d97Sdrh# No GLOB optimization without an index.
36055ef4d97Sdrh#
36155ef4d97Sdrhdo_test like-3.17 {
36255ef4d97Sdrh  set sqlite_like_count 0
36355ef4d97Sdrh  queryplan {
36455ef4d97Sdrh    SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1;
36555ef4d97Sdrh  }
3667c171098Sdrh} {abc abcd sort t1 *}
36755ef4d97Sdrhdo_test like-3.18 {
36855ef4d97Sdrh  set sqlite_like_count
36955ef4d97Sdrh} 12
37055ef4d97Sdrh
37155ef4d97Sdrh# GLOB is optimized regardless of the case_sensitive_like setting.
37255ef4d97Sdrh#
37355ef4d97Sdrhdo_test like-3.19 {
37455ef4d97Sdrh  set sqlite_like_count 0
3759da058bbSdrh  db eval {CREATE INDEX i1 ON t1(x);}
37655ef4d97Sdrh  queryplan {
37755ef4d97Sdrh    SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1;
37855ef4d97Sdrh  }
37955ef4d97Sdrh} {abc abcd nosort {} i1}
38055ef4d97Sdrhdo_test like-3.20 {
38155ef4d97Sdrh  set sqlite_like_count
38255ef4d97Sdrh} 0
38355ef4d97Sdrhdo_test like-3.21 {
38455ef4d97Sdrh  set sqlite_like_count 0
3857c171098Sdrh  db eval {PRAGMA case_sensitive_like=on;}
38655ef4d97Sdrh  queryplan {
38755ef4d97Sdrh    SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1;
38855ef4d97Sdrh  }
38955ef4d97Sdrh} {abc abcd nosort {} i1}
39055ef4d97Sdrhdo_test like-3.22 {
39155ef4d97Sdrh  set sqlite_like_count
39255ef4d97Sdrh} 0
39355ef4d97Sdrhdo_test like-3.23 {
39455ef4d97Sdrh  set sqlite_like_count 0
3957c171098Sdrh  db eval {PRAGMA case_sensitive_like=off;}
39655ef4d97Sdrh  queryplan {
39755ef4d97Sdrh    SELECT x FROM t1 WHERE x GLOB 'a[bc]d' ORDER BY 1;
39855ef4d97Sdrh  }
39955ef4d97Sdrh} {abd acd nosort {} i1}
40055ef4d97Sdrhdo_test like-3.24 {
40155ef4d97Sdrh  set sqlite_like_count
40255ef4d97Sdrh} 6
40355ef4d97Sdrh
40493ee23ccSdrh# GLOB optimization when there is no wildcard.  Ticket [e090183531fc2747]
40593ee23ccSdrh#
40693ee23ccSdrhdo_test like-3.25 {
40793ee23ccSdrh  queryplan {
40893ee23ccSdrh    SELECT x FROM t1 WHERE x GLOB 'a' ORDER BY 1;
40993ee23ccSdrh  }
41093ee23ccSdrh} {a nosort {} i1}
41193ee23ccSdrhdo_test like-3.26 {
41293ee23ccSdrh  queryplan {
41393ee23ccSdrh    SELECT x FROM t1 WHERE x GLOB 'abcd' ORDER BY 1;
41493ee23ccSdrh  }
41593ee23ccSdrh} {abcd nosort {} i1}
41693ee23ccSdrhdo_test like-3.27 {
41793ee23ccSdrh  queryplan {
41893ee23ccSdrh    SELECT x FROM t1 WHERE x GLOB 'abcde' ORDER BY 1;
41993ee23ccSdrh  }
42093ee23ccSdrh} {nosort {} i1}
42193ee23ccSdrh
42293ee23ccSdrh
42393ee23ccSdrh
4248b3d990bSdrh# No optimization if the LHS of the LIKE is not a column name or
4258b3d990bSdrh# if the RHS is not a string.
4268b3d990bSdrh#
4278b3d990bSdrhdo_test like-4.1 {
4288b3d990bSdrh  execsql {PRAGMA case_sensitive_like=on}
4298b3d990bSdrh  set sqlite_like_count 0
4308b3d990bSdrh  queryplan {
4318b3d990bSdrh    SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1
4328b3d990bSdrh  }
4338b3d990bSdrh} {abc abcd nosort {} i1}
4348b3d990bSdrhdo_test like-4.2 {
4358b3d990bSdrh  set sqlite_like_count
4368b3d990bSdrh} 0
4378b3d990bSdrhdo_test like-4.3 {
4388b3d990bSdrh  set sqlite_like_count 0
4398b3d990bSdrh  queryplan {
4408b3d990bSdrh    SELECT x FROM t1 WHERE +x LIKE 'abc%' ORDER BY 1
4418b3d990bSdrh  }
4428b3d990bSdrh} {abc abcd nosort {} i1}
4438b3d990bSdrhdo_test like-4.4 {
4448b3d990bSdrh  set sqlite_like_count
4458b3d990bSdrh} 12
4468b3d990bSdrhdo_test like-4.5 {
4478b3d990bSdrh  set sqlite_like_count 0
4488b3d990bSdrh  queryplan {
4498b3d990bSdrh    SELECT x FROM t1 WHERE x LIKE ('ab' || 'c%') ORDER BY 1
4508b3d990bSdrh  }
4518b3d990bSdrh} {abc abcd nosort {} i1}
4528b3d990bSdrhdo_test like-4.6 {
4538b3d990bSdrh  set sqlite_like_count
4548b3d990bSdrh} 12
4558b3d990bSdrh
456d64fe2f3Sdrh# Collating sequences on the index disable the LIKE optimization.
457d64fe2f3Sdrh# Or if the NOCASE collating sequence is used, the LIKE optimization
458d64fe2f3Sdrh# is enabled when case_sensitive_like is OFF.
459d64fe2f3Sdrh#
460d64fe2f3Sdrhdo_test like-5.1 {
461d64fe2f3Sdrh  execsql {PRAGMA case_sensitive_like=off}
462d64fe2f3Sdrh  set sqlite_like_count 0
463d64fe2f3Sdrh  queryplan {
464d64fe2f3Sdrh    SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1
465d64fe2f3Sdrh  }
466d64fe2f3Sdrh} {ABC {ABC abc xyz} abc abcd nosort {} i1}
467d64fe2f3Sdrhdo_test like-5.2 {
468d64fe2f3Sdrh  set sqlite_like_count
469d64fe2f3Sdrh} 12
470d64fe2f3Sdrhdo_test like-5.3 {
471d64fe2f3Sdrh  execsql {
472c4ac22e9Sdrh    CREATE TABLE t2(x TEXT COLLATE NOCASE);
4733f4d1d1bSdrh    INSERT INTO t2 SELECT * FROM t1 ORDER BY rowid;
474d64fe2f3Sdrh    CREATE INDEX i2 ON t2(x COLLATE NOCASE);
475d64fe2f3Sdrh  }
476d64fe2f3Sdrh  set sqlite_like_count 0
477d64fe2f3Sdrh  queryplan {
478d64fe2f3Sdrh    SELECT x FROM t2 WHERE x LIKE 'abc%' ORDER BY 1
479d64fe2f3Sdrh  }
480d64fe2f3Sdrh} {abc ABC {ABC abc xyz} abcd nosort {} i2}
481d64fe2f3Sdrhdo_test like-5.4 {
482d64fe2f3Sdrh  set sqlite_like_count
483d64fe2f3Sdrh} 0
484d64fe2f3Sdrhdo_test like-5.5 {
485d64fe2f3Sdrh  execsql {
486d64fe2f3Sdrh    PRAGMA case_sensitive_like=on;
487d64fe2f3Sdrh  }
488d64fe2f3Sdrh  set sqlite_like_count 0
489d64fe2f3Sdrh  queryplan {
490d64fe2f3Sdrh    SELECT x FROM t2 WHERE x LIKE 'abc%' ORDER BY 1
491d64fe2f3Sdrh  }
492d64fe2f3Sdrh} {abc abcd nosort {} i2}
493d64fe2f3Sdrhdo_test like-5.6 {
494d64fe2f3Sdrh  set sqlite_like_count
495d64fe2f3Sdrh} 12
496d64fe2f3Sdrhdo_test like-5.7 {
497d64fe2f3Sdrh  execsql {
498d64fe2f3Sdrh    PRAGMA case_sensitive_like=off;
499d64fe2f3Sdrh  }
500d64fe2f3Sdrh  set sqlite_like_count 0
501d64fe2f3Sdrh  queryplan {
502d64fe2f3Sdrh    SELECT x FROM t2 WHERE x GLOB 'abc*' ORDER BY 1
503d64fe2f3Sdrh  }
504d64fe2f3Sdrh} {abc abcd nosort {} i2}
505d64fe2f3Sdrhdo_test like-5.8 {
506d64fe2f3Sdrh  set sqlite_like_count
507d64fe2f3Sdrh} 12
5089f504eabSdrhdo_test like-5.11 {
5099f504eabSdrh  execsql {PRAGMA case_sensitive_like=off}
5109f504eabSdrh  set sqlite_like_count 0
5119f504eabSdrh  queryplan {
5129f504eabSdrh    SELECT x FROM t1 WHERE x LIKE 'ABC%' ORDER BY 1
5139f504eabSdrh  }
5149f504eabSdrh} {ABC {ABC abc xyz} abc abcd nosort {} i1}
5159f504eabSdrhdo_test like-5.12 {
5169f504eabSdrh  set sqlite_like_count
5179f504eabSdrh} 12
5189f504eabSdrhdo_test like-5.13 {
5199f504eabSdrh  set sqlite_like_count 0
5209f504eabSdrh  queryplan {
5219f504eabSdrh    SELECT x FROM t2 WHERE x LIKE 'ABC%' ORDER BY 1
5229f504eabSdrh  }
5239f504eabSdrh} {abc ABC {ABC abc xyz} abcd nosort {} i2}
5249f504eabSdrhdo_test like-5.14 {
5259f504eabSdrh  set sqlite_like_count
5269f504eabSdrh} 0
5279f504eabSdrhdo_test like-5.15 {
5289f504eabSdrh  execsql {
5299f504eabSdrh    PRAGMA case_sensitive_like=on;
5309f504eabSdrh  }
5319f504eabSdrh  set sqlite_like_count 0
5329f504eabSdrh  queryplan {
5339f504eabSdrh    SELECT x FROM t2 WHERE x LIKE 'ABC%' ORDER BY 1
5349f504eabSdrh  }
5359f504eabSdrh} {ABC {ABC abc xyz} nosort {} i2}
5369f504eabSdrhdo_test like-5.16 {
5379f504eabSdrh  set sqlite_like_count
5389f504eabSdrh} 12
5399f504eabSdrhdo_test like-5.17 {
5409f504eabSdrh  execsql {
5419f504eabSdrh    PRAGMA case_sensitive_like=off;
5429f504eabSdrh  }
5439f504eabSdrh  set sqlite_like_count 0
5449f504eabSdrh  queryplan {
5459f504eabSdrh    SELECT x FROM t2 WHERE x GLOB 'ABC*' ORDER BY 1
5469f504eabSdrh  }
5479f504eabSdrh} {ABC {ABC abc xyz} nosort {} i2}
5489f504eabSdrhdo_test like-5.18 {
5499f504eabSdrh  set sqlite_like_count
5509f504eabSdrh} 12
5519f504eabSdrh
5529f504eabSdrh# Boundary case.  The prefix for a LIKE comparison is rounded up
5539f504eabSdrh# when constructing the comparison.  Example:  "ab" becomes "ac".
5549f504eabSdrh# In other words, the last character is increased by one.
5559f504eabSdrh#
5569f504eabSdrh# Make sure this happens correctly when the last character is a
5579f504eabSdrh# "z" and we are doing case-insensitive comparisons.
5589f504eabSdrh#
5599f504eabSdrh# Ticket #2959
5609f504eabSdrh#
5619f504eabSdrhdo_test like-5.21 {
5629f504eabSdrh  execsql {
5639f504eabSdrh    PRAGMA case_sensitive_like=off;
5649f504eabSdrh    INSERT INTO t2 VALUES('ZZ-upper-upper');
5659f504eabSdrh    INSERT INTO t2 VALUES('zZ-lower-upper');
5669f504eabSdrh    INSERT INTO t2 VALUES('Zz-upper-lower');
5679f504eabSdrh    INSERT INTO t2 VALUES('zz-lower-lower');
5689f504eabSdrh  }
5699f504eabSdrh  queryplan {
5709f504eabSdrh    SELECT x FROM t2 WHERE x LIKE 'zz%';
5719f504eabSdrh  }
5729f504eabSdrh} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2}
5739f504eabSdrhdo_test like-5.22 {
5749f504eabSdrh  queryplan {
5759f504eabSdrh    SELECT x FROM t2 WHERE x LIKE 'zZ%';
5769f504eabSdrh  }
5779f504eabSdrh} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2}
5789f504eabSdrhdo_test like-5.23 {
5799f504eabSdrh  queryplan {
5809f504eabSdrh    SELECT x FROM t2 WHERE x LIKE 'Zz%';
5819f504eabSdrh  }
5829f504eabSdrh} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2}
5839f504eabSdrhdo_test like-5.24 {
5849f504eabSdrh  queryplan {
5859f504eabSdrh    SELECT x FROM t2 WHERE x LIKE 'ZZ%';
5869f504eabSdrh  }
5879f504eabSdrh} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2}
5889f504eabSdrhdo_test like-5.25 {
5899da058bbSdrh  db eval {
5909f504eabSdrh    PRAGMA case_sensitive_like=on;
591c4ac22e9Sdrh    CREATE TABLE t3(x TEXT);
5929f504eabSdrh    CREATE INDEX i3 ON t3(x);
5939f504eabSdrh    INSERT INTO t3 VALUES('ZZ-upper-upper');
5949f504eabSdrh    INSERT INTO t3 VALUES('zZ-lower-upper');
5959f504eabSdrh    INSERT INTO t3 VALUES('Zz-upper-lower');
5969f504eabSdrh    INSERT INTO t3 VALUES('zz-lower-lower');
5979da058bbSdrh  }
5989da058bbSdrh  queryplan {
5999f504eabSdrh    SELECT x FROM t3 WHERE x LIKE 'zz%';
6009f504eabSdrh  }
6019f504eabSdrh} {zz-lower-lower nosort {} i3}
6029f504eabSdrhdo_test like-5.26 {
6039f504eabSdrh  queryplan {
6049f504eabSdrh    SELECT x FROM t3 WHERE x LIKE 'zZ%';
6059f504eabSdrh  }
6069f504eabSdrh} {zZ-lower-upper nosort {} i3}
6079f504eabSdrhdo_test like-5.27 {
6089f504eabSdrh  queryplan {
6099f504eabSdrh    SELECT x FROM t3 WHERE x LIKE 'Zz%';
6109f504eabSdrh  }
6119f504eabSdrh} {Zz-upper-lower nosort {} i3}
6129f504eabSdrhdo_test like-5.28 {
6139f504eabSdrh  queryplan {
6149f504eabSdrh    SELECT x FROM t3 WHERE x LIKE 'ZZ%';
6159f504eabSdrh  }
6169f504eabSdrh} {ZZ-upper-upper nosort {} i3}
6179f504eabSdrh
618d64fe2f3Sdrh
6199c86df52Sdrh# ticket #2407
6209c86df52Sdrh#
6219c86df52Sdrh# Make sure the LIKE prefix optimization does not strip off leading
6229c86df52Sdrh# characters of the like pattern that happen to be quote characters.
6239c86df52Sdrh#
6249c86df52Sdrhdo_test like-6.1 {
6259c86df52Sdrh  foreach x { 'abc 'bcd 'def 'ax } {
6264152e677Sdanielk1977    set x2 '[string map {' ''} $x]'
6274152e677Sdanielk1977    db eval "INSERT INTO t2 VALUES($x2)"
6289c86df52Sdrh  }
6299c86df52Sdrh  execsql {
6309c86df52Sdrh    SELECT * FROM t2 WHERE x LIKE '''a%'
6319c86df52Sdrh  }
6329c86df52Sdrh} {'abc 'ax}
6338b3d990bSdrh
63401495b99Sdrhdo_test like-7.1 {
63501495b99Sdrh  execsql {
636c4ac22e9Sdrh    SELECT rowid, * FROM t1 WHERE rowid GLOB '1*' ORDER BY rowid;
63701495b99Sdrh  }
638c4ac22e9Sdrh} {1 a 10 ABC 11 CDE 12 {ABC abc xyz}}
63901495b99Sdrh
640e3602be8Sdrh# ticket #3345.
641e3602be8Sdrh#
642e3602be8Sdrh# Overloading the LIKE function with -1 for the number of arguments
643e3602be8Sdrh# will overload both the 2-argument and the 3-argument LIKE.
644e3602be8Sdrh#
645e3602be8Sdrhdo_test like-8.1 {
646e3602be8Sdrh  db eval {
647e3602be8Sdrh    CREATE TABLE t8(x);
648e3602be8Sdrh    INSERT INTO t8 VALUES('abcdef');
649e3602be8Sdrh    INSERT INTO t8 VALUES('ghijkl');
650e3602be8Sdrh    INSERT INTO t8 VALUES('mnopqr');
651e3602be8Sdrh    SELECT 1, x FROM t8 WHERE x LIKE '%h%';
652e3602be8Sdrh    SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
653e3602be8Sdrh  }
654e3602be8Sdrh} {1 ghijkl 2 ghijkl}
655e3602be8Sdrhdo_test like-8.2 {
656e3602be8Sdrh  proc newlike {args} {return 1} ;# Alternative LIKE is always return TRUE
657e3602be8Sdrh  db function like newlike       ;# Uses -1 for nArg in sqlite3_create_function
658e3602be8Sdrh  db cache flush
659e3602be8Sdrh  db eval {
660e3602be8Sdrh    SELECT 1, x FROM t8 WHERE x LIKE '%h%';
661e3602be8Sdrh    SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
662e3602be8Sdrh  }
663e3602be8Sdrh} {1 ghijkl 2 ghijkl}
664e3602be8Sdrhdo_test like-8.3 {
665e3602be8Sdrh  db function like -argcount 2 newlike
666e3602be8Sdrh  db eval {
667e3602be8Sdrh    SELECT 1, x FROM t8 WHERE x LIKE '%h%';
668e3602be8Sdrh    SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
669e3602be8Sdrh  }
670e3602be8Sdrh} {1 abcdef 1 ghijkl 1 mnopqr 2 ghijkl}
671e3602be8Sdrhdo_test like-8.4 {
672e3602be8Sdrh  db function like -argcount 3 newlike
673e3602be8Sdrh  db eval {
674e3602be8Sdrh    SELECT 1, x FROM t8 WHERE x LIKE '%h%';
675e3602be8Sdrh    SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
676e3602be8Sdrh  }
677e3602be8Sdrh} {1 abcdef 1 ghijkl 1 mnopqr 2 abcdef 2 ghijkl 2 mnopqr}
678e3602be8Sdrh
679e3602be8Sdrh
6806bd2c735Sdanifcapable like_opt&&!icu {
6815bd98aefSdrh  # Evaluate SQL.  Return the result set followed by the
6825bd98aefSdrh  # and the number of full-scan steps.
6835bd98aefSdrh  #
6845bd98aefSdrh  db close
6855bd98aefSdrh  sqlite3 db test.db
6865bd98aefSdrh  proc count_steps {sql} {
6875bd98aefSdrh    set r [db eval $sql]
6885bd98aefSdrh    lappend r scan [db status step] sort [db status sort]
6895bd98aefSdrh  }
6905bd98aefSdrh  do_test like-9.1 {
6915bd98aefSdrh    count_steps {
6925bd98aefSdrh       SELECT x FROM t2 WHERE x LIKE 'x%'
6935bd98aefSdrh    }
6945bd98aefSdrh  } {xyz scan 0 sort 0}
6955bd98aefSdrh  do_test like-9.2 {
6965bd98aefSdrh    count_steps {
6975bd98aefSdrh       SELECT x FROM t2 WHERE x LIKE '_y%'
6985bd98aefSdrh    }
6995bd98aefSdrh  } {xyz scan 19 sort 0}
7005bd98aefSdrh  do_test like-9.3.1 {
7015bd98aefSdrh    set res [sqlite3_exec_hex db {
7025bd98aefSdrh       SELECT x FROM t2 WHERE x LIKE '%78%25'
7035bd98aefSdrh    }]
7045bd98aefSdrh  } {0 {x xyz}}
7055bd98aefSdrh  ifcapable explain {
7065bd98aefSdrh    do_test like-9.3.2 {
7075bd98aefSdrh      set res [sqlite3_exec_hex db {
7085bd98aefSdrh         EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%78%25'
7095bd98aefSdrh      }]
7105bd98aefSdrh      regexp {INDEX i2} $res
7115bd98aefSdrh    } {1}
7125bd98aefSdrh  }
7135bd98aefSdrh  do_test like-9.4.1 {
7145bd98aefSdrh    sqlite3_exec_hex db {INSERT INTO t2 VALUES('%ffhello')}
7155bd98aefSdrh    set res [sqlite3_exec_hex db {
7165bd98aefSdrh       SELECT substr(x,2) AS x FROM t2 WHERE +x LIKE '%ff%25'
7175bd98aefSdrh    }]
7185bd98aefSdrh  } {0 {x hello}}
7195bd98aefSdrh  do_test like-9.4.2 {
7205bd98aefSdrh    set res [sqlite3_exec_hex db {
7215bd98aefSdrh       SELECT substr(x,2) AS x FROM t2 WHERE x LIKE '%ff%25'
7225bd98aefSdrh    }]
7235bd98aefSdrh  } {0 {x hello}}
7245bd98aefSdrh  ifcapable explain {
7255bd98aefSdrh    do_test like-9.4.3 {
7265bd98aefSdrh      set res [sqlite3_exec_hex db {
7275bd98aefSdrh         EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%ff%25'
7285bd98aefSdrh      }]
7298210233cSdrh      regexp {SCAN t2} $res
7303f4d1d1bSdrh    } {1}
7315bd98aefSdrh  }
7325bd98aefSdrh  do_test like-9.5.1 {
7335bd98aefSdrh    set res [sqlite3_exec_hex db {
7345bd98aefSdrh       SELECT x FROM t2 WHERE x LIKE '%fe%25'
7355bd98aefSdrh    }]
7365bd98aefSdrh  } {0 {}}
7375bd98aefSdrh  ifcapable explain {
7385bd98aefSdrh    do_test like-9.5.2 {
7395bd98aefSdrh      set res [sqlite3_exec_hex db {
7405bd98aefSdrh         EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%fe%25'
7415bd98aefSdrh      }]
7425bd98aefSdrh      regexp {INDEX i2} $res
7435bd98aefSdrh    } {1}
7445bd98aefSdrh  }
7455bd98aefSdrh
746c4ac22e9Sdrh  # Do an SQL statement.  Append the search count to the end of the result.
747c4ac22e9Sdrh  #
748c4ac22e9Sdrh  proc count sql {
749c4ac22e9Sdrh    set ::sqlite_search_count 0
750c4ac22e9Sdrh    set ::sqlite_like_count 0
751c4ac22e9Sdrh    return [concat [execsql $sql] scan $::sqlite_search_count \
752c4ac22e9Sdrh             like $::sqlite_like_count]
753c4ac22e9Sdrh  }
754c4ac22e9Sdrh
755c4ac22e9Sdrh  # The LIKE and GLOB optimizations do not work on columns with
756c4ac22e9Sdrh  # affinity other than TEXT.
757c4ac22e9Sdrh  # Ticket #3901
758c4ac22e9Sdrh  #
759c4ac22e9Sdrh  do_test like-10.1 {
760c4ac22e9Sdrh    db close
761c4ac22e9Sdrh    sqlite3 db test.db
762c4ac22e9Sdrh    execsql {
763c4ac22e9Sdrh      CREATE TABLE t10(
764c4ac22e9Sdrh        a INTEGER PRIMARY KEY,
765c4ac22e9Sdrh        b INTEGER COLLATE nocase UNIQUE,
766c4ac22e9Sdrh        c NUMBER COLLATE nocase UNIQUE,
767c4ac22e9Sdrh        d BLOB COLLATE nocase UNIQUE,
768c4ac22e9Sdrh        e COLLATE nocase UNIQUE,
769c4ac22e9Sdrh        f TEXT COLLATE nocase UNIQUE
770c4ac22e9Sdrh      );
771c4ac22e9Sdrh      INSERT INTO t10 VALUES(1,1,1,1,1,1);
772c4ac22e9Sdrh      INSERT INTO t10 VALUES(12,12,12,12,12,12);
773c4ac22e9Sdrh      INSERT INTO t10 VALUES(123,123,123,123,123,123);
774c4ac22e9Sdrh      INSERT INTO t10 VALUES(234,234,234,234,234,234);
775c4ac22e9Sdrh      INSERT INTO t10 VALUES(345,345,345,345,345,345);
776c4ac22e9Sdrh      INSERT INTO t10 VALUES(45,45,45,45,45,45);
777c4ac22e9Sdrh    }
778c4ac22e9Sdrh    count {
779083310dfSdrh      SELECT a FROM t10 WHERE b LIKE '12%' ORDER BY +a;
780c4ac22e9Sdrh    }
781c4ac22e9Sdrh  } {12 123 scan 5 like 6}
782c4ac22e9Sdrh  do_test like-10.2 {
783c4ac22e9Sdrh    count {
784083310dfSdrh      SELECT a FROM t10 WHERE c LIKE '12%' ORDER BY +a;
785c4ac22e9Sdrh    }
786c4ac22e9Sdrh  } {12 123 scan 5 like 6}
787c4ac22e9Sdrh  do_test like-10.3 {
788c4ac22e9Sdrh    count {
789083310dfSdrh      SELECT a FROM t10 WHERE d LIKE '12%' ORDER BY +a;
790c4ac22e9Sdrh    }
791c4ac22e9Sdrh  } {12 123 scan 5 like 6}
792c4ac22e9Sdrh  do_test like-10.4 {
793c4ac22e9Sdrh    count {
794083310dfSdrh      SELECT a FROM t10 WHERE e LIKE '12%' ORDER BY +a;
795c4ac22e9Sdrh    }
796c4ac22e9Sdrh  } {12 123 scan 5 like 6}
79741d2e66eSdrh  ifcapable like_match_blobs {
79841d2e66eSdrh    do_test like-10.5a {
799c4ac22e9Sdrh      count {
800083310dfSdrh        SELECT a FROM t10 WHERE f LIKE '12%' ORDER BY +a;
801c4ac22e9Sdrh      }
802a9c18a90Sdrh    } {12 123 scan 4 like 0}
80341d2e66eSdrh  } else {
80441d2e66eSdrh    do_test like-10.5b {
80541d2e66eSdrh      count {
80641d2e66eSdrh        SELECT a FROM t10 WHERE f LIKE '12%' ORDER BY +a;
80741d2e66eSdrh      }
80841d2e66eSdrh    } {12 123 scan 3 like 0}
80941d2e66eSdrh  }
810c4ac22e9Sdrh  do_test like-10.6 {
811c4ac22e9Sdrh    count {
812083310dfSdrh      SELECT a FROM t10 WHERE a LIKE '12%' ORDER BY +a;
813c4ac22e9Sdrh    }
814c4ac22e9Sdrh  } {12 123 scan 5 like 6}
815c4ac22e9Sdrh  do_test like-10.10 {
816c4ac22e9Sdrh    execsql {
817c4ac22e9Sdrh      CREATE TABLE t10b(
818c4ac22e9Sdrh        a INTEGER PRIMARY KEY,
819c4ac22e9Sdrh        b INTEGER UNIQUE,
820c4ac22e9Sdrh        c NUMBER UNIQUE,
821c4ac22e9Sdrh        d BLOB UNIQUE,
822c4ac22e9Sdrh        e UNIQUE,
823c4ac22e9Sdrh        f TEXT UNIQUE
824c4ac22e9Sdrh      );
825c4ac22e9Sdrh      INSERT INTO t10b SELECT * FROM t10;
826c4ac22e9Sdrh    }
827c4ac22e9Sdrh    count {
828083310dfSdrh      SELECT a FROM t10b WHERE b GLOB '12*' ORDER BY +a;
829c4ac22e9Sdrh    }
830c4ac22e9Sdrh  } {12 123 scan 5 like 6}
831c4ac22e9Sdrh  do_test like-10.11 {
832c4ac22e9Sdrh    count {
833083310dfSdrh      SELECT a FROM t10b WHERE c GLOB '12*' ORDER BY +a;
834c4ac22e9Sdrh    }
835c4ac22e9Sdrh  } {12 123 scan 5 like 6}
836c4ac22e9Sdrh  do_test like-10.12 {
837c4ac22e9Sdrh    count {
838083310dfSdrh      SELECT a FROM t10b WHERE d GLOB '12*' ORDER BY +a;
839c4ac22e9Sdrh    }
840c4ac22e9Sdrh  } {12 123 scan 5 like 6}
841c4ac22e9Sdrh  do_test like-10.13 {
842c4ac22e9Sdrh    count {
843083310dfSdrh      SELECT a FROM t10b WHERE e GLOB '12*' ORDER BY +a;
844c4ac22e9Sdrh    }
845c4ac22e9Sdrh  } {12 123 scan 5 like 6}
84641d2e66eSdrh  ifcapable like_match_blobs {
847c4ac22e9Sdrh    do_test like-10.14 {
848c4ac22e9Sdrh      count {
849083310dfSdrh        SELECT a FROM t10b WHERE f GLOB '12*' ORDER BY +a;
850c4ac22e9Sdrh      }
851a9c18a90Sdrh    } {12 123 scan 4 like 0}
85241d2e66eSdrh  } else {
85341d2e66eSdrh    do_test like-10.14 {
85441d2e66eSdrh      count {
85541d2e66eSdrh        SELECT a FROM t10b WHERE f GLOB '12*' ORDER BY +a;
85641d2e66eSdrh      }
85741d2e66eSdrh    } {12 123 scan 3 like 0}
85841d2e66eSdrh  }
859c4ac22e9Sdrh  do_test like-10.15 {
860c4ac22e9Sdrh    count {
861083310dfSdrh      SELECT a FROM t10b WHERE a GLOB '12*' ORDER BY +a;
862c4ac22e9Sdrh    }
863c4ac22e9Sdrh  } {12 123 scan 5 like 6}
8646bd2c735Sdan}
865c4ac22e9Sdrh
8668342e49fSdrh# LIKE and GLOB where the default collating sequence is not appropriate
8678342e49fSdrh# but an index with the appropriate collating sequence exists.
8688342e49fSdrh#
8698342e49fSdrhdo_test like-11.0 {
8708342e49fSdrh  execsql {
8718342e49fSdrh    CREATE TABLE t11(
8728342e49fSdrh      a INTEGER PRIMARY KEY,
8738342e49fSdrh      b TEXT COLLATE nocase,
8748342e49fSdrh      c TEXT COLLATE binary
8758342e49fSdrh    );
8768342e49fSdrh    INSERT INTO t11 VALUES(1, 'a','a');
8778342e49fSdrh    INSERT INTO t11 VALUES(2, 'ab','ab');
8788342e49fSdrh    INSERT INTO t11 VALUES(3, 'abc','abc');
8798342e49fSdrh    INSERT INTO t11 VALUES(4, 'abcd','abcd');
8808342e49fSdrh    INSERT INTO t11 VALUES(5, 'A','A');
8818342e49fSdrh    INSERT INTO t11 VALUES(6, 'AB','AB');
8828342e49fSdrh    INSERT INTO t11 VALUES(7, 'ABC','ABC');
8838342e49fSdrh    INSERT INTO t11 VALUES(8, 'ABCD','ABCD');
8848342e49fSdrh    INSERT INTO t11 VALUES(9, 'x','x');
8858342e49fSdrh    INSERT INTO t11 VALUES(10, 'yz','yz');
8868342e49fSdrh    INSERT INTO t11 VALUES(11, 'X','X');
8878342e49fSdrh    INSERT INTO t11 VALUES(12, 'YZ','YZ');
8888342e49fSdrh    SELECT count(*) FROM t11;
8898342e49fSdrh  }
8908342e49fSdrh} {12}
8918342e49fSdrhdo_test like-11.1 {
8927c171098Sdrh  db eval {PRAGMA case_sensitive_like=OFF;}
8938342e49fSdrh  queryplan {
8948342e49fSdrh    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
8958342e49fSdrh  }
8968342e49fSdrh} {abc abcd ABC ABCD nosort t11 *}
8978342e49fSdrhdo_test like-11.2 {
8987c171098Sdrh  db eval {PRAGMA case_sensitive_like=ON;}
8998342e49fSdrh  queryplan {
9008342e49fSdrh    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
9018342e49fSdrh  }
9028342e49fSdrh} {abc abcd nosort t11 *}
9038342e49fSdrhdo_test like-11.3 {
9047c171098Sdrh  db eval {
9058342e49fSdrh    PRAGMA case_sensitive_like=OFF;
9068342e49fSdrh    CREATE INDEX t11b ON t11(b);
9077c171098Sdrh  }
9087c171098Sdrh  queryplan {
909083310dfSdrh    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a;
9108342e49fSdrh  }
9118342e49fSdrh} {abc abcd ABC ABCD sort {} t11b}
9128342e49fSdrhdo_test like-11.4 {
9137c171098Sdrh  db eval {PRAGMA case_sensitive_like=ON;}
9148342e49fSdrh  queryplan {
9158342e49fSdrh    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
9168342e49fSdrh  }
9178342e49fSdrh} {abc abcd nosort t11 *}
9188342e49fSdrhdo_test like-11.5 {
9197c171098Sdrh  db eval {
9208342e49fSdrh    PRAGMA case_sensitive_like=OFF;
9218342e49fSdrh    DROP INDEX t11b;
9228342e49fSdrh    CREATE INDEX t11bnc ON t11(b COLLATE nocase);
9237c171098Sdrh  }
9247c171098Sdrh  queryplan {
925083310dfSdrh    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a;
9268342e49fSdrh  }
9278342e49fSdrh} {abc abcd ABC ABCD sort {} t11bnc}
9288342e49fSdrhdo_test like-11.6 {
9297c171098Sdrh  db eval {CREATE INDEX t11bb ON t11(b COLLATE binary);}
9308342e49fSdrh  queryplan {
931083310dfSdrh    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a;
9328342e49fSdrh  }
9338342e49fSdrh} {abc abcd ABC ABCD sort {} t11bnc}
9348342e49fSdrhdo_test like-11.7 {
9357c171098Sdrh  db eval {PRAGMA case_sensitive_like=ON;}
9368342e49fSdrh  queryplan {
937083310dfSdrh    SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a;
9388342e49fSdrh  }
9398342e49fSdrh} {abc abcd sort {} t11bb}
9408342e49fSdrhdo_test like-11.8 {
9417c171098Sdrh  db eval {PRAGMA case_sensitive_like=OFF;}
9428342e49fSdrh  queryplan {
943083310dfSdrh    SELECT b FROM t11 WHERE b GLOB 'abc*' ORDER BY +a;
9448342e49fSdrh  }
9458342e49fSdrh} {abc abcd sort {} t11bb}
9468342e49fSdrhdo_test like-11.9 {
9477c171098Sdrh  db eval {
9488342e49fSdrh    CREATE INDEX t11cnc ON t11(c COLLATE nocase);
9498342e49fSdrh    CREATE INDEX t11cb ON t11(c COLLATE binary);
9507c171098Sdrh  }
9517c171098Sdrh  queryplan {
952083310dfSdrh    SELECT c FROM t11 WHERE c LIKE 'abc%' ORDER BY +a;
9538342e49fSdrh  }
9548342e49fSdrh} {abc abcd ABC ABCD sort {} t11cnc}
9558342e49fSdrhdo_test like-11.10 {
9568342e49fSdrh  queryplan {
957083310dfSdrh    SELECT c FROM t11 WHERE c GLOB 'abc*' ORDER BY +a;
9588342e49fSdrh  }
9598342e49fSdrh} {abc abcd sort {} t11cb}
9608342e49fSdrh
9616ade453cSdrh# A COLLATE clause on the pattern does not change the result of a
9626ade453cSdrh# LIKE operator.
9636ade453cSdrh#
9646ade453cSdrhdo_execsql_test like-12.1 {
9656ade453cSdrh  CREATE TABLE t12nc(id INTEGER, x TEXT UNIQUE COLLATE nocase);
9666ade453cSdrh  INSERT INTO t12nc VALUES(1,'abcde'),(2,'uvwxy'),(3,'ABCDEF');
9676ade453cSdrh  CREATE TABLE t12b(id INTEGER, x TEXT UNIQUE COLLATE binary);
9686ade453cSdrh  INSERT INTO t12b VALUES(1,'abcde'),(2,'uvwxy'),(3,'ABCDEF');
9696ade453cSdrh  SELECT id FROM t12nc WHERE x LIKE 'abc%' ORDER BY +id;
9706ade453cSdrh} {1 3}
9716ade453cSdrhdo_execsql_test like-12.2 {
9726ade453cSdrh  SELECT id FROM t12b WHERE x LIKE 'abc%' ORDER BY +id;
9736ade453cSdrh} {1 3}
9746ade453cSdrhdo_execsql_test like-12.3 {
9756ade453cSdrh  SELECT id FROM t12nc WHERE x LIKE 'abc%' COLLATE binary ORDER BY +id;
9766ade453cSdrh} {1 3}
9776ade453cSdrhdo_execsql_test like-12.4 {
9786ade453cSdrh  SELECT id FROM t12b WHERE x LIKE 'abc%' COLLATE binary ORDER BY +id;
9796ade453cSdrh} {1 3}
9806ade453cSdrhdo_execsql_test like-12.5 {
9816ade453cSdrh  SELECT id FROM t12nc WHERE x LIKE 'abc%' COLLATE nocase ORDER BY +id;
9826ade453cSdrh} {1 3}
9836ade453cSdrhdo_execsql_test like-12.6 {
9846ade453cSdrh  SELECT id FROM t12b WHERE x LIKE 'abc%' COLLATE nocase ORDER BY +id;
9856ade453cSdrh} {1 3}
9866ade453cSdrh
9876ade453cSdrh# Adding a COLLATE clause to the pattern of a LIKE operator does nothing
9886ade453cSdrh# to change the suitability of using an index to satisfy that LIKE
9896ade453cSdrh# operator.
9906ade453cSdrh#
9916ade453cSdrhdo_execsql_test like-12.11 {
9926ade453cSdrh  EXPLAIN QUERY PLAN
9936ade453cSdrh  SELECT id FROM t12nc WHERE x LIKE 'abc%' ORDER BY +id;
9946ade453cSdrh} {/SEARCH/}
9956ade453cSdrhdo_execsql_test like-12.12 {
9966ade453cSdrh  EXPLAIN QUERY PLAN
9976ade453cSdrh  SELECT id FROM t12b WHERE x LIKE 'abc%' ORDER BY +id;
9986ade453cSdrh} {/SCAN/}
9996ade453cSdrhdo_execsql_test like-12.13 {
10006ade453cSdrh  EXPLAIN QUERY PLAN
10016ade453cSdrh  SELECT id FROM t12nc WHERE x LIKE 'abc%' COLLATE nocase ORDER BY +id;
10026ade453cSdrh} {/SEARCH/}
10036ade453cSdrhdo_execsql_test like-12.14 {
10046ade453cSdrh  EXPLAIN QUERY PLAN
10056ade453cSdrh  SELECT id FROM t12b WHERE x LIKE 'abc%' COLLATE nocase ORDER BY +id;
10066ade453cSdrh} {/SCAN/}
10076ade453cSdrhdo_execsql_test like-12.15 {
10086ade453cSdrh  EXPLAIN QUERY PLAN
10096ade453cSdrh  SELECT id FROM t12nc WHERE x LIKE 'abc%' COLLATE binary ORDER BY +id;
10106ade453cSdrh} {/SEARCH/}
10116ade453cSdrhdo_execsql_test like-12.16 {
10126ade453cSdrh  EXPLAIN QUERY PLAN
10136ade453cSdrh  SELECT id FROM t12b WHERE x LIKE 'abc%' COLLATE binary ORDER BY +id;
10146ade453cSdrh} {/SCAN/}
10156ade453cSdrh
1016fb397260Sdrh# Ticket [https://www.sqlite.org/src/tktview/80369eddd5c94d49f7fbbcf5]
1017fb397260Sdrh# 2016-01-20
1018fb397260Sdrh#
1019fb397260Sdrhdo_execsql_test like-13.1 {
1020fb397260Sdrh  SELECT char(0x304d) LIKE char(0x306d);
1021fb397260Sdrh} {0}
1022fb397260Sdrhdo_execsql_test like-13.2 {
1023fb397260Sdrh  SELECT char(0x4d) LIKE char(0x306d);
1024fb397260Sdrh} {0}
1025fb397260Sdrhdo_execsql_test like-13.3 {
1026fb397260Sdrh  SELECT char(0x304d) LIKE char(0x6d);
1027fb397260Sdrh} {0}
1028fb397260Sdrhdo_execsql_test like-13.4 {
1029fb397260Sdrh  SELECT char(0x4d) LIKE char(0x6d);
1030fb397260Sdrh} {1}
1031fb397260Sdrh
10327a40707bSdrh# Performance testing for patterns with many wildcards.  These LIKE and GLOB
10337a40707bSdrh# patterns were quite slow with SQLite 3.15.2 and earlier.
10347a40707bSdrh#
10357a40707bSdrhdo_test like-14.1 {
10367a40707bSdrh  set x [lindex [time {
10377a40707bSdrh    db one {SELECT 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz'GLOB'*a*a*a*a*a*a*a*a*y'}
10387a40707bSdrh  }] 0]
1039*f5576936Slarrybr  set tlimit [expr {1000 * $::sqlite_options(configslower)}]
1040*f5576936Slarrybr  puts -nonewline " ($x ms - want less than $tlimit) "
1041*f5576936Slarrybr  expr {$x<$tlimit}
10427a40707bSdrh} {1}
10437a40707bSdrhifcapable !icu {
10447a40707bSdrh  do_test like-14.2 {
10457a40707bSdrh    set x [lindex [time {
10467a40707bSdrh      db one {SELECT 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz'LIKE'%a%a%a%a%a%a%a%a%y'}
10477a40707bSdrh    }] 0]
1048*f5576936Slarrybr  set tlimit [expr {1000 * $::sqlite_options(configslower)}]
1049*f5576936Slarrybr  puts -nonewline " ($x ms - want less than $tlimit) "
1050*f5576936Slarrybr  expr {$x<$tlimit}
10517a40707bSdrh  } {1}
10527a40707bSdrh}
10535bd98aefSdrh
10549325c87cSdrhifcapable !icu {
10551d42ea71Sdrh# As of 2017-07-27 (3.21.0) the LIKE optimization works with ESCAPE as
10561d42ea71Sdrh# long as the ESCAPE is a single-byte literal.
10571d42ea71Sdrh#
10581d42ea71Sdrhdb close
10591d42ea71Sdrhsqlite3 db :memory:
10601d42ea71Sdrhdo_execsql_test like-15.100 {
10611d42ea71Sdrh  CREATE TABLE t15(x TEXT COLLATE nocase, y, PRIMARY KEY(x));
10621d42ea71Sdrh  INSERT INTO t15(x,y) VALUES
10631d42ea71Sdrh    ('abcde',1), ('ab%de',2), ('a_cde',3),
10641d42ea71Sdrh    ('uvwxy',11),('uvwx%',12),('uvwx_',13),
10651d42ea71Sdrh    ('_bcde',21),('%bcde',22),
10661d42ea71Sdrh    ('abcd_',31),('abcd%',32),
10671d42ea71Sdrh    ('ab%xy',41);
10681d42ea71Sdrh  SELECT y FROM t15 WHERE x LIKE 'ab/%d%' ESCAPE '/';
10691d42ea71Sdrh} {2}
10701d42ea71Sdrhdo_execsql_test like-15.101 {
10711d42ea71Sdrh  EXPLAIN QUERY PLAN
10721d42ea71Sdrh  SELECT y FROM t15 WHERE x LIKE 'ab/%d%' ESCAPE '/';
10731d42ea71Sdrh} {/SEARCH/}
10741d42ea71Sdrhdo_execsql_test like-15.102 {
10751d42ea71Sdrh  EXPLAIN QUERY PLAN
10761d42ea71Sdrh  SELECT y FROM t15 WHERE x LIKE 'ab/%d%' ESCAPE '//';
10771d42ea71Sdrh} {/SCAN/}
10781d42ea71Sdrhdo_execsql_test like-15.103 {
10791d42ea71Sdrh  EXPLAIN QUERY PLAN
10801d42ea71Sdrh  SELECT y FROM t15 WHERE x LIKE 'ab/%d%' ESCAPE '';
10811d42ea71Sdrh} {/SCAN/}
10821d42ea71Sdrhdo_execsql_test like-15.110 {
10831d42ea71Sdrh  SELECT y FROM t15 WHERE x LIKE 'abcdx%%' ESCAPE 'x';
10841d42ea71Sdrh} {32}
10851d42ea71Sdrhdo_execsql_test like-15.111 {
10861d42ea71Sdrh  SELECT y FROM t15 WHERE x LIKE 'abx%%' ESCAPE 'x' ORDER BY +y
10871d42ea71Sdrh} {2 41}
10881d42ea71Sdrhdo_execsql_test like-15.112 {
10891d42ea71Sdrh  EXPLAIN QUERY PLAN
10901d42ea71Sdrh  SELECT y FROM t15 WHERE x LIKE 'abx%%' ESCAPE 'x' ORDER BY +y
10911d42ea71Sdrh} {/SEARCH/}
10921d42ea71Sdrhdo_execsql_test like-15.120 {
10931d42ea71Sdrh  SELECT y FROM t15 WHERE x LIKE '/%bc%' ESCAPE '/';
10941d42ea71Sdrh} {22}
10951d42ea71Sdrhdo_execsql_test like-15.121 {
10961d42ea71Sdrh  EXPLAIN QUERY PLAN
10971d42ea71Sdrh  SELECT y FROM t15 WHERE x LIKE '/%bc%' ESCAPE '/';
10981d42ea71Sdrh} {/SEARCH/}
10999325c87cSdrh}
11001d42ea71Sdrh
110132d0f64eSdan#-------------------------------------------------------------------------
110232d0f64eSdan# Tests for ticket [b1d8c79314].
110332d0f64eSdan#
110432d0f64eSdanreset_db
110532d0f64eSdando_execsql_test 16.0 {
110632d0f64eSdan  CREATE TABLE t1(a INTEGER COLLATE NOCASE);
110732d0f64eSdan  CREATE INDEX i1 ON t1(a);
110832d0f64eSdan  INSERT INTO t1 VALUES(' 1x');
110932d0f64eSdan  INSERT INTO t1 VALUES(' 1-');
111032d0f64eSdan}
111132d0f64eSdando_execsql_test 16.1 {
111232d0f64eSdan  SELECT * FROM t1 WHERE a LIKE ' 1%';
111332d0f64eSdan} {{ 1x} { 1-}}
111432d0f64eSdando_execsql_test 16.2 {
111532d0f64eSdan  SELECT * FROM t1 WHERE a LIKE ' 1-';
111632d0f64eSdan} {{ 1-}}
111732d0f64eSdan
1118589c7876Sdrh# 2020-03-19
1119589c7876Sdrh# The ESCAPE clause on LIKE takes precedence over wildcards
1120589c7876Sdrh#
1121589c7876Sdrhdo_execsql_test 17.0 {
1122589c7876Sdrh  DROP TABLE IF EXISTS t1;
1123589c7876Sdrh  CREATE TABLE t1(id INTEGER PRIMARY KEY, x TEXT);
1124589c7876Sdrh  INSERT INTO t1 VALUES
1125589c7876Sdrh    (1,'abcde'),
1126589c7876Sdrh    (2,'abc_'),
1127589c7876Sdrh    (3,'abc__'),
1128589c7876Sdrh    (4,'abc%'),
1129589c7876Sdrh    (5,'abc%%');
1130589c7876Sdrh  SELECT id FROM t1 WHERE x LIKE 'abc%%' ESCAPE '%';
1131589c7876Sdrh} {4}
1132589c7876Sdrhdo_execsql_test 17.1 {
1133589c7876Sdrh  SELECT id FROM t1 WHERE x LIKE 'abc__' ESCAPE '_';
1134589c7876Sdrh} {2}
1135589c7876Sdrh
113633941691Sdrh# 2021-02-15 ticket c0aeea67d58ae0fd
113733941691Sdrh#
113833941691Sdrhdo_execsql_test 17.1 {
113933941691Sdrh  SELECT 'x' LIKE '%' ESCAPE '_';
114033941691Sdrh} {1}
114133941691Sdrh
114233941691Sdrh
114355ef4d97Sdrhfinish_test
1144