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
diff --git a/src/callback.c b/src/callback.c
index 90d9e59..d25836b 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.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"
@@ -261,6 +261,49 @@
 }
 
 /*
+** 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
 ** pointer to the FuncDef structure that defines that function, or return
@@ -289,21 +332,24 @@
   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 @@
   ** 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 @@
   ** 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) ){
diff --git a/src/func.c b/src/func.c
index 975f7dc..0f4f0a6 100644
--- a/src/func.c
+++ b/src/func.c
@@ -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 @@
 #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]);
+  }
+}
diff --git a/src/global.c b/src/global.c
index fa59d4a..2f0782e 100644
--- a/src/global.c
+++ b/src/global.c
@@ -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 @@
    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;
diff --git a/src/main.c b/src/main.c
index 42ca5cc..9421a08 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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 @@
   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 @@
   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 @@
   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 @@
 #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 @@
                  | 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);
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 1d1474a..167b21c 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -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 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 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;
@@ -593,6 +594,16 @@
 };
 
 /*
+** 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.
 **
 ** The sqlite.lastRowid records the last insert rowid generated by an
@@ -688,7 +699,7 @@
   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 @@
 ** 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 @@
   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 @@
 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 @@
 #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*);