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>