Esempio n. 1
0
/*
** 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);
}
Esempio n. 2
0
/*
** 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;
}
Esempio n. 3
0
/*
** 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;
}
Esempio n. 4
0
/*
** 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;
}
Esempio n. 6
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
/*
** 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;
}
Esempio n. 10
0
File: vtab.c Progetto: ngdmcc/sqlite
/*
** 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);
}
Esempio n. 12
0
/*
** 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;
}
Esempio n. 14
0
/*
** 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);
}
Esempio n. 15
0
File: callback.c Progetto: cznic/cc
/*
** 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;
}
Esempio n. 16
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;
  }
}
Esempio n. 17
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;
}
Esempio n. 18
0
/*
** 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);
}
Esempio n. 19
0
SWITCH_DECLARE(void *) switch_core_hash_find(switch_hash_t *hash, const char *key)
{
	return sqlite3HashFind(&hash->table, key, (int) strlen(key) + 1);
}
Esempio n. 20
0
/*
** 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);
}
Esempio n. 21
0
/*
** 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;
}
Esempio n. 23
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);
}
Esempio n. 25
0
/*
** 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);
}
Esempio n. 26
0
/*
** 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);
}
Esempio n. 27
0
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);
}
Esempio n. 29
0
/*
** 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 );
    }
}