aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/callback.c19
-rw-r--r--src/tclsqlite.c26
2 files changed, 32 insertions, 13 deletions
diff --git a/src/callback.c b/src/callback.c
index e891f3321..8e8cd1751 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -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;
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index 083b31c29..152a44464 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -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;