Improvements to the application-defined function mechanism so that it is

more compact and runs faster, especially when the application defines
thousands of new SQL functions.

FossilOrigin-Name: 3201fbcc5105d23132e6b8b7ac825e66af4f8a39
This commit is contained in:
drh 2016-02-15 00:34:16 +00:00
parent e75a9eb9bb
commit 80738d9c3e
15 changed files with 189 additions and 182 deletions

View File

@ -1,5 +1,5 @@
C Provide\sSqlite3_SafeInit()\sand\sSqlite3_SafeUnload()\sentry\spoints\son\sthe\sTCL\ninterface,\sbut\shave\sthe\salways\sreturn\sTCL_ERROR,\sbecause\sthe\snon-standard\s\nTCL\sbuilds\son\sMacs\srequire\sthis. C Improvements\sto\sthe\sapplication-defined\sfunction\smechanism\sso\sthat\sit\sis\nmore\scompact\sand\sruns\sfaster,\sespecially\swhen\sthe\sapplication\sdefines\nthousands\sof\snew\sSQL\sfunctions.
D 2016-02-13T18:54:10.051 D 2016-02-15T00:34:16.170
F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347 F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347
@ -284,9 +284,9 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 1fbb01c26c64528088f1df8015992fefda387889 F src/alter.c 7603afbd61f55e7c644b8de4a42f33e58c0b7eaa
F src/analyze.c fbf0e80d83cc893734e872f932f249a056b86e11 F src/analyze.c b148441c7d35b5514ec1a66f9df97be8fa4c68a1
F src/attach.c c16c2648a577fa3def2adfa48c28901376389bc5 F src/attach.c 07aa6e77c3906d46d4c36d7c81641dedd6adac91
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc
F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf
@ -295,17 +295,17 @@ F src/btree.c 4c8caaeed7878aafdb607c3d2bcbc365bb0d19a1
F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e F src/btree.h 368ceeb4bd9312dc8df2ffd64b4b7dbcf4db5f8e
F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5
F src/build.c 54866fbafa09d494269bdefc79995eb7207003a6 F src/build.c 54866fbafa09d494269bdefc79995eb7207003a6
F src/callback.c ed6c2a4a712eb7287ff64e20e3c23265dfb8a7ce F src/callback.c 0643b8fb06c95a8977beb201b268210d4b131a22
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198
F src/date.c ca17321bc17cca8f40e0843edea4fafff974998e F src/date.c 0b73e681c11fca867fec554750c07fe0d4e417c1
F src/dbstat.c b2ec6793eef97aebb4d171d490a4ffdfa9f2475c F src/dbstat.c b2ec6793eef97aebb4d171d490a4ffdfa9f2475c
F src/delete.c 48802aa3ee6339f576d074336d3ae1b5f40e240f F src/delete.c 48802aa3ee6339f576d074336d3ae1b5f40e240f
F src/expr.c fbf0706199aea23c54efe36b6932d8307c4eb872 F src/expr.c 9adb58153f6e943b703d43e9a1f67f77b5a75721
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 08edad1fce30f761f14b3997e89bad58f9f7f4e0 F src/fkey.c 08edad1fce30f761f14b3997e89bad58f9f7f4e0
F src/func.c 86e55fee35b9577e485f47d9dd5c1d34cd513288 F src/func.c 552d300265aed09eea21f68ac742a440550c0062
F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260 F src/global.c ded7b97efd16efda5062b65e857198e46c40e652
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
@ -313,7 +313,7 @@ F src/insert.c 9ca97272e9f74ed0efddf3b4350ee12740cebbef
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c b1b0880fc474abfab89e737b0ecfde0bd7a60902 F src/legacy.c b1b0880fc474abfab89e737b0ecfde0bd7a60902
F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b
F src/main.c b67a45397b93b7ba8fbd6bfcb03423d245baed05 F src/main.c 17cfc8ba39fd86bc8201213140db53a65ff3cf2a
F src/malloc.c 337e9808b5231855fe28857950f4f60ae42c417f F src/malloc.c 337e9808b5231855fe28857950f4f60ae42c417f
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
@ -346,14 +346,14 @@ F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
F src/prepare.c c12b786713df3e8270c0f85f988c5359d8b4d87c F src/prepare.c c12b786713df3e8270c0f85f988c5359d8b4d87c
F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26 F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 9f7ce3a3c087afb7597b7c916c99126ff3f12f0c F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20
F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e
F src/select.c ff80004a9a6ece891a8d9327a88e7b6e2588ee6d F src/select.c ff80004a9a6ece891a8d9327a88e7b6e2588ee6d
F src/shell.c 0367440658104bf2ce8d8a9a5a713a4b11c9acbe F src/shell.c 0367440658104bf2ce8d8a9a5a713a4b11c9acbe
F src/sqlite.h.in f80c6ebd85588fc514bfedf3ecb00cec269cb410 F src/sqlite.h.in f80c6ebd85588fc514bfedf3ecb00cec269cb410
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d
F src/sqliteInt.h 04ca5b3cdb3bcf87ba6300d5d36b51498f65f28c F src/sqliteInt.h ddd4a48f3ac2a423f003027e73bd8422bfa4d991
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
@ -411,7 +411,7 @@ F src/treeview.c dc39ccf04e9331237388b9cb73289c9d87ea050b
F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280
F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca
F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18 F src/utf.c 10cc2519e82e3369344d0969ad4b1a333dc86d18
F src/util.c 49ce0a65306c1c51d61cb5bc214c71cb62452de6 F src/util.c 8073bbdab9cc7209f6741bd44264ede606cbadc6
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
F src/vdbe.c c193299e595a13eba247738e22fce25c49346a6c F src/vdbe.c c193299e595a13eba247738e22fce25c49346a6c
F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512 F src/vdbe.h c743791f723049db94f009e3e30958952bc2d512
@ -419,7 +419,7 @@ F src/vdbeInt.h 4b69d5451bcadd473e745af53ef1e8abfdce0a79
F src/vdbeapi.c 9324f6baee1a1b2284c6543e98f916888a81e459 F src/vdbeapi.c 9324f6baee1a1b2284c6543e98f916888a81e459
F src/vdbeaux.c deae5d3bd45da0e57c7d9e1d7436333d142dc3bb F src/vdbeaux.c deae5d3bd45da0e57c7d9e1d7436333d142dc3bb
F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db F src/vdbeblob.c 3b570b730109e8f653d9d2081649f6e7015113db
F src/vdbemem.c 68fcfac37dc6601d98c32cc5adee4d39f2c1b7b4 F src/vdbemem.c e0dbb7bb9c2ec566c53c6575b4f51b3fcd426811
F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174 F src/vdbesort.c ef3c6d1f1a7d44cf67bb2bee59ea3d1fe5bad174
F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484 F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484
F src/vtab.c bef51b4f693d82b4b0184457faa8625654534091 F src/vtab.c bef51b4f693d82b4b0184457faa8625654534091
@ -1427,7 +1427,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f F tool/warnings.sh ef6ebc6fd8d2dc35db3b622015c16a023d4fef4f
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P a049fbbde5da2e43d41aa8c2b41f9eb21507ac76 P 37ec3015ec95035d31e3672f520908a0d36c9d67
R 0ed7109e4c77d1cb323166614bc90c67 R 8daa9c28aeb9b7a90a9f45db47e6f0fa
T *branch * many-app-functions
T *sym-many-app-functions *
T -sym-trunk *
U drh U drh
Z 0875f4eabfb763252145d2214f48fc91 Z 4df4dc22cfe3910711fb118d648968ac

View File

@ -1 +1 @@
37ec3015ec95035d31e3672f520908a0d36c9d67 3201fbcc5105d23132e6b8b7ac825e66af4f8a39

View File

@ -229,7 +229,7 @@ static void renameTriggerFunc(
** Register built-in functions used to help implement ALTER TABLE ** Register built-in functions used to help implement ALTER TABLE
*/ */
void sqlite3AlterFunctions(void){ void sqlite3AlterFunctions(void){
static SQLITE_WSD FuncDef aAlterTableFuncs[] = { static FuncDef aAlterTableFuncs[] = {
FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc), FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc),
#ifndef SQLITE_OMIT_TRIGGER #ifndef SQLITE_OMIT_TRIGGER
FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc), FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc),
@ -238,13 +238,7 @@ void sqlite3AlterFunctions(void){
FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc), FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc),
#endif #endif
}; };
int i; sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAlterTableFuncs);
for(i=0; i<ArraySize(aAlterTableFuncs); i++){
sqlite3FuncDefInsert(pHash, &aFunc[i]);
}
} }
/* /*

View File

@ -481,8 +481,7 @@ static const FuncDef statInitFuncdef = {
statInit, /* xSFunc */ statInit, /* xSFunc */
0, /* xFinalize */ 0, /* xFinalize */
"stat_init", /* zName */ "stat_init", /* zName */
0, /* pHash */ {0}
0 /* pDestructor */
}; };
#ifdef SQLITE_ENABLE_STAT4 #ifdef SQLITE_ENABLE_STAT4
@ -781,8 +780,7 @@ static const FuncDef statPushFuncdef = {
statPush, /* xSFunc */ statPush, /* xSFunc */
0, /* xFinalize */ 0, /* xFinalize */
"stat_push", /* zName */ "stat_push", /* zName */
0, /* pHash */ {0}
0 /* pDestructor */
}; };
#define STAT_GET_STAT1 0 /* "stat" column of stat1 table */ #define STAT_GET_STAT1 0 /* "stat" column of stat1 table */
@ -927,8 +925,7 @@ static const FuncDef statGetFuncdef = {
statGet, /* xSFunc */ statGet, /* xSFunc */
0, /* xFinalize */ 0, /* xFinalize */
"stat_get", /* zName */ "stat_get", /* zName */
0, /* pHash */ {0}
0 /* pDestructor */
}; };
static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){ static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){

View File

@ -392,8 +392,7 @@ void sqlite3Detach(Parse *pParse, Expr *pDbname){
detachFunc, /* xSFunc */ detachFunc, /* xSFunc */
0, /* xFinalize */ 0, /* xFinalize */
"sqlite_detach", /* zName */ "sqlite_detach", /* zName */
0, /* pHash */ {0}
0 /* pDestructor */
}; };
codeAttach(pParse, SQLITE_DETACH, &detach_func, pDbname, 0, 0, pDbname); codeAttach(pParse, SQLITE_DETACH, &detach_func, pDbname, 0, 0, pDbname);
} }
@ -412,8 +411,7 @@ void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
attachFunc, /* xSFunc */ attachFunc, /* xSFunc */
0, /* xFinalize */ 0, /* xFinalize */
"sqlite_attach", /* zName */ "sqlite_attach", /* zName */
0, /* pHash */ {0}
0 /* pDestructor */
}; };
codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey); codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey);
} }

View File

@ -284,14 +284,12 @@ static int matchQuality(
** a pointer to the matching FuncDef if found, or 0 if there is no match. ** a pointer to the matching FuncDef if found, or 0 if there is no match.
*/ */
static FuncDef *functionSearch( static FuncDef *functionSearch(
FuncDefHash *pHash, /* Hash table to search */
int h, /* Hash of the name */ int h, /* Hash of the name */
const char *zFunc, /* Name of function */ const char *zFunc /* Name of function */
int nFunc /* Number of bytes in zFunc */
){ ){
FuncDef *p; FuncDef *p;
for(p=pHash->a[h]; p; p=p->pHash){ for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){
if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 && p->zName[nFunc]==0 ){ if( sqlite3StrICmp(p->zName, zFunc)==0 ){
return p; return p;
} }
} }
@ -301,23 +299,26 @@ static FuncDef *functionSearch(
/* /*
** Insert a new FuncDef into a FuncDefHash hash table. ** Insert a new FuncDef into a FuncDefHash hash table.
*/ */
void sqlite3FuncDefInsert( void sqlite3InsertBuiltinFuncs(
FuncDefHash *pHash, /* The hash table into which to insert */ FuncDef *aDef, /* List of global functions to be inserted */
FuncDef *pDef /* The function definition to insert */ int nDef /* Length of the apDef[] list */
){ ){
FuncDef *pOther; int i;
int nName = sqlite3Strlen30(pDef->zName); for(i=0; i<nDef; i++){
u8 c1 = (u8)pDef->zName[0]; FuncDef *pOther;
int h = (sqlite3UpperToLower[c1] + nName) % ArraySize(pHash->a); const char *zName = aDef[i].zName;
pOther = functionSearch(pHash, h, pDef->zName, nName); int nName = sqlite3Strlen30(zName);
if( pOther ){ int h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ;
assert( pOther!=pDef && pOther->pNext!=pDef ); pOther = functionSearch(h, zName);
pDef->pNext = pOther->pNext; if( pOther ){
pOther->pNext = pDef; assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] );
}else{ aDef[i].pNext = pOther->pNext;
pDef->pNext = 0; pOther->pNext = &aDef[i];
pDef->pHash = pHash->a[h]; }else{
pHash->a[h] = pDef; aDef[i].pNext = 0;
aDef[i].u.pHash = sqlite3BuiltinFunctions.a[h];
sqlite3BuiltinFunctions.a[h] = &aDef[i];
}
} }
} }
@ -344,8 +345,7 @@ void sqlite3FuncDefInsert(
*/ */
FuncDef *sqlite3FindFunction( FuncDef *sqlite3FindFunction(
sqlite3 *db, /* An open database */ sqlite3 *db, /* An open database */
const char *zName, /* Name of the function. Not null-terminated */ const char *zName, /* Name of the function. zero-terminated */
int nName, /* Number of characters in the name */
int nArg, /* Number of arguments. -1 means any number */ int nArg, /* Number of arguments. -1 means any number */
u8 enc, /* Preferred text encoding */ u8 enc, /* Preferred text encoding */
u8 createFlag /* Create new entry if true and does not otherwise exist */ u8 createFlag /* Create new entry if true and does not otherwise exist */
@ -354,14 +354,15 @@ FuncDef *sqlite3FindFunction(
FuncDef *pBest = 0; /* Best match found so far */ FuncDef *pBest = 0; /* Best match found so far */
int bestScore = 0; /* Score of best match */ int bestScore = 0; /* Score of best match */
int h; /* Hash value */ int h; /* Hash value */
int nName; /* Length of the name */
assert( nArg>=(-2) ); assert( nArg>=(-2) );
assert( nArg>=(-1) || createFlag==0 ); assert( nArg>=(-1) || createFlag==0 );
h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a); nName = sqlite3Strlen30(zName);
/* First search for a match amongst the application-defined functions. /* First search for a match amongst the application-defined functions.
*/ */
p = functionSearch(&db->aFunc, h, zName, nName); p = (FuncDef*)sqlite3HashFind(&db->aFunc, zName);
while( p ){ while( p ){
int score = matchQuality(p, nArg, enc); int score = matchQuality(p, nArg, enc);
if( score>bestScore ){ if( score>bestScore ){
@ -384,9 +385,9 @@ FuncDef *sqlite3FindFunction(
** So we must not search for built-ins when creating a new function. ** So we must not search for built-ins when creating a new function.
*/ */
if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){ if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){
FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
bestScore = 0; bestScore = 0;
p = functionSearch(pHash, h, zName, nName); h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ;
p = functionSearch(h, zName);
while( p ){ while( p ){
int score = matchQuality(p, nArg, enc); int score = matchQuality(p, nArg, enc);
if( score>bestScore ){ if( score>bestScore ){
@ -403,12 +404,19 @@ FuncDef *sqlite3FindFunction(
*/ */
if( createFlag && bestScore<FUNC_PERFECT_MATCH && if( createFlag && bestScore<FUNC_PERFECT_MATCH &&
(pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){ (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
FuncDef *pOther;
pBest->zName = (char *)&pBest[1]; pBest->zName = (char *)&pBest[1];
pBest->nArg = (u16)nArg; pBest->nArg = (u16)nArg;
pBest->funcFlags = enc; pBest->funcFlags = enc;
memcpy(pBest->zName, zName, nName); memcpy(pBest->zName, zName, nName+1);
pBest->zName[nName] = 0; pOther = (FuncDef*)sqlite3HashInsert(&db->aFunc, pBest->zName, pBest);
sqlite3FuncDefInsert(&db->aFunc, pBest); if( pOther==pBest ){
sqlite3DbFree(db, pBest);
sqlite3OomFault(db);
return 0;
}else{
pBest->pNext = pOther;
}
} }
if( pBest && (pBest->xSFunc || createFlag) ){ if( pBest && (pBest->xSFunc || createFlag) ){

View File

@ -1136,7 +1136,7 @@ static void currentTimeFunc(
** external linkage. ** external linkage.
*/ */
void sqlite3RegisterDateTimeFunctions(void){ void sqlite3RegisterDateTimeFunctions(void){
static SQLITE_WSD FuncDef aDateTimeFuncs[] = { static FuncDef aDateTimeFuncs[] = {
#ifndef SQLITE_OMIT_DATETIME_FUNCS #ifndef SQLITE_OMIT_DATETIME_FUNCS
DFUNCTION(julianday, -1, 0, 0, juliandayFunc ), DFUNCTION(julianday, -1, 0, 0, juliandayFunc ),
DFUNCTION(date, -1, 0, 0, dateFunc ), DFUNCTION(date, -1, 0, 0, dateFunc ),
@ -1152,11 +1152,5 @@ void sqlite3RegisterDateTimeFunctions(void){
STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc), STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
#endif #endif
}; };
int i; sqlite3InsertBuiltinFuncs(aDateTimeFuncs, ArraySize(aDateTimeFuncs));
FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs);
for(i=0; i<ArraySize(aDateTimeFuncs); i++){
sqlite3FuncDefInsert(pHash, &aFunc[i]);
}
} }

View File

@ -2888,7 +2888,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
ExprList *pFarg; /* List of function arguments */ ExprList *pFarg; /* List of function arguments */
int nFarg; /* Number of function arguments */ int nFarg; /* Number of function arguments */
FuncDef *pDef; /* The function definition object */ FuncDef *pDef; /* The function definition object */
int nId; /* Length of the function name in bytes */
const char *zId; /* The function name */ const char *zId; /* The function name */
u32 constMask = 0; /* Mask of function arguments that are constant */ u32 constMask = 0; /* Mask of function arguments that are constant */
int i; /* Loop counter */ int i; /* Loop counter */
@ -2904,10 +2903,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
nFarg = pFarg ? pFarg->nExpr : 0; nFarg = pFarg ? pFarg->nExpr : 0;
assert( !ExprHasProperty(pExpr, EP_IntValue) ); assert( !ExprHasProperty(pExpr, EP_IntValue) );
zId = pExpr->u.zToken; zId = pExpr->u.zToken;
nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(db, zId, nFarg, enc, 0);
pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0);
if( pDef==0 || pDef->xFinalize!=0 ){ if( pDef==0 || pDef->xFinalize!=0 ){
sqlite3ErrorMsg(pParse, "unknown function: %.*s()", nId, zId); sqlite3ErrorMsg(pParse, "unknown function: %s()", zId);
break; break;
} }
@ -4132,7 +4130,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
pItem->iMem = ++pParse->nMem; pItem->iMem = ++pParse->nMem;
assert( !ExprHasProperty(pExpr, EP_IntValue) ); assert( !ExprHasProperty(pExpr, EP_IntValue) );
pItem->pFunc = sqlite3FindFunction(pParse->db, pItem->pFunc = sqlite3FindFunction(pParse->db,
pExpr->u.zToken, sqlite3Strlen30(pExpr->u.zToken), pExpr->u.zToken,
pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0); pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0);
if( pExpr->flags & EP_Distinct ){ if( pExpr->flags & EP_Distinct ){
pItem->iDistinct = pParse->nTab++; pItem->iDistinct = pParse->nTab++;

View File

@ -1611,7 +1611,7 @@ static void groupConcatFinalize(sqlite3_context *context){
** of the built-in functions above are part of the global function set. ** of the built-in functions above are part of the global function set.
** This routine only deals with those that are not global. ** This routine only deals with those that are not global.
*/ */
void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){
int rc = sqlite3_overload_function(db, "MATCH", 2); int rc = sqlite3_overload_function(db, "MATCH", 2);
assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
if( rc==SQLITE_NOMEM ){ if( rc==SQLITE_NOMEM ){
@ -1624,8 +1624,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
*/ */
static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){ static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){
FuncDef *pDef; FuncDef *pDef;
pDef = sqlite3FindFunction(db, zName, sqlite3Strlen30(zName), pDef = sqlite3FindFunction(db, zName, 2, SQLITE_UTF8, 0);
2, SQLITE_UTF8, 0);
if( ALWAYS(pDef) ){ if( ALWAYS(pDef) ){
pDef->funcFlags |= flagVal; pDef->funcFlags |= flagVal;
} }
@ -1673,9 +1672,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
return 0; return 0;
} }
assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
pDef = sqlite3FindFunction(db, pExpr->u.zToken, pDef = sqlite3FindFunction(db, pExpr->u.zToken, 2, SQLITE_UTF8, 0);
sqlite3Strlen30(pExpr->u.zToken),
2, SQLITE_UTF8, 0);
if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){ if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){
return 0; return 0;
} }
@ -1699,7 +1696,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
** **
** After this routine runs ** After this routine runs
*/ */
void sqlite3RegisterGlobalFunctions(void){ void sqlite3RegisterBuiltinFunctions(void){
/* /*
** The following array holds FuncDef structures for all of the functions ** The following array holds FuncDef structures for all of the functions
** defined in this file. ** defined in this file.
@ -1707,8 +1704,27 @@ void sqlite3RegisterGlobalFunctions(void){
** The array cannot be constant since changes are made to the ** The array cannot be constant since changes are made to the
** FuncDef.pHash elements at start-time. The elements of this array ** FuncDef.pHash elements at start-time. The elements of this array
** are read-only after initialization is complete. ** are read-only after initialization is complete.
**
** For peak efficiency, put the most frequently used function last.
*/ */
static SQLITE_WSD FuncDef aBuiltinFunc[] = { static FuncDef aBuiltinFunc[] = {
#ifdef SQLITE_SOUNDEX
FUNCTION(soundex, 1, 0, 0, soundexFunc ),
#endif
#ifndef SQLITE_OMIT_LOAD_EXTENSION
VFUNCTION(load_extension, 1, 0, 0, loadExt ),
VFUNCTION(load_extension, 2, 0, 0, loadExt ),
#endif
#if SQLITE_USER_AUTHENTICATION
FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ),
#endif
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION(ltrim, 1, 1, 0, trimFunc ), FUNCTION(ltrim, 1, 1, 0, trimFunc ),
FUNCTION(ltrim, 2, 1, 0, trimFunc ), FUNCTION(ltrim, 2, 1, 0, trimFunc ),
FUNCTION(rtrim, 1, 2, 0, trimFunc ), FUNCTION(rtrim, 1, 2, 0, trimFunc ),
@ -1726,8 +1742,6 @@ void sqlite3RegisterGlobalFunctions(void){
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
FUNCTION(instr, 2, 0, 0, instrFunc ), FUNCTION(instr, 2, 0, 0, instrFunc ),
FUNCTION(substr, 2, 0, 0, substrFunc ),
FUNCTION(substr, 3, 0, 0, substrFunc ),
FUNCTION(printf, -1, 0, 0, printfFunc ), FUNCTION(printf, -1, 0, 0, printfFunc ),
FUNCTION(unicode, 1, 0, 0, unicodeFunc ), FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
FUNCTION(char, -1, 0, 0, charFunc ), FUNCTION(char, -1, 0, 0, charFunc ),
@ -1738,40 +1752,22 @@ void sqlite3RegisterGlobalFunctions(void){
#endif #endif
FUNCTION(upper, 1, 0, 0, upperFunc ), FUNCTION(upper, 1, 0, 0, upperFunc ),
FUNCTION(lower, 1, 0, 0, lowerFunc ), FUNCTION(lower, 1, 0, 0, lowerFunc ),
FUNCTION(coalesce, 1, 0, 0, 0 ),
FUNCTION(coalesce, 0, 0, 0, 0 ),
FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
FUNCTION(hex, 1, 0, 0, hexFunc ), FUNCTION(hex, 1, 0, 0, hexFunc ),
FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE), FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
VFUNCTION(random, 0, 0, 0, randomFunc ), VFUNCTION(random, 0, 0, 0, randomFunc ),
VFUNCTION(randomblob, 1, 0, 0, randomBlob ), VFUNCTION(randomblob, 1, 0, 0, randomBlob ),
FUNCTION(nullif, 2, 0, 1, nullifFunc ), FUNCTION(nullif, 2, 0, 1, nullifFunc ),
DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ), DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ), FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ),
#if SQLITE_USER_AUTHENTICATION
FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ),
#endif
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
FUNCTION(quote, 1, 0, 0, quoteFunc ), FUNCTION(quote, 1, 0, 0, quoteFunc ),
VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid), VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
VFUNCTION(changes, 0, 0, 0, changes ), VFUNCTION(changes, 0, 0, 0, changes ),
VFUNCTION(total_changes, 0, 0, 0, total_changes ), VFUNCTION(total_changes, 0, 0, 0, total_changes ),
FUNCTION(replace, 3, 0, 0, replaceFunc ), FUNCTION(replace, 3, 0, 0, replaceFunc ),
FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ), FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
#ifdef SQLITE_SOUNDEX FUNCTION(substr, 2, 0, 0, substrFunc ),
FUNCTION(soundex, 1, 0, 0, soundexFunc ), FUNCTION(substr, 3, 0, 0, substrFunc ),
#endif
#ifndef SQLITE_OMIT_LOAD_EXTENSION
VFUNCTION(load_extension, 1, 0, 0, loadExt ),
VFUNCTION(load_extension, 2, 0, 0, loadExt ),
#endif
AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ), AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ), AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ), AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
@ -1789,20 +1785,32 @@ void sqlite3RegisterGlobalFunctions(void){
LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE), LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE), LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
#endif #endif
FUNCTION(coalesce, 1, 0, 0, 0 ),
FUNCTION(coalesce, 0, 0, 0, 0 ),
FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
}; };
int i;
FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aBuiltinFunc);
for(i=0; i<ArraySize(aBuiltinFunc); i++){
sqlite3FuncDefInsert(pHash, &aFunc[i]);
}
sqlite3RegisterDateTimeFunctions();
#ifndef SQLITE_OMIT_ALTERTABLE #ifndef SQLITE_OMIT_ALTERTABLE
sqlite3AlterFunctions(); sqlite3AlterFunctions();
#endif #endif
#if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4) #if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4)
sqlite3AnalyzeFunctions(); sqlite3AnalyzeFunctions();
#endif
sqlite3RegisterDateTimeFunctions();
sqlite3InsertBuiltinFuncs(aBuiltinFunc, ArraySize(aBuiltinFunc));
#if 0 /* Enable to print out how the built-in functions are hashed */
{
int i;
FuncDef *p;
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
printf("FUNC-HASH %02d:", i);
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash){
int n = sqlite3Strlen30(p->zName);
int h = p->zName[0] + n;
printf(" %s(%d)", p->zName, h);
}
printf("\n");
}
}
#endif #endif
} }

View File

@ -219,7 +219,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
** database connections. After initialization, this table is ** database connections. After initialization, this table is
** read-only. ** read-only.
*/ */
SQLITE_WSD FuncDefHash sqlite3GlobalFunctions; FuncDefHash sqlite3BuiltinFunctions;
/* /*
** Constant tokens for values 0 and 1. ** Constant tokens for values 0 and 1.

View File

@ -218,7 +218,6 @@ int sqlite3_initialize(void){
*/ */
sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex); sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex);
if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){ if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){
FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
sqlite3GlobalConfig.inProgress = 1; sqlite3GlobalConfig.inProgress = 1;
#ifdef SQLITE_ENABLE_SQLLOG #ifdef SQLITE_ENABLE_SQLLOG
{ {
@ -226,8 +225,8 @@ int sqlite3_initialize(void){
sqlite3_init_sqllog(); sqlite3_init_sqllog();
} }
#endif #endif
memset(pHash, 0, sizeof(sqlite3GlobalFunctions)); memset(&sqlite3BuiltinFunctions, 0, sizeof(sqlite3BuiltinFunctions));
sqlite3RegisterGlobalFunctions(); sqlite3RegisterBuiltinFunctions();
if( sqlite3GlobalConfig.isPCacheInit==0 ){ if( sqlite3GlobalConfig.isPCacheInit==0 ){
rc = sqlite3PcacheInitialize(); rc = sqlite3PcacheInitialize();
} }
@ -958,7 +957,7 @@ void sqlite3CloseSavepoints(sqlite3 *db){
** with SQLITE_ANY as the encoding. ** with SQLITE_ANY as the encoding.
*/ */
static void functionDestroy(sqlite3 *db, FuncDef *p){ static void functionDestroy(sqlite3 *db, FuncDef *p){
FuncDestructor *pDestructor = p->pDestructor; FuncDestructor *pDestructor = p->u.pDestructor;
if( pDestructor ){ if( pDestructor ){
pDestructor->nRef--; pDestructor->nRef--;
if( pDestructor->nRef==0 ){ if( pDestructor->nRef==0 ){
@ -1140,18 +1139,17 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
*/ */
sqlite3ConnectionClosed(db); sqlite3ConnectionClosed(db);
for(j=0; j<ArraySize(db->aFunc.a); j++){ for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
FuncDef *pNext, *pHash, *p; FuncDef *pNext, *p;
for(p=db->aFunc.a[j]; p; p=pHash){ p = sqliteHashData(i);
pHash = p->pHash; do{
while( p ){ functionDestroy(db, p);
functionDestroy(db, p); pNext = p->pNext;
pNext = p->pNext; sqlite3DbFree(db, p);
sqlite3DbFree(db, p); p = pNext;
p = pNext; }while( p );
}
}
} }
sqlite3HashClear(&db->aFunc);
for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){ for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){
CollSeq *pColl = (CollSeq *)sqliteHashData(i); CollSeq *pColl = (CollSeq *)sqliteHashData(i);
/* Invoke any destructors registered for collation sequence user data. */ /* Invoke any destructors registered for collation sequence user data. */
@ -1630,7 +1628,7 @@ int sqlite3CreateFunc(
** is being overridden/deleted but there are no active VMs, allow the ** is being overridden/deleted but there are no active VMs, allow the
** operation to continue but invalidate all precompiled statements. ** operation to continue but invalidate all precompiled statements.
*/ */
p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0); p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 0);
if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==enc && p->nArg==nArg ){ if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==enc && p->nArg==nArg ){
if( db->nVdbeActive ){ if( db->nVdbeActive ){
sqlite3ErrorWithMsg(db, SQLITE_BUSY, sqlite3ErrorWithMsg(db, SQLITE_BUSY,
@ -1642,7 +1640,7 @@ int sqlite3CreateFunc(
} }
} }
p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 1); p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1);
assert(p || db->mallocFailed); assert(p || db->mallocFailed);
if( !p ){ if( !p ){
return SQLITE_NOMEM; return SQLITE_NOMEM;
@ -1655,7 +1653,7 @@ int sqlite3CreateFunc(
if( pDestructor ){ if( pDestructor ){
pDestructor->nRef++; pDestructor->nRef++;
} }
p->pDestructor = pDestructor; p->u.pDestructor = pDestructor;
p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags; p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags;
testcase( p->funcFlags & SQLITE_DETERMINISTIC ); testcase( p->funcFlags & SQLITE_DETERMINISTIC );
p->xSFunc = xSFunc ? xSFunc : xStep; p->xSFunc = xSFunc ? xSFunc : xStep;
@ -1770,7 +1768,6 @@ int sqlite3_overload_function(
const char *zName, const char *zName,
int nArg int nArg
){ ){
int nName = sqlite3Strlen30(zName);
int rc = SQLITE_OK; int rc = SQLITE_OK;
#ifdef SQLITE_ENABLE_API_ARMOR #ifdef SQLITE_ENABLE_API_ARMOR
@ -1779,7 +1776,7 @@ int sqlite3_overload_function(
} }
#endif #endif
sqlite3_mutex_enter(db->mutex); sqlite3_mutex_enter(db->mutex);
if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){ if( sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)==0 ){
rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8,
0, sqlite3InvalidFunction, 0, 0, 0); 0, sqlite3InvalidFunction, 0, 0, 0);
} }
@ -2361,8 +2358,8 @@ static const int aHardLimit[] = {
#if SQLITE_MAX_VDBE_OP<40 #if SQLITE_MAX_VDBE_OP<40
# error SQLITE_MAX_VDBE_OP must be at least 40 # error SQLITE_MAX_VDBE_OP must be at least 40
#endif #endif
#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>1000 #if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>127
# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 1000 # error SQLITE_MAX_FUNCTION_ARG must be between 0 and 127
#endif #endif
#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>125 #if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>125
# error SQLITE_MAX_ATTACHED must be between 0 and 125 # error SQLITE_MAX_ATTACHED must be between 0 and 125
@ -2886,7 +2883,7 @@ static int openDatabase(
** is accessed. ** is accessed.
*/ */
sqlite3Error(db, SQLITE_OK); sqlite3Error(db, SQLITE_OK);
sqlite3RegisterBuiltinFunctions(db); sqlite3RegisterPerConnectionBuiltinFunctions(db);
/* Load automatic extensions - extensions that have been registered /* Load automatic extensions - extensions that have been registered
** using the sqlite3_automatic_extension() API. ** using the sqlite3_automatic_extension() API.

View File

@ -656,9 +656,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
notValid(pParse, pNC, "functions", NC_PartIdx); notValid(pParse, pNC, "functions", NC_PartIdx);
zId = pExpr->u.zToken; zId = pExpr->u.zToken;
nId = sqlite3Strlen30(zId); nId = sqlite3Strlen30(zId);
pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
if( pDef==0 ){ if( pDef==0 ){
pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0);
if( pDef==0 ){ if( pDef==0 ){
no_such_func = 1; no_such_func = 1;
}else{ }else{

View File

@ -1109,13 +1109,15 @@ struct LookasideSlot {
}; };
/* /*
** A hash table for function definitions. ** A hash table for built-in function definitions. (Application-defined
** functions use a regular table table from hash.h.)
** **
** Hash each FuncDef structure into one of the FuncDefHash.a[] slots. ** Hash each FuncDef structure into one of the FuncDefHash.a[] slots.
** Collisions are on the FuncDef.pHash chain. ** Collisions are on the FuncDef.u.pHash chain.
*/ */
#define SQLITE_FUNC_HASH_SZ 23
struct FuncDefHash { struct FuncDefHash {
FuncDef *a[23]; /* Hash table for functions */ FuncDef *a[SQLITE_FUNC_HASH_SZ]; /* Hash table for functions */
}; };
#ifdef SQLITE_USER_AUTHENTICATION #ifdef SQLITE_USER_AUTHENTICATION
@ -1243,7 +1245,7 @@ struct sqlite3 {
VTable **aVTrans; /* Virtual tables with open transactions */ VTable **aVTrans; /* Virtual tables with open transactions */
VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */ VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */
#endif #endif
FuncDefHash aFunc; /* Hash table of connection functions */ Hash aFunc; /* Hash table of connection functions */
Hash aCollSeq; /* All collating sequences */ Hash aCollSeq; /* All collating sequences */
BusyHandler busyHandler; /* Busy callback */ BusyHandler busyHandler; /* Busy callback */
Db aDbStatic[2]; /* Static space for the 2 default backends */ Db aDbStatic[2]; /* Static space for the 2 default backends */
@ -1370,20 +1372,26 @@ struct sqlite3 {
/* /*
** Each SQL function is defined by an instance of the following ** Each SQL function is defined by an instance of the following
** structure. A pointer to this structure is stored in the sqlite.aFunc ** structure. For global built-in functions (ex: substr(), max(), count())
** hash table. When multiple functions have the same name, the hash table ** a pointer to this structure is held in the sqlite3BuiltinFunctions object.
** points to a linked list of these structures. ** For per-connection application-defined functions, a pointer to this
** structure is held in the db->aHash hash table.
**
** The u.pHash field is used by the global built-ins. The u.pDestructor
** field is used by per-connection app-def functions.
*/ */
struct FuncDef { struct FuncDef {
i16 nArg; /* Number of arguments. -1 means unlimited */ i8 nArg; /* Number of arguments. -1 means unlimited */
u16 funcFlags; /* Some combination of SQLITE_FUNC_* */ u16 funcFlags; /* Some combination of SQLITE_FUNC_* */
void *pUserData; /* User data parameter */ void *pUserData; /* User data parameter */
FuncDef *pNext; /* Next function with same name */ FuncDef *pNext; /* Next function with same name */
void (*xSFunc)(sqlite3_context*,int,sqlite3_value**); /* func or agg-step */ void (*xSFunc)(sqlite3_context*,int,sqlite3_value**); /* func or agg-step */
void (*xFinalize)(sqlite3_context*); /* Agg finalizer */ void (*xFinalize)(sqlite3_context*); /* Agg finalizer */
char *zName; /* SQL name of the function. */ char *zName; /* SQL name of the function. */
FuncDef *pHash; /* Next with a different name but the same hash */ union {
FuncDestructor *pDestructor; /* Reference counted destructor function */ FuncDef *pHash; /* Next with a different name but the same hash */
FuncDestructor *pDestructor; /* Reference counted destructor function */
} u;
}; };
/* /*
@ -1463,28 +1471,28 @@ struct FuncDestructor {
*/ */
#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, 0, 0} SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \ #define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, 0, 0} SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \ #define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, 0, 0} SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \ #define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
{nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\ {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, 0, 0} SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \ {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
pArg, 0, xFunc, 0, #zName, 0, 0} pArg, 0, xFunc, 0, #zName, }
#define LIKEFUNC(zName, nArg, arg, flags) \ #define LIKEFUNC(zName, nArg, arg, flags) \
{nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \ {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
(void *)arg, 0, likeFunc, 0, #zName, 0, 0} (void *)arg, 0, likeFunc, 0, #zName, {0} }
#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ #define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName,0,0} SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}}
#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \ #define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName,0,0} SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}}
/* /*
** All current savepoints are stored in a linked list starting at ** All current savepoints are stored in a linked list starting at
@ -3225,7 +3233,7 @@ int sqlite3IsIdChar(u8);
/* /*
** Internal function prototypes ** Internal function prototypes
*/ */
#define sqlite3StrICmp sqlite3_stricmp int sqlite3StrICmp(const char*,const char*);
int sqlite3Strlen30(const char*); int sqlite3Strlen30(const char*);
#define sqlite3StrNICmp sqlite3_strnicmp #define sqlite3StrNICmp sqlite3_strnicmp
@ -3572,11 +3580,11 @@ void sqlite3SelectSetName(Select*,const char*);
#else #else
# define sqlite3SelectSetName(A,B) # define sqlite3SelectSetName(A,B)
#endif #endif
void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); void sqlite3InsertBuiltinFuncs(FuncDef*,int);
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8); FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
void sqlite3RegisterBuiltinFunctions(sqlite3*); void sqlite3RegisterBuiltinFunctions(void);
void sqlite3RegisterDateTimeFunctions(void); void sqlite3RegisterDateTimeFunctions(void);
void sqlite3RegisterGlobalFunctions(void); void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*);
int sqlite3SafetyCheckOk(sqlite3*); int sqlite3SafetyCheckOk(sqlite3*);
int sqlite3SafetyCheckSickOrOk(sqlite3*); int sqlite3SafetyCheckSickOrOk(sqlite3*);
void sqlite3ChangeCookie(Parse*, int); void sqlite3ChangeCookie(Parse*, int);
@ -3737,7 +3745,7 @@ extern const unsigned char sqlite3UpperToLower[];
extern const unsigned char sqlite3CtypeMap[]; extern const unsigned char sqlite3CtypeMap[];
extern const Token sqlite3IntTokens[]; extern const Token sqlite3IntTokens[];
extern SQLITE_WSD struct Sqlite3Config sqlite3Config; extern SQLITE_WSD struct Sqlite3Config sqlite3Config;
extern SQLITE_WSD FuncDefHash sqlite3GlobalFunctions; extern FuncDefHash sqlite3BuiltinFunctions;
#ifndef SQLITE_OMIT_WSD #ifndef SQLITE_OMIT_WSD
extern int sqlite3PendingByte; extern int sqlite3PendingByte;
#endif #endif

View File

@ -256,16 +256,25 @@ void sqlite3TokenInit(Token *p, char *z){
** independence" that SQLite uses internally when comparing identifiers. ** independence" that SQLite uses internally when comparing identifiers.
*/ */
int sqlite3_stricmp(const char *zLeft, const char *zRight){ int sqlite3_stricmp(const char *zLeft, const char *zRight){
register unsigned char *a, *b;
if( zLeft==0 ){ if( zLeft==0 ){
return zRight ? -1 : 0; return zRight ? -1 : 0;
}else if( zRight==0 ){ }else if( zRight==0 ){
return 1; return 1;
} }
return sqlite3StrICmp(zLeft, zRight);
}
int sqlite3StrICmp(const char *zLeft, const char *zRight){
unsigned char *a, *b;
int c;
a = (unsigned char *)zLeft; a = (unsigned char *)zLeft;
b = (unsigned char *)zRight; b = (unsigned char *)zRight;
while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; } for(;;){
return UpperToLower[*a] - UpperToLower[*b]; c = (int)UpperToLower[*a] - (int)UpperToLower[*b];
if( c || *a==0 ) break;
a++;
b++;
}
return c;
} }
int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
register unsigned char *a, *b; register unsigned char *a, *b;

View File

@ -1186,7 +1186,6 @@ static int valueFromFunction(
FuncDef *pFunc = 0; /* Function definition */ FuncDef *pFunc = 0; /* Function definition */
sqlite3_value *pVal = 0; /* New value */ sqlite3_value *pVal = 0; /* New value */
int rc = SQLITE_OK; /* Return code */ int rc = SQLITE_OK; /* Return code */
int nName; /* Size of function name in bytes */
ExprList *pList = 0; /* Function arguments */ ExprList *pList = 0; /* Function arguments */
int i; /* Iterator variable */ int i; /* Iterator variable */
@ -1194,8 +1193,7 @@ static int valueFromFunction(
assert( (p->flags & EP_TokenOnly)==0 ); assert( (p->flags & EP_TokenOnly)==0 );
pList = p->x.pList; pList = p->x.pList;
if( pList ) nVal = pList->nExpr; if( pList ) nVal = pList->nExpr;
nName = sqlite3Strlen30(p->u.zToken); pFunc = sqlite3FindFunction(db, p->u.zToken, nVal, enc, 0);
pFunc = sqlite3FindFunction(db, p->u.zToken, nName, nVal, enc, 0);
assert( pFunc ); assert( pFunc );
if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0
|| (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL) || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
@ -1457,15 +1455,10 @@ static void recordFunc(
** Register built-in functions used to help read ANALYZE data. ** Register built-in functions used to help read ANALYZE data.
*/ */
void sqlite3AnalyzeFunctions(void){ void sqlite3AnalyzeFunctions(void){
static SQLITE_WSD FuncDef aAnalyzeTableFuncs[] = { static FuncDef aAnalyzeTableFuncs[] = {
FUNCTION(sqlite_record, 1, 0, 0, recordFunc), FUNCTION(sqlite_record, 1, 0, 0, recordFunc),
}; };
int i; sqlite3InsertBuiltinFuncs(aAnalyzeTableFuncs, ArraySize(aAnalyzeTableFuncs));
FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAnalyzeTableFuncs);
for(i=0; i<ArraySize(aAnalyzeTableFuncs); i++){
sqlite3FuncDefInsert(pHash, &aFunc[i]);
}
} }
/* /*