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