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