/* ** 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) { Trigger *pTrigger = 0; int i; const char *zDb; const char *zName; int nName; sqlite3 *db = pParse->db; if( sqlite3ThreadDataReadOnly()->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+1); if( pTrigger ) break; } if( !pTrigger ) { sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); goto drop_trigger_cleanup; } sqlite3DropTriggerPtr(pParse, pTrigger, 0); drop_trigger_cleanup: sqlite3SrcListDelete(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, 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 || (sqlite3ThreadDataReadOnly()->mallocFailed && pDel==pColl) ); sqliteFree(pDel); } } return pColl; }
/* ** This is the test layer's wrapper around sqlite3OsRealloc(). */ static void * OSREALLOC(void *pRealloc, int n){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT sqlite3_nMaxAlloc = MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc); #endif assert( !sqlite3_mallocDisallowed ); if( !sqlite3TestMallocFail() ){ u32 *p = (u32 *)getOsPointer(pRealloc); checkGuards(p); p = sqlite3OsRealloc(p, n + TESTALLOC_OVERHEAD); applyGuards(p); relinkAlloc(p); return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]); } return 0; }
/* ** This is the test layer's wrapper around sqlite3OsMalloc(). */ static void * OSMALLOC(int n){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT sqlite3_nMaxAlloc = MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc); #endif assert( !sqlite3_mallocDisallowed ); if( !sqlite3TestMallocFail() ){ u32 *p; p = (u32 *)sqlite3OsMalloc(n + TESTALLOC_OVERHEAD); assert(p); sqlite3_nMalloc++; applyGuards(p); linkAlloc(p); return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]); } return 0; }
/* ** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE ** statement. The module name has been parsed, but the optional list ** of parameters that follow the module name are still pending. */ void sqlite3VtabBeginParse( Parse *pParse, /* Parsing context */ Token *pName1, /* Name of new table, or database name */ Token *pName2, /* Name of new table or NULL */ Token *pModuleName /* Name of the module for the virtual table */ ){ int iDb; /* The database the table is being created in */ Table *pTable; /* The new virtual table */ #ifndef SQLITE_OMIT_SHARED_CACHE if( sqlite3ThreadDataReadOnly()->useSharedData ){ sqlite3ErrorMsg(pParse, "Cannot use virtual tables in shared-cache mode"); return; } #endif sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0); pTable = pParse->pNewTable; if( pTable==0 || pParse->nErr ) return; assert( 0==pTable->pIndex ); iDb = sqlite3SchemaToIndex(pParse->db, pTable->pSchema); assert( iDb>=0 ); pTable->isVirtual = 1; pTable->nModuleArg = 0; addModuleArgument(pTable, sqlite3NameFromToken(pModuleName)); addModuleArgument(pTable, sqlite3StrDup(pParse->db->aDb[iDb].zName)); addModuleArgument(pTable, sqlite3StrDup(pTable->zName)); pParse->sNameToken.n = pModuleName->z + pModuleName->n - pName1->z; #ifndef SQLITE_OMIT_AUTHORIZATION /* Creating a virtual table invokes the authorization callback twice. ** The first invocation, to obtain permission to INSERT a row into the ** sqlite_master table, has already been made by sqlite3StartTable(). ** The second call, to obtain permission to create the table, is made now. */ if( pTable->azModuleArg ){ sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, pTable->azModuleArg[0], pParse->db->aDb[iDb].zName); } #endif }
/* ** Execute SQL code. Return one of the SQLITE_ success/failure ** codes. Also write an error message into memory obtained from ** malloc() and make *pzErrMsg point to that message. ** ** If the SQL is a query, then for each row in the query result ** the xCallback() function is called. pArg becomes the first ** argument to xCallback(). If xCallback=NULL then no callback ** is invoked, even for queries. */ int sqlite3_exec( sqlite3 *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ sqlite3_callback xCallback, /* Invoke this callback routine */ void *pArg, /* First argument to xCallback() */ char **pzErrMsg /* Write error messages here */ ){ int rc = SQLITE_OK; const char *zLeftover; sqlite3_stmt *pStmt = 0; char **azCols = 0; int nRetry = 0; int nChange = 0; int nCallback; if( zSql==0 ) return SQLITE_OK; while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){ int nCol; char **azVals = 0; pStmt = 0; rc = sqlite3_prepare(db, zSql, -1, &pStmt, &zLeftover); if( rc!=SQLITE_OK ){ if( pStmt ) sqlite3_finalize(pStmt); continue; } if( !pStmt ){ /* this happens for a comment or white-space */ zSql = zLeftover; continue; } db->nChange += nChange; nCallback = 0; nCol = sqlite3_column_count(pStmt); azCols = sqliteMalloc(2*nCol*sizeof(const char *)); if( nCol && !azCols ){ goto exec_out; } while( 1 ){ int i; rc = sqlite3_step(pStmt); /* Invoke the callback function if required */ if( xCallback && (SQLITE_ROW==rc || (SQLITE_DONE==rc && !nCallback && db->flags&SQLITE_NullCallback)) ){ if( 0==nCallback ){ for(i=0; i<nCol; i++){ azCols[i] = (char *)sqlite3_column_name(pStmt, i); } nCallback++; } if( rc==SQLITE_ROW ){ azVals = &azCols[nCol]; for(i=0; i<nCol; i++){ azVals[i] = (char *)sqlite3_column_text(pStmt, i); } } if( xCallback(pArg, nCol, azVals, azCols) ){ rc = SQLITE_ABORT; goto exec_out; } } if( rc!=SQLITE_ROW ){ rc = sqlite3_finalize(pStmt); pStmt = 0; if( db->pVdbe==0 ){ nChange = db->nChange; } if( rc!=SQLITE_SCHEMA ){ nRetry = 0; zSql = zLeftover; while( isspace((unsigned char)zSql[0]) ) zSql++; } break; } } sqliteFree(azCols); azCols = 0; } exec_out: if( pStmt ) sqlite3_finalize(pStmt); if( azCols ) sqliteFree(azCols); if( sqlite3ThreadDataReadOnly()->mallocFailed ){ rc = SQLITE_NOMEM; sqlite3MallocClearFailed(); } if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){ *pzErrMsg = malloc(1+strlen(sqlite3_errmsg(db))); if( *pzErrMsg ){ strcpy(*pzErrMsg, sqlite3_errmsg(db)); } }else if( pzErrMsg ){ *pzErrMsg = 0; } return rc; }
/* ** This procedure generates VDBE code for a single invocation of either the ** sqlite_detach() or sqlite_attach() SQL user functions. */ static void codeAttach( Parse *pParse, /* The parser context */ int type, /* Either SQLITE_ATTACH or SQLITE_DETACH */ const char *zFunc, /* Either "sqlite_attach" or "sqlite_detach */ int nFunc, /* Number of args to pass to zFunc */ Expr *pAuthArg, /* Expression to pass to authorization callback */ Expr *pFilename, /* Name of database file */ Expr *pDbname, /* Name of the database to use internally */ Expr *pKey /* Database key for encryption extension */ ){ int rc; NameContext sName; Vdbe *v; FuncDef *pFunc; sqlite3* db = pParse->db; #ifndef SQLITE_OMIT_AUTHORIZATION assert( sqlite3ThreadDataReadOnly()->mallocFailed || pAuthArg ); if( pAuthArg ){ char *zAuthArg = sqlite3NameFromToken(&pAuthArg->span); if( !zAuthArg ){ goto attach_end; } rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); sqliteFree(zAuthArg); if(rc!=SQLITE_OK ){ goto attach_end; } } #endif /* SQLITE_OMIT_AUTHORIZATION */ memset(&sName, 0, sizeof(NameContext)); sName.pParse = pParse; if( SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) || SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) || SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey)) ){ pParse->nErr++; goto attach_end; } v = sqlite3GetVdbe(pParse); sqlite3ExprCode(pParse, pFilename); sqlite3ExprCode(pParse, pDbname); sqlite3ExprCode(pParse, pKey); assert(v || sqlite3ThreadDataReadOnly()->mallocFailed); if( v ){ sqlite3VdbeAddOp(v, OP_Function, 0, nFunc); pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0); sqlite3VdbeChangeP3(v, -1, (char *)pFunc, P3_FUNCDEF); /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this ** statement only). For DETACH, set it to false (expire all existing ** statements). */ sqlite3VdbeAddOp(v, OP_Expire, (type==SQLITE_ATTACH), 0); } attach_end: sqlite3ExprDelete(pFilename); sqlite3ExprDelete(pDbname); sqlite3ExprDelete(pKey); }
/* ** 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 = 0; Table *pTab; char *zName = 0; /* Name of the trigger */ sqlite3 *db = pParse->db; int iDb; /* The database to store the trigger in */ Token *pName; /* The unqualified db name */ DbFixer sFix; int iTabDb; 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 || sqlite3ThreadDataReadOnly()->mallocFailed ) { goto trigger_cleanup; } pTab = sqlite3SrcListLookup(pParse, pTableName); if( 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( sqlite3ThreadDataReadOnly()->mallocFailed ) 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].pSchema->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( 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*)sqliteMalloc(sizeof(Trigger)); if( pTrigger==0 ) goto trigger_cleanup; pTrigger->name = zName; zName = 0; pTrigger->table = sqliteStrDup(pTableName->a[0].zName); pTrigger->pSchema = db->aDb[iDb].pSchema; pTrigger->pTabSchema = pTab->pSchema; pTrigger->op = op; pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; 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); if( !pParse->pNewTrigger ) { sqlite3DeleteTrigger(pTrigger); } else { assert( pParse->pNewTrigger==pTrigger ); } }
/* ** 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("type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC); } if( db->init.busy ) { int n; Table *pTab; Trigger *pDel; pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash, pTrig->name, strlen(pTrig->name)+1, pTrig); if( pDel ) { assert( sqlite3ThreadDataReadOnly()->mallocFailed && pDel==pTrig ); goto triggerfinish_cleanup; } n = strlen(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(pTrig); assert( !pParse->pNewTrigger ); sqlite3DeleteTriggerStep(pStepList); }