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