1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Calling sqlite3_create_function with nArg==(-1) does not override prior

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
This commit is contained in:
drh
2008-09-09 12:31:33 +00:00
parent 4d60af9b0b
commit e3602be8fd
6 changed files with 87 additions and 28 deletions

View File

@ -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

View File

@ -1 +1 @@
a6dee85b823355cb381163c93c8366aa4395ae6a
5aa5b8044a14f59559c1839dc0799b0d2f990809

View 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;

View 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;
}
zName = Tcl_GetStringFromObj(objv[2], 0);
}
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);
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;

View 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

View 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