Initialize the global built-in function table at start-time

instead of at compile-time.  This is less prone to malfunction when
compile-time parameters very. (CVS 5583)

FossilOrigin-Name: ef6936e50adb9ebea39c890167403fff01bbb5ed
This commit is contained in:
drh 2008-08-21 18:49:27 +00:00
parent 801880f66c
commit 70a8ca3c1e
11 changed files with 146 additions and 265 deletions

View File

@ -157,7 +157,7 @@ NAWK = @AWK@
#
OBJS0 = alter.lo analyze.lo attach.lo auth.lo bitvec.lo btmutex.lo \
btree.lo build.lo callback.lo complete.lo date.lo \
delete.lo expr.lo fault.lo func2.lo global.lo \
delete.lo expr.lo fault.lo func.lo global.lo \
hash.lo journal.lo insert.lo loadext.lo \
main.lo malloc.lo mem1.lo mem2.lo mem3.lo mem4.lo mem5.lo mem6.lo \
mutex.lo mutex_os2.lo mutex_unix.lo mutex_w32.lo \
@ -198,6 +198,7 @@ SRC = \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
$(TOP)/src/fault.c \
$(TOP)/src/func.c \
$(TOP)/src/global.c \
$(TOP)/src/hash.c \
$(TOP)/src/hash.h \
@ -265,7 +266,6 @@ SRC = \
# Generated source code files
#
SRC += \
func2.c \
keywordhash.h \
opcodes.c \
opcodes.h \
@ -521,8 +521,8 @@ expr.lo: $(TOP)/src/expr.c $(HDR)
fault.lo: $(TOP)/src/fault.c $(HDR)
$(LTCOMPILE) -c $(TOP)/src/fault.c
func2.lo: func2.c $(HDR)
$(LTCOMPILE) -c func2.c
func.lo: $(TOP)/src/func.c $(HDR)
$(LTCOMPILE) -c $(TOP)/src/func.c
global.lo: $(TOP)/src/global.c $(HDR)
$(LTCOMPILE) -c $(TOP)/src/global.c
@ -616,11 +616,6 @@ parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/addopcodes.awk
mv parse.h parse.h.temp
$(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h
func2.c: $(TOP)/src/func.c $(HDR)
$(BCC) -o mkfunction$(BEXE) $(OPTS) $(OPT_FEATURE_FLAGS) $(TOP)/tool/mkfunction.c -I$(TOP)/src -I.
cat $(TOP)/src/func.c > func2.c
./mkfunction$(BEXE) >> func2.c
pragma.lo: $(TOP)/src/pragma.c $(HDR)
$(LTCOMPILE) -c $(TOP)/src/pragma.c

17
main.mk
View File

@ -51,7 +51,7 @@ TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP) -I$(TOP)/ext/rtree
LIBOBJ+= alter.o analyze.o attach.o auth.o \
bitvec.o btmutex.o btree.o build.o \
callback.o complete.o date.o delete.o \
expr.o fault.o func2.o global.o hash.o \
expr.o fault.o func.o global.o hash.o \
icu.o insert.o journal.o legacy.o loadext.o \
main.o malloc.o mem1.o mem2.o mem3.o mem4.o mem5.o mem6.o \
mutex.o mutex_os2.o mutex_unix.o mutex_w32.o \
@ -83,6 +83,7 @@ SRC = \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
$(TOP)/src/fault.c \
$(TOP)/src/func.c \
$(TOP)/src/global.c \
$(TOP)/src/hash.c \
$(TOP)/src/hash.h \
@ -142,7 +143,6 @@ SRC = \
$(TOP)/src/vdbeblob.c \
$(TOP)/src/vdbefifo.c \
$(TOP)/src/vdbemem.c \
$(TOP)/src/pcache.c \
$(TOP)/src/vdbeInt.h \
$(TOP)/src/vtab.c \
$(TOP)/src/walker.c \
@ -193,7 +193,6 @@ SRC += \
opcodes.h \
parse.c \
parse.h \
func2.c \
sqlite3.h
@ -231,7 +230,7 @@ TESTSRC = \
TESTSRC2 = \
$(TOP)/src/attach.c $(TOP)/src/btree.c $(TOP)/src/build.c $(TOP)/src/date.c \
$(TOP)/src/expr.c func2.c $(TOP)/src/insert.c $(TOP)/src/os.c \
$(TOP)/src/expr.c $(TOP)/src/func.c $(TOP)/src/insert.c $(TOP)/src/os.c \
$(TOP)/src/os_os2.c $(TOP)/src/os_unix.c $(TOP)/src/os_win.c \
$(TOP)/src/pager.c $(TOP)/src/pragma.c $(TOP)/src/prepare.c \
$(TOP)/src/printf.c $(TOP)/src/random.c $(TOP)/src/pcache.c \
@ -349,12 +348,8 @@ opcodes.c: opcodes.h $(TOP)/mkopcodec.awk
sort -n -b -k 3 opcodes.h | $(NAWK) -f $(TOP)/mkopcodec.awk >opcodes.c
opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk
cat parse.h $(TOP)/src/vdbe.c |$(NAWK) -f $(TOP)/mkopcodeh.awk >opcodes.h
func2.c: $(TOP)/src/func.c $(HDR)
$(BCC) -o mkfunction $(OPTS) $(TOP)/tool/mkfunction.c -I$(TOP)/src -I.
cat $(TOP)/src/func.c > func2.c
./mkfunction >> func2.c
cat parse.h $(TOP)/src/vdbe.c | \
$(NAWK) -f $(TOP)/mkopcodeh.awk >opcodes.h
# Rules to build parse.c and parse.h - the outputs of lemon.
#
@ -497,4 +492,4 @@ clean:
rm -f *.da *.bb *.bbg gmon.out
rm -rf tsrc target_source
rm -f testloadext.dll libtestloadext.so
rm -f sqlite3.c fts?amal.c tclsqlite3.c func2.c
rm -f sqlite3.c fts?amal.c tclsqlite3.c

View File

@ -1,7 +1,7 @@
C Fix\ssoft-heap-limit\srelated\stest\ssuite\sfailures.\s(CVS\s5582)
D 2008-08-21T15:54:01
C Initialize\sthe\sglobal\sbuilt-in\sfunction\stable\sat\sstart-time\ninstead\sof\sat\scompile-time.\s\sThis\sis\sless\sprone\sto\smalfunction\swhen\ncompile-time\sparameters\svery.\s(CVS\s5583)
D 2008-08-21T18:49:28
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 0b1c022000f55221454a7846022f11674d8024bf
F Makefile.in 51b727303f84cf055e29514d8248e5eaf9701379
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F README b974cdc3f9f12b87e851b04e75996d720ebf81ac
F VERSION d1968c7d42b95f18d5fdb5cf7f4cef21797572fa
@ -76,7 +76,7 @@ F ext/rtree/rtree_util.tcl ee0a0311eb12175319d78bfb37302320496cee6e
F ext/rtree/viewrtree.tcl 09526398dae87a5a87c5aac2b3854dbaf8376869
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
F ltmain.sh 09fe5815427dc7d0abb188bbcdf0e34896577210
F main.mk 4bb354f1e952a13ee8a02b42837b37c4b198d9a7
F main.mk 5ce1477b7fdc00f5c981f06e5708255dc217902c
F mkdll.sh 79d1ed6ae221c10589dd969f130f8a3cccfffbb7
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
@ -100,14 +100,14 @@ F src/btree.c 3078f7a5c7cde1e74d884dfa57410125d21586fb
F src/btree.h 6371c5e599fab391a150c96afbc10062b276d107
F src/btreeInt.h ab18c7b4980314e9e4b402e5dcde09f3c2545576
F src/build.c 160c71acca8f643f436ed6c1ee2f684c88df4dfe
F src/callback.c 1b1a5c580cdf7d83db24001bf8e5c09e2b08658f
F src/callback.c 26f18b3cb5e44120390a8d2d97907889feb47bc5
F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c
F src/date.c 52a54811218a76da6235420f532ece841159a96d
F src/delete.c 5105c67c741f934379722de5e11fdd73ea4d82b5
F src/expr.c 4651d08422474f7e4bcb9a35da00c33ebe719a2d
F src/fault.c 3638519d1e0b82bccfafcb9f5ff491918b28f8e1
F src/func.c d97ff7b72f3ddcd88970048e2894954a3f5b01d8
F src/global.c b9c96ee2317a6e1391763c7db1098a6473a91863
F src/func.c f52c6d1b5d08b94ea348059e1bd067580490dd60
F src/global.c 39350827d0bce0fe10cca8b13c5dfca3438b4f65
F src/hash.c eb64e48f3781100e5934f759fbe72a63a8fe78cb
F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
F src/hwtime.h 4a1d45f4cae1f402ea19686acf24acf4f0cb53cb
@ -115,7 +115,7 @@ F src/insert.c 110cca7845ed5a66c08fdd413b02e706ae34455f
F src/journal.c cffd2cd214e58c0e99c3ff632b3bee6c7cbb260e
F src/legacy.c aac57bd984e666059011ea01ec4383892a253be3
F src/loadext.c eb1fe4f44d7c8ff53fc0c6a4388ab79fbd34cd64
F src/main.c aaf5af6ffe2c05f8ea4d75a850581a68ac529fa0
F src/main.c 2513e9bb233a8ebc4aaa766a37528ef255cde7fb
F src/malloc.c 7ccc630b359f57a47b6034af54e42eb838eebd46
F src/md5.c 008216bbb5d34c6fbab5357aa68575ad8a31516a
F src/mem1.c 3a7fe31d8290baa3bb203af72f7dfd6323966bcd
@ -149,7 +149,7 @@ F src/select.c e71462393fe0f9d2bf41378763b96659e8780e43
F src/shell.c d83b578a8ccdd3e0e7fef4388a0887ce9f810967
F src/sqlite.h.in 54e51c22e2294c5989156b0aec87aa44168ac1f0
F src/sqlite3ext.h 1e3887c9bd3ae66cb599e922824b04cd0d0f2c3e
F src/sqliteInt.h d1ddf30df8d7eb3e15e7d70ebe347e0c17255165
F src/sqliteInt.h 15096ac72b783de470c7f89888560e2ddaa83898
F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
F src/status.c 8caa772cd9310bc297280f7cf0ede4d69ed5b801
F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8
@ -605,10 +605,9 @@ F tool/lempar.c 770dc64b74429daf9611676f43bfbd7c1bed0152
F tool/memleak.awk 4e7690a51bf3ed757e611273d43fe3f65b510133
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
F tool/memleak3.tcl 7707006ee908cffff210c98158788d85bb3fcdbf
F tool/mkfunction.c 72c656fbc1a20ec426a94cd80cda5eea5b7b8bc7
F tool/mkkeywordhash.c ef93810fc41fb3d3dbacf9a33a29be88ea99ffa9
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
F tool/mksqlite3c.tcl f5645b2e7ee71fa9633ca5c90ada3ae9120b4a3c
F tool/mksqlite3c.tcl c4542127796826a26f89567c7bbaecafaf42a120
F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
F tool/omittest.tcl 5a25ea687df5da8dd9b94bf1683f5cf2c210e51d
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
@ -623,7 +622,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
P d68dad73d0a85c6213a96982d0366c790871b693
R b1b9ce7ac833bb03734065aa230b3a65
U danielk1977
Z 442c477497b5c11bc6fcf9ea22d419f7
P 2091d9a5260b1d7e27ff5ca93e60dae1e3b12081
R b949ccba5219ea8fee93a425d2cbcc5d
U drh
Z f9a9c8cdda97c141f21d737763887781

View File

@ -1 +1 @@
2091d9a5260b1d7e27ff5ca93e60dae1e3b12081
ef6936e50adb9ebea39c890167403fff01bbb5ed

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.27 2008/08/20 14:49:24 danielk1977 Exp $
** $Id: callback.c,v 1.28 2008/08/21 18:49:28 drh Exp $
*/
#include "sqliteInt.h"
@ -260,6 +260,49 @@ static int matchQuality(FuncDef *p, int nArg, u8 enc){
return match;
}
/*
** Search a FuncDefHash for a function with the given name. Return
** a pointer to the matching FuncDef if found, or 0 if there is no match.
*/
static FuncDef *functionSearch(
FuncDefHash *pHash, /* Hash table to search */
int h, /* Hash of the name */
const char *zFunc, /* Name of function */
int nFunc /* Number of bytes in zFunc */
){
FuncDef *p;
for(p=pHash->a[h]; p; p=p->pHash){
if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 && p->zName[nFunc]==0 ){
return p;
}
}
return 0;
}
/*
** Insert a new FuncDef into a FuncDefHash hash table.
*/
void sqlite3FuncDefInsert(
FuncDefHash *pHash, /* The hash table into which to insert */
FuncDef *pDef /* The function definition to insert */
){
FuncDef *pOther;
int nName = strlen(pDef->zName);
u8 c1 = (u8)pDef->zName[0];
int h = (sqlite3UpperToLower[c1] + nName) % ArraySize(pHash->a);
pOther = functionSearch(pHash, h, pDef->zName, nName);
if( pOther ){
pDef->pNext = pOther->pNext;
pOther->pNext = pDef;
}else{
pDef->pNext = 0;
pDef->pHash = pHash->a[h];
pHash->a[h] = pDef;
}
}
/*
** Locate a user function given a name, a number of arguments and a flag
** indicating whether the function prefers UTF-16 over UTF-8. Return a
@ -289,21 +332,24 @@ FuncDef *sqlite3FindFunction(
int createFlag /* Create new entry if true and does not otherwise exist */
){
FuncDef *p; /* Iterator variable */
FuncDef *pFirst; /* First function with this name */
FuncDef *pBest = 0; /* Best match found so far */
int bestmatch = 0;
int bestScore = 0; /* Score of best match */
int h; /* Hash value */
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
if( nArg<-1 ) nArg = -1;
h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a);
pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName);
for(p=pFirst; p; p=p->pNext){
int match = matchQuality(p, nArg, enc);
if( match>bestmatch ){
p = functionSearch(&db->aFunc, h, zName, nName);
while( p ){
int score = matchQuality(p, nArg, enc);
if( score>bestScore ){
pBest = p;
bestmatch = match;
bestScore = score;
}
p = p->pNext;
}
/* If the createFlag parameter is false and no match was found amongst
@ -311,16 +357,14 @@ FuncDef *sqlite3FindFunction(
** function to use.
*/
if( !createFlag && !pBest ){
FuncDef *aFunc;
int nFunc;
int i;
nFunc = sqlite3GetBuiltinFunction(zName, nName, &aFunc);
for(i=0; i<nFunc; i++){
int match = matchQuality(&aFunc[i], nArg, enc);
if( match>bestmatch ){
pBest = &aFunc[i];
bestmatch = match;
p = functionSearch(&sqlite3FuncBuiltins, h, zName, nName);
while( p ){
int score = matchQuality(p, nArg, enc);
if( score>bestScore ){
pBest = p;
bestScore = score;
}
p = p->pNext;
}
}
@ -328,19 +372,14 @@ FuncDef *sqlite3FindFunction(
** exact match for the name, number of arguments and encoding, then add a
** new entry to the hash table and return it.
*/
if( createFlag && bestmatch<6 &&
if( createFlag && bestScore<6 &&
(pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
pBest->zName = (char *)&pBest[1];
pBest->nArg = nArg;
pBest->pNext = pFirst;
pBest->iPrefEnc = enc;
memcpy(pBest->zName, zName, nName);
pBest->zName[nName] = 0;
if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){
db->mallocFailed = 1;
sqlite3DbFree(db, pBest);
return 0;
}
sqlite3FuncDefInsert(&db->aFunc, pBest);
}
if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){

View File

@ -16,7 +16,7 @@
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.197 2008/08/20 14:49:24 danielk1977 Exp $
** $Id: func.c,v 1.198 2008/08/21 18:49:28 drh Exp $
*/
#ifndef CREATE_BUILTIN_HASHTABLE
@ -1422,3 +1422,13 @@ static FuncDef aBuiltinFunc[] = {
#endif
};
/*
** Build up the global built-in function table at initialization
** time.
*/
void sqlite3RegisterGlobalFunctions(void){
int i;
for(i=0; i<ArraySize(aBuiltinFunc); i++){
sqlite3FuncDefInsert(&sqlite3FuncBuiltins, &aBuiltinFunc[i]);
}
}

View File

@ -12,7 +12,7 @@
**
** This file contains definitions of global variables and contants.
**
** $Id: global.c,v 1.4 2008/07/28 19:34:53 drh Exp $
** $Id: global.c,v 1.5 2008/08/21 18:49:28 drh Exp $
*/
#include "sqliteInt.h"
@ -75,3 +75,11 @@ struct Sqlite3Config sqlite3Config = {
500, /* nLookaside */
/* Other fields all default to zero */
};
/*
** Hash table for global functions - functions common to all
** database connections. After initialization, this table is
** read-only.
*/
FuncDefHash sqlite3FuncBuiltins;

View File

@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.491 2008/08/20 16:35:10 drh Exp $
** $Id: main.c,v 1.492 2008/08/21 18:49:28 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -147,6 +147,8 @@ int sqlite3_initialize(void){
sqlite3_mutex_enter(sqlite3Config.pInitMutex);
if( sqlite3Config.isInit==0 && inProgress==0 ){
inProgress = 1;
memset(&sqlite3FuncBuiltins, 0, sizeof(sqlite3FuncBuiltins));
sqlite3RegisterGlobalFunctions();
rc = sqlite3_os_init();
if( rc==SQLITE_OK ){
rc = sqlite3PcacheInitialize();
@ -566,14 +568,17 @@ int sqlite3_close(sqlite3 *db){
sqlite3ResetInternalSchema(db, 0);
assert( db->nDb<=2 );
assert( db->aDb==db->aDbStatic );
for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
FuncDef *pFunc, *pNext;
for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
pNext = pFunc->pNext;
sqlite3DbFree(db, pFunc);
for(j=0; j<ArraySize(db->aFunc.a); j++){
FuncDef *pNext, *pHash, *p;
for(p=db->aFunc.a[j]; p; p=pHash){
pHash = p->pHash;
while( p ){
pNext = p->pNext;
sqlite3DbFree(db, p);
p = pNext;
}
}
}
for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){
CollSeq *pColl = (CollSeq *)sqliteHashData(i);
/* Invoke any destructors registered for collation sequence user data. */
@ -596,7 +601,6 @@ int sqlite3_close(sqlite3 *db){
sqlite3HashClear(&db->aModule);
#endif
sqlite3HashClear(&db->aFunc);
sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
if( db->pErr ){
sqlite3ValueFree(db->pErr);
@ -1371,6 +1375,9 @@ static const int aHardLimit[] = {
#if SQLITE_MAX_VARIABLE_NUMBER<1
# error SQLITE_MAX_VARIABLE_NUMBER must be at least 1
#endif
#if SQLITE_MAX_COLUMN>32767
# error SQLITE_MAX_COLUMN must not exceed 32767
#endif
/*
@ -1466,7 +1473,6 @@ static int openDatabase(
| SQLITE_LoadExtension
#endif
;
sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0);
sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0);
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3HashInit(&db->aModule, SQLITE_HASH_STRING, 0);

View File

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.757 2008/08/20 16:35:10 drh Exp $
** @(#) $Id: sqliteInt.h,v 1.758 2008/08/21 18:49:28 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@ -366,7 +366,7 @@ typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
typedef INT16_TYPE i16; /* 2-byte signed integer */
typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
typedef UINT8_TYPE i8; /* 1-byte signed integer */
typedef INT8_TYPE i8; /* 1-byte signed integer */
/*
** Macros to determine whether the machine is big or little endian,
@ -455,6 +455,7 @@ typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct FKey FKey;
typedef struct FuncDef FuncDef;
typedef struct FuncDefHash FuncDefHash;
typedef struct IdList IdList;
typedef struct Index Index;
typedef struct KeyClass KeyClass;
@ -592,6 +593,16 @@ struct LookasideSlot {
LookasideSlot *pNext; /* Next buffer in the list of free buffers */
};
/*
** A hash table for function definitions.
**
** Hash each FuncDef structure into one of the FuncDefHash.a[] slots.
** Collisions are on the FuncDef.pHash chain.
*/
struct FuncDefHash {
FuncDef *a[23]; /* Hash table for functions */
};
/*
** Each database is an instance of the following structure.
**
@ -688,7 +699,7 @@ struct sqlite3 {
sqlite3_vtab **aVTrans; /* Virtual tables with open transactions */
int nVTrans; /* Allocated size of aVTrans */
#endif
Hash aFunc; /* All functions that can be in SQL exprs */
FuncDefHash aFunc; /* Hash table of connection functions */
Hash aCollSeq; /* All collating sequences */
BusyHandler busyHandler; /* Busy callback */
int busyTimeout; /* Busy handler timeout, in msec */
@ -753,7 +764,7 @@ struct sqlite3 {
** points to a linked list of these structures.
*/
struct FuncDef {
i16 nArg; /* Number of arguments. -1 means unlimited */
i8 nArg; /* Number of arguments. -1 means unlimited */
u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */
u8 needCollSeq; /* True if sqlite3GetFuncCollSeq() might be called */
u8 flags; /* Some combination of SQLITE_FUNC_* */
@ -763,14 +774,15 @@ struct FuncDef {
void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */
void (*xFinalize)(sqlite3_context*); /* Aggregate finializer */
char *zName; /* SQL name of the function. */
FuncDef *pHash; /* Next with a different name but the same hash */
};
/*
** Possible values for FuncDef.flags
*/
#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
#define SQLITE_FUNC_EPHEM 0x04 /* Ephermeral. Delete with VDBE */
#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
#define SQLITE_FUNC_EPHEM 0x04 /* Ephermeral. Delete with VDBE */
/*
** Each SQLite module (virtual table definition) is defined by an
@ -2127,9 +2139,11 @@ ExprList *sqlite3ExprListDup(sqlite3*,ExprList*);
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*);
IdList *sqlite3IdListDup(sqlite3*,IdList*);
Select *sqlite3SelectDup(sqlite3*,Select*);
void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*);
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int);
void sqlite3RegisterBuiltinFunctions(sqlite3*);
void sqlite3RegisterDateTimeFunctions(sqlite3*);
void sqlite3RegisterGlobalFunctions(void);
int sqlite3GetBuiltinFunction(const char *, int, FuncDef **);
#ifdef SQLITE_DEBUG
int sqlite3SafetyOn(sqlite3*);
@ -2268,6 +2282,7 @@ void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
extern const unsigned char sqlite3UpperToLower[];
extern struct Sqlite3Config sqlite3Config;
extern FuncDefHash sqlite3FuncBuiltins;
#endif
void sqlite3RootPageMoved(Db*, int, int);
void sqlite3Reindex(Parse*, Token*, Token*);

View File

@ -1,186 +0,0 @@
/*
** This file contains a standalone program used to generate C code that
** implements a static hash table to store the definitions of built-in
** SQL functions in SQLite.
*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
/*
** The SQLite source file "func.c" is included below.
**
** By defining the 4 macros and typedef below before including "func.c",
** most of the code is excluded. What is left is an array of constant
** strings, aBuiltinFunc[], containing the names of SQLite's built-in
** SQL functions. i.e.:
**
** const char aBuiltinFunc[] = { "like", "glob", "min", "max" ... };
**
** The data from aBuiltinFunc[] is used by this program to create the
** static hash table.
*/
#define CREATE_BUILTIN_HASHTABLE 1
#define FUNCTION(zName,w,x,y,z) #zName
#define AGGREGATE(zName,v,w,x,y,z) #zName
#define LIKEFUNC(zName,x,y,z) #zName
#define FuncDef const char *
#include "func.c"
/* The number of buckets in the static hash table. */
#define HASHSIZE 127
typedef unsigned char u8;
/* An array to map all upper-case characters into their corresponding
** lower-case character.
*/
static const u8 sqlite3UpperToLower[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
252,253,254,255
};
#define UpperToLower sqlite3UpperToLower
int sqlite3StrICmp(const char *zLeft, const char *zRight){
register unsigned char *a, *b;
a = (unsigned char *)zLeft;
b = (unsigned char *)zRight;
while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
return UpperToLower[*a] - UpperToLower[*b];
}
static int hashstring(const char *zName){
int ii;
unsigned int iKey = 0;
for(ii=0; zName[ii]; ii++){
iKey = (iKey<<3) + (u8)sqlite3UpperToLower[(u8)zName[ii]];
}
iKey = iKey%HASHSIZE;
return iKey;
}
static void printarray(const char *zName, u8 *aArray, int nArray){
int ii;
printf(" static u8 %s[%d] = {", zName, nArray);
for(ii=0; ii<nArray; ii++){
if( (ii%16)==0 ){
printf("\n ");
}
printf("%2d, ", aArray[ii]);
}
printf("\n };\n");
}
int main(int argc, char **argv){
int nFunc; /* Number of entries in the aBuiltinFunc array */
u8 anFunc[256];
u8 aHash[HASHSIZE];
u8 aNext[256];
int ii;
int iHead;
nFunc = (sizeof(aBuiltinFunc)/sizeof(const char *));
assert(nFunc<256);
memset(aHash, (unsigned char)nFunc, sizeof(aHash));
memset(aNext, (unsigned char)nFunc, sizeof(aNext));
memset(anFunc, 0, sizeof(anFunc));
iHead = -1;
for(ii=0; ii<nFunc; ii++){
int iHash;
if( iHead>=0 && 0==sqlite3StrICmp(aBuiltinFunc[ii], aBuiltinFunc[iHead]) ){
anFunc[iHead]++;
continue;
}else{
/* The routine generated by this program assumes that if there are
** two or more entries in the aBuiltinFunc[] array with the same
** name (i.e. two versions of the "max" function), then they must
** be stored in adjacent slots. The following block detects the
** problem if this is not the case.
*/
int jj;
for(jj=0; jj<ii; jj++){
if( 0==sqlite3StrICmp(aBuiltinFunc[ii], aBuiltinFunc[jj]) ){
fprintf(stderr, "Error in func.c\n");
return -1;
}
}
iHead = ii;
anFunc[iHead] = 1;
}
iHash = hashstring(aBuiltinFunc[ii]);
if( aHash[iHash]!=nFunc ){
int iNext = aHash[iHash];
while( aNext[iNext]!=nFunc ){
iNext = aNext[iNext];
}
aNext[iNext] = ii;
}else{
aHash[iHash] = ii;
}
}
printf(
"/******* Automatically Generated code - do not edit **************/\n"
"int sqlite3GetBuiltinFunction(\n"
" const char *zName, \n"
" int nName, \n"
" FuncDef **paFunc\n"
"){\n"
);
printarray("aHash", aHash, HASHSIZE);
printarray("anFunc", anFunc, nFunc);
printarray("aNext", aNext, nFunc);
printf(" FuncDef *pNoFunc = &aBuiltinFunc[%d];\n", nFunc);
printf(
" unsigned int iKey = 0; /* Hash of case-insensitive string zName. */\n"
" int ii;\n"
" FuncDef *pFunc;\n"
"\n"
);
printf(
" assert( (sizeof(aBuiltinFunc)/sizeof(aBuiltinFunc[0]))==%d );\n", nFunc
);
printf(
" /* Generate the hash of zName */\n"
" for(ii=0; ii<nName; ii++){\n"
" iKey = (iKey<<3) + (u8)sqlite3UpperToLower[(u8)zName[ii]];\n"
" }\n"
" iKey = iKey%%127;\n"
"\n"
" pFunc = &aBuiltinFunc[iKey = aHash[iKey]];\n"
" while( pFunc!=pNoFunc && sqlite3StrNICmp(pFunc->zName, zName, nName) ){\n"
" pFunc = &aBuiltinFunc[iKey = aNext[iKey]];\n"
" }\n"
"\n"
" *paFunc = pFunc;\n"
" return anFunc[iKey];\n"
"}\n"
);
return 0;
}

View File

@ -256,7 +256,7 @@ foreach file {
build.c
callback.c
delete.c
func2.c
func.c
insert.c
legacy.c
loadext.c