blob: f779ee9aa2476e27779b10c2666c361eb8d968c7 [file] [log] [blame]
drh55ef4d92005-08-14 01:20:37 +00001# 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#
drhc4ac22e2009-06-07 23:45:10 +000016# $Id: like.test,v 1.13 2009/06/07 23:45:11 drh Exp $
drh55ef4d92005-08-14 01:20:37 +000017
18set testdir [file dirname $argv0]
19source $testdir/tester.tcl
20
21# Create some sample data to work with.
22#
23do_test like-1.0 {
24 execsql {
25 CREATE TABLE t1(x TEXT);
26 }
27 foreach str {
28 a
29 ab
30 abc
31 abcd
32
33 acd
34 abd
35 bc
36 bcd
37
38 xyz
39 ABC
40 CDE
41 {ABC abc xyz}
42 } {
danielk19773bdca9c2006-01-17 09:35:01 +000043 db eval {INSERT INTO t1 VALUES(:str)}
drh55ef4d92005-08-14 01:20:37 +000044 }
45 execsql {
46 SELECT count(*) FROM t1;
47 }
48} {12}
49
50# Test that both case sensitive and insensitive version of LIKE work.
51#
52do_test like-1.1 {
53 execsql {
54 SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
55 }
56} {ABC abc}
57do_test like-1.2 {
58 execsql {
59 SELECT x FROM t1 WHERE x GLOB 'abc' ORDER BY 1;
60 }
61} {abc}
62do_test like-1.3 {
63 execsql {
64 SELECT x FROM t1 WHERE x LIKE 'ABC' ORDER BY 1;
65 }
66} {ABC abc}
67do_test like-1.4 {
68 execsql {
69 SELECT x FROM t1 WHERE x LIKE 'aBc' ORDER BY 1;
70 }
71} {ABC abc}
drhd2cb50b2009-01-09 21:41:17 +000072do_test like-1.5.1 {
drhc7060c42011-06-26 23:44:35 +000073 # Use sqlite3_exec() to verify fix for ticket [25ee81271091] 2011-06-26
74 sqlite3_exec db {PRAGMA case_sensitive_like=on}
75} {0 {}}
76do_test like-1.5.2 {
drh55ef4d92005-08-14 01:20:37 +000077 execsql {
drh55ef4d92005-08-14 01:20:37 +000078 SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
79 }
80} {abc}
drhc7060c42011-06-26 23:44:35 +000081do_test like-1.5.3 {
drhd2cb50b2009-01-09 21:41:17 +000082 execsql {
83 PRAGMA case_sensitive_like; -- no argument; does not change setting
84 SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
85 }
86} {abc}
drh55ef4d92005-08-14 01:20:37 +000087do_test like-1.6 {
88 execsql {
89 SELECT x FROM t1 WHERE x GLOB 'abc' ORDER BY 1;
90 }
91} {abc}
92do_test like-1.7 {
93 execsql {
94 SELECT x FROM t1 WHERE x LIKE 'ABC' ORDER BY 1;
95 }
96} {ABC}
97do_test like-1.8 {
98 execsql {
99 SELECT x FROM t1 WHERE x LIKE 'aBc' ORDER BY 1;
100 }
101} {}
102do_test like-1.9 {
103 execsql {
104 PRAGMA case_sensitive_like=off;
105 SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
106 }
107} {ABC abc}
drhd2cb50b2009-01-09 21:41:17 +0000108do_test like-1.10 {
109 execsql {
110 PRAGMA case_sensitive_like; -- No argument, does not change setting.
111 SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
112 }
113} {ABC abc}
drh55ef4d92005-08-14 01:20:37 +0000114
115# Tests of the REGEXP operator
116#
drhc8872962012-09-12 18:45:31 +0000117db eval {SELECT sqlite_compileoption_used('ENABLE_REGEXP') AS has_regexp} break;
118if {$has_regexp==0} {
drh55ef4d92005-08-14 01:20:37 +0000119 proc test_regexp {a b} {
120 return [regexp $a $b]
121 }
dan6bd2c732010-11-01 05:42:26 +0000122 db function regexp -argcount 2 test_regexp
drhc8872962012-09-12 18:45:31 +0000123 puts "# installing substitute REGEXP function"
124}
125do_test like-2.1 {
drh55ef4d92005-08-14 01:20:37 +0000126 execsql {
127 SELECT x FROM t1 WHERE x REGEXP 'abc' ORDER BY 1;
128 }
129} {{ABC abc xyz} abc abcd}
130do_test like-2.2 {
131 execsql {
132 SELECT x FROM t1 WHERE x REGEXP '^abc' ORDER BY 1;
133 }
134} {abc abcd}
135
danielk1977619a3692006-06-14 08:48:25 +0000136# Tests of the MATCH operator
137#
138do_test like-2.3 {
139 proc test_match {a b} {
140 return [string match $a $b]
141 }
drhe3602be2008-09-09 12:31:33 +0000142 db function match -argcount 2 test_match
danielk1977619a3692006-06-14 08:48:25 +0000143 execsql {
144 SELECT x FROM t1 WHERE x MATCH '*abc*' ORDER BY 1;
145 }
146} {{ABC abc xyz} abc abcd}
147do_test like-2.4 {
148 execsql {
149 SELECT x FROM t1 WHERE x MATCH 'abc*' ORDER BY 1;
150 }
151} {abc abcd}
152
drh55ef4d92005-08-14 01:20:37 +0000153# For the remaining tests, we need to have the like optimizations
154# enabled.
155#
156ifcapable !like_opt {
157 finish_test
158 return
159}
160
161# This procedure executes the SQL. Then it appends to the result the
162# "sort" or "nosort" keyword (as in the cksort procedure above) then
163# it appends the ::sqlite_query_plan variable.
164#
165proc queryplan {sql} {
166 set ::sqlite_sort_count 0
167 set data [execsql $sql]
168 if {$::sqlite_sort_count} {set x sort} {set x nosort}
169 lappend data $x
170 return [concat $data $::sqlite_query_plan]
171}
172
173# Perform tests on the like optimization.
174#
175# With no index on t1.x and with case sensitivity turned off, no optimization
176# is performed.
177#
178do_test like-3.1 {
179 set sqlite_like_count 0
180 queryplan {
181 SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
182 }
183} {ABC {ABC abc xyz} abc abcd sort t1 {}}
184do_test like-3.2 {
185 set sqlite_like_count
186} {12}
187
188# With an index on t1.x and case sensitivity on, optimize completely.
189#
190do_test like-3.3 {
191 set sqlite_like_count 0
192 execsql {
193 PRAGMA case_sensitive_like=on;
194 CREATE INDEX i1 ON t1(x);
195 }
196 queryplan {
197 SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
198 }
199} {abc abcd nosort {} i1}
200do_test like-3.4 {
201 set sqlite_like_count
202} 0
203
drh93ee23c2010-07-22 12:33:57 +0000204# The LIKE optimization still works when the RHS is a string with no
205# wildcard. Ticket [e090183531fc2747]
206#
207do_test like-3.4.2 {
208 queryplan {
209 SELECT x FROM t1 WHERE x LIKE 'a' ORDER BY 1;
210 }
211} {a nosort {} i1}
212do_test like-3.4.3 {
213 queryplan {
214 SELECT x FROM t1 WHERE x LIKE 'ab' ORDER BY 1;
215 }
216} {ab nosort {} i1}
217do_test like-3.4.4 {
218 queryplan {
219 SELECT x FROM t1 WHERE x LIKE 'abcd' ORDER BY 1;
220 }
221} {abcd nosort {} i1}
222do_test like-3.4.5 {
223 queryplan {
224 SELECT x FROM t1 WHERE x LIKE 'abcde' ORDER BY 1;
225 }
226} {nosort {} i1}
227
228
drh55ef4d92005-08-14 01:20:37 +0000229# Partial optimization when the pattern does not end in '%'
230#
231do_test like-3.5 {
232 set sqlite_like_count 0
233 queryplan {
234 SELECT x FROM t1 WHERE x LIKE 'a_c' ORDER BY 1;
235 }
236} {abc nosort {} i1}
237do_test like-3.6 {
238 set sqlite_like_count
239} 6
240do_test like-3.7 {
241 set sqlite_like_count 0
242 queryplan {
243 SELECT x FROM t1 WHERE x LIKE 'ab%d' ORDER BY 1;
244 }
245} {abcd abd nosort {} i1}
246do_test like-3.8 {
247 set sqlite_like_count
248} 4
249do_test like-3.9 {
250 set sqlite_like_count 0
251 queryplan {
252 SELECT x FROM t1 WHERE x LIKE 'a_c%' ORDER BY 1;
253 }
254} {abc abcd nosort {} i1}
255do_test like-3.10 {
256 set sqlite_like_count
257} 6
258
259# No optimization when the pattern begins with a wildcard.
260# Note that the index is still used but only for sorting.
261#
262do_test like-3.11 {
263 set sqlite_like_count 0
264 queryplan {
265 SELECT x FROM t1 WHERE x LIKE '%bcd' ORDER BY 1;
266 }
267} {abcd bcd nosort {} i1}
268do_test like-3.12 {
269 set sqlite_like_count
270} 12
271
272# No optimization for case insensitive LIKE
273#
274do_test like-3.13 {
275 set sqlite_like_count 0
276 queryplan {
277 PRAGMA case_sensitive_like=off;
278 SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
279 }
280} {ABC {ABC abc xyz} abc abcd nosort {} i1}
281do_test like-3.14 {
282 set sqlite_like_count
283} 12
284
285# No optimization without an index.
286#
287do_test like-3.15 {
288 set sqlite_like_count 0
289 queryplan {
290 PRAGMA case_sensitive_like=on;
291 DROP INDEX i1;
292 SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1;
293 }
294} {abc abcd sort t1 {}}
295do_test like-3.16 {
296 set sqlite_like_count
297} 12
298
299# No GLOB optimization without an index.
300#
301do_test like-3.17 {
302 set sqlite_like_count 0
303 queryplan {
304 SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1;
305 }
306} {abc abcd sort t1 {}}
307do_test like-3.18 {
308 set sqlite_like_count
309} 12
310
311# GLOB is optimized regardless of the case_sensitive_like setting.
312#
313do_test like-3.19 {
314 set sqlite_like_count 0
drh9da058b2011-08-17 00:40:58 +0000315 db eval {CREATE INDEX i1 ON t1(x);}
drh55ef4d92005-08-14 01:20:37 +0000316 queryplan {
drh55ef4d92005-08-14 01:20:37 +0000317 SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1;
318 }
319} {abc abcd nosort {} i1}
320do_test like-3.20 {
321 set sqlite_like_count
322} 0
323do_test like-3.21 {
324 set sqlite_like_count 0
325 queryplan {
326 PRAGMA case_sensitive_like=on;
327 SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1;
328 }
329} {abc abcd nosort {} i1}
330do_test like-3.22 {
331 set sqlite_like_count
332} 0
333do_test like-3.23 {
334 set sqlite_like_count 0
335 queryplan {
336 PRAGMA case_sensitive_like=off;
337 SELECT x FROM t1 WHERE x GLOB 'a[bc]d' ORDER BY 1;
338 }
339} {abd acd nosort {} i1}
340do_test like-3.24 {
341 set sqlite_like_count
342} 6
343
drh93ee23c2010-07-22 12:33:57 +0000344# GLOB optimization when there is no wildcard. Ticket [e090183531fc2747]
345#
346do_test like-3.25 {
347 queryplan {
348 SELECT x FROM t1 WHERE x GLOB 'a' ORDER BY 1;
349 }
350} {a nosort {} i1}
351do_test like-3.26 {
352 queryplan {
353 SELECT x FROM t1 WHERE x GLOB 'abcd' ORDER BY 1;
354 }
355} {abcd nosort {} i1}
356do_test like-3.27 {
357 queryplan {
358 SELECT x FROM t1 WHERE x GLOB 'abcde' ORDER BY 1;
359 }
360} {nosort {} i1}
361
362
363
drh8b3d9902005-08-19 00:14:42 +0000364# No optimization if the LHS of the LIKE is not a column name or
365# if the RHS is not a string.
366#
367do_test like-4.1 {
368 execsql {PRAGMA case_sensitive_like=on}
369 set sqlite_like_count 0
370 queryplan {
371 SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1
372 }
373} {abc abcd nosort {} i1}
374do_test like-4.2 {
375 set sqlite_like_count
376} 0
377do_test like-4.3 {
378 set sqlite_like_count 0
379 queryplan {
380 SELECT x FROM t1 WHERE +x LIKE 'abc%' ORDER BY 1
381 }
382} {abc abcd nosort {} i1}
383do_test like-4.4 {
384 set sqlite_like_count
385} 12
386do_test like-4.5 {
387 set sqlite_like_count 0
388 queryplan {
389 SELECT x FROM t1 WHERE x LIKE ('ab' || 'c%') ORDER BY 1
390 }
391} {abc abcd nosort {} i1}
392do_test like-4.6 {
393 set sqlite_like_count
394} 12
395
drhd64fe2f2005-08-28 17:00:23 +0000396# Collating sequences on the index disable the LIKE optimization.
397# Or if the NOCASE collating sequence is used, the LIKE optimization
398# is enabled when case_sensitive_like is OFF.
399#
400do_test like-5.1 {
401 execsql {PRAGMA case_sensitive_like=off}
402 set sqlite_like_count 0
403 queryplan {
404 SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1
405 }
406} {ABC {ABC abc xyz} abc abcd nosort {} i1}
407do_test like-5.2 {
408 set sqlite_like_count
409} 12
410do_test like-5.3 {
411 execsql {
drhc4ac22e2009-06-07 23:45:10 +0000412 CREATE TABLE t2(x TEXT COLLATE NOCASE);
drhd64fe2f2005-08-28 17:00:23 +0000413 INSERT INTO t2 SELECT * FROM t1;
414 CREATE INDEX i2 ON t2(x COLLATE NOCASE);
415 }
416 set sqlite_like_count 0
417 queryplan {
418 SELECT x FROM t2 WHERE x LIKE 'abc%' ORDER BY 1
419 }
420} {abc ABC {ABC abc xyz} abcd nosort {} i2}
421do_test like-5.4 {
422 set sqlite_like_count
423} 0
424do_test like-5.5 {
425 execsql {
426 PRAGMA case_sensitive_like=on;
427 }
428 set sqlite_like_count 0
429 queryplan {
430 SELECT x FROM t2 WHERE x LIKE 'abc%' ORDER BY 1
431 }
432} {abc abcd nosort {} i2}
433do_test like-5.6 {
434 set sqlite_like_count
435} 12
436do_test like-5.7 {
437 execsql {
438 PRAGMA case_sensitive_like=off;
439 }
440 set sqlite_like_count 0
441 queryplan {
442 SELECT x FROM t2 WHERE x GLOB 'abc*' ORDER BY 1
443 }
444} {abc abcd nosort {} i2}
445do_test like-5.8 {
446 set sqlite_like_count
447} 12
drh9f504ea2008-02-23 21:55:39 +0000448do_test like-5.11 {
449 execsql {PRAGMA case_sensitive_like=off}
450 set sqlite_like_count 0
451 queryplan {
452 SELECT x FROM t1 WHERE x LIKE 'ABC%' ORDER BY 1
453 }
454} {ABC {ABC abc xyz} abc abcd nosort {} i1}
455do_test like-5.12 {
456 set sqlite_like_count
457} 12
458do_test like-5.13 {
459 set sqlite_like_count 0
460 queryplan {
461 SELECT x FROM t2 WHERE x LIKE 'ABC%' ORDER BY 1
462 }
463} {abc ABC {ABC abc xyz} abcd nosort {} i2}
464do_test like-5.14 {
465 set sqlite_like_count
466} 0
467do_test like-5.15 {
468 execsql {
469 PRAGMA case_sensitive_like=on;
470 }
471 set sqlite_like_count 0
472 queryplan {
473 SELECT x FROM t2 WHERE x LIKE 'ABC%' ORDER BY 1
474 }
475} {ABC {ABC abc xyz} nosort {} i2}
476do_test like-5.16 {
477 set sqlite_like_count
478} 12
479do_test like-5.17 {
480 execsql {
481 PRAGMA case_sensitive_like=off;
482 }
483 set sqlite_like_count 0
484 queryplan {
485 SELECT x FROM t2 WHERE x GLOB 'ABC*' ORDER BY 1
486 }
487} {ABC {ABC abc xyz} nosort {} i2}
488do_test like-5.18 {
489 set sqlite_like_count
490} 12
491
492# Boundary case. The prefix for a LIKE comparison is rounded up
493# when constructing the comparison. Example: "ab" becomes "ac".
494# In other words, the last character is increased by one.
495#
496# Make sure this happens correctly when the last character is a
497# "z" and we are doing case-insensitive comparisons.
498#
499# Ticket #2959
500#
501do_test like-5.21 {
502 execsql {
503 PRAGMA case_sensitive_like=off;
504 INSERT INTO t2 VALUES('ZZ-upper-upper');
505 INSERT INTO t2 VALUES('zZ-lower-upper');
506 INSERT INTO t2 VALUES('Zz-upper-lower');
507 INSERT INTO t2 VALUES('zz-lower-lower');
508 }
509 queryplan {
510 SELECT x FROM t2 WHERE x LIKE 'zz%';
511 }
512} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2}
513do_test like-5.22 {
514 queryplan {
515 SELECT x FROM t2 WHERE x LIKE 'zZ%';
516 }
517} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2}
518do_test like-5.23 {
519 queryplan {
520 SELECT x FROM t2 WHERE x LIKE 'Zz%';
521 }
522} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2}
523do_test like-5.24 {
524 queryplan {
525 SELECT x FROM t2 WHERE x LIKE 'ZZ%';
526 }
527} {zz-lower-lower zZ-lower-upper Zz-upper-lower ZZ-upper-upper nosort {} i2}
528do_test like-5.25 {
drh9da058b2011-08-17 00:40:58 +0000529 db eval {
drh9f504ea2008-02-23 21:55:39 +0000530 PRAGMA case_sensitive_like=on;
drhc4ac22e2009-06-07 23:45:10 +0000531 CREATE TABLE t3(x TEXT);
drh9f504ea2008-02-23 21:55:39 +0000532 CREATE INDEX i3 ON t3(x);
533 INSERT INTO t3 VALUES('ZZ-upper-upper');
534 INSERT INTO t3 VALUES('zZ-lower-upper');
535 INSERT INTO t3 VALUES('Zz-upper-lower');
536 INSERT INTO t3 VALUES('zz-lower-lower');
drh9da058b2011-08-17 00:40:58 +0000537 }
538 queryplan {
drh9f504ea2008-02-23 21:55:39 +0000539 SELECT x FROM t3 WHERE x LIKE 'zz%';
540 }
541} {zz-lower-lower nosort {} i3}
542do_test like-5.26 {
543 queryplan {
544 SELECT x FROM t3 WHERE x LIKE 'zZ%';
545 }
546} {zZ-lower-upper nosort {} i3}
547do_test like-5.27 {
548 queryplan {
549 SELECT x FROM t3 WHERE x LIKE 'Zz%';
550 }
551} {Zz-upper-lower nosort {} i3}
552do_test like-5.28 {
553 queryplan {
554 SELECT x FROM t3 WHERE x LIKE 'ZZ%';
555 }
556} {ZZ-upper-upper nosort {} i3}
557
drhd64fe2f2005-08-28 17:00:23 +0000558
drh9c86df52007-06-11 12:56:15 +0000559# ticket #2407
560#
561# Make sure the LIKE prefix optimization does not strip off leading
562# characters of the like pattern that happen to be quote characters.
563#
564do_test like-6.1 {
565 foreach x { 'abc 'bcd 'def 'ax } {
danielk19774152e672007-09-12 17:01:45 +0000566 set x2 '[string map {' ''} $x]'
567 db eval "INSERT INTO t2 VALUES($x2)"
drh9c86df52007-06-11 12:56:15 +0000568 }
569 execsql {
570 SELECT * FROM t2 WHERE x LIKE '''a%'
571 }
572} {'abc 'ax}
drh8b3d9902005-08-19 00:14:42 +0000573
drh01495b92008-01-23 12:52:40 +0000574do_test like-7.1 {
575 execsql {
drhc4ac22e2009-06-07 23:45:10 +0000576 SELECT rowid, * FROM t1 WHERE rowid GLOB '1*' ORDER BY rowid;
drh01495b92008-01-23 12:52:40 +0000577 }
drhc4ac22e2009-06-07 23:45:10 +0000578} {1 a 10 ABC 11 CDE 12 {ABC abc xyz}}
drh01495b92008-01-23 12:52:40 +0000579
drhe3602be2008-09-09 12:31:33 +0000580# ticket #3345.
581#
582# Overloading the LIKE function with -1 for the number of arguments
583# will overload both the 2-argument and the 3-argument LIKE.
584#
585do_test like-8.1 {
586 db eval {
587 CREATE TABLE t8(x);
588 INSERT INTO t8 VALUES('abcdef');
589 INSERT INTO t8 VALUES('ghijkl');
590 INSERT INTO t8 VALUES('mnopqr');
591 SELECT 1, x FROM t8 WHERE x LIKE '%h%';
592 SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
593 }
594} {1 ghijkl 2 ghijkl}
595do_test like-8.2 {
596 proc newlike {args} {return 1} ;# Alternative LIKE is always return TRUE
597 db function like newlike ;# Uses -1 for nArg in sqlite3_create_function
598 db cache flush
599 db eval {
600 SELECT 1, x FROM t8 WHERE x LIKE '%h%';
601 SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
602 }
603} {1 ghijkl 2 ghijkl}
604do_test like-8.3 {
605 db function like -argcount 2 newlike
606 db eval {
607 SELECT 1, x FROM t8 WHERE x LIKE '%h%';
608 SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
609 }
610} {1 abcdef 1 ghijkl 1 mnopqr 2 ghijkl}
611do_test like-8.4 {
612 db function like -argcount 3 newlike
613 db eval {
614 SELECT 1, x FROM t8 WHERE x LIKE '%h%';
615 SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
616 }
617} {1 abcdef 1 ghijkl 1 mnopqr 2 abcdef 2 ghijkl 2 mnopqr}
618
619
dan6bd2c732010-11-01 05:42:26 +0000620ifcapable like_opt&&!icu {
drh5bd98ae2009-01-07 18:24:03 +0000621 # Evaluate SQL. Return the result set followed by the
622 # and the number of full-scan steps.
623 #
624 db close
625 sqlite3 db test.db
626 proc count_steps {sql} {
627 set r [db eval $sql]
628 lappend r scan [db status step] sort [db status sort]
629 }
630 do_test like-9.1 {
631 count_steps {
632 SELECT x FROM t2 WHERE x LIKE 'x%'
633 }
634 } {xyz scan 0 sort 0}
635 do_test like-9.2 {
636 count_steps {
637 SELECT x FROM t2 WHERE x LIKE '_y%'
638 }
639 } {xyz scan 19 sort 0}
640 do_test like-9.3.1 {
641 set res [sqlite3_exec_hex db {
642 SELECT x FROM t2 WHERE x LIKE '%78%25'
643 }]
644 } {0 {x xyz}}
645 ifcapable explain {
646 do_test like-9.3.2 {
647 set res [sqlite3_exec_hex db {
648 EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%78%25'
649 }]
650 regexp {INDEX i2} $res
651 } {1}
652 }
653 do_test like-9.4.1 {
654 sqlite3_exec_hex db {INSERT INTO t2 VALUES('%ffhello')}
655 set res [sqlite3_exec_hex db {
656 SELECT substr(x,2) AS x FROM t2 WHERE +x LIKE '%ff%25'
657 }]
658 } {0 {x hello}}
659 do_test like-9.4.2 {
660 set res [sqlite3_exec_hex db {
661 SELECT substr(x,2) AS x FROM t2 WHERE x LIKE '%ff%25'
662 }]
663 } {0 {x hello}}
664 ifcapable explain {
665 do_test like-9.4.3 {
666 set res [sqlite3_exec_hex db {
667 EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%ff%25'
668 }]
669 regexp {INDEX i2} $res
670 } {0}
671 }
672 do_test like-9.5.1 {
673 set res [sqlite3_exec_hex db {
674 SELECT x FROM t2 WHERE x LIKE '%fe%25'
675 }]
676 } {0 {}}
677 ifcapable explain {
678 do_test like-9.5.2 {
679 set res [sqlite3_exec_hex db {
680 EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%fe%25'
681 }]
682 regexp {INDEX i2} $res
683 } {1}
684 }
drh5bd98ae2009-01-07 18:24:03 +0000685
dan6bd2c732010-11-01 05:42:26 +0000686 # Do an SQL statement. Append the search count to the end of the result.
687 #
688 proc count sql {
689 set ::sqlite_search_count 0
690 set ::sqlite_like_count 0
691 return [concat [execsql $sql] scan $::sqlite_search_count \
692 like $::sqlite_like_count]
693 }
drhc4ac22e2009-06-07 23:45:10 +0000694
dan6bd2c732010-11-01 05:42:26 +0000695 # The LIKE and GLOB optimizations do not work on columns with
696 # affinity other than TEXT.
697 # Ticket #3901
698 #
699 do_test like-10.1 {
700 db close
701 sqlite3 db test.db
702 execsql {
703 CREATE TABLE t10(
704 a INTEGER PRIMARY KEY,
705 b INTEGER COLLATE nocase UNIQUE,
706 c NUMBER COLLATE nocase UNIQUE,
707 d BLOB COLLATE nocase UNIQUE,
708 e COLLATE nocase UNIQUE,
709 f TEXT COLLATE nocase UNIQUE
710 );
711 INSERT INTO t10 VALUES(1,1,1,1,1,1);
712 INSERT INTO t10 VALUES(12,12,12,12,12,12);
713 INSERT INTO t10 VALUES(123,123,123,123,123,123);
714 INSERT INTO t10 VALUES(234,234,234,234,234,234);
715 INSERT INTO t10 VALUES(345,345,345,345,345,345);
716 INSERT INTO t10 VALUES(45,45,45,45,45,45);
717 }
718 count {
drh083310d2011-01-28 01:57:41 +0000719 SELECT a FROM t10 WHERE b LIKE '12%' ORDER BY +a;
dan6bd2c732010-11-01 05:42:26 +0000720 }
721 } {12 123 scan 5 like 6}
722 do_test like-10.2 {
723 count {
drh083310d2011-01-28 01:57:41 +0000724 SELECT a FROM t10 WHERE c LIKE '12%' ORDER BY +a;
dan6bd2c732010-11-01 05:42:26 +0000725 }
726 } {12 123 scan 5 like 6}
727 do_test like-10.3 {
728 count {
drh083310d2011-01-28 01:57:41 +0000729 SELECT a FROM t10 WHERE d LIKE '12%' ORDER BY +a;
dan6bd2c732010-11-01 05:42:26 +0000730 }
731 } {12 123 scan 5 like 6}
732 do_test like-10.4 {
733 count {
drh083310d2011-01-28 01:57:41 +0000734 SELECT a FROM t10 WHERE e LIKE '12%' ORDER BY +a;
dan6bd2c732010-11-01 05:42:26 +0000735 }
736 } {12 123 scan 5 like 6}
737 do_test like-10.5 {
738 count {
drh083310d2011-01-28 01:57:41 +0000739 SELECT a FROM t10 WHERE f LIKE '12%' ORDER BY +a;
dan6bd2c732010-11-01 05:42:26 +0000740 }
741 } {12 123 scan 3 like 0}
742 do_test like-10.6 {
743 count {
drh083310d2011-01-28 01:57:41 +0000744 SELECT a FROM t10 WHERE a LIKE '12%' ORDER BY +a;
dan6bd2c732010-11-01 05:42:26 +0000745 }
746 } {12 123 scan 5 like 6}
747 do_test like-10.10 {
748 execsql {
749 CREATE TABLE t10b(
750 a INTEGER PRIMARY KEY,
751 b INTEGER UNIQUE,
752 c NUMBER UNIQUE,
753 d BLOB UNIQUE,
754 e UNIQUE,
755 f TEXT UNIQUE
756 );
757 INSERT INTO t10b SELECT * FROM t10;
758 }
759 count {
drh083310d2011-01-28 01:57:41 +0000760 SELECT a FROM t10b WHERE b GLOB '12*' ORDER BY +a;
dan6bd2c732010-11-01 05:42:26 +0000761 }
762 } {12 123 scan 5 like 6}
763 do_test like-10.11 {
764 count {
drh083310d2011-01-28 01:57:41 +0000765 SELECT a FROM t10b WHERE c GLOB '12*' ORDER BY +a;
dan6bd2c732010-11-01 05:42:26 +0000766 }
767 } {12 123 scan 5 like 6}
768 do_test like-10.12 {
769 count {
drh083310d2011-01-28 01:57:41 +0000770 SELECT a FROM t10b WHERE d GLOB '12*' ORDER BY +a;
dan6bd2c732010-11-01 05:42:26 +0000771 }
772 } {12 123 scan 5 like 6}
773 do_test like-10.13 {
774 count {
drh083310d2011-01-28 01:57:41 +0000775 SELECT a FROM t10b WHERE e GLOB '12*' ORDER BY +a;
dan6bd2c732010-11-01 05:42:26 +0000776 }
777 } {12 123 scan 5 like 6}
778 do_test like-10.14 {
779 count {
drh083310d2011-01-28 01:57:41 +0000780 SELECT a FROM t10b WHERE f GLOB '12*' ORDER BY +a;
dan6bd2c732010-11-01 05:42:26 +0000781 }
782 } {12 123 scan 3 like 0}
783 do_test like-10.15 {
784 count {
drh083310d2011-01-28 01:57:41 +0000785 SELECT a FROM t10b WHERE a GLOB '12*' ORDER BY +a;
dan6bd2c732010-11-01 05:42:26 +0000786 }
787 } {12 123 scan 5 like 6}
788}
drhc4ac22e2009-06-07 23:45:10 +0000789
drh8342e492010-07-22 17:49:52 +0000790# LIKE and GLOB where the default collating sequence is not appropriate
791# but an index with the appropriate collating sequence exists.
792#
793do_test like-11.0 {
794 execsql {
795 CREATE TABLE t11(
796 a INTEGER PRIMARY KEY,
797 b TEXT COLLATE nocase,
798 c TEXT COLLATE binary
799 );
800 INSERT INTO t11 VALUES(1, 'a','a');
801 INSERT INTO t11 VALUES(2, 'ab','ab');
802 INSERT INTO t11 VALUES(3, 'abc','abc');
803 INSERT INTO t11 VALUES(4, 'abcd','abcd');
804 INSERT INTO t11 VALUES(5, 'A','A');
805 INSERT INTO t11 VALUES(6, 'AB','AB');
806 INSERT INTO t11 VALUES(7, 'ABC','ABC');
807 INSERT INTO t11 VALUES(8, 'ABCD','ABCD');
808 INSERT INTO t11 VALUES(9, 'x','x');
809 INSERT INTO t11 VALUES(10, 'yz','yz');
810 INSERT INTO t11 VALUES(11, 'X','X');
811 INSERT INTO t11 VALUES(12, 'YZ','YZ');
812 SELECT count(*) FROM t11;
813 }
814} {12}
815do_test like-11.1 {
816 queryplan {
817 PRAGMA case_sensitive_like=OFF;
818 SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
819 }
820} {abc abcd ABC ABCD nosort t11 *}
821do_test like-11.2 {
822 queryplan {
823 PRAGMA case_sensitive_like=ON;
824 SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
825 }
826} {abc abcd nosort t11 *}
827do_test like-11.3 {
828 queryplan {
829 PRAGMA case_sensitive_like=OFF;
830 CREATE INDEX t11b ON t11(b);
drh083310d2011-01-28 01:57:41 +0000831 SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a;
drh8342e492010-07-22 17:49:52 +0000832 }
833} {abc abcd ABC ABCD sort {} t11b}
834do_test like-11.4 {
835 queryplan {
836 PRAGMA case_sensitive_like=ON;
837 SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
838 }
839} {abc abcd nosort t11 *}
840do_test like-11.5 {
841 queryplan {
842 PRAGMA case_sensitive_like=OFF;
843 DROP INDEX t11b;
844 CREATE INDEX t11bnc ON t11(b COLLATE nocase);
drh083310d2011-01-28 01:57:41 +0000845 SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a;
drh8342e492010-07-22 17:49:52 +0000846 }
847} {abc abcd ABC ABCD sort {} t11bnc}
848do_test like-11.6 {
849 queryplan {
850 CREATE INDEX t11bb ON t11(b COLLATE binary);
drh083310d2011-01-28 01:57:41 +0000851 SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a;
drh8342e492010-07-22 17:49:52 +0000852 }
853} {abc abcd ABC ABCD sort {} t11bnc}
854do_test like-11.7 {
855 queryplan {
856 PRAGMA case_sensitive_like=ON;
drh083310d2011-01-28 01:57:41 +0000857 SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a;
drh8342e492010-07-22 17:49:52 +0000858 }
859} {abc abcd sort {} t11bb}
860do_test like-11.8 {
861 queryplan {
862 PRAGMA case_sensitive_like=OFF;
drh083310d2011-01-28 01:57:41 +0000863 SELECT b FROM t11 WHERE b GLOB 'abc*' ORDER BY +a;
drh8342e492010-07-22 17:49:52 +0000864 }
865} {abc abcd sort {} t11bb}
866do_test like-11.9 {
867 queryplan {
868 CREATE INDEX t11cnc ON t11(c COLLATE nocase);
869 CREATE INDEX t11cb ON t11(c COLLATE binary);
drh083310d2011-01-28 01:57:41 +0000870 SELECT c FROM t11 WHERE c LIKE 'abc%' ORDER BY +a;
drh8342e492010-07-22 17:49:52 +0000871 }
872} {abc abcd ABC ABCD sort {} t11cnc}
873do_test like-11.10 {
874 queryplan {
drh083310d2011-01-28 01:57:41 +0000875 SELECT c FROM t11 WHERE c GLOB 'abc*' ORDER BY +a;
drh8342e492010-07-22 17:49:52 +0000876 }
877} {abc abcd sort {} t11cb}
878
drh5bd98ae2009-01-07 18:24:03 +0000879
drh55ef4d92005-08-14 01:20:37 +0000880finish_test