Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
callback.c548 linesDownload Raw Back to src
1/*2** 2005 May 23 3**4** The author disclaims copyright to this source code.  In place of5** 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 tables14** of user defined functions and collation sequences.15*/16 17#include "sqliteInt.h"18 19/*20** Invoke the 'collation needed' callback to request a collation sequence21** in the encoding enc of name zName, length nName.22*/23static void callCollNeeded(sqlite3 *db, int enc, const char *zName){24  assert( !db->xCollNeeded || !db->xCollNeeded16 );25  if( db->xCollNeeded ){26    char *zExternal = sqlite3DbStrDup(db, zName);27    if( !zExternal ) return;28    db->xCollNeeded(db->pCollNeededArg, db, enc, zExternal);29    sqlite3DbFree(db, zExternal);30  }31#ifndef SQLITE_OMIT_UTF1632  if( db->xCollNeeded16 ){33    char const *zExternal;34    sqlite3_value *pTmp = sqlite3ValueNew(db);35    sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC);36    zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE);37    if( zExternal ){38      db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal);39    }40    sqlite3ValueFree(pTmp);41  }42#endif43}44 45/*46** This routine is called if the collation factory fails to deliver a47** collation function in the best encoding but there may be other versions48** of this collation function (for other text encodings) available. Use one49** of these instead if they exist. Avoid a UTF-8 <-> UTF-16 conversion if50** possible.51*/52static int synthCollSeq(sqlite3 *db, CollSeq *pColl){53  CollSeq *pColl2;54  char *z = pColl->zName;55  int i;56  static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 };57  for(i=0; i<3; i++){58    pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, 0);59    if( pColl2->xCmp!=0 ){60      memcpy(pColl, pColl2, sizeof(CollSeq));61      pColl->xDel = 0;         /* Do not copy the destructor */62      return SQLITE_OK;63    }64  }65  return SQLITE_ERROR;66}67 68/*69** This routine is called on a collation sequence before it is used to70** check that it is defined. An undefined collation sequence exists when71** a database is loaded that contains references to collation sequences72** that have not been defined by sqlite3_create_collation() etc.73**74** If required, this routine calls the 'collation needed' callback to75** request a definition of the collating sequence. If this doesn't work, 76** an equivalent collating sequence that uses a text encoding different77** from the main database is substituted, if one is available.78*/79int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){80  if( pColl && pColl->xCmp==0 ){81    const char *zName = pColl->zName;82    sqlite3 *db = pParse->db;83    CollSeq *p = sqlite3GetCollSeq(pParse, ENC(db), pColl, zName);84    if( !p ){85      return SQLITE_ERROR;86    }87    assert( p==pColl );88  }89  return SQLITE_OK;90}91 92 93 94/*95** Locate and return an entry from the db.aCollSeq hash table. If the entry96** specified by zName and nName is not found and parameter 'create' is97** true, then create a new entry. Otherwise return NULL.98**99** Each pointer stored in the sqlite3.aCollSeq hash table contains an100** array of three CollSeq structures. The first is the collation sequence101** preferred for UTF-8, the second UTF-16le, and the third UTF-16be.102**103** Stored immediately after the three collation sequences is a copy of104** the collation sequence name. A pointer to this string is stored in105** each collation sequence structure.106*/107static CollSeq *findCollSeqEntry(108  sqlite3 *db,          /* Database connection */109  const char *zName,    /* Name of the collating sequence */110  int create            /* Create a new entry if true */111){112  CollSeq *pColl;113  pColl = sqlite3HashFind(&db->aCollSeq, zName);114 115  if( 0==pColl && create ){116    int nName = sqlite3Strlen30(zName) + 1;117    pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName);118    if( pColl ){119      CollSeq *pDel = 0;120      pColl[0].zName = (char*)&pColl[3];121      pColl[0].enc = SQLITE_UTF8;122      pColl[1].zName = (char*)&pColl[3];123      pColl[1].enc = SQLITE_UTF16LE;124      pColl[2].zName = (char*)&pColl[3];125      pColl[2].enc = SQLITE_UTF16BE;126      memcpy(pColl[0].zName, zName, nName);127      pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, pColl);128 129      /* If a malloc() failure occurred in sqlite3HashInsert(), it will 130      ** return the pColl pointer to be deleted (because it wasn't added131      ** to the hash table).132      */133      assert( pDel==0 || pDel==pColl );134      if( pDel!=0 ){135        sqlite3OomFault(db);136        sqlite3DbFree(db, pDel);137        pColl = 0;138      }139    }140  }141  return pColl;142}143 144/*145** Parameter zName points to a UTF-8 encoded string nName bytes long.146** Return the CollSeq* pointer for the collation sequence named zName147** for the encoding 'enc' from the database 'db'.148**149** If the entry specified is not found and 'create' is true, then create a150** new entry.  Otherwise return NULL.151**152** A separate function sqlite3LocateCollSeq() is a wrapper around153** this routine.  sqlite3LocateCollSeq() invokes the collation factory154** if necessary and generates an error message if the collating sequence155** cannot be found.156**157** See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq()158*/159CollSeq *sqlite3FindCollSeq(160  sqlite3 *db,          /* Database connection to search */161  u8 enc,               /* Desired text encoding */162  const char *zName,    /* Name of the collating sequence.  Might be NULL */163  int create            /* True to create CollSeq if doesn't already exist */164){165  CollSeq *pColl;166  assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );167  assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );168  if( zName ){169    pColl = findCollSeqEntry(db, zName, create);170    if( pColl ) pColl += enc-1;171  }else{172    pColl = db->pDfltColl;173  }174  return pColl;175}176 177/*178** Change the text encoding for a database connection. This means that179** the pDfltColl must change as well.180*/181void sqlite3SetTextEncoding(sqlite3 *db, u8 enc){182  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );183  db->enc = enc;184  /* EVIDENCE-OF: R-08308-17224 The default collating function for all185  ** strings is BINARY. 186  */187  db->pDfltColl = sqlite3FindCollSeq(db, enc, sqlite3StrBINARY, 0);188  sqlite3ExpirePreparedStatements(db, 1);189}190 191/*192** This function is responsible for invoking the collation factory callback193** or substituting a collation sequence of a different encoding when the194** requested collation sequence is not available in the desired encoding.195** 196** If it is not NULL, then pColl must point to the database native encoding 197** collation sequence with name zName, length nName.198**199** The return value is either the collation sequence to be used in database200** db for collation type name zName, length nName, or NULL, if no collation201** sequence can be found.  If no collation is found, leave an error message.202**203** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()204*/205CollSeq *sqlite3GetCollSeq(206  Parse *pParse,        /* Parsing context */207  u8 enc,               /* The desired encoding for the collating sequence */208  CollSeq *pColl,       /* Collating sequence with native encoding, or NULL */209  const char *zName     /* Collating sequence name */210){211  CollSeq *p;212  sqlite3 *db = pParse->db;213 214  p = pColl;215  if( !p ){216    p = sqlite3FindCollSeq(db, enc, zName, 0);217  }218  if( !p || !p->xCmp ){219    /* No collation sequence of this type for this encoding is registered.220    ** Call the collation factory to see if it can supply us with one.221    */222    callCollNeeded(db, enc, zName);223    p = sqlite3FindCollSeq(db, enc, zName, 0);224  }225  if( p && !p->xCmp && synthCollSeq(db, p) ){226    p = 0;227  }228  assert( !p || p->xCmp );229  if( p==0 ){230    sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);231    pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ;232  }233  return p;234}235 236/*237** This function returns the collation sequence for database native text238** encoding identified by the string zName.239**240** If the requested collation sequence is not available, or not available241** in the database native encoding, the collation factory is invoked to242** request it. If the collation factory does not supply such a sequence,243** and the sequence is available in another text encoding, then that is244** returned instead.245**246** If no versions of the requested collations sequence are available, or247** another error occurs, NULL is returned and an error message written into248** pParse.249**250** This routine is a wrapper around sqlite3FindCollSeq().  This routine251** invokes the collation factory if the named collation cannot be found252** and generates an error message.253**254** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq()255*/256CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){257  sqlite3 *db = pParse->db;258  u8 enc = ENC(db);259  u8 initbusy = db->init.busy;260  CollSeq *pColl;261 262  pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);263  if( !initbusy && (!pColl || !pColl->xCmp) ){264    pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);265  }266 267  return pColl;268}269 270/* During the search for the best function definition, this procedure271** is called to test how well the function passed as the first argument272** matches the request for a function with nArg arguments in a system273** that uses encoding enc. The value returned indicates how well the274** request is matched. A higher value indicates a better match.275**276** If nArg is -1 that means to only return a match (non-zero) if p->nArg277** is also -1.  In other words, we are searching for a function that278** takes a variable number of arguments.279**280** If nArg is -2 that means that we are searching for any function 281** regardless of the number of arguments it uses, so return a positive282** match score for any283**284** The returned value is always between 0 and 6, as follows:285**286** 0: Not a match.287** 1: UTF8/16 conversion required and function takes any number of arguments.288** 2: UTF16 byte order change required and function takes any number of args.289** 3: encoding matches and function takes any number of arguments290** 4: UTF8/16 conversion required - argument count matches exactly291** 5: UTF16 byte order conversion required - argument count matches exactly292** 6: Perfect match:  encoding and argument count match exactly.293**294** If nArg==(-2) then any function with a non-null xSFunc is295** a perfect match and any function with xSFunc NULL is296** a non-match.297*/298#define FUNC_PERFECT_MATCH 6  /* The score for a perfect match */299static int matchQuality(300  FuncDef *p,     /* The function we are evaluating for match quality */301  int nArg,       /* Desired number of arguments.  (-1)==any */302  u8 enc          /* Desired text encoding */303){304  int match;305  assert( p->nArg>=(-4) && p->nArg!=(-2) );306  assert( nArg>=(-2) );307 308  /* Wrong number of arguments means "no match" */309  if( p->nArg!=nArg ){310    if( nArg==(-2) ) return p->xSFunc==0 ? 0 : FUNC_PERFECT_MATCH;311    if( p->nArg>=0 ) return 0;312    /* Special p->nArg values available to built-in functions only:313    **    -3     1 or more arguments required314    **    -4     2 or more arguments required315    */316    if( p->nArg<(-2) && nArg<(-2-p->nArg) ) return 0;317  }318 319  /* Give a better score to a function with a specific number of arguments320  ** than to function that accepts any number of arguments. */321  if( p->nArg==nArg ){322    match = 4;323  }else{324    match = 1;325  }326 327  /* Bonus points if the text encoding matches */328  if( enc==(p->funcFlags & SQLITE_FUNC_ENCMASK) ){329    match += 2;  /* Exact encoding match */330  }else if( (enc & p->funcFlags & 2)!=0 ){331    match += 1;  /* Both are UTF16, but with different byte orders */332  }333 334  return match;335}336 337/*338** Search a FuncDefHash for a function with the given name.  Return339** a pointer to the matching FuncDef if found, or 0 if there is no match.340*/341FuncDef *sqlite3FunctionSearch(342  int h,               /* Hash of the name */343  const char *zFunc    /* Name of function */344){345  FuncDef *p;346  for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){347    assert( p->funcFlags & SQLITE_FUNC_BUILTIN );348    if( sqlite3StrICmp(p->zName, zFunc)==0 ){349      return p;350    }351  }352  return 0;353}354 355/*356** Insert a new FuncDef into a FuncDefHash hash table.357*/358void sqlite3InsertBuiltinFuncs(359  FuncDef *aDef,      /* List of global functions to be inserted */360  int nDef            /* Length of the apDef[] list */361){362  int i;363  for(i=0; i<nDef; i++){364    FuncDef *pOther;365    const char *zName = aDef[i].zName;366    int nName = sqlite3Strlen30(zName);367    int h = SQLITE_FUNC_HASH(zName[0], nName);368    assert( aDef[i].funcFlags & SQLITE_FUNC_BUILTIN );369    pOther = sqlite3FunctionSearch(h, zName);370    if( pOther ){371      assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] );372      aDef[i].pNext = pOther->pNext;373      pOther->pNext = &aDef[i];374    }else{375      aDef[i].pNext = 0;376      aDef[i].u.pHash = sqlite3BuiltinFunctions.a[h];377      sqlite3BuiltinFunctions.a[h] = &aDef[i];378    }379  }380}381  382  383 384/*385** Locate a user function given a name, a number of arguments and a flag386** indicating whether the function prefers UTF-16 over UTF-8.  Return a387** pointer to the FuncDef structure that defines that function, or return388** NULL if the function does not exist.389**390** If the createFlag argument is true, then a new (blank) FuncDef391** structure is created and liked into the "db" structure if a392** no matching function previously existed.393**394** If nArg is -2, then the first valid function found is returned.  A395** function is valid if xSFunc is non-zero.  The nArg==(-2)396** case is used to see if zName is a valid function name for some number397** of arguments.  If nArg is -2, then createFlag must be 0.398**399** If createFlag is false, then a function with the required name and400** number of arguments may be returned even if the eTextRep flag does not401** match that requested.402*/403FuncDef *sqlite3FindFunction(404  sqlite3 *db,       /* An open database */405  const char *zName, /* Name of the function.  zero-terminated */406  int nArg,          /* Number of arguments.  -1 means any number */407  u8 enc,            /* Preferred text encoding */408  u8 createFlag      /* Create new entry if true and does not otherwise exist */409){410  FuncDef *p;         /* Iterator variable */411  FuncDef *pBest = 0; /* Best match found so far */412  int bestScore = 0;  /* Score of best match */413  int h;              /* Hash value */414  int nName;          /* Length of the name */415 416  assert( nArg>=(-2) );417  assert( nArg>=(-1) || createFlag==0 );418  nName = sqlite3Strlen30(zName);419 420  /* First search for a match amongst the application-defined functions.421  */422  p = (FuncDef*)sqlite3HashFind(&db->aFunc, zName);423  while( p ){424    int score = matchQuality(p, nArg, enc);425    if( score>bestScore ){426      pBest = p;427      bestScore = score;428    }429    p = p->pNext;430  }431 432  /* If no match is found, search the built-in functions.433  **434  ** If the DBFLAG_PreferBuiltin flag is set, then search the built-in435  ** functions even if a prior app-defined function was found.  And give436  ** priority to built-in functions.437  **438  ** Except, if createFlag is true, that means that we are trying to439  ** install a new function.  Whatever FuncDef structure is returned it will440  ** have fields overwritten with new information appropriate for the441  ** new function.  But the FuncDefs for built-in functions are read-only.442  ** So we must not search for built-ins when creating a new function.443  */ 444  if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){445    bestScore = 0;446    h = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zName[0]], nName);447    p = sqlite3FunctionSearch(h, zName);448    while( p ){449      int score = matchQuality(p, nArg, enc);450      if( score>bestScore ){451        pBest = p;452        bestScore = score;453      }454      p = p->pNext;455    }456  }457 458  /* If the createFlag parameter is true and the search did not reveal an459  ** exact match for the name, number of arguments and encoding, then add a460  ** new entry to the hash table and return it.461  */462  if( createFlag && bestScore<FUNC_PERFECT_MATCH && 463      (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){464    FuncDef *pOther;465    u8 *z;466    pBest->zName = (const char*)&pBest[1];467    pBest->nArg = (u16)nArg;468    pBest->funcFlags = enc;469    memcpy((char*)&pBest[1], zName, nName+1);470    for(z=(u8*)pBest->zName; *z; z++) *z = sqlite3UpperToLower[*z];471    pOther = (FuncDef*)sqlite3HashInsert(&db->aFunc, pBest->zName, pBest);472    if( pOther==pBest ){473      sqlite3DbFree(db, pBest);474      sqlite3OomFault(db);475      return 0;476    }else{477      pBest->pNext = pOther;478    }479  }480 481  if( pBest && (pBest->xSFunc || createFlag) ){482    return pBest;483  }484  return 0;485}486 487/*488** Free all resources held by the schema structure. The void* argument points489** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the 490** pointer itself, it just cleans up subsidiary resources (i.e. the contents491** of the schema hash tables).492**493** The Schema.cache_size variable is not cleared.494*/495void sqlite3SchemaClear(void *p){496  Hash temp1;497  Hash temp2;498  HashElem *pElem;499  Schema *pSchema = (Schema *)p;500  sqlite3 xdb;501 502  memset(&xdb, 0, sizeof(xdb));503  temp1 = pSchema->tblHash;504  temp2 = pSchema->trigHash;505  sqlite3HashInit(&pSchema->trigHash);506  sqlite3HashClear(&pSchema->idxHash);507  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){508    sqlite3DeleteTrigger(&xdb, (Trigger*)sqliteHashData(pElem));509  }510 511  sqlite3HashClear(&temp2);512  sqlite3HashInit(&pSchema->tblHash);513  for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){514    Table *pTab = sqliteHashData(pElem);515    sqlite3DeleteTable(&xdb, pTab);516  }517  sqlite3HashClear(&temp1);518  sqlite3HashClear(&pSchema->fkeyHash);519  pSchema->pSeqTab = 0;520  if( pSchema->schemaFlags & DB_SchemaLoaded ){521    pSchema->iGeneration++;522  }523  pSchema->schemaFlags &= ~(DB_SchemaLoaded|DB_ResetWanted);524}525 526/*527** Find and return the schema associated with a BTree.  Create528** a new one if necessary.529*/530Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){531  Schema * p;532  if( pBt ){533    p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear);534  }else{535    p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema));536  }537  if( !p ){538    sqlite3OomFault(db);539  }else if ( 0==p->file_format ){540    sqlite3HashInit(&p->tblHash);541    sqlite3HashInit(&p->idxHash);542    sqlite3HashInit(&p->trigHash);543    sqlite3HashInit(&p->fkeyHash);544    p->enc = SQLITE_UTF8;545  }546  return p;547}548