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