]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Calling sqlite3_create_function with nArg==(-1) does not override prior
authordrh <drh@noemail.net>
Tue, 9 Sep 2008 12:31:33 +0000 (12:31 +0000)
committerdrh <drh@noemail.net>
Tue, 9 Sep 2008 12:31:33 +0000 (12:31 +0000)
calls on the same function name with nArg>=0.  Ticket #3345.  Add the
new -argcount option to the "function" method in the TCL interface. (CVS 5684)

FossilOrigin-Name: 5aa5b8044a14f59559c1839dc0799b0d2f990809

manifest
manifest.uuid
src/callback.c
src/tclsqlite.c
test/like.test
test/tclsqlite.test

index 87e9c7e73ebaa4ee83f9316b897d0ba6be089c7d..4865c0b56390a47baf98019aec72993b5ae21684 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sC++ism\sin\spager.c\s(variable\suseAtomicWrite\snot\sdeclard\sat\sthe\stop\sof\sits\sscope).\s(CVS\s5683)
-D 2008-09-08T15:35:07
+C Calling\ssqlite3_create_function\swith\snArg==(-1)\sdoes\snot\soverride\sprior\ncalls\son\sthe\ssame\sfunction\sname\swith\snArg>=0.\s\sTicket\s#3345.\s\sAdd\sthe\nnew\s-argcount\soption\sto\sthe\s"function"\smethod\sin\sthe\sTCL\sinterface.\s(CVS\s5684)
+D 2008-09-09T12:31:34
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in d15a7ebfe5e057a72a49805ffb302dbb601c8329
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -103,7 +103,7 @@ F src/btree.c 6ea37de364f483496f60e47c996b429a9f313d54
 F src/btree.h 6371c5e599fab391a150c96afbc10062b276d107
 F src/btreeInt.h ab18c7b4980314e9e4b402e5dcde09f3c2545576
 F src/build.c 160c71acca8f643f436ed6c1ee2f684c88df4dfe
-F src/callback.c cfc8d4f95fd831e25532d0fee2af5306283f4835
+F src/callback.c 7a40fd44da3eb89e7f6eff30aa6f940c45d73a97
 F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c
 F src/date.c 5c092296c03d658e84884121a694150964d6861d
 F src/delete.c bae6684aa02e1f7cf6328023157c91d9cf94200b
@@ -155,7 +155,7 @@ F src/sqliteInt.h 4a43cd9dcb7d5a6664a981f08e64d555acbca1bc
 F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
 F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
 F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8
-F src/tclsqlite.c 7f5c49f4347c197e869fef86b35b2251ca45f7c2
+F src/tclsqlite.c a6a346f42322ae1df980228306da6c3cea4dd680
 F src/test1.c 349606445a5a938e9fa9b5e410413632c6c25f87
 F src/test2.c eaa77124786649eedf47d3c5e94d8070c0da228f
 F src/test3.c e85b7ce5c28c3ce7fbdbf7f98e1467b19786c62b
@@ -391,7 +391,7 @@ F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19
 F test/jrnlmode.test 1ab9729d6bbb6fb355cbb4bb41f1f0c271fc251a
 F test/lastinsert.test 474d519c68cb79d07ecae56a763aa7f322c72f51
 F test/laststmtchanges.test 18ead86c8a87ade949a1d5658f6dc4bb111d1b02
-F test/like.test 2a3ddbd5d91503f914eabae67a47c4196fe33a58
+F test/like.test fef924922828d5a2a5bff80b9bdd9ff57a1ca500
 F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
 F test/limit.test 2db7b3b34fb925b8e847d583d2eb67531d0ce67e
 F test/loadext.test 4972cb5a12ba70f23f827452b8265be08bb6d8cd
@@ -503,7 +503,7 @@ F test/substr.test 4be572ac017143e59b4058dc75c91a0d0dc6d4e0
 F test/sync.test ded6b39d8d8ca3c0c5518516c6371b3316d3e3a3
 F test/table.test 13b1c2e2fb4727b35ee1fb7641fc469214fd2455
 F test/tableapi.test 505031f15b18a750184d967d2c896cf88fcc969c
-F test/tclsqlite.test 9689ded2f8909362e869eb8bd8c2f5219f4f12af
+F test/tclsqlite.test b2074cf37a6f7b3fb0544a7bac7bc8ff3ac6ea77
 F test/tempdb.test b88ac8a19823cf771d742bf61eef93ef337c06b1
 F test/temptable.test 19b851b9e3e64d91e9867619b2a3f5fffee6e125
 F test/tester.tcl 12fd8394caeb71f7d961707da8668756389bc9d3
@@ -633,7 +633,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P 8b600ed083d48784df4b1da1320a01bebbf233d7
-R ffda790045fe743907465f52ace9412e
-U danielk1977
-Z 3f4db5a2e713c7718c372d8ef3c17aff
+P a6dee85b823355cb381163c93c8366aa4395ae6a
+R ef041795a1f812a73913c8f5ffd83ed9
+U drh
+Z ef224dd97bd8e2824d90a691c3098d84
index 03fed3fad1eab731ca16e728da47954f29286879..84670ba53a0428f15c47f32dd6976ee5c1d581d6 100644 (file)
@@ -1 +1 @@
-a6dee85b823355cb381163c93c8366aa4395ae6a
\ No newline at end of file
+5aa5b8044a14f59559c1839dc0799b0d2f990809
\ No newline at end of file
index e891f3321d5517c8750e4e1d4a207e504a6a7a4f..8e8cd1751cdb596afe9dc08e72ebc4c3051eeb13 100644 (file)
@@ -13,7 +13,7 @@
 ** This file contains functions used to access the internal hash tables
 ** of user defined functions and collation sequences.
 **
-** $Id: callback.c,v 1.30 2008/09/01 18:34:20 danielk1977 Exp $
+** $Id: callback.c,v 1.31 2008/09/09 12:31:34 drh Exp $
 */
 
 #include "sqliteInt.h"
@@ -341,7 +341,8 @@ FuncDef *sqlite3FindFunction(
   if( nArg<-1 ) nArg = -1;
   h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a);
 
-
+  /* First search for a match amongst the application-defined functions.
+  */
   p = functionSearch(&db->aFunc, h, zName, nName);
   while( p ){
     int score = matchQuality(p, nArg, enc);
@@ -352,9 +353,13 @@ FuncDef *sqlite3FindFunction(
     p = p->pNext;
   }
 
-  /* If the createFlag parameter is false and no match was found amongst
-  ** the custom functions stored in sqlite3.aFunc, try to find a built-in
-  ** function to use.
+  /* If no match is found, search the built-in functions.
+  **
+  ** Except, if createFlag is true, that means that we are trying to
+  ** install a new function.  Whatever FuncDef structure is returned will
+  ** have fields overwritten with new information appropriate for the
+  ** new function.  But the FuncDefs for built-in functions are read-only.
+  ** So we must not search for built-ins when creating a new function.
   */ 
   if( !createFlag && !pBest ){
     FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
@@ -369,11 +374,11 @@ FuncDef *sqlite3FindFunction(
     }
   }
 
-  /* If the createFlag parameter is true, and the seach did not reveal an
+  /* If the createFlag parameter is true and the search did not reveal an
   ** exact match for the name, number of arguments and encoding, then add a
   ** new entry to the hash table and return it.
   */
-  if( createFlag && bestScore<6 && 
+  if( createFlag && (bestScore<6 || pBest->nArg!=nArg) && 
       (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
     pBest->zName = (char *)&pBest[1];
     pBest->nArg = nArg;
index 083b31c2901220ec2b4b475ec5f3f79a607421ee..152a4446414f55dfda37b9ba8b87295322e76780 100644 (file)
@@ -12,7 +12,7 @@
 ** A TCL Interface to SQLite.  Append this file to sqlite3.c and
 ** compile the whole thing to build a TCL-enabled version of SQLite.
 **
-** $Id: tclsqlite.c,v 1.223 2008/09/03 01:08:01 drh Exp $
+** $Id: tclsqlite.c,v 1.224 2008/09/09 12:31:34 drh Exp $
 */
 #include "tcl.h"
 #include <errno.h>
@@ -1872,7 +1872,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
   }
 
   /*
-  **     $db function NAME SCRIPT
+  **     $db function NAME [-argcount N] SCRIPT
   **
   ** Create a new SQL function called NAME.  Whenever that function is
   ** called, invoke SCRIPT to evaluate the function.
@@ -1881,12 +1881,26 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
     SqlFunc *pFunc;
     Tcl_Obj *pScript;
     char *zName;
-    if( objc!=4 ){
-      Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT");
+    int nArg = -1;
+    if( objc==6 ){
+      const char *z = Tcl_GetString(objv[3]);
+      int n = strlen(z);
+      if( n>2 && strncmp(z, "-argcount",n)==0 ){
+        if( Tcl_GetIntFromObj(interp, objv[4], &nArg) ) return TCL_ERROR;
+        if( nArg<0 ){
+          Tcl_AppendResult(interp, "number of arguments must be non-negative",
+                           (char*)0);
+          return TCL_ERROR;
+        }
+      }
+      pScript = objv[5];
+    }else if( objc!=4 ){
+      Tcl_WrongNumArgs(interp, 2, objv, "NAME [-argcount N] SCRIPT");
       return TCL_ERROR;
+    }else{
+      pScript = objv[3];
     }
     zName = Tcl_GetStringFromObj(objv[2], 0);
-    pScript = objv[3];
     pFunc = findSqlFunc(pDb, zName);
     if( pFunc==0 ) return TCL_ERROR;
     if( pFunc->pScript ){
@@ -1895,7 +1909,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
     pFunc->pScript = pScript;
     Tcl_IncrRefCount(pScript);
     pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript);
-    rc = sqlite3_create_function(pDb->db, zName, -1, SQLITE_UTF8,
+    rc = sqlite3_create_function(pDb->db, zName, nArg, SQLITE_UTF8,
         pFunc, tclSqlFunc, 0, 0);
     if( rc!=SQLITE_OK ){
       rc = TCL_ERROR;
index 57f1086d91c406a81d46e30963f1b95b76d36bf0..38951cb03ddce069c88a2fa45c504237fd6f9559 100644 (file)
@@ -13,7 +13,7 @@
 # in particular the optimizations that occur to help those operators
 # run faster.
 #
-# $Id: like.test,v 1.9 2008/02/23 21:55:40 drh Exp $
+# $Id: like.test,v 1.10 2008/09/09 12:31:34 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -120,7 +120,7 @@ do_test like-2.3 {
   proc test_match {a b} {
     return [string match $a $b]
   }
-  db function match test_match
+  db function match -argcount 2 test_match
   execsql {
     SELECT x FROM t1 WHERE x MATCH '*abc*' ORDER BY 1;
   }
@@ -511,4 +511,44 @@ do_test like-7.1 {
   }
 } {a}
 
+# ticket #3345.
+#
+# Overloading the LIKE function with -1 for the number of arguments
+# will overload both the 2-argument and the 3-argument LIKE.
+#
+do_test like-8.1 {
+  db eval {
+    CREATE TABLE t8(x);
+    INSERT INTO t8 VALUES('abcdef');
+    INSERT INTO t8 VALUES('ghijkl');
+    INSERT INTO t8 VALUES('mnopqr');
+    SELECT 1, x FROM t8 WHERE x LIKE '%h%';
+    SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
+  }
+} {1 ghijkl 2 ghijkl}
+do_test like-8.2 {
+  proc newlike {args} {return 1} ;# Alternative LIKE is always return TRUE
+  db function like newlike       ;# Uses -1 for nArg in sqlite3_create_function
+  db cache flush
+  db eval {
+    SELECT 1, x FROM t8 WHERE x LIKE '%h%';
+    SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
+  }
+} {1 ghijkl 2 ghijkl}
+do_test like-8.3 {
+  db function like -argcount 2 newlike
+  db eval {
+    SELECT 1, x FROM t8 WHERE x LIKE '%h%';
+    SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
+  }
+} {1 abcdef 1 ghijkl 1 mnopqr 2 ghijkl}
+do_test like-8.4 {
+  db function like -argcount 3 newlike
+  db eval {
+    SELECT 1, x FROM t8 WHERE x LIKE '%h%';
+    SELECT 2, x FROM t8 WHERE x LIKE '%h%' ESCAPE 'x';
+  }
+} {1 abcdef 1 ghijkl 1 mnopqr 2 abcdef 2 ghijkl 2 mnopqr}
+
+
 finish_test
index 741a07eac57d5661af61f8b25d03329d5e5a086e..c95b7acb034e7d60dc17415935af88a1a4acc2bd 100644 (file)
@@ -15,7 +15,7 @@
 # interface is pretty well tested.  This file contains some addition
 # tests for fringe issues that the main test suite does not cover.
 #
-# $Id: tclsqlite.test,v 1.68 2008/09/03 00:43:15 drh Exp $
+# $Id: tclsqlite.test,v 1.69 2008/09/09 12:31:34 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -118,7 +118,7 @@ do_test tcl-1.14 {
 do_test tcl-1.15 {
   set v [catch {db function} msg]
   lappend v $msg
-} {1 {wrong # args: should be "db function NAME SCRIPT"}}
+} {1 {wrong # args: should be "db function NAME [-argcount N] SCRIPT"}}
 do_test tcl-1.16 {
   set v [catch {db last_insert_rowid xyz} msg]
   lappend v $msg