]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
First cut at an implementation of the REPLACE() function. We might yet
authordrh <drh@noemail.net>
Sat, 17 Mar 2007 13:27:54 +0000 (13:27 +0000)
committerdrh <drh@noemail.net>
Sat, 17 Mar 2007 13:27:54 +0000 (13:27 +0000)
make this a compile-time option or move it into a separate source file. (CVS 3697)

FossilOrigin-Name: c2fe746ea782f84e850aaf3af7f5536b027a19a1

manifest
manifest.uuid
src/func.c
test/func.test

index b6fff56b9b3ba546b0989acf94cc55f1b14bcfa7..a20b20afb256db1061101b081e9fb0a0e6fcb3f7 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\scrash2.test,\sfor\srobustness\stesting\swith\svariable\sdisk\sblock\ssize.\s(CVS\s3696)
-D 2007-03-17T10:28:05
+C First\scut\sat\san\simplementation\sof\sthe\sREPLACE()\sfunction.\s\sWe\smight\syet\nmake\sthis\sa\scompile-time\soption\sor\smove\sit\sinto\sa\sseparate\ssource\sfile.\s(CVS\s3697)
+D 2007-03-17T13:27:55
 F Makefile.in 1fe3d0b46e40fd684e1e61f8e8056cefed16de9f
 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -67,7 +67,7 @@ F src/date.c 393c73fc027597e008dcd81454544659e978b05c
 F src/delete.c 151d08386bf9c9e7f92f6b9106c71efec2def184
 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
 F src/expr.c b5c65202c7ada4b1ec24f0f010bb73c92ab44e6d
-F src/func.c b7e1e220a6795ecae7649815145ea5f8644dfa5f
+F src/func.c 683c2d66a2ea386372f01afcd595bb1f026f1c12
 F src/hash.c 449f3d6620193aa557f5d86cbc5cc6b87702b185
 F src/hash.h 1b3f7e2609141fd571f62199fc38687d262e9564
 F src/insert.c 72cb64b698796f2005c0158e098124d9490868bb
@@ -221,7 +221,7 @@ F test/fts2g.test c69a8ab43ec77d123976ba6cf9422d647ae63032
 F test/fts2h.test 223af921323b409d4b5b18ff4e51619541b174bb
 F test/fts2i.test 1b22451d1f13f7c509baec620dc3a4a754885dd6
 F test/fts2j.test f68d7611f76309bc8b94170f3740d9fbbc061d9b
-F test/func.test 71938e2ac704d8ce12f11810d475597640656ae9
+F test/func.test 86c3322c9209be36354981354278553b3491393f
 F test/hook.test 7e7645fd9a033f79cce8fdff151e32715e7ec50a
 F test/in.test 369cb2aa1eab02296b4ec470732fe8c131260b1d
 F test/index.test e65df12bed94b2903ee89987115e1578687e9266
@@ -437,7 +437,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P c4be8d9949fc7b5e1bed757423c5195f38069048
-R 786fefa2d7d4a54acc7c3b42a1497810
-U danielk1977
-Z 9168113432a3c177fb5aa5377927a80e
+P b0f8203dbbf1036418a2dcc480f352f761826194
+R 1f5e4827e9584f1f16dd1e58366ed649
+U drh
+Z 93e91ca49be183cbbf3f15fa9aa6c1e3
index 788fd0fa6df4b10893c26be75fa87f19b3e6b012..cd8aadf2f979c98395d3260855de4161447830c9 100644 (file)
@@ -1 +1 @@
-b0f8203dbbf1036418a2dcc480f352f761826194
\ No newline at end of file
+c2fe746ea782f84e850aaf3af7f5536b027a19a1
\ No newline at end of file
index 5ef9608c15647c27e2a5e347a5c5706d5faadb22..cfd377eeb79d9e96f238c88d15d0696224ebd85f 100644 (file)
@@ -16,7 +16,7 @@
 ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
 ** All other code has file scope.
 **
-** $Id: func.c,v 1.136 2007/01/29 17:58:28 drh Exp $
+** $Id: func.c,v 1.137 2007/03/17 13:27:55 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -669,6 +669,65 @@ static void hexFunc(
   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.
@@ -1081,8 +1140,9 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
     { "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 },
+    { "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
index 9ccd8e1803b689370260f1cb43af884312040b34..2f966cc44b3168a1c1b8ea1757d76282c36377f3 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this file is testing built-in functions.
 #
-# $Id: func.test,v 1.57 2007/01/29 17:58:28 drh Exp $
+# $Id: func.test,v 1.58 2007/03/17 13:27:56 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -729,4 +729,49 @@ if {![catch {db eval {SELECT soundex('hello')}}]} {
   }
 }
 
+# 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