Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Slightly smaller and faster LIKE/GLOB comparison implementation. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
5dddcc78eec5bcd0c7e8fe1b70875ce7 |
User & Date: | drh 2016-01-11 03:48:18.694 |
Context
2016-01-11
| ||
12:13 | If a single page is written to the wal file more than once, instead of appending the second and subsequent copy to the wal file, overwrite the first. Update: See the important bug fix at [f694e60a]! (check-in: d493d4f118 user: dan tags: trunk) | |
03:48 | Slightly smaller and faster LIKE/GLOB comparison implementation. (check-in: 5dddcc78ee user: drh tags: trunk) | |
2016-01-08
| ||
22:31 | Typo fix in the previous commit. (check-in: 52c1660398 user: drh tags: trunk) | |
Changes
Changes to src/func.c.
︙ | ︙ | |||
563 564 565 566 567 568 569 | sqlite3_result_int(context, sqlite3_total_changes(db)); } /* ** A structure defining how to do GLOB-style comparisons. */ struct compareInfo { | | | | | | 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 | sqlite3_result_int(context, sqlite3_total_changes(db)); } /* ** A structure defining how to do GLOB-style comparisons. */ struct compareInfo { u8 matchAll; /* "*" or "%" */ u8 matchOne; /* "?" or "_" */ u8 matchSet; /* "[" or 0 */ u8 noCase; /* true to ignore case differences */ }; /* ** For LIKE and GLOB matching on EBCDIC machines, assume that every ** character is exactly one byte in size. Also, provde the Utf8Read() ** macro for fast reading of the next character in the common case where ** the next character is ASCII. |
︙ | ︙ | |||
629 630 631 632 633 634 635 | ** ** This routine is usually quick, but can be N**2 in the worst case. */ static int patternCompare( const u8 *zPattern, /* The glob pattern */ const u8 *zString, /* The string to compare against the glob */ const struct compareInfo *pInfo, /* Information about how to do the compare */ | | < < < < < < < < | | | 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 | ** ** This routine is usually quick, but can be N**2 in the worst case. */ static int patternCompare( const u8 *zPattern, /* The glob pattern */ const u8 *zString, /* The string to compare against the glob */ const struct compareInfo *pInfo, /* Information about how to do the compare */ u32 matchOther /* The escape char (LIKE) or '[' (GLOB) */ ){ u32 c, c2; /* Next pattern and input string chars */ u32 matchOne = pInfo->matchOne; /* "?" or "_" */ u32 matchAll = pInfo->matchAll; /* "*" or "%" */ u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */ const u8 *zEscaped = 0; /* One past the last escaped input char */ while( (c = Utf8Read(zPattern))!=0 ){ if( c==matchAll ){ /* Match "*" */ /* Skip over multiple "*" characters in the pattern. If there ** are also "?" characters, skip those as well, but consume a ** single character of the input string for each "?" skipped */ while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){ if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){ return 0; } } if( c==0 ){ return 1; /* "*" at the end of the pattern matches */ }else if( c==matchOther ){ if( pInfo->matchSet==0 ){ c = sqlite3Utf8Read(&zPattern); if( c==0 ) return 0; }else{ /* "[...]" immediately follows the "*". We have to do a slow ** recursive search in this case, but it is an unusual case. */ assert( matchOther<0x80 ); /* '[' is a single-byte character */ while( *zString && patternCompare(&zPattern[-1],zString,pInfo,matchOther)==0 ){ SQLITE_SKIP_UTF8(zString); } return *zString!=0; } } /* At this point variable c contains the first character of the |
︙ | ︙ | |||
692 693 694 695 696 697 698 | cx = sqlite3Toupper(c); c = sqlite3Tolower(c); }else{ cx = c; } while( (c2 = *(zString++))!=0 ){ if( c2!=c && c2!=cx ) continue; | | | | | 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 | cx = sqlite3Toupper(c); c = sqlite3Tolower(c); }else{ cx = c; } while( (c2 = *(zString++))!=0 ){ if( c2!=c && c2!=cx ) continue; if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1; } }else{ while( (c2 = Utf8Read(zString))!=0 ){ if( c2!=c ) continue; if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1; } } return 0; } if( c==matchOther ){ if( pInfo->matchSet==0 ){ c = sqlite3Utf8Read(&zPattern); if( c==0 ) return 0; zEscaped = zPattern; }else{ u32 prior_c = 0; int seen = 0; int invert = 0; |
︙ | ︙ | |||
756 757 758 759 760 761 762 | return *zString==0; } /* ** The sqlite3_strglob() interface. */ int sqlite3_strglob(const char *zGlobPattern, const char *zString){ | | | 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 | return *zString==0; } /* ** The sqlite3_strglob() interface. */ int sqlite3_strglob(const char *zGlobPattern, const char *zString){ return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[')==0; } /* ** The sqlite3_strlike() interface. */ int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){ return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc)==0; |
︙ | ︙ | |||
794 795 796 797 798 799 800 | */ static void likeFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const unsigned char *zA, *zB; | | > | 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 | */ static void likeFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const unsigned char *zA, *zB; u32 escape; int nPat; sqlite3 *db = sqlite3_context_db_handle(context); struct compareInfo *pInfo = sqlite3_user_data(context); #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS if( sqlite3_value_type(argv[0])==SQLITE_BLOB || sqlite3_value_type(argv[1])==SQLITE_BLOB ){ #ifdef SQLITE_TEST sqlite3_like_count++; |
︙ | ︙ | |||
836 837 838 839 840 841 842 843 844 | if( zEsc==0 ) return; if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){ sqlite3_result_error(context, "ESCAPE expression must be a single character", -1); return; } escape = sqlite3Utf8Read(&zEsc); } if( zA && zB ){ | > > < < | 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 | if( zEsc==0 ) return; if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){ sqlite3_result_error(context, "ESCAPE expression must be a single character", -1); return; } escape = sqlite3Utf8Read(&zEsc); }else{ escape = pInfo->matchSet; } if( zA && zB ){ #ifdef SQLITE_TEST sqlite3_like_count++; #endif sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)); } } /* ** Implementation of the NULLIF(x,y) function. The result is the first ** argument if the arguments are different. The result is NULL if the |
︙ | ︙ |