/* ** This function is called to drop a trigger from the database schema. ** ** This may be called directly from the parser and therefore identifies ** the trigger by name. The sqlite3DropTriggerPtr() routine does the ** same job as this routine except it takes a pointer to the trigger ** instead of the trigger name. **/ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){ Trigger *pTrigger = 0; int i; const char *zDb; const char *zName; int nName; sqlite3 *db = pParse->db; if( db->mallocFailed ) goto drop_trigger_cleanup; if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto drop_trigger_cleanup; } assert( pName->nSrc==1 ); zDb = pName->a[0].zDatabase; zName = pName->a[0].zName; nName = strlen(zName); for(i=OMIT_TEMPDB; i<db->nDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName); if( pTrigger ) break; } if( !pTrigger ){ if( !noErr ){ sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); } goto drop_trigger_cleanup; } sqlite3DropTriggerPtr(pParse, pTrigger); drop_trigger_cleanup: sqlite3SrcListDelete(pName); }
/* ** This function is invoked by the vdbe to call the xCreate method ** of the virtual table named zTab in database iDb. ** ** If an error occurs, *pzErr is set to point an an English language ** description of the error and an SQLITE_XXX error code is returned. ** In this case the caller must call sqlite3DbFree(db, ) on *pzErr. */ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ int rc = SQLITE_OK; Table *pTab; Module *pMod; const char *zMod; pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); assert( pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVTable ); /* Locate the required virtual table module */ zMod = pTab->azModuleArg[0]; pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod)); /* If the module has been registered and includes a Create method, ** invoke it now. If the module has not been registered, return an ** error. Otherwise, do nothing. */ if( !pMod ){ *pzErr = sqlite3MPrintf(db, "no such module: %s", zMod); rc = SQLITE_ERROR; }else{ rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr); } /* Justification of ALWAYS(): The xConstructor method is required to ** create a valid sqlite3_vtab if it returns SQLITE_OK. */ if( rc==SQLITE_OK && ALWAYS(sqlite3GetVTable(db, pTab)) ){ rc = growVTrans(db); if( rc==SQLITE_OK ){ addToVTrans(db, sqlite3GetVTable(db, pTab)); } } return rc; }
/* ** This function is invoked by the parser to call the xConnect() method ** of the virtual table pTab. If an error occurs, an error code is returned ** and an error left in pParse. ** ** This call is a no-op if table pTab is not a virtual table. */ int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){ sqlite3 *db = pParse->db; const char *zMod; Module *pMod; int rc; assert( pTab ); if( (pTab->tabFlags & TF_Virtual)==0 || sqlite3GetVTable(db, pTab) ){ return SQLITE_OK; } /* Locate the required virtual table module */ zMod = pTab->azModuleArg[0]; pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod)); if( !pMod ){ const char *zModule = pTab->azModuleArg[0]; sqlite3ErrorMsg(pParse, "no such module: %s", zModule); rc = SQLITE_ERROR; }else{ char *zErr = 0; rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr); if( rc!=SQLITE_OK ){ sqlite3ErrorMsg(pParse, "%s", zErr); } sqlite3DbFree(db, zErr); } return rc; }
/* ** Locate and return an entry from the db.aCollSeq hash table. If the entry ** specified by zName and nName is not found and parameter 'create' is ** true, then create a new entry. Otherwise return NULL. ** ** Each pointer stored in the sqlite3.aCollSeq hash table contains an ** array of three CollSeq structures. The first is the collation sequence ** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be. ** ** Stored immediately after the three collation sequences is a copy of ** the collation sequence name. A pointer to this string is stored in ** each collation sequence structure. */ static CollSeq *findCollSeqEntry( sqlite3 *db, const char *zName, int nName, int create ) { CollSeq *pColl; if( nName<0 ) nName = strlen(zName); pColl = sqlite3HashFind(&db->aCollSeq, zName, nName); if( 0==pColl && create ) { pColl = sqliteMalloc( 3*sizeof(*pColl) + nName + 1 ); if( pColl ) { CollSeq *pDel = 0; pColl[0].zName = (char*)&pColl[3]; pColl[0].enc = SQLITE_UTF8; pColl[1].zName = (char*)&pColl[3]; pColl[1].enc = SQLITE_UTF16LE; pColl[2].zName = (char*)&pColl[3]; pColl[2].enc = SQLITE_UTF16BE; memcpy(pColl[0].zName, zName, nName); pColl[0].zName[nName] = 0; pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl); /* If a malloc() failure occured in sqlite3HashInsert(), it will ** return the pColl pointer to be deleted (because it wasn't added ** to the hash table). */ assert( !pDel || (sqlite3_malloc_failed && pDel==pColl) ); sqliteFree(pDel); } } return pColl; }
static int exist_callback(void *pArg, int argc, char **argv, char **columnNames){ extension_cache *cache; char key[ARRAY_SIZE]; int pri; time_t now; int needs_add=0; switch_config *config=NULL; int timeout=0; char *context; if (pArg) { config = pArg; timeout = config->timeout; } if (!timeout) timeout = default_timeout; context = argv[5] ? argv[5] : argv[0]; if (!strcmp(context,"_any_")) { ast_verbose(VERBOSE_PREFIX_2 "SQLiteSwitch: magic extension: %s not cached\n",argv[1]); return 0; } snprintf(key, ARRAY_SIZE, "%s.%s", argv[1], context); time(&now); pri = atoi(argv[2]); cache = (extension_cache *) sqlite3HashFind(&extens,key,strlen(key)); if (! cache) { cache = malloc(sizeof(extension_cache)); needs_add = 1; } if (needs_add || cache->expires < now) { memset(cache,0,sizeof(extension_cache)); strncpy(cache->context,argv[0],sizeof(cache->context)); strncpy(cache->exten,argv[1],sizeof(cache->exten)); } cache->expires = now + timeout; if (config && ! config->seeheads) { ast_verbose(VERBOSE_PREFIX_2 "SQLiteSwitch: extension %s@%s will expire in %d seconds\n",argv[1],context,timeout); config->seeheads = 1; } strncpy(cache->app_name[pri], argv[3], sizeof(cache->app_name[pri])); strncpy(cache->app_data[pri], argv[4], sizeof(cache->app_data[pri])); if (needs_add) { sqlite3HashInsert(&extens, key, strlen(key), cache); } return 0; }
/* ** This function is called when the pager layer first opens a database file ** and is checking for a hot-journal. */ static int asyncCheckReservedLock(OsFile *id){ AsyncFile *pFile = (AsyncFile*)id; int rc; pthread_mutex_lock(&async.lockMutex); rc = (int)sqlite3HashFind(&async.aLock, pFile->zName, pFile->nName); pthread_mutex_unlock(&async.lockMutex); ASYNC_TRACE(("CHECK-LOCK %d (%s)\n", rc, pFile->zName)); return rc>SHARED_LOCK; }
SWITCH_DECLARE(void *) switch_core_hash_find_locked(switch_hash_t *hash, const char *key, switch_mutex_t *mutex) { void *val; if (mutex) { switch_mutex_lock(mutex); } val = sqlite3HashFind(&hash->table, key, (int) strlen(key) + 1); if (mutex) { switch_mutex_unlock(mutex); } return val; }
SWITCH_DECLARE(void *) switch_core_hash_find_rdlock(switch_hash_t *hash, const char *key, switch_thread_rwlock_t *rwlock) { void *val; if (rwlock) { switch_thread_rwlock_rdlock(rwlock); } val = sqlite3HashFind(&hash->table, key, (int) strlen(key) + 1); if (rwlock) { switch_thread_rwlock_unlock(rwlock); } return val; }
/* ** The actual function that does the work of creating a new module. ** This function implements the sqlite3_create_module() and ** sqlite3_create_module_v2() interfaces. */ static int createModule( sqlite3 *db, /* Database in which module is registered */ const char *zName, /* Name assigned to this module */ const sqlite3_module *pModule, /* The definition of the module */ void *pAux, /* Context pointer for xCreate/xConnect */ void (*xDestroy)(void *) /* Module destructor function */ ){ int rc = SQLITE_OK; sqlite3_mutex_enter(db->mutex); if( sqlite3HashFind(&db->aModule, zName) ){ rc = SQLITE_MISUSE_BKPT; }else{ (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy); } rc = sqlite3ApiExit(db, rc); if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux); sqlite3_mutex_leave(db->mutex); return rc; }
/* ** The actual function that does the work of creating a new module. ** This function implements the sqlite3_create_module() and ** sqlite3_create_module_v2() interfaces. */ static int createModule( sqlite3 *db, /* Database in which module is registered */ const char *zName, /* Name assigned to this module */ const sqlite3_module *pModule, /* The definition of the module */ void *pAux, /* Context pointer for xCreate/xConnect */ void (*xDestroy)(void *) /* Module destructor function */ ){ int rc = SQLITE_OK; int nName; sqlite3_mutex_enter(db->mutex); nName = sqlite3Strlen30(zName); if( sqlite3HashFind(&db->aModule, zName) ){ rc = SQLITE_MISUSE_BKPT; }else{ Module *pMod; pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1); if( pMod ){ Module *pDel; char *zCopy = (char *)(&pMod[1]); memcpy(zCopy, zName, nName+1); pMod->zName = zCopy; pMod->pModule = pModule; pMod->pAux = pAux; pMod->xDestroy = xDestroy; pMod->pEpoTab = 0; pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); assert( pDel==0 || pDel==pMod ); if( pDel ){ db->mallocFailed = 1; sqlite3DbFree(db, pDel); } } } rc = sqlite3ApiExit(db, rc); if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux); sqlite3_mutex_leave(db->mutex); return rc; }
/* ** This function is called to drop a trigger from the database schema. ** ** This may be called directly from the parser and therefore identifies ** the trigger by name. The sqlite3DropTriggerPtr() routine does the ** same job as this routine except it takes a pointer to the trigger ** instead of the trigger name. **/ SQLITE_PRIVATE void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){ Trigger *pTrigger = 0; int i; const char *zDb; const char *zName; int nName; sqlite3 *db = pParse->db; if( db->mallocFailed ) goto drop_trigger_cleanup; if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto drop_trigger_cleanup; } assert( pName->nSrc==1 ); zDb = pName->a[0].zDatabase; zName = pName->a[0].zName; nName = sqlite3Strlen30(zName); assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; i<db->nDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName); if( pTrigger ) break; } if( !pTrigger ){ if( !noErr ){ sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); }else{ sqlite3CodeVerifyNamedSchema(pParse, zDb); } pParse->checkSchema = 1; goto drop_trigger_cleanup; } sqlite3DropTriggerPtr(pParse, pTrigger); drop_trigger_cleanup: sqlite3SrcListDelete(db, pName); }
/* ** Locate and return an entry from the db.aCollSeq hash table. If the entry ** specified by zName and nName is not found and parameter 'create' is ** true, then create a new entry. Otherwise return NULL. ** ** Each pointer stored in the sqlite3.aCollSeq hash table contains an ** array of three CollSeq structures. The first is the collation sequence ** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be. ** ** Stored immediately after the three collation sequences is a copy of ** the collation sequence name. A pointer to this string is stored in ** each collation sequence structure. */ static CollSeq *findCollSeqEntry( sqlite3 *db, /* Database connection */ const char *zName, /* Name of the collating sequence */ int create /* Create a new entry if true */ ){ CollSeq *pColl; int nName = sqlite3Strlen30(zName); pColl = sqlite3HashFind(&db->aCollSeq, zName, nName); if( 0==pColl && create ){ pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 ); if( pColl ){ CollSeq *pDel = 0; pColl[0].zName = (char*)&pColl[3]; pColl[0].enc = SQLITE_UTF8; pColl[1].zName = (char*)&pColl[3]; pColl[1].enc = SQLITE_UTF16LE; pColl[2].zName = (char*)&pColl[3]; pColl[2].enc = SQLITE_UTF16BE; memcpy(pColl[0].zName, zName, nName); pColl[0].zName[nName] = 0; pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl); /* If a malloc() failure occurred in sqlite3HashInsert(), it will ** return the pColl pointer to be deleted (because it wasn't added ** to the hash table). */ assert( pDel==0 || pDel==pColl ); if( pDel!=0 ){ db->mallocFailed = 1; sqlite3DbFree(db, pDel); pColl = 0; } } } return pColl; }
static int SQLiteSwitch_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) { int res = 0; char key[ARRAY_SIZE]; extension_cache *cache; time_t now; char *errmsg = NULL; char databuf[ARRAY_SIZE]; char *table,*tmp,*filename=NULL; int expires=0; switch_config config; sqlite3 *db=NULL; char *sql = NULL; memset(&config,0,sizeof(switch_config)); memset(databuf,0,ARRAY_SIZE); strncpy(databuf,data,ARRAY_SIZE); if (!strlen(databuf)) strncpy(databuf,switch_table,ARRAY_SIZE); table = databuf; tmp = strchr(table,':'); if (tmp) { *tmp = '\0'; tmp++; expires = atoi(tmp); filename = strchr(tmp,':'); if (filename) { *filename = '\0'; filename++; } } if (!expires) expires = default_timeout; config.timeout = expires; if (!filename) filename = switch_dbfile; //ast_log(LOG_NOTICE, "SQLiteSwitch_exists %d: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", res, context, exten, priority, callerid ? callerid : "<unknown>", data); time(&now); snprintf(key, ARRAY_SIZE, "%s.%s", exten, context); ast_verbose(VERBOSE_PREFIX_2 "SQLiteSwitch_exists lookup [%s]: ",key); cache = (extension_cache *) sqlite3HashFind(&extens,key,strlen(key)); ast_verbose("%s\n",cache ? "match" : "fail"); if (! cache || (cache && cache->expires < now) ) { if ((db = open_db(filename))) { if((sql = sqlite3_mprintf("select *,'%q' as real_context from %q where (context='%q' or context='_any_') and exten='%q' order by context,exten,pri", context, table, context, exten ))) { sqlite3_exec( db, sql, exist_callback, &config, &errmsg ); if (errmsg) { ast_log(LOG_WARNING,"SQL ERR [%s]\n",errmsg); sqlite3_free(errmsg); errmsg = NULL; } } else { ast_log(LOG_WARNING,"malloc failed, good luck!\n"); } sqlite3_close(db); if (sql) { sqlite3_free(sql); sql = NULL; } cache = (extension_cache *) sqlite3HashFind(&extens,key,strlen(key)); } else { ast_log(LOG_WARNING,"ERROR OPEINING DB.\n"); return -1; } } if (cache) { ast_verbose(VERBOSE_PREFIX_2 "SQLiteSwitch_exists lookup [%s,%d]: ",key,priority); res = strlen(cache->app_name[priority]) ? 1 : 0; ast_verbose("%s\n",res ? "match" : "fail"); } return res; }
/* ** This function returns a pointer to the head of a linked list of FK ** constraints for which table pTab is the parent table. For example, ** given the following schema: ** ** CREATE TABLE t1(a PRIMARY KEY); ** CREATE TABLE t2(b REFERENCES t1(a); ** ** Calling this function with table "t1" as an argument returns a pointer ** to the FKey structure representing the foreign key constraint on table ** "t2". Calling this function with "t2" as the argument would return a ** NULL pointer (as there are no FK constraints for which t2 is the parent ** table). */ FKey *sqlite3FkReferences(Table *pTab){ int nName = sqlite3Strlen30(pTab->zName); return (FKey *)sqlite3HashFind(&pTab->pSchema->fkeyHash, pTab->zName, nName); }
/* ** 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 ** NULL if the function does not exist. ** ** If the createFlag argument is true, then a new (blank) FuncDef ** structure is created and liked into the "db" structure if a ** no matching function previously existed. ** ** If nArg is -2, then the first valid function found is returned. A ** function is valid if xSFunc is non-zero. The nArg==(-2) ** case is used to see if zName is a valid function name for some number ** of arguments. If nArg is -2, then createFlag must be 0. ** ** If createFlag is false, then a function with the required name and ** number of arguments may be returned even if the eTextRep flag does not ** match that requested. */ FuncDef *sqlite3FindFunction( sqlite3 *db, /* An open database */ const char *zName, /* Name of the function. zero-terminated */ int nArg, /* Number of arguments. -1 means any number */ u8 enc, /* Preferred text encoding */ u8 createFlag /* Create new entry if true and does not otherwise exist */ ){ FuncDef *p; /* Iterator variable */ FuncDef *pBest = 0; /* Best match found so far */ int bestScore = 0; /* Score of best match */ int h; /* Hash value */ int nName; /* Length of the name */ assert( nArg>=(-2) ); assert( nArg>=(-1) || createFlag==0 ); nName = sqlite3Strlen30(zName); /* First search for a match amongst the application-defined functions. */ p = (FuncDef*)sqlite3HashFind(&db->aFunc, zName); while( p ){ int score = matchQuality(p, nArg, enc); if( score>bestScore ){ pBest = p; bestScore = score; } p = p->pNext; } /* If no match is found, search the built-in functions. ** ** If the DBFLAG_PreferBuiltin flag is set, then search the built-in ** functions even if a prior app-defined function was found. And give ** priority to built-in functions. ** ** Except, if createFlag is true, that means that we are trying to ** install a new function. Whatever FuncDef structure is returned it will ** have fields overwritten with new information appropriate for the ** new function. But the FuncDefs for built-in functions are read-only. ** So we must not search for built-ins when creating a new function. */ if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){ bestScore = 0; h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ; p = functionSearch(h, zName); while( p ){ int score = matchQuality(p, nArg, enc); if( score>bestScore ){ pBest = p; bestScore = score; } p = p->pNext; } } /* If the createFlag parameter is true and the search did not reveal an ** exact match for the name, number of arguments and encoding, then add a ** new entry to the hash table and return it. */ if( createFlag && bestScore<FUNC_PERFECT_MATCH && (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){ FuncDef *pOther; pBest->zName = (const char*)&pBest[1]; pBest->nArg = (u16)nArg; pBest->funcFlags = enc; memcpy((char*)&pBest[1], zName, nName+1); pOther = (FuncDef*)sqlite3HashInsert(&db->aFunc, pBest->zName, pBest); if( pOther==pBest ){ sqlite3DbFree(db, pBest); sqlite3OomFault(db); return 0; }else{ pBest->pNext = pOther; } } if( pBest && (pBest->xSFunc || createFlag) ){ return pBest; } return 0; }
/* ** The parser calls this routine after the CREATE VIRTUAL TABLE statement ** has been completely parsed. */ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ Table *pTab; /* The table being constructed */ sqlite3 *db; /* The database connection */ char *zModule; /* The module name of the table: USING modulename */ Module *pMod = 0; addArgumentToVtab(pParse); pParse->sArg.z = 0; /* Lookup the module name. */ pTab = pParse->pNewTable; if( pTab==0 ) return; db = pParse->db; if( pTab->nModuleArg<1 ) return; zModule = pTab->azModuleArg[0]; pMod = (Module *)sqlite3HashFind(&db->aModule, zModule, strlen(zModule)); pTab->pMod = pMod; /* If the CREATE VIRTUAL TABLE statement is being entered for the ** first time (in other words if the virtual table is actually being ** created now instead of just being read out of sqlite_master) then ** do additional initialization work and store the statement text ** in the sqlite_master table. */ if( !db->init.busy ){ char *zStmt; char *zWhere; int iDb; Vdbe *v; /* Compute the complete text of the CREATE VIRTUAL TABLE statement */ if( pEnd ){ pParse->sNameToken.n = pEnd->z - pParse->sNameToken.z + pEnd->n; } zStmt = sqlite3MPrintf("CREATE VIRTUAL TABLE %T", &pParse->sNameToken); /* A slot for the record has already been allocated in the ** SQLITE_MASTER table. We just need to update that slot with all ** the information we've collected. ** ** The top of the stack is the rootpage allocated by sqlite3StartTable(). ** This value is always 0 and is ignored, a virtual table does not have a ** rootpage. The next entry on the stack is the rowid of the record ** in the sqlite_master table. */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); sqlite3NestedParse(pParse, "UPDATE %Q.%s " "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q " "WHERE rowid=#1", db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTab->zName, pTab->zName, zStmt ); sqliteFree(zStmt); v = sqlite3GetVdbe(pParse); sqlite3ChangeCookie(db, v, iDb); sqlite3VdbeAddOp(v, OP_Expire, 0, 0); zWhere = sqlite3MPrintf("name='%q'", pTab->zName); sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 1, zWhere, P3_DYNAMIC); sqlite3VdbeOp3(v, OP_VCreate, iDb, 0, pTab->zName, strlen(pTab->zName) + 1); } /* If we are rereading the sqlite_master table create the in-memory ** record of the table. If the module has already been registered, ** also call the xConnect method here. */ else { Table *pOld; Schema *pSchema = pTab->pSchema; const char *zName = pTab->zName; int nName = strlen(zName) + 1; pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab); if( pOld ){ assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ return; } pSchema->db = pParse->db; pParse->pNewTable = 0; } }
/* ** Create a new collating function for database "db". The name is zName ** and the encoding is enc. */ static int createCollation( sqlite3* db, const char *zName, int enc, void* pCtx, int(*xCompare)(void*,int,const void*,int,const void*), void(*xDel)(void*) ){ CollSeq *pColl; int enc2; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } assert( sqlite3_mutex_held(db->mutex) ); /* If SQLITE_UTF16 is specified as the encoding type, transform this ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. */ enc2 = enc & ~SQLITE_UTF16_ALIGNED; if( enc2==SQLITE_UTF16 ){ enc2 = SQLITE_UTF16NATIVE; } if( (enc2&~3)!=0 ){ sqlite3Error(db, SQLITE_ERROR, "unknown encoding"); return SQLITE_ERROR; } /* Check if this call is removing or replacing an existing collation ** sequence. If so, and there are active VMs, return busy. If there ** are no active VMs, invalidate any pre-compiled statements. */ pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 0); if( pColl && pColl->xCmp ){ if( db->activeVdbeCnt ){ sqlite3Error(db, SQLITE_BUSY, "Unable to delete/modify collation sequence due to active statements"); return SQLITE_BUSY; } sqlite3ExpirePreparedStatements(db); /* If collation sequence pColl was created directly by a call to ** sqlite3_create_collation, and not generated by synthCollSeq(), ** then any copies made by synthCollSeq() need to be invalidated. ** Also, collation destructor - CollSeq.xDel() - function may need ** to be called. */ if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){ CollSeq *aColl = (CollSeq*)sqlite3HashFind(&db->aCollSeq, zName, strlen(zName)); int j; for(j=0; j<3; j++){ CollSeq *p = &aColl[j]; if( p->enc==pColl->enc ){ if( p->xDel ){ p->xDel(p->pUser); } p->xCmp = 0; } } } } pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 1); if( pColl ){ pColl->xCmp = xCompare; pColl->pUser = pCtx; pColl->xDel = xDel; pColl->enc = enc2 | (enc & SQLITE_UTF16_ALIGNED); } sqlite3Error(db, SQLITE_OK, 0); return SQLITE_OK; }
/* ** Return a pointer to the Table structure for the table that a trigger ** is set on. */ static Table *tableOfTrigger(Trigger *pTrigger){ return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table); }
SWITCH_DECLARE(void *) switch_core_hash_find(switch_hash_t *hash, const char *key) { return sqlite3HashFind(&hash->table, key, (int) strlen(key) + 1); }
/* ** This routine is called after all of the trigger actions have been parsed ** in order to complete the process of building the trigger. */ void sqlite3FinishTrigger( Parse *pParse, /* Parser context */ TriggerStep *pStepList, /* The triggered program */ Token *pAll /* Token that describes the complete CREATE TRIGGER */ ){ Trigger *pTrig = 0; /* The trigger whose construction is finishing up */ sqlite3 *db = pParse->db; /* The database */ DbFixer sFix; int iDb; /* Database containing the trigger */ pTrig = pParse->pNewTrigger; pParse->pNewTrigger = 0; if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup; iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); pTrig->step_list = pStepList; while( pStepList ){ pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken) && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ goto triggerfinish_cleanup; } /* if we are not initializing, and this trigger is not on a TEMP table, ** build the sqlite_master entry */ if( !db->init.busy ){ Vdbe *v; char *z; /* Make an entry in the sqlite_master table */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto triggerfinish_cleanup; sqlite3BeginWriteOperation(pParse, 0, iDb); z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n); sqlite3NestedParse(pParse, "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrig->name, pTrig->table, z); sqlite3DbFree(db, z); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf( db, "type='trigger' AND name='%q'", pTrig->name), P4_DYNAMIC ); } if( db->init.busy ){ int n; Table *pTab; Trigger *pDel; pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash, pTrig->name, sqlite3Strlen30(pTrig->name), pTrig); if( pDel ){ assert( pDel==pTrig ); db->mallocFailed = 1; goto triggerfinish_cleanup; } n = sqlite3Strlen30(pTrig->table) + 1; pTab = sqlite3HashFind(&pTrig->pTabSchema->tblHash, pTrig->table, n); assert( pTab!=0 ); pTrig->pNext = pTab->pTrigger; pTab->pTrigger = pTrig; pTrig = 0; } triggerfinish_cleanup: sqlite3DeleteTrigger(db, pTrig); assert( !pParse->pNewTrigger ); sqlite3DeleteTriggerStep(db, pStepList); }
/* ** 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 ** NULL if the function does not exist. ** ** If the createFlag argument is true, then a new (blank) FuncDef ** structure is created and liked into the "db" structure if a ** no matching function previously existed. When createFlag is true ** and the nArg parameter is -1, then only a function that accepts ** any number of arguments will be returned. ** ** If createFlag is false and nArg is -1, then the first valid ** function found is returned. A function is valid if either xFunc ** or xStep is non-zero. ** ** If createFlag is false, then a function with the required name and ** number of arguments may be returned even if the eTextRep flag does not ** match that requested. */ FuncDef *sqlite3FindFunction( sqlite3 *db, /* An open database */ const char *zName, /* Name of the function. Not null-terminated */ int nName, /* Number of characters in the name */ int nArg, /* Number of arguments. -1 means any number */ u8 enc, /* Preferred text encoding */ 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; assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); if( nArg<-1 ) nArg = -1; pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName); for(p=pFirst; p; p=p->pNext){ /* During the search for the best function definition, bestmatch is set ** as follows to indicate the quality of the match with the definition ** pointed to by pBest: ** ** 0: pBest is NULL. No match has been found. ** 1: A variable arguments function that prefers UTF-8 when a UTF-16 ** encoding is requested, or vice versa. ** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is ** requested, or vice versa. ** 3: A variable arguments function using the same text encoding. ** 4: A function with the exact number of arguments requested that ** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa. ** 5: A function with the exact number of arguments requested that ** prefers UTF-16LE when UTF-16BE is requested, or vice versa. ** 6: An exact match. ** ** A larger value of 'matchqual' indicates a more desirable match. */ if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){ int match = 1; /* Quality of this match */ if( p->nArg==nArg || nArg==-1 ){ match = 4; } if( enc==p->iPrefEnc ){ match += 2; } else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) || (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){ match += 1; } if( match>bestmatch ){ pBest = p; bestmatch = match; } } } /* If the createFlag parameter is true, and the seach did not reveal an ** 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 && (pBest = sqliteMalloc(sizeof(*pBest)+nName))!=0 ){ 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) ){ sqliteFree(pBest); return 0; } } if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){ return pBest; } return 0; }
/* ** Given a file descriptor, locate lockInfo and openCnt structures that ** describes that file descriptor. Create a new ones if necessary. The ** return values might be unset if an error occurs. ** ** Return the number of errors. */ static int findLockInfo( int fd, /* The file descriptor used in the key */ struct lockInfo **ppLock, /* Return the lockInfo structure here */ struct openCnt **ppOpen /* Return the openCnt structure here */ ){ int rc; struct lockKey key1; struct openKey key2; struct stat statbuf; struct lockInfo *pLock; struct openCnt *pOpen; rc = fstat(fd, &statbuf); if( rc!=0 ) return 1; memset(&key1, 0, sizeof(key1)); key1.dev = statbuf.st_dev; key1.ino = statbuf.st_ino; #ifdef SQLITE_UNIX_THREADS if( threadsOverrideEachOthersLocks<0 ){ testThreadLockingBehavior(fd); } key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self(); #endif memset(&key2, 0, sizeof(key2)); key2.dev = statbuf.st_dev; key2.ino = statbuf.st_ino; pLock = (struct lockInfo*)sqlite3HashFind(&lockHash, &key1, sizeof(key1)); if( pLock==0 ){ struct lockInfo *pOld; pLock = sqliteMallocRaw( sizeof(*pLock) ); if( pLock==0 ) return 1; pLock->key = key1; pLock->nRef = 1; pLock->cnt = 0; pLock->locktype = 0; pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock); if( pOld!=0 ){ assert( pOld==pLock ); sqliteFree(pLock); return 1; } }else{ pLock->nRef++; } *ppLock = pLock; pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); if( pOpen==0 ){ struct openCnt *pOld; pOpen = sqliteMallocRaw( sizeof(*pOpen) ); if( pOpen==0 ){ releaseLockInfo(pLock); return 1; } pOpen->key = key2; pOpen->nRef = 1; pOpen->nLock = 0; pOpen->nPending = 0; pOpen->aPending = 0; pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen); if( pOld!=0 ){ assert( pOld==pOpen ); sqliteFree(pOpen); releaseLockInfo(pLock); return 1; } }else{ pOpen->nRef++; } *ppOpen = pOpen; return 0; }
static void db_seq_drop_func( sqlite3_context *context, int argc, sqlite3_value **argv) { Btree *p; BtShared *pBt; CACHED_DB *cache_entry; SEQ_COOKIE cookie; int mutex_held, rc; sqlite3 *db; db = sqlite3_context_db_handle(context); p = db->aDb[0].pBt; pBt = p->pBt; mutex_held = 0; memset(&cookie, 0, sizeof(cookie)); if (!p->connected && (rc = btreeOpenEnvironment(p, 1)) != SQLITE_OK) { btreeSeqError(context, SQLITE_ERROR, "Sequence drop failed: connection could not be opened."); return; } sqlite3_snprintf(BT_MAX_SEQ_NAME, cookie.name, "seq_%s", sqlite3_value_text(argv[0])); cookie.name_len = (int)strlen(cookie.name); rc = btreeSeqGetHandle(context, p, SEQ_HANDLE_OPEN, &cookie); if (rc != SQLITE_OK) { /* If the handle doesn't exist, return an error. */ if (rc == DB_NOTFOUND) btreeSeqError(context, dberr2sqlite(rc, NULL), "no such sequence: %s", cookie.name + 4); else if (rc != SQLITE_ERROR) btreeSeqError(context, dberr2sqlite(rc, NULL), "Fail to drop sequence %s. Error: %s", cookie.name + 4, db_strerror(rc)); return; } sqlite3_mutex_enter(pBt->mutex); mutex_held = 1; cache_entry = sqlite3HashFind(&pBt->db_cache, cookie.name, cookie.name_len); if (cache_entry == NULL) goto done; if (cookie.cache != 0 && db->autoCommit == 0) { btreeSeqError(context, SQLITE_ERROR, "Cannot drop caching sequence in a transaction."); rc = SQLITE_ERROR; goto done; } sqlite3_mutex_leave(pBt->mutex); if ((rc = btreeSeqStartTransaction(context, p, 1)) != SQLITE_OK) { btreeSeqError(context, SQLITE_ERROR, "Could not begin transaction for drop."); return; } /* * Drop the mutex - it's not valid to begin a transaction while * holding the mutex. We can drop it safely because it's use is to * protect handle cache changes. */ sqlite3_mutex_enter(pBt->mutex); btreeSeqRemoveHandle(context, p, cache_entry); done: sqlite3_mutex_leave(pBt->mutex); if (rc == SQLITE_OK) sqlite3_result_int(context, SQLITE_OK); }
/* ** This routine is called after all of the trigger actions have been parsed ** in order to complete the process of building the trigger. */ SQLITE_PRIVATE void sqlite3FinishTrigger( Parse *pParse, /* Parser context */ TriggerStep *pStepList, /* The triggered program */ Token *pAll /* Token that describes the complete CREATE TRIGGER */ ){ Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */ char *zName; /* Name of trigger */ sqlite3 *db = pParse->db; /* The database */ DbFixer sFix; /* Fixer object */ int iDb; /* Database containing the trigger */ Token nameToken; /* Trigger name for error reporting */ pParse->pNewTrigger = 0; if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; zName = pTrig->zName; iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); pTrig->step_list = pStepList; while( pStepList ){ pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } nameToken.z = pTrig->zName; nameToken.n = sqlite3Strlen30(nameToken.z); sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken); if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) || sqlite3FixExpr(&sFix, pTrig->pWhen) ){ goto triggerfinish_cleanup; } /* if we are not initializing, ** build the sqlite_master entry */ if( !db->init.busy ){ Vdbe *v; char *z; /* Make an entry in the sqlite_master table */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto triggerfinish_cleanup; sqlite3BeginWriteOperation(pParse, 0, iDb); z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n); sqlite3NestedParse(pParse, "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zName, pTrig->table, z); sqlite3DbFree(db, z); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddParseSchemaOp(v, iDb, sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName)); } if( db->init.busy ){ Trigger *pLink = pTrig; Hash *pHash = &db->aDb[iDb].pSchema->trigHash; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); pTrig = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), pTrig); if( pTrig ){ db->mallocFailed = 1; }else if( pLink->pSchema==pLink->pTabSchema ){ Table *pTab; int n = sqlite3Strlen30(pLink->table); pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table, n); assert( pTab!=0 ); pLink->pNext = pTab->pTrigger; pTab->pTrigger = pLink; } } triggerfinish_cleanup: sqlite3DeleteTrigger(db, pTrig); assert( !pParse->pNewTrigger ); sqlite3DeleteTriggerStep(db, pStepList); }
/* ** Return a pointer to the Table structure for the table that a trigger ** is set on. */ static Table *tableOfTrigger(Trigger *pTrigger){ int n = strlen(pTrigger->table) + 1; return (Table*)sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n); }
/* ** This routine is called after all of the trigger actions have been parsed ** in order to complete the process of building the trigger. */ void sqlite3FinishTrigger( Parse *pParse, /* Parser context */ TriggerStep *pStepList, /* The triggered program */ Token *pAll /* Token that describes the complete CREATE TRIGGER */ ){ Trigger *pTrig = 0; /* The trigger whose construction is finishing up */ sqlite3 *db = pParse->db; /* The database */ DbFixer sFix; int iDb; /* Database containing the trigger */ pTrig = pParse->pNewTrigger; pParse->pNewTrigger = 0; if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup; iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); pTrig->step_list = pStepList; while( pStepList ){ pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken) && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ goto triggerfinish_cleanup; } /* if we are not initializing, and this trigger is not on a TEMP table, ** build the sqlite_master entry */ if( !db->init.busy ){ static const VdbeOpList insertTrig[] = { { OP_NewRowid, 0, 0, 0 }, { OP_String8, 0, 0, "trigger" }, { OP_String8, 0, 0, 0 }, /* 2: trigger name */ { OP_String8, 0, 0, 0 }, /* 3: table name */ { OP_Integer, 0, 0, 0 }, { OP_String8, 0, 0, "CREATE TRIGGER "}, { OP_String8, 0, 0, 0 }, /* 6: SQL */ { OP_Concat, 0, 0, 0 }, { OP_MakeRecord, 5, 0, "aaada" }, { OP_Insert, 0, 0, 0 }, }; int addr; Vdbe *v; /* Make an entry in the sqlite_master table */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto triggerfinish_cleanup; sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3OpenMasterTable(pParse, iDb); addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig); sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0); sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0); sqlite3VdbeChangeP3(v, addr+6, (char*)pAll->z, pAll->n); sqlite3ChangeCookie(db, v, iDb); sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, sqlite3MPrintf( db, "type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC ); } if( db->init.busy ){ int n; Table *pTab; Trigger *pDel; pDel = (Trigger*)sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash, pTrig->name, strlen(pTrig->name), pTrig); if( pDel ){ assert( pDel==pTrig ); db->mallocFailed = 1; goto triggerfinish_cleanup; } n = strlen(pTrig->table) + 1; pTab = (Table*)sqlite3HashFind(&pTrig->pTabSchema->tblHash, pTrig->table, n); assert( pTab!=0 ); pTrig->pNext = pTab->pTrigger; pTab->pTrigger = pTrig; pTrig = 0; } triggerfinish_cleanup: sqlite3DeleteTrigger(pTrig); assert( !pParse->pNewTrigger ); sqlite3DeleteTriggerStep(pStepList); }
static int btreeSeqGetHandle(sqlite3_context *context, Btree *p, int mode, SEQ_COOKIE *cookie) { BtShared *pBt; CACHED_DB *cache_entry, *stale_db; int ret; cache_entry = NULL; ret = SQLITE_OK; pBt = p->pBt; /* Does not support in-memory db and temp db for now */ if (pBt->dbStorage != DB_STORE_NAMED) { btreeSeqError(context, SQLITE_ERROR, "Sequences do not support in-memory or " "temporary databases."); return (SQLITE_ERROR); } /* * The process here is: * - Is the handle already in the cache - if so, just return. * - Else, does the sequence already exist: * + No: create the sequence * - open a handle and add it to the cache * * Use the cookie to store the name. If the handle is cached, the value * will be overwritten. */ sqlite3_mutex_enter(pBt->mutex); cache_entry = sqlite3HashFind(&pBt->db_cache, cookie->name, cookie->name_len); sqlite3_mutex_leave(pBt->mutex); if (CACHE_ENTRY_VALID(cache_entry)) { /* Check to see if the handle is no longer valid. */ if (btreeSeqExists(context, p, cookie->name) == 0) { btreeSeqRemoveHandle(context, p, cache_entry); return (DB_NOTFOUND); } if (mode == SEQ_HANDLE_OPEN) { assert(cache_entry->cookie != NULL); memcpy(cookie, cache_entry->cookie, sizeof(SEQ_COOKIE)); cookie->handle = (DB_SEQUENCE *)cache_entry->dbp; return (SQLITE_OK); } else if (mode == SEQ_HANDLE_CREATE) { cookie->handle = NULL; return (DB_KEYEXIST); } } /* * The handle wasn't found; Get seq handle by open or create the * sequence with the given name. */ if ((ret = btreeSeqOpen(context, p, cookie)) != 0) { if (mode == SEQ_HANDLE_CREATE) ret = btreeSeqCreate(context, p, cookie); } else if (mode == SEQ_HANDLE_CREATE) { return DB_KEYEXIST; } if (ret != 0) { if (cookie->handle != NULL) cookie->handle->close(cookie->handle, 0); return (ret); } /* * We dropped the pBt->mutex after the lookup failed, grab it * again before inserting into the cache. That means there is a race * adding the handle to the cache, so we need to deal with that. */ sqlite3_mutex_enter(pBt->mutex); /* Check to see if someone beat us to adding the handle. */ cache_entry = sqlite3HashFind(&pBt->db_cache, cookie->name, cookie->name_len); if (CACHE_ENTRY_VALID(cache_entry)) { cookie->handle->close(cookie->handle, 0); cookie->handle = (DB_SEQUENCE *)cache_entry->dbp; goto err; } /* Add the new handle to the cache. */ if ((cache_entry = (CACHED_DB *)sqlite3_malloc(sizeof(CACHED_DB))) == NULL) { btreeSeqError(context, SQLITE_NOMEM, "Memory allocation failure during sequence create."); ret = SQLITE_NOMEM; goto err; } memset(cache_entry, 0, sizeof(CACHED_DB)); if ((cache_entry->cookie = (SEQ_COOKIE *)sqlite3_malloc(sizeof(SEQ_COOKIE))) == NULL) { btreeSeqError(context, SQLITE_NOMEM, "Memory allocation failure during sequence create."); ret = SQLITE_NOMEM; goto err; } sqlite3_snprintf( sizeof(cache_entry->key), cache_entry->key, cookie->name); /* * Hack alert! * We're assigning the sequence to the DB pointer in the cached entry * it makes everything simpler, since much of the code in btree.c is * coded assuming dbp will be populated. It just means we need to be a * bit careful using DB handles from the cache now. */ cache_entry->dbp = (DB *)cookie->handle; cache_entry->is_sequence = 1; memcpy(cache_entry->cookie, cookie, sizeof(SEQ_COOKIE)); stale_db = sqlite3HashInsert(&pBt->db_cache, cache_entry->key, cookie->name_len, cache_entry); if (stale_db) { sqlite3_free(stale_db); /* * Hash table out of memory when returned pointer is * same as the original value pointer. */ if (stale_db == cache_entry) { btreeSeqError(context, SQLITE_NOMEM, MSG_MALLOC_FAIL); ret = SQLITE_NOMEM; goto err; } } err: sqlite3_mutex_leave(pBt->mutex); if (ret != 0 && cache_entry != NULL) { if (cache_entry->cookie != NULL) sqlite3_free(cache_entry->cookie); sqlite3_free(cache_entry); } return (ret); }
/* ** Return a pointer to the Table structure for the table that a trigger ** is set on. */ static Table *tableOfTrigger(Trigger *pTrigger){ int n = sqlite3Strlen30(pTrigger->table); return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n); }
/* ** This is called by the parser when it sees a CREATE TRIGGER statement ** up to the point of the BEGIN before the trigger actions. A Trigger ** structure is generated based on the information available and stored ** in pParse->pNewTrigger. After the trigger actions have been parsed, the ** sqlite3FinishTrigger() function is called to complete the trigger ** construction process. */ void sqlite3BeginTrigger( Parse *pParse, /* The parse context of the CREATE TRIGGER statement */ Token *pName1, /* The name of the trigger */ Token *pName2, /* The name of the trigger */ int tr_tm, /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */ int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */ IdList *pColumns, /* column list if this is an UPDATE OF trigger */ SrcList *pTableName,/* The name of the table/view the trigger applies to */ int foreach, /* One of TK_ROW or TK_STATEMENT */ Expr *pWhen, /* WHEN clause */ int isTemp /* True if the TEMPORARY keyword is present */ ){ Trigger *pTrigger; Table *pTab; char *zName = 0; /* Name of the trigger */ sqlite *db = pParse->db; int iDb; /* The database to store the trigger in */ Token *pName; /* The unqualified db name */ DbFixer sFix; if( isTemp ){ /* If TEMP was specified, then the trigger name may not be qualified. */ if( pName2 && pName2->n>0 ){ sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name"); goto trigger_cleanup; } iDb = 1; pName = pName1; }else{ /* Figure out the db that the the trigger will be created in */ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); if( iDb<0 ){ goto trigger_cleanup; } } /* If the trigger name was unqualified, and the table is a temp table, ** then set iDb to 1 to create the trigger in the temporary database. ** If sqlite3SrcListLookup() returns 0, indicating the table does not ** exist, the error is caught by the block below. */ if( !pTableName || sqlite3_malloc_failed ) goto trigger_cleanup; pTab = sqlite3SrcListLookup(pParse, pTableName); if( pName2->n==0 && pTab && pTab->iDb==1 ){ iDb = 1; } /* Ensure the table name matches database name and that the table exists */ if( sqlite3_malloc_failed ) goto trigger_cleanup; assert( pTableName->nSrc==1 ); if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) && sqlite3FixSrcList(&sFix, pTableName) ){ goto trigger_cleanup; } pTab = sqlite3SrcListLookup(pParse, pTableName); if( !pTab ){ /* The table does not exist. */ goto trigger_cleanup; } /* Check that the trigger name is not reserved and that no trigger of the ** specified name exists */ zName = sqlite3NameFromToken(pName); if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto trigger_cleanup; } if( sqlite3HashFind(&(db->aDb[iDb].trigHash), zName,pName->n+1) ){ sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); goto trigger_cleanup; } /* Do not create a trigger on a system table */ if( (iDb!=1 && sqlite3StrICmp(pTab->zName, MASTER_NAME)==0) || (iDb==1 && sqlite3StrICmp(pTab->zName, TEMP_MASTER_NAME)==0) ){ sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); pParse->nErr++; goto trigger_cleanup; } /* INSTEAD of triggers are only for views and views only support INSTEAD ** of triggers. */ if( pTab->pSelect && tr_tm!=TK_INSTEAD ){ sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0); goto trigger_cleanup; } if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" " trigger on table: %S", pTableName, 0); goto trigger_cleanup; } #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_CREATE_TRIGGER; const char *zDb = db->aDb[pTab->iDb].zName; const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; if( pTab->iDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ goto trigger_cleanup; } if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(pTab->iDb), 0, zDb)){ goto trigger_cleanup; } } #endif /* INSTEAD OF triggers can only appear on views and BEFORE triggers ** cannot appear on views. So we might as well translate every ** INSTEAD OF trigger into a BEFORE trigger. It simplifies code ** elsewhere. */ if (tr_tm == TK_INSTEAD){ tr_tm = TK_BEFORE; } /* Build the Trigger object */ pTrigger = (Trigger*)sqliteMalloc(sizeof(Trigger)); if( pTrigger==0 ) goto trigger_cleanup; pTrigger->name = zName; zName = 0; pTrigger->table = sqliteStrDup(pTableName->a[0].zName); if( sqlite3_malloc_failed ) goto trigger_cleanup; pTrigger->iDb = iDb; pTrigger->iTabDb = pTab->iDb; pTrigger->op = op; pTrigger->tr_tm = tr_tm; pTrigger->pWhen = sqlite3ExprDup(pWhen); pTrigger->pColumns = sqlite3IdListDup(pColumns); pTrigger->foreach = foreach; sqlite3TokenCopy(&pTrigger->nameToken,pName); assert( pParse->pNewTrigger==0 ); pParse->pNewTrigger = pTrigger; trigger_cleanup: sqliteFree(zName); sqlite3SrcListDelete(pTableName); sqlite3IdListDelete(pColumns); sqlite3ExprDelete(pWhen); }
/* ** This is called by the parser when it sees a CREATE TRIGGER statement ** up to the point of the BEGIN before the trigger actions. A Trigger ** structure is generated based on the information available and stored ** in pParse->pNewTrigger. After the trigger actions have been parsed, the ** sqlite3FinishTrigger() function is called to complete the trigger ** construction process. */ SQLITE_PRIVATE void sqlite3BeginTrigger( Parse *pParse, /* The parse context of the CREATE TRIGGER statement */ Token *pName1, /* The name of the trigger */ Token *pName2, /* The name of the trigger */ int tr_tm, /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */ int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */ IdList *pColumns, /* column list if this is an UPDATE OF trigger */ SrcList *pTableName,/* The name of the table/view the trigger applies to */ Expr *pWhen, /* WHEN clause */ int isTemp, /* True if the TEMPORARY keyword is present */ int noErr /* Suppress errors if the trigger already exists */ ){ Trigger *pTrigger = 0; /* The new trigger */ Table *pTab; /* Table that the trigger fires off of */ char *zName = 0; /* Name of the trigger */ sqlite3 *db = pParse->db; /* The database connection */ int iDb; /* The database to store the trigger in */ Token *pName; /* The unqualified db name */ DbFixer sFix; /* State vector for the DB fixer */ int iTabDb; /* Index of the database holding pTab */ assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */ assert( pName2!=0 ); assert( op==TK_INSERT || op==TK_UPDATE || op==TK_DELETE ); assert( op>0 && op<0xff ); if( isTemp ){ /* If TEMP was specified, then the trigger name may not be qualified. */ if( pName2->n>0 ){ sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name"); goto trigger_cleanup; } iDb = 1; pName = pName1; }else{ /* Figure out the db that the trigger will be created in */ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); if( iDb<0 ){ goto trigger_cleanup; } } if( !pTableName || db->mallocFailed ){ goto trigger_cleanup; } /* A long-standing parser bug is that this syntax was allowed: ** ** CREATE TRIGGER attached.demo AFTER INSERT ON attached.tab .... ** ^^^^^^^^ ** ** To maintain backwards compatibility, ignore the database ** name on pTableName if we are reparsing our of SQLITE_MASTER. */ if( db->init.busy && iDb!=1 ){ sqlite3DbFree(db, pTableName->a[0].zDatabase); pTableName->a[0].zDatabase = 0; } /* If the trigger name was unqualified, and the table is a temp table, ** then set iDb to 1 to create the trigger in the temporary database. ** If sqlite3SrcListLookup() returns 0, indicating the table does not ** exist, the error is caught by the block below. */ pTab = sqlite3SrcListLookup(pParse, pTableName); if( db->init.busy==0 && pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ iDb = 1; } /* Ensure the table name matches database name and that the table exists */ if( db->mallocFailed ) goto trigger_cleanup; assert( pTableName->nSrc==1 ); sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName); if( sqlite3FixSrcList(&sFix, pTableName) ){ goto trigger_cleanup; } pTab = sqlite3SrcListLookup(pParse, pTableName); if( !pTab ){ /* The table does not exist. */ if( db->init.iDb==1 ){ /* Ticket #3810. ** Normally, whenever a table is dropped, all associated triggers are ** dropped too. But if a TEMP trigger is created on a non-TEMP table ** and the table is dropped by a different database connection, the ** trigger is not visible to the database connection that does the ** drop so the trigger cannot be dropped. This results in an ** "orphaned trigger" - a trigger whose associated table is missing. */ db->init.orphanTrigger = 1; } goto trigger_cleanup; } if( IsVirtual(pTab) ){ sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables"); goto trigger_cleanup; } /* Check that the trigger name is not reserved and that no trigger of the ** specified name exists */ zName = sqlite3NameFromToken(db, pName); if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto trigger_cleanup; } assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), zName, sqlite3Strlen30(zName)) ){ if( !noErr ){ sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); }else{ assert( !db->init.busy ); sqlite3CodeVerifySchema(pParse, iDb); } goto trigger_cleanup; } /* Do not create a trigger on a system table */ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); pParse->nErr++; goto trigger_cleanup; } /* INSTEAD of triggers are only for views and views only support INSTEAD ** of triggers. */ if( pTab->pSelect && tr_tm!=TK_INSTEAD ){ sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0); goto trigger_cleanup; } if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" " trigger on table: %S", pTableName, 0); goto trigger_cleanup; } iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_CREATE_TRIGGER; const char *zDb = db->aDb[iTabDb].zName; const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ goto trigger_cleanup; } if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){ goto trigger_cleanup; } } #endif /* INSTEAD OF triggers can only appear on views and BEFORE triggers ** cannot appear on views. So we might as well translate every ** INSTEAD OF trigger into a BEFORE trigger. It simplifies code ** elsewhere. */ if (tr_tm == TK_INSTEAD){ tr_tm = TK_BEFORE; } /* Build the Trigger object */ pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger)); if( pTrigger==0 ) goto trigger_cleanup; pTrigger->zName = zName; zName = 0; pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName); pTrigger->pSchema = db->aDb[iDb].pSchema; pTrigger->pTabSchema = pTab->pSchema; pTrigger->op = (u8)op; pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); pTrigger->pColumns = sqlite3IdListDup(db, pColumns); assert( pParse->pNewTrigger==0 ); pParse->pNewTrigger = pTrigger; trigger_cleanup: sqlite3DbFree(db, zName); sqlite3SrcListDelete(db, pTableName); sqlite3IdListDelete(db, pColumns); sqlite3ExprDelete(db, pWhen); if( !pParse->pNewTrigger ){ sqlite3DeleteTrigger(db, pTrigger); }else{ assert( pParse->pNewTrigger==pTrigger ); } }