Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | First cut at an implementation of the REPLACE() function. We might yet make this a compile-time option or move it into a separate source file. (CVS 3697) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
c2fe746ea782f84e850aaf3af7f5536b |
User & Date: | drh 2007-03-17 13:27:55.000 |
Context
2007-03-17
| ||
17:52 | Added TRIM, LTRIM, and RTRIM functions. (CVS 3698) (check-in: 6fe13eeade user: drh tags: trunk) | |
13:27 | First cut at an implementation of the REPLACE() function. We might yet make this a compile-time option or move it into a separate source file. (CVS 3697) (check-in: c2fe746ea7 user: drh tags: trunk) | |
10:28 | Add crash2.test, for robustness testing with variable disk block size. (CVS 3696) (check-in: b0f8203dbb user: danielk1977 tags: trunk) | |
Changes
Changes to src/func.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: func.c,v 1.137 2007/03/17 13:27:55 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* #include <math.h> */ #include <stdlib.h> #include <assert.h> #include "vdbeInt.h" |
︙ | ︙ | |||
664 665 666 667 668 669 670 671 672 673 674 675 676 677 | unsigned char c = *pBlob; *(z++) = hexdigits[(c>>4)&0xf]; *(z++) = hexdigits[c&0xf]; } *z = 0; sqlite3_result_text(context, zHex, n*2, sqlite3_free); } #ifdef SQLITE_SOUNDEX /* ** Compute the soundex encoding of a word. */ static void soundexFunc( sqlite3_context *context, | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 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 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 | unsigned char c = *pBlob; *(z++) = hexdigits[(c>>4)&0xf]; *(z++) = hexdigits[c&0xf]; } *z = 0; sqlite3_result_text(context, zHex, n*2, sqlite3_free); } /* ** The replace() function. Three arguments are all strings: call ** them A, B, and C. The result is also a string which is derived ** from A by replacing every occurance of B with C. The match ** must be exact. Collating sequences are not used. */ static void replaceFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const unsigned char *zStr; /* The input string A */ const unsigned char *zPattern; /* The pattern string B */ const unsigned char *zRep; /* The replacement string C */ unsigned char *zOut; /* The output */ int nStr; /* Size of zStr */ int nPattern; /* Size of zPattern */ int nRep; /* Size of zRep */ int nOut; /* Maximum size of zOut */ int loopLimit; /* Last zStr[] that might match zPattern[] */ int i, j; /* Loop counters */ assert( argc==3 ); if( sqlite3_value_type(argv[0])==SQLITE_NULL || sqlite3_value_type(argv[1])==SQLITE_NULL || sqlite3_value_type(argv[2])==SQLITE_NULL ){ return; } nStr = sqlite3_value_bytes(argv[0]); zStr = sqlite3_value_text(argv[0]); nPattern = sqlite3_value_bytes(argv[1]); zPattern = sqlite3_value_text(argv[1]); nRep = sqlite3_value_bytes(argv[2]); zRep = sqlite3_value_text(argv[2]); if( nPattern>=nRep ){ nOut = nStr; }else{ nOut = (nStr/nPattern + 1)*nRep; } zOut = sqlite3_malloc(nOut+1); if( zOut==0 ) return; loopLimit = nStr - nPattern; for(i=j=0; i<=loopLimit; i++){ if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){ zOut[j++] = zStr[i]; }else{ memcpy(&zOut[j], zRep, nRep); j += nRep; i += nPattern-1; } } memcpy(&zOut[j], &zStr[i], nStr-i); j += nStr - i; assert( j<=nOut ); zOut[j] = 0; sqlite3_result_text(context, (char*)zOut, j, sqlite3_free); } #ifdef SQLITE_SOUNDEX /* ** Compute the soundex encoding of a word. */ static void soundexFunc( sqlite3_context *context, |
︙ | ︙ | |||
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 | { "randomblob", 1, 0, SQLITE_UTF8, 0, randomBlob }, { "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc }, { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc}, { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc }, { "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid }, { "changes", 0, 1, SQLITE_UTF8, 0, changes }, { "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes }, #ifdef SQLITE_SOUNDEX { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, #endif #ifndef SQLITE_OMIT_LOAD_EXTENSION { "load_extension", 1, 1, SQLITE_UTF8, 0, loadExt }, { "load_extension", 2, 1, SQLITE_UTF8, 0, loadExt }, #endif | > | 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 | { "randomblob", 1, 0, SQLITE_UTF8, 0, randomBlob }, { "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc }, { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc}, { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc }, { "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid }, { "changes", 0, 1, SQLITE_UTF8, 0, changes }, { "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes }, { "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc }, #ifdef SQLITE_SOUNDEX { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, #endif #ifndef SQLITE_OMIT_LOAD_EXTENSION { "load_extension", 1, 1, SQLITE_UTF8, 0, loadExt }, { "load_extension", 2, 1, SQLITE_UTF8, 0, loadExt }, #endif |
︙ | ︙ |
Changes to test/func.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing built-in functions. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing built-in functions. # # $Id: func.test,v 1.58 2007/03/17 13:27:56 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create a table to work with. # do_test func-0.0 { |
︙ | ︙ | |||
724 725 726 727 728 729 730 731 732 | } { incr i do_test func-20.$i { execsql {SELECT soundex($name)} } $sdx } } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 | } { incr i do_test func-20.$i { execsql {SELECT soundex($name)} } $sdx } } # Tests of the REPLACE function. # do_test func-21.1 { catchsql { SELECT replace(1,2); } } {1 {wrong number of arguments to function replace()}} do_test func-21.2 { catchsql { SELECT replace(1,2,3,4); } } {1 {wrong number of arguments to function replace()}} do_test func-21.3 { execsql { SELECT typeof(replace("This is the main test string", NULL, "ALT")); } } {null} do_test func-21.4 { execsql { SELECT typeof(replace(NULL, "main", "ALT")); } } {null} do_test func-21.5 { execsql { SELECT typeof(replace("This is the main test string", "main", NULL)); } } {null} do_test func-21.6 { execsql { SELECT replace("This is the main test string", "main", "ALT"); } } {{This is the ALT test string}} do_test func-21.7 { execsql { SELECT replace("This is the main test string", "main", "larger-main"); } } {{This is the larger-main test string}} do_test func-21.8 { execsql { SELECT replace("aaaaaaa", "a", "0123456789"); } } {0123456789012345678901234567890123456789012345678901234567890123456789} finish_test |