| OLD | NEW | 
 | (Empty) | 
|    1 /* |  | 
|    2 ** 2005 May 23  |  | 
|    3 ** |  | 
|    4 ** The author disclaims copyright to this source code.  In place of |  | 
|    5 ** a legal notice, here is a blessing: |  | 
|    6 ** |  | 
|    7 **    May you do good and not evil. |  | 
|    8 **    May you find forgiveness for yourself and forgive others. |  | 
|    9 **    May you share freely, never taking more than you give. |  | 
|   10 ** |  | 
|   11 ************************************************************************* |  | 
|   12 ** |  | 
|   13 ** This file contains functions used to access the internal hash tables |  | 
|   14 ** of user defined functions and collation sequences. |  | 
|   15 ** |  | 
|   16 ** $Id: callback.c,v 1.42 2009/06/17 00:35:31 drh Exp $ |  | 
|   17 */ |  | 
|   18  |  | 
|   19 #include "sqliteInt.h" |  | 
|   20  |  | 
|   21 /* |  | 
|   22 ** Invoke the 'collation needed' callback to request a collation sequence |  | 
|   23 ** in the encoding enc of name zName, length nName. |  | 
|   24 */ |  | 
|   25 static void callCollNeeded(sqlite3 *db, int enc, const char *zName){ |  | 
|   26   assert( !db->xCollNeeded || !db->xCollNeeded16 ); |  | 
|   27   if( db->xCollNeeded ){ |  | 
|   28     char *zExternal = sqlite3DbStrDup(db, zName); |  | 
|   29     if( !zExternal ) return; |  | 
|   30     db->xCollNeeded(db->pCollNeededArg, db, enc, zExternal); |  | 
|   31     sqlite3DbFree(db, zExternal); |  | 
|   32   } |  | 
|   33 #ifndef SQLITE_OMIT_UTF16 |  | 
|   34   if( db->xCollNeeded16 ){ |  | 
|   35     char const *zExternal; |  | 
|   36     sqlite3_value *pTmp = sqlite3ValueNew(db); |  | 
|   37     sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC); |  | 
|   38     zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE); |  | 
|   39     if( zExternal ){ |  | 
|   40       db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal); |  | 
|   41     } |  | 
|   42     sqlite3ValueFree(pTmp); |  | 
|   43   } |  | 
|   44 #endif |  | 
|   45 } |  | 
|   46  |  | 
|   47 /* |  | 
|   48 ** This routine is called if the collation factory fails to deliver a |  | 
|   49 ** collation function in the best encoding but there may be other versions |  | 
|   50 ** of this collation function (for other text encodings) available. Use one |  | 
|   51 ** of these instead if they exist. Avoid a UTF-8 <-> UTF-16 conversion if |  | 
|   52 ** possible. |  | 
|   53 */ |  | 
|   54 static int synthCollSeq(sqlite3 *db, CollSeq *pColl){ |  | 
|   55   CollSeq *pColl2; |  | 
|   56   char *z = pColl->zName; |  | 
|   57   int i; |  | 
|   58   static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 }; |  | 
|   59   for(i=0; i<3; i++){ |  | 
|   60     pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, 0); |  | 
|   61     if( pColl2->xCmp!=0 ){ |  | 
|   62       memcpy(pColl, pColl2, sizeof(CollSeq)); |  | 
|   63       pColl->xDel = 0;         /* Do not copy the destructor */ |  | 
|   64       return SQLITE_OK; |  | 
|   65     } |  | 
|   66   } |  | 
|   67   return SQLITE_ERROR; |  | 
|   68 } |  | 
|   69  |  | 
|   70 /* |  | 
|   71 ** This function is responsible for invoking the collation factory callback |  | 
|   72 ** or substituting a collation sequence of a different encoding when the |  | 
|   73 ** requested collation sequence is not available in the desired encoding. |  | 
|   74 **  |  | 
|   75 ** If it is not NULL, then pColl must point to the database native encoding  |  | 
|   76 ** collation sequence with name zName, length nName. |  | 
|   77 ** |  | 
|   78 ** The return value is either the collation sequence to be used in database |  | 
|   79 ** db for collation type name zName, length nName, or NULL, if no collation |  | 
|   80 ** sequence can be found. |  | 
|   81 ** |  | 
|   82 ** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq() |  | 
|   83 */ |  | 
|   84 CollSeq *sqlite3GetCollSeq( |  | 
|   85   sqlite3* db,          /* The database connection */ |  | 
|   86   u8 enc,               /* The desired encoding for the collating sequence */ |  | 
|   87   CollSeq *pColl,       /* Collating sequence with native encoding, or NULL */ |  | 
|   88   const char *zName     /* Collating sequence name */ |  | 
|   89 ){ |  | 
|   90   CollSeq *p; |  | 
|   91  |  | 
|   92   p = pColl; |  | 
|   93   if( !p ){ |  | 
|   94     p = sqlite3FindCollSeq(db, enc, zName, 0); |  | 
|   95   } |  | 
|   96   if( !p || !p->xCmp ){ |  | 
|   97     /* No collation sequence of this type for this encoding is registered. |  | 
|   98     ** Call the collation factory to see if it can supply us with one. |  | 
|   99     */ |  | 
|  100     callCollNeeded(db, enc, zName); |  | 
|  101     p = sqlite3FindCollSeq(db, enc, zName, 0); |  | 
|  102   } |  | 
|  103   if( p && !p->xCmp && synthCollSeq(db, p) ){ |  | 
|  104     p = 0; |  | 
|  105   } |  | 
|  106   assert( !p || p->xCmp ); |  | 
|  107   return p; |  | 
|  108 } |  | 
|  109  |  | 
|  110 /* |  | 
|  111 ** This routine is called on a collation sequence before it is used to |  | 
|  112 ** check that it is defined. An undefined collation sequence exists when |  | 
|  113 ** a database is loaded that contains references to collation sequences |  | 
|  114 ** that have not been defined by sqlite3_create_collation() etc. |  | 
|  115 ** |  | 
|  116 ** If required, this routine calls the 'collation needed' callback to |  | 
|  117 ** request a definition of the collating sequence. If this doesn't work,  |  | 
|  118 ** an equivalent collating sequence that uses a text encoding different |  | 
|  119 ** from the main database is substituted, if one is available. |  | 
|  120 */ |  | 
|  121 int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){ |  | 
|  122   if( pColl ){ |  | 
|  123     const char *zName = pColl->zName; |  | 
|  124     sqlite3 *db = pParse->db; |  | 
|  125     CollSeq *p = sqlite3GetCollSeq(db, ENC(db), pColl, zName); |  | 
|  126     if( !p ){ |  | 
|  127       sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); |  | 
|  128       pParse->nErr++; |  | 
|  129       return SQLITE_ERROR; |  | 
|  130     } |  | 
|  131     assert( p==pColl ); |  | 
|  132   } |  | 
|  133   return SQLITE_OK; |  | 
|  134 } |  | 
|  135  |  | 
|  136  |  | 
|  137  |  | 
|  138 /* |  | 
|  139 ** Locate and return an entry from the db.aCollSeq hash table. If the entry |  | 
|  140 ** specified by zName and nName is not found and parameter 'create' is |  | 
|  141 ** true, then create a new entry. Otherwise return NULL. |  | 
|  142 ** |  | 
|  143 ** Each pointer stored in the sqlite3.aCollSeq hash table contains an |  | 
|  144 ** array of three CollSeq structures. The first is the collation sequence |  | 
|  145 ** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be. |  | 
|  146 ** |  | 
|  147 ** Stored immediately after the three collation sequences is a copy of |  | 
|  148 ** the collation sequence name. A pointer to this string is stored in |  | 
|  149 ** each collation sequence structure. |  | 
|  150 */ |  | 
|  151 static CollSeq *findCollSeqEntry( |  | 
|  152   sqlite3 *db,          /* Database connection */ |  | 
|  153   const char *zName,    /* Name of the collating sequence */ |  | 
|  154   int create            /* Create a new entry if true */ |  | 
|  155 ){ |  | 
|  156   CollSeq *pColl; |  | 
|  157   int nName = sqlite3Strlen30(zName); |  | 
|  158   pColl = sqlite3HashFind(&db->aCollSeq, zName, nName); |  | 
|  159  |  | 
|  160   if( 0==pColl && create ){ |  | 
|  161     pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 ); |  | 
|  162     if( pColl ){ |  | 
|  163       CollSeq *pDel = 0; |  | 
|  164       pColl[0].zName = (char*)&pColl[3]; |  | 
|  165       pColl[0].enc = SQLITE_UTF8; |  | 
|  166       pColl[1].zName = (char*)&pColl[3]; |  | 
|  167       pColl[1].enc = SQLITE_UTF16LE; |  | 
|  168       pColl[2].zName = (char*)&pColl[3]; |  | 
|  169       pColl[2].enc = SQLITE_UTF16BE; |  | 
|  170       memcpy(pColl[0].zName, zName, nName); |  | 
|  171       pColl[0].zName[nName] = 0; |  | 
|  172       pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl); |  | 
|  173  |  | 
|  174       /* If a malloc() failure occurred in sqlite3HashInsert(), it will  |  | 
|  175       ** return the pColl pointer to be deleted (because it wasn't added |  | 
|  176       ** to the hash table). |  | 
|  177       */ |  | 
|  178       assert( pDel==0 || pDel==pColl ); |  | 
|  179       if( pDel!=0 ){ |  | 
|  180         db->mallocFailed = 1; |  | 
|  181         sqlite3DbFree(db, pDel); |  | 
|  182         pColl = 0; |  | 
|  183       } |  | 
|  184     } |  | 
|  185   } |  | 
|  186   return pColl; |  | 
|  187 } |  | 
|  188  |  | 
|  189 /* |  | 
|  190 ** Parameter zName points to a UTF-8 encoded string nName bytes long. |  | 
|  191 ** Return the CollSeq* pointer for the collation sequence named zName |  | 
|  192 ** for the encoding 'enc' from the database 'db'. |  | 
|  193 ** |  | 
|  194 ** If the entry specified is not found and 'create' is true, then create a |  | 
|  195 ** new entry.  Otherwise return NULL. |  | 
|  196 ** |  | 
|  197 ** A separate function sqlite3LocateCollSeq() is a wrapper around |  | 
|  198 ** this routine.  sqlite3LocateCollSeq() invokes the collation factory |  | 
|  199 ** if necessary and generates an error message if the collating sequence |  | 
|  200 ** cannot be found. |  | 
|  201 ** |  | 
|  202 ** See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq() |  | 
|  203 */ |  | 
|  204 CollSeq *sqlite3FindCollSeq( |  | 
|  205   sqlite3 *db, |  | 
|  206   u8 enc, |  | 
|  207   const char *zName, |  | 
|  208   int create |  | 
|  209 ){ |  | 
|  210   CollSeq *pColl; |  | 
|  211   if( zName ){ |  | 
|  212     pColl = findCollSeqEntry(db, zName, create); |  | 
|  213   }else{ |  | 
|  214     pColl = db->pDfltColl; |  | 
|  215   } |  | 
|  216   assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); |  | 
|  217   assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE ); |  | 
|  218   if( pColl ) pColl += enc-1; |  | 
|  219   return pColl; |  | 
|  220 } |  | 
|  221  |  | 
|  222 /* During the search for the best function definition, this procedure |  | 
|  223 ** is called to test how well the function passed as the first argument |  | 
|  224 ** matches the request for a function with nArg arguments in a system |  | 
|  225 ** that uses encoding enc. The value returned indicates how well the |  | 
|  226 ** request is matched. A higher value indicates a better match. |  | 
|  227 ** |  | 
|  228 ** The returned value is always between 0 and 6, as follows: |  | 
|  229 ** |  | 
|  230 ** 0: Not a match, or if nArg<0 and the function is has no implementation. |  | 
|  231 ** 1: A variable arguments function that prefers UTF-8 when a UTF-16 |  | 
|  232 **    encoding is requested, or vice versa. |  | 
|  233 ** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is |  | 
|  234 **    requested, or vice versa. |  | 
|  235 ** 3: A variable arguments function using the same text encoding. |  | 
|  236 ** 4: A function with the exact number of arguments requested that |  | 
|  237 **    prefers UTF-8 when a UTF-16 encoding is requested, or vice versa. |  | 
|  238 ** 5: A function with the exact number of arguments requested that |  | 
|  239 **    prefers UTF-16LE when UTF-16BE is requested, or vice versa. |  | 
|  240 ** 6: An exact match. |  | 
|  241 ** |  | 
|  242 */ |  | 
|  243 static int matchQuality(FuncDef *p, int nArg, u8 enc){ |  | 
|  244   int match = 0; |  | 
|  245   if( p->nArg==-1 || p->nArg==nArg  |  | 
|  246    || (nArg==-1 && (p->xFunc!=0 || p->xStep!=0)) |  | 
|  247   ){ |  | 
|  248     match = 1; |  | 
|  249     if( p->nArg==nArg || nArg==-1 ){ |  | 
|  250       match = 4; |  | 
|  251     } |  | 
|  252     if( enc==p->iPrefEnc ){ |  | 
|  253       match += 2; |  | 
|  254     } |  | 
|  255     else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) || |  | 
|  256              (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){ |  | 
|  257       match += 1; |  | 
|  258     } |  | 
|  259   } |  | 
|  260   return match; |  | 
|  261 } |  | 
|  262  |  | 
|  263 /* |  | 
|  264 ** Search a FuncDefHash for a function with the given name.  Return |  | 
|  265 ** a pointer to the matching FuncDef if found, or 0 if there is no match. |  | 
|  266 */ |  | 
|  267 static FuncDef *functionSearch( |  | 
|  268   FuncDefHash *pHash,  /* Hash table to search */ |  | 
|  269   int h,               /* Hash of the name */ |  | 
|  270   const char *zFunc,   /* Name of function */ |  | 
|  271   int nFunc            /* Number of bytes in zFunc */ |  | 
|  272 ){ |  | 
|  273   FuncDef *p; |  | 
|  274   for(p=pHash->a[h]; p; p=p->pHash){ |  | 
|  275     if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 && p->zName[nFunc]==0 ){ |  | 
|  276       return p; |  | 
|  277     } |  | 
|  278   } |  | 
|  279   return 0; |  | 
|  280 } |  | 
|  281  |  | 
|  282 /* |  | 
|  283 ** Insert a new FuncDef into a FuncDefHash hash table. |  | 
|  284 */ |  | 
|  285 void sqlite3FuncDefInsert( |  | 
|  286   FuncDefHash *pHash,  /* The hash table into which to insert */ |  | 
|  287   FuncDef *pDef        /* The function definition to insert */ |  | 
|  288 ){ |  | 
|  289   FuncDef *pOther; |  | 
|  290   int nName = sqlite3Strlen30(pDef->zName); |  | 
|  291   u8 c1 = (u8)pDef->zName[0]; |  | 
|  292   int h = (sqlite3UpperToLower[c1] + nName) % ArraySize(pHash->a); |  | 
|  293   pOther = functionSearch(pHash, h, pDef->zName, nName); |  | 
|  294   if( pOther ){ |  | 
|  295     assert( pOther!=pDef && pOther->pNext!=pDef ); |  | 
|  296     pDef->pNext = pOther->pNext; |  | 
|  297     pOther->pNext = pDef; |  | 
|  298   }else{ |  | 
|  299     pDef->pNext = 0; |  | 
|  300     pDef->pHash = pHash->a[h]; |  | 
|  301     pHash->a[h] = pDef; |  | 
|  302   } |  | 
|  303 } |  | 
|  304    |  | 
|  305    |  | 
|  306  |  | 
|  307 /* |  | 
|  308 ** Locate a user function given a name, a number of arguments and a flag |  | 
|  309 ** indicating whether the function prefers UTF-16 over UTF-8.  Return a |  | 
|  310 ** pointer to the FuncDef structure that defines that function, or return |  | 
|  311 ** NULL if the function does not exist. |  | 
|  312 ** |  | 
|  313 ** If the createFlag argument is true, then a new (blank) FuncDef |  | 
|  314 ** structure is created and liked into the "db" structure if a |  | 
|  315 ** no matching function previously existed.  When createFlag is true |  | 
|  316 ** and the nArg parameter is -1, then only a function that accepts |  | 
|  317 ** any number of arguments will be returned. |  | 
|  318 ** |  | 
|  319 ** If createFlag is false and nArg is -1, then the first valid |  | 
|  320 ** function found is returned.  A function is valid if either xFunc |  | 
|  321 ** or xStep is non-zero. |  | 
|  322 ** |  | 
|  323 ** If createFlag is false, then a function with the required name and |  | 
|  324 ** number of arguments may be returned even if the eTextRep flag does not |  | 
|  325 ** match that requested. |  | 
|  326 */ |  | 
|  327 FuncDef *sqlite3FindFunction( |  | 
|  328   sqlite3 *db,       /* An open database */ |  | 
|  329   const char *zName, /* Name of the function.  Not null-terminated */ |  | 
|  330   int nName,         /* Number of characters in the name */ |  | 
|  331   int nArg,          /* Number of arguments.  -1 means any number */ |  | 
|  332   u8 enc,            /* Preferred text encoding */ |  | 
|  333   int createFlag     /* Create new entry if true and does not otherwise exist */ |  | 
|  334 ){ |  | 
|  335   FuncDef *p;         /* Iterator variable */ |  | 
|  336   FuncDef *pBest = 0; /* Best match found so far */ |  | 
|  337   int bestScore = 0;  /* Score of best match */ |  | 
|  338   int h;              /* Hash value */ |  | 
|  339  |  | 
|  340  |  | 
|  341   assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); |  | 
|  342   h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a); |  | 
|  343  |  | 
|  344   /* First search for a match amongst the application-defined functions. |  | 
|  345   */ |  | 
|  346   p = functionSearch(&db->aFunc, h, zName, nName); |  | 
|  347   while( p ){ |  | 
|  348     int score = matchQuality(p, nArg, enc); |  | 
|  349     if( score>bestScore ){ |  | 
|  350       pBest = p; |  | 
|  351       bestScore = score; |  | 
|  352     } |  | 
|  353     p = p->pNext; |  | 
|  354   } |  | 
|  355  |  | 
|  356   /* If no match is found, search the built-in functions. |  | 
|  357   ** |  | 
|  358   ** Except, if createFlag is true, that means that we are trying to |  | 
|  359   ** install a new function.  Whatever FuncDef structure is returned will |  | 
|  360   ** have fields overwritten with new information appropriate for the |  | 
|  361   ** new function.  But the FuncDefs for built-in functions are read-only. |  | 
|  362   ** So we must not search for built-ins when creating a new function. |  | 
|  363   */  |  | 
|  364   if( !createFlag && !pBest ){ |  | 
|  365     FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); |  | 
|  366     p = functionSearch(pHash, h, zName, nName); |  | 
|  367     while( p ){ |  | 
|  368       int score = matchQuality(p, nArg, enc); |  | 
|  369       if( score>bestScore ){ |  | 
|  370         pBest = p; |  | 
|  371         bestScore = score; |  | 
|  372       } |  | 
|  373       p = p->pNext; |  | 
|  374     } |  | 
|  375   } |  | 
|  376  |  | 
|  377   /* If the createFlag parameter is true and the search did not reveal an |  | 
|  378   ** exact match for the name, number of arguments and encoding, then add a |  | 
|  379   ** new entry to the hash table and return it. |  | 
|  380   */ |  | 
|  381   if( createFlag && (bestScore<6 || pBest->nArg!=nArg) &&  |  | 
|  382       (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){ |  | 
|  383     pBest->zName = (char *)&pBest[1]; |  | 
|  384     pBest->nArg = (u16)nArg; |  | 
|  385     pBest->iPrefEnc = enc; |  | 
|  386     memcpy(pBest->zName, zName, nName); |  | 
|  387     pBest->zName[nName] = 0; |  | 
|  388     sqlite3FuncDefInsert(&db->aFunc, pBest); |  | 
|  389   } |  | 
|  390  |  | 
|  391   if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){ |  | 
|  392     return pBest; |  | 
|  393   } |  | 
|  394   return 0; |  | 
|  395 } |  | 
|  396  |  | 
|  397 /* |  | 
|  398 ** Free all resources held by the schema structure. The void* argument points |  | 
|  399 ** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the  |  | 
|  400 ** pointer itself, it just cleans up subsiduary resources (i.e. the contents |  | 
|  401 ** of the schema hash tables). |  | 
|  402 ** |  | 
|  403 ** The Schema.cache_size variable is not cleared. |  | 
|  404 */ |  | 
|  405 void sqlite3SchemaFree(void *p){ |  | 
|  406   Hash temp1; |  | 
|  407   Hash temp2; |  | 
|  408   HashElem *pElem; |  | 
|  409   Schema *pSchema = (Schema *)p; |  | 
|  410  |  | 
|  411   temp1 = pSchema->tblHash; |  | 
|  412   temp2 = pSchema->trigHash; |  | 
|  413   sqlite3HashInit(&pSchema->trigHash); |  | 
|  414   sqlite3HashClear(&pSchema->idxHash); |  | 
|  415   for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ |  | 
|  416     sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem)); |  | 
|  417   } |  | 
|  418   sqlite3HashClear(&temp2); |  | 
|  419   sqlite3HashInit(&pSchema->tblHash); |  | 
|  420   for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ |  | 
|  421     Table *pTab = sqliteHashData(pElem); |  | 
|  422     assert( pTab->dbMem==0 ); |  | 
|  423     sqlite3DeleteTable(pTab); |  | 
|  424   } |  | 
|  425   sqlite3HashClear(&temp1); |  | 
|  426   pSchema->pSeqTab = 0; |  | 
|  427   pSchema->flags &= ~DB_SchemaLoaded; |  | 
|  428 } |  | 
|  429  |  | 
|  430 /* |  | 
|  431 ** Find and return the schema associated with a BTree.  Create |  | 
|  432 ** a new one if necessary. |  | 
|  433 */ |  | 
|  434 Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ |  | 
|  435   Schema * p; |  | 
|  436   if( pBt ){ |  | 
|  437     p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaFree); |  | 
|  438   }else{ |  | 
|  439     p = (Schema *)sqlite3MallocZero(sizeof(Schema)); |  | 
|  440   } |  | 
|  441   if( !p ){ |  | 
|  442     db->mallocFailed = 1; |  | 
|  443   }else if ( 0==p->file_format ){ |  | 
|  444     sqlite3HashInit(&p->tblHash); |  | 
|  445     sqlite3HashInit(&p->idxHash); |  | 
|  446     sqlite3HashInit(&p->trigHash); |  | 
|  447     p->enc = SQLITE_UTF8; |  | 
|  448   } |  | 
|  449   return p; |  | 
|  450 } |  | 
| OLD | NEW |