Mercurial > audlegacy
comparison sqlite/trigger.c @ 1434:b6b61becdf4e trunk
[svn] - add sqlite/ directory
| author | nenolod |
|---|---|
| date | Thu, 27 Jul 2006 22:41:31 -0700 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1433:3cbe3d14ea68 | 1434:b6b61becdf4e |
|---|---|
| 1 /* | |
| 2 ** | |
| 3 ** The author disclaims copyright to this source code. In place of | |
| 4 ** a legal notice, here is a blessing: | |
| 5 ** | |
| 6 ** May you do good and not evil. | |
| 7 ** May you find forgiveness for yourself and forgive others. | |
| 8 ** May you share freely, never taking more than you give. | |
| 9 ** | |
| 10 ************************************************************************* | |
| 11 * | |
| 12 */ | |
| 13 #include "sqliteInt.h" | |
| 14 | |
| 15 #ifndef SQLITE_OMIT_TRIGGER | |
| 16 /* | |
| 17 ** Delete a linked list of TriggerStep structures. | |
| 18 */ | |
| 19 void sqlite3DeleteTriggerStep(TriggerStep *pTriggerStep){ | |
| 20 while( pTriggerStep ){ | |
| 21 TriggerStep * pTmp = pTriggerStep; | |
| 22 pTriggerStep = pTriggerStep->pNext; | |
| 23 | |
| 24 if( pTmp->target.dyn ) sqliteFree((char*)pTmp->target.z); | |
| 25 sqlite3ExprDelete(pTmp->pWhere); | |
| 26 sqlite3ExprListDelete(pTmp->pExprList); | |
| 27 sqlite3SelectDelete(pTmp->pSelect); | |
| 28 sqlite3IdListDelete(pTmp->pIdList); | |
| 29 | |
| 30 sqliteFree(pTmp); | |
| 31 } | |
| 32 } | |
| 33 | |
| 34 /* | |
| 35 ** This is called by the parser when it sees a CREATE TRIGGER statement | |
| 36 ** up to the point of the BEGIN before the trigger actions. A Trigger | |
| 37 ** structure is generated based on the information available and stored | |
| 38 ** in pParse->pNewTrigger. After the trigger actions have been parsed, the | |
| 39 ** sqlite3FinishTrigger() function is called to complete the trigger | |
| 40 ** construction process. | |
| 41 */ | |
| 42 void sqlite3BeginTrigger( | |
| 43 Parse *pParse, /* The parse context of the CREATE TRIGGER statement */ | |
| 44 Token *pName1, /* The name of the trigger */ | |
| 45 Token *pName2, /* The name of the trigger */ | |
| 46 int tr_tm, /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */ | |
| 47 int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */ | |
| 48 IdList *pColumns, /* column list if this is an UPDATE OF trigger */ | |
| 49 SrcList *pTableName,/* The name of the table/view the trigger applies to */ | |
| 50 int foreach, /* One of TK_ROW or TK_STATEMENT */ | |
| 51 Expr *pWhen, /* WHEN clause */ | |
| 52 int isTemp /* True if the TEMPORARY keyword is present */ | |
| 53 ){ | |
| 54 Trigger *pTrigger = 0; | |
| 55 Table *pTab; | |
| 56 char *zName = 0; /* Name of the trigger */ | |
| 57 sqlite3 *db = pParse->db; | |
| 58 int iDb; /* The database to store the trigger in */ | |
| 59 Token *pName; /* The unqualified db name */ | |
| 60 DbFixer sFix; | |
| 61 int iTabDb; | |
| 62 | |
| 63 assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */ | |
| 64 assert( pName2!=0 ); | |
| 65 if( isTemp ){ | |
| 66 /* If TEMP was specified, then the trigger name may not be qualified. */ | |
| 67 if( pName2->n>0 ){ | |
| 68 sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name"); | |
| 69 goto trigger_cleanup; | |
| 70 } | |
| 71 iDb = 1; | |
| 72 pName = pName1; | |
| 73 }else{ | |
| 74 /* Figure out the db that the the trigger will be created in */ | |
| 75 iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); | |
| 76 if( iDb<0 ){ | |
| 77 goto trigger_cleanup; | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 /* If the trigger name was unqualified, and the table is a temp table, | |
| 82 ** then set iDb to 1 to create the trigger in the temporary database. | |
| 83 ** If sqlite3SrcListLookup() returns 0, indicating the table does not | |
| 84 ** exist, the error is caught by the block below. | |
| 85 */ | |
| 86 if( !pTableName || sqlite3MallocFailed() ){ | |
| 87 goto trigger_cleanup; | |
| 88 } | |
| 89 pTab = sqlite3SrcListLookup(pParse, pTableName); | |
| 90 if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ | |
| 91 iDb = 1; | |
| 92 } | |
| 93 | |
| 94 /* Ensure the table name matches database name and that the table exists */ | |
| 95 if( sqlite3MallocFailed() ) goto trigger_cleanup; | |
| 96 assert( pTableName->nSrc==1 ); | |
| 97 if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) && | |
| 98 sqlite3FixSrcList(&sFix, pTableName) ){ | |
| 99 goto trigger_cleanup; | |
| 100 } | |
| 101 pTab = sqlite3SrcListLookup(pParse, pTableName); | |
| 102 if( !pTab ){ | |
| 103 /* The table does not exist. */ | |
| 104 goto trigger_cleanup; | |
| 105 } | |
| 106 | |
| 107 /* Check that the trigger name is not reserved and that no trigger of the | |
| 108 ** specified name exists */ | |
| 109 zName = sqlite3NameFromToken(pName); | |
| 110 if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ | |
| 111 goto trigger_cleanup; | |
| 112 } | |
| 113 if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), zName,strlen(zName)) ){ | |
| 114 sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); | |
| 115 goto trigger_cleanup; | |
| 116 } | |
| 117 | |
| 118 /* Do not create a trigger on a system table */ | |
| 119 if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ | |
| 120 sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); | |
| 121 pParse->nErr++; | |
| 122 goto trigger_cleanup; | |
| 123 } | |
| 124 | |
| 125 /* INSTEAD of triggers are only for views and views only support INSTEAD | |
| 126 ** of triggers. | |
| 127 */ | |
| 128 if( pTab->pSelect && tr_tm!=TK_INSTEAD ){ | |
| 129 sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", | |
| 130 (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0); | |
| 131 goto trigger_cleanup; | |
| 132 } | |
| 133 if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ | |
| 134 sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" | |
| 135 " trigger on table: %S", pTableName, 0); | |
| 136 goto trigger_cleanup; | |
| 137 } | |
| 138 iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); | |
| 139 | |
| 140 #ifndef SQLITE_OMIT_AUTHORIZATION | |
| 141 { | |
| 142 int code = SQLITE_CREATE_TRIGGER; | |
| 143 const char *zDb = db->aDb[iTabDb].zName; | |
| 144 const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; | |
| 145 if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; | |
| 146 if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ | |
| 147 goto trigger_cleanup; | |
| 148 } | |
| 149 if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){ | |
| 150 goto trigger_cleanup; | |
| 151 } | |
| 152 } | |
| 153 #endif | |
| 154 | |
| 155 /* INSTEAD OF triggers can only appear on views and BEFORE triggers | |
| 156 ** cannot appear on views. So we might as well translate every | |
| 157 ** INSTEAD OF trigger into a BEFORE trigger. It simplifies code | |
| 158 ** elsewhere. | |
| 159 */ | |
| 160 if (tr_tm == TK_INSTEAD){ | |
| 161 tr_tm = TK_BEFORE; | |
| 162 } | |
| 163 | |
| 164 /* Build the Trigger object */ | |
| 165 pTrigger = (Trigger*)sqliteMalloc(sizeof(Trigger)); | |
| 166 if( pTrigger==0 ) goto trigger_cleanup; | |
| 167 pTrigger->name = zName; | |
| 168 zName = 0; | |
| 169 pTrigger->table = sqliteStrDup(pTableName->a[0].zName); | |
| 170 pTrigger->pSchema = db->aDb[iDb].pSchema; | |
| 171 pTrigger->pTabSchema = pTab->pSchema; | |
| 172 pTrigger->op = op; | |
| 173 pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; | |
| 174 pTrigger->pWhen = sqlite3ExprDup(pWhen); | |
| 175 pTrigger->pColumns = sqlite3IdListDup(pColumns); | |
| 176 pTrigger->foreach = foreach; | |
| 177 sqlite3TokenCopy(&pTrigger->nameToken,pName); | |
| 178 assert( pParse->pNewTrigger==0 ); | |
| 179 pParse->pNewTrigger = pTrigger; | |
| 180 | |
| 181 trigger_cleanup: | |
| 182 sqliteFree(zName); | |
| 183 sqlite3SrcListDelete(pTableName); | |
| 184 sqlite3IdListDelete(pColumns); | |
| 185 sqlite3ExprDelete(pWhen); | |
| 186 if( !pParse->pNewTrigger ){ | |
| 187 sqlite3DeleteTrigger(pTrigger); | |
| 188 }else{ | |
| 189 assert( pParse->pNewTrigger==pTrigger ); | |
| 190 } | |
| 191 } | |
| 192 | |
| 193 /* | |
| 194 ** This routine is called after all of the trigger actions have been parsed | |
| 195 ** in order to complete the process of building the trigger. | |
| 196 */ | |
| 197 void sqlite3FinishTrigger( | |
| 198 Parse *pParse, /* Parser context */ | |
| 199 TriggerStep *pStepList, /* The triggered program */ | |
| 200 Token *pAll /* Token that describes the complete CREATE TRIGGER */ | |
| 201 ){ | |
| 202 Trigger *pTrig = 0; /* The trigger whose construction is finishing up */ | |
| 203 sqlite3 *db = pParse->db; /* The database */ | |
| 204 DbFixer sFix; | |
| 205 int iDb; /* Database containing the trigger */ | |
| 206 | |
| 207 pTrig = pParse->pNewTrigger; | |
| 208 pParse->pNewTrigger = 0; | |
| 209 if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup; | |
| 210 iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); | |
| 211 pTrig->step_list = pStepList; | |
| 212 while( pStepList ){ | |
| 213 pStepList->pTrig = pTrig; | |
| 214 pStepList = pStepList->pNext; | |
| 215 } | |
| 216 if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken) | |
| 217 && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ | |
| 218 goto triggerfinish_cleanup; | |
| 219 } | |
| 220 | |
| 221 /* if we are not initializing, and this trigger is not on a TEMP table, | |
| 222 ** build the sqlite_master entry | |
| 223 */ | |
| 224 if( !db->init.busy ){ | |
| 225 static const VdbeOpList insertTrig[] = { | |
| 226 { OP_NewRowid, 0, 0, 0 }, | |
| 227 { OP_String8, 0, 0, "trigger" }, | |
| 228 { OP_String8, 0, 0, 0 }, /* 2: trigger name */ | |
| 229 { OP_String8, 0, 0, 0 }, /* 3: table name */ | |
| 230 { OP_Integer, 0, 0, 0 }, | |
| 231 { OP_String8, 0, 0, "CREATE TRIGGER "}, | |
| 232 { OP_String8, 0, 0, 0 }, /* 6: SQL */ | |
| 233 { OP_Concat, 0, 0, 0 }, | |
| 234 { OP_MakeRecord, 5, 0, "aaada" }, | |
| 235 { OP_Insert, 0, 0, 0 }, | |
| 236 }; | |
| 237 int addr; | |
| 238 Vdbe *v; | |
| 239 | |
| 240 /* Make an entry in the sqlite_master table */ | |
| 241 v = sqlite3GetVdbe(pParse); | |
| 242 if( v==0 ) goto triggerfinish_cleanup; | |
| 243 sqlite3BeginWriteOperation(pParse, 0, iDb); | |
| 244 sqlite3OpenMasterTable(pParse, iDb); | |
| 245 addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig); | |
| 246 sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0); | |
| 247 sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0); | |
| 248 sqlite3VdbeChangeP3(v, addr+6, (char*)pAll->z, pAll->n); | |
| 249 sqlite3ChangeCookie(db, v, iDb); | |
| 250 sqlite3VdbeAddOp(v, OP_Close, 0, 0); | |
| 251 sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, | |
| 252 sqlite3MPrintf("type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC); | |
| 253 } | |
| 254 | |
| 255 if( db->init.busy ){ | |
| 256 int n; | |
| 257 Table *pTab; | |
| 258 Trigger *pDel; | |
| 259 pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash, | |
| 260 pTrig->name, strlen(pTrig->name), pTrig); | |
| 261 if( pDel ){ | |
| 262 assert( sqlite3MallocFailed() && pDel==pTrig ); | |
| 263 goto triggerfinish_cleanup; | |
| 264 } | |
| 265 n = strlen(pTrig->table) + 1; | |
| 266 pTab = sqlite3HashFind(&pTrig->pTabSchema->tblHash, pTrig->table, n); | |
| 267 assert( pTab!=0 ); | |
| 268 pTrig->pNext = pTab->pTrigger; | |
| 269 pTab->pTrigger = pTrig; | |
| 270 pTrig = 0; | |
| 271 } | |
| 272 | |
| 273 triggerfinish_cleanup: | |
| 274 sqlite3DeleteTrigger(pTrig); | |
| 275 assert( !pParse->pNewTrigger ); | |
| 276 sqlite3DeleteTriggerStep(pStepList); | |
| 277 } | |
| 278 | |
| 279 /* | |
| 280 ** Make a copy of all components of the given trigger step. This has | |
| 281 ** the effect of copying all Expr.token.z values into memory obtained | |
| 282 ** from sqliteMalloc(). As initially created, the Expr.token.z values | |
| 283 ** all point to the input string that was fed to the parser. But that | |
| 284 ** string is ephemeral - it will go away as soon as the sqlite3_exec() | |
| 285 ** call that started the parser exits. This routine makes a persistent | |
| 286 ** copy of all the Expr.token.z strings so that the TriggerStep structure | |
| 287 ** will be valid even after the sqlite3_exec() call returns. | |
| 288 */ | |
| 289 static void sqlitePersistTriggerStep(TriggerStep *p){ | |
| 290 if( p->target.z ){ | |
| 291 p->target.z = (u8*)sqliteStrNDup((char*)p->target.z, p->target.n); | |
| 292 p->target.dyn = 1; | |
| 293 } | |
| 294 if( p->pSelect ){ | |
| 295 Select *pNew = sqlite3SelectDup(p->pSelect); | |
| 296 sqlite3SelectDelete(p->pSelect); | |
| 297 p->pSelect = pNew; | |
| 298 } | |
| 299 if( p->pWhere ){ | |
| 300 Expr *pNew = sqlite3ExprDup(p->pWhere); | |
| 301 sqlite3ExprDelete(p->pWhere); | |
| 302 p->pWhere = pNew; | |
| 303 } | |
| 304 if( p->pExprList ){ | |
| 305 ExprList *pNew = sqlite3ExprListDup(p->pExprList); | |
| 306 sqlite3ExprListDelete(p->pExprList); | |
| 307 p->pExprList = pNew; | |
| 308 } | |
| 309 if( p->pIdList ){ | |
| 310 IdList *pNew = sqlite3IdListDup(p->pIdList); | |
| 311 sqlite3IdListDelete(p->pIdList); | |
| 312 p->pIdList = pNew; | |
| 313 } | |
| 314 } | |
| 315 | |
| 316 /* | |
| 317 ** Turn a SELECT statement (that the pSelect parameter points to) into | |
| 318 ** a trigger step. Return a pointer to a TriggerStep structure. | |
| 319 ** | |
| 320 ** The parser calls this routine when it finds a SELECT statement in | |
| 321 ** body of a TRIGGER. | |
| 322 */ | |
| 323 TriggerStep *sqlite3TriggerSelectStep(Select *pSelect){ | |
| 324 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); | |
| 325 if( pTriggerStep==0 ) { | |
| 326 sqlite3SelectDelete(pSelect); | |
| 327 return 0; | |
| 328 } | |
| 329 | |
| 330 pTriggerStep->op = TK_SELECT; | |
| 331 pTriggerStep->pSelect = pSelect; | |
| 332 pTriggerStep->orconf = OE_Default; | |
| 333 sqlitePersistTriggerStep(pTriggerStep); | |
| 334 | |
| 335 return pTriggerStep; | |
| 336 } | |
| 337 | |
| 338 /* | |
| 339 ** Build a trigger step out of an INSERT statement. Return a pointer | |
| 340 ** to the new trigger step. | |
| 341 ** | |
| 342 ** The parser calls this routine when it sees an INSERT inside the | |
| 343 ** body of a trigger. | |
| 344 */ | |
| 345 TriggerStep *sqlite3TriggerInsertStep( | |
| 346 Token *pTableName, /* Name of the table into which we insert */ | |
| 347 IdList *pColumn, /* List of columns in pTableName to insert into */ | |
| 348 ExprList *pEList, /* The VALUE clause: a list of values to be inserted */ | |
| 349 Select *pSelect, /* A SELECT statement that supplies values */ | |
| 350 int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ | |
| 351 ){ | |
| 352 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); | |
| 353 | |
| 354 assert(pEList == 0 || pSelect == 0); | |
| 355 assert(pEList != 0 || pSelect != 0); | |
| 356 | |
| 357 if( pTriggerStep ){ | |
| 358 pTriggerStep->op = TK_INSERT; | |
| 359 pTriggerStep->pSelect = pSelect; | |
| 360 pTriggerStep->target = *pTableName; | |
| 361 pTriggerStep->pIdList = pColumn; | |
| 362 pTriggerStep->pExprList = pEList; | |
| 363 pTriggerStep->orconf = orconf; | |
| 364 sqlitePersistTriggerStep(pTriggerStep); | |
| 365 }else{ | |
| 366 sqlite3IdListDelete(pColumn); | |
| 367 sqlite3ExprListDelete(pEList); | |
| 368 sqlite3SelectDup(pSelect); | |
| 369 } | |
| 370 | |
| 371 return pTriggerStep; | |
| 372 } | |
| 373 | |
| 374 /* | |
| 375 ** Construct a trigger step that implements an UPDATE statement and return | |
| 376 ** a pointer to that trigger step. The parser calls this routine when it | |
| 377 ** sees an UPDATE statement inside the body of a CREATE TRIGGER. | |
| 378 */ | |
| 379 TriggerStep *sqlite3TriggerUpdateStep( | |
| 380 Token *pTableName, /* Name of the table to be updated */ | |
| 381 ExprList *pEList, /* The SET clause: list of column and new values */ | |
| 382 Expr *pWhere, /* The WHERE clause */ | |
| 383 int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ | |
| 384 ){ | |
| 385 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); | |
| 386 if( pTriggerStep==0 ) return 0; | |
| 387 | |
| 388 pTriggerStep->op = TK_UPDATE; | |
| 389 pTriggerStep->target = *pTableName; | |
| 390 pTriggerStep->pExprList = pEList; | |
| 391 pTriggerStep->pWhere = pWhere; | |
| 392 pTriggerStep->orconf = orconf; | |
| 393 sqlitePersistTriggerStep(pTriggerStep); | |
| 394 | |
| 395 return pTriggerStep; | |
| 396 } | |
| 397 | |
| 398 /* | |
| 399 ** Construct a trigger step that implements a DELETE statement and return | |
| 400 ** a pointer to that trigger step. The parser calls this routine when it | |
| 401 ** sees a DELETE statement inside the body of a CREATE TRIGGER. | |
| 402 */ | |
| 403 TriggerStep *sqlite3TriggerDeleteStep(Token *pTableName, Expr *pWhere){ | |
| 404 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); | |
| 405 if( pTriggerStep==0 ) return 0; | |
| 406 | |
| 407 pTriggerStep->op = TK_DELETE; | |
| 408 pTriggerStep->target = *pTableName; | |
| 409 pTriggerStep->pWhere = pWhere; | |
| 410 pTriggerStep->orconf = OE_Default; | |
| 411 sqlitePersistTriggerStep(pTriggerStep); | |
| 412 | |
| 413 return pTriggerStep; | |
| 414 } | |
| 415 | |
| 416 /* | |
| 417 ** Recursively delete a Trigger structure | |
| 418 */ | |
| 419 void sqlite3DeleteTrigger(Trigger *pTrigger){ | |
| 420 if( pTrigger==0 ) return; | |
| 421 sqlite3DeleteTriggerStep(pTrigger->step_list); | |
| 422 sqliteFree(pTrigger->name); | |
| 423 sqliteFree(pTrigger->table); | |
| 424 sqlite3ExprDelete(pTrigger->pWhen); | |
| 425 sqlite3IdListDelete(pTrigger->pColumns); | |
| 426 if( pTrigger->nameToken.dyn ) sqliteFree((char*)pTrigger->nameToken.z); | |
| 427 sqliteFree(pTrigger); | |
| 428 } | |
| 429 | |
| 430 /* | |
| 431 ** This function is called to drop a trigger from the database schema. | |
| 432 ** | |
| 433 ** This may be called directly from the parser and therefore identifies | |
| 434 ** the trigger by name. The sqlite3DropTriggerPtr() routine does the | |
| 435 ** same job as this routine except it takes a pointer to the trigger | |
| 436 ** instead of the trigger name. | |
| 437 **/ | |
| 438 void sqlite3DropTrigger(Parse *pParse, SrcList *pName){ | |
| 439 Trigger *pTrigger = 0; | |
| 440 int i; | |
| 441 const char *zDb; | |
| 442 const char *zName; | |
| 443 int nName; | |
| 444 sqlite3 *db = pParse->db; | |
| 445 | |
| 446 if( sqlite3MallocFailed() ) goto drop_trigger_cleanup; | |
| 447 if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ | |
| 448 goto drop_trigger_cleanup; | |
| 449 } | |
| 450 | |
| 451 assert( pName->nSrc==1 ); | |
| 452 zDb = pName->a[0].zDatabase; | |
| 453 zName = pName->a[0].zName; | |
| 454 nName = strlen(zName); | |
| 455 for(i=OMIT_TEMPDB; i<db->nDb; i++){ | |
| 456 int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ | |
| 457 if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; | |
| 458 pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName); | |
| 459 if( pTrigger ) break; | |
| 460 } | |
| 461 if( !pTrigger ){ | |
| 462 sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); | |
| 463 goto drop_trigger_cleanup; | |
| 464 } | |
| 465 sqlite3DropTriggerPtr(pParse, pTrigger); | |
| 466 | |
| 467 drop_trigger_cleanup: | |
| 468 sqlite3SrcListDelete(pName); | |
| 469 } | |
| 470 | |
| 471 /* | |
| 472 ** Return a pointer to the Table structure for the table that a trigger | |
| 473 ** is set on. | |
| 474 */ | |
| 475 static Table *tableOfTrigger(Trigger *pTrigger){ | |
| 476 int n = strlen(pTrigger->table) + 1; | |
| 477 return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n); | |
| 478 } | |
| 479 | |
| 480 | |
| 481 /* | |
| 482 ** Drop a trigger given a pointer to that trigger. | |
| 483 */ | |
| 484 void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ | |
| 485 Table *pTable; | |
| 486 Vdbe *v; | |
| 487 sqlite3 *db = pParse->db; | |
| 488 int iDb; | |
| 489 | |
| 490 iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema); | |
| 491 assert( iDb>=0 && iDb<db->nDb ); | |
| 492 pTable = tableOfTrigger(pTrigger); | |
| 493 assert( pTable ); | |
| 494 assert( pTable->pSchema==pTrigger->pSchema || iDb==1 ); | |
| 495 #ifndef SQLITE_OMIT_AUTHORIZATION | |
| 496 { | |
| 497 int code = SQLITE_DROP_TRIGGER; | |
| 498 const char *zDb = db->aDb[iDb].zName; | |
| 499 const char *zTab = SCHEMA_TABLE(iDb); | |
| 500 if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; | |
| 501 if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) || | |
| 502 sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ | |
| 503 return; | |
| 504 } | |
| 505 } | |
| 506 #endif | |
| 507 | |
| 508 /* Generate code to destroy the database record of the trigger. | |
| 509 */ | |
| 510 assert( pTable!=0 ); | |
| 511 if( (v = sqlite3GetVdbe(pParse))!=0 ){ | |
| 512 int base; | |
| 513 static const VdbeOpList dropTrigger[] = { | |
| 514 { OP_Rewind, 0, ADDR(9), 0}, | |
| 515 { OP_String8, 0, 0, 0}, /* 1 */ | |
| 516 { OP_Column, 0, 1, 0}, | |
| 517 { OP_Ne, 0, ADDR(8), 0}, | |
| 518 { OP_String8, 0, 0, "trigger"}, | |
| 519 { OP_Column, 0, 0, 0}, | |
| 520 { OP_Ne, 0, ADDR(8), 0}, | |
| 521 { OP_Delete, 0, 0, 0}, | |
| 522 { OP_Next, 0, ADDR(1), 0}, /* 8 */ | |
| 523 }; | |
| 524 | |
| 525 sqlite3BeginWriteOperation(pParse, 0, iDb); | |
| 526 sqlite3OpenMasterTable(pParse, iDb); | |
| 527 base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); | |
| 528 sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0); | |
| 529 sqlite3ChangeCookie(db, v, iDb); | |
| 530 sqlite3VdbeAddOp(v, OP_Close, 0, 0); | |
| 531 sqlite3VdbeOp3(v, OP_DropTrigger, iDb, 0, pTrigger->name, 0); | |
| 532 } | |
| 533 } | |
| 534 | |
| 535 /* | |
| 536 ** Remove a trigger from the hash tables of the sqlite* pointer. | |
| 537 */ | |
| 538 void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ | |
| 539 Trigger *pTrigger; | |
| 540 int nName = strlen(zName); | |
| 541 pTrigger = sqlite3HashInsert(&(db->aDb[iDb].pSchema->trigHash), | |
| 542 zName, nName, 0); | |
| 543 if( pTrigger ){ | |
| 544 Table *pTable = tableOfTrigger(pTrigger); | |
| 545 assert( pTable!=0 ); | |
| 546 if( pTable->pTrigger == pTrigger ){ | |
| 547 pTable->pTrigger = pTrigger->pNext; | |
| 548 }else{ | |
| 549 Trigger *cc = pTable->pTrigger; | |
| 550 while( cc ){ | |
| 551 if( cc->pNext == pTrigger ){ | |
| 552 cc->pNext = cc->pNext->pNext; | |
| 553 break; | |
| 554 } | |
| 555 cc = cc->pNext; | |
| 556 } | |
| 557 assert(cc); | |
| 558 } | |
| 559 sqlite3DeleteTrigger(pTrigger); | |
| 560 db->flags |= SQLITE_InternChanges; | |
| 561 } | |
| 562 } | |
| 563 | |
| 564 /* | |
| 565 ** pEList is the SET clause of an UPDATE statement. Each entry | |
| 566 ** in pEList is of the format <id>=<expr>. If any of the entries | |
| 567 ** in pEList have an <id> which matches an identifier in pIdList, | |
| 568 ** then return TRUE. If pIdList==NULL, then it is considered a | |
| 569 ** wildcard that matches anything. Likewise if pEList==NULL then | |
| 570 ** it matches anything so always return true. Return false only | |
| 571 ** if there is no match. | |
| 572 */ | |
| 573 static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){ | |
| 574 int e; | |
| 575 if( !pIdList || !pEList ) return 1; | |
| 576 for(e=0; e<pEList->nExpr; e++){ | |
| 577 if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1; | |
| 578 } | |
| 579 return 0; | |
| 580 } | |
| 581 | |
| 582 /* | |
| 583 ** Return a bit vector to indicate what kind of triggers exist for operation | |
| 584 ** "op" on table pTab. If pChanges is not NULL then it is a list of columns | |
| 585 ** that are being updated. Triggers only match if the ON clause of the | |
| 586 ** trigger definition overlaps the set of columns being updated. | |
| 587 ** | |
| 588 ** The returned bit vector is some combination of TRIGGER_BEFORE and | |
| 589 ** TRIGGER_AFTER. | |
| 590 */ | |
| 591 int sqlite3TriggersExist( | |
| 592 Parse *pParse, /* Used to check for recursive triggers */ | |
| 593 Table *pTab, /* The table the contains the triggers */ | |
| 594 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */ | |
| 595 ExprList *pChanges /* Columns that change in an UPDATE statement */ | |
| 596 ){ | |
| 597 Trigger *pTrigger = pTab->pTrigger; | |
| 598 int mask = 0; | |
| 599 | |
| 600 while( pTrigger ){ | |
| 601 if( pTrigger->op==op && checkColumnOverLap(pTrigger->pColumns, pChanges) ){ | |
| 602 mask |= pTrigger->tr_tm; | |
| 603 } | |
| 604 pTrigger = pTrigger->pNext; | |
| 605 } | |
| 606 return mask; | |
| 607 } | |
| 608 | |
| 609 /* | |
| 610 ** Convert the pStep->target token into a SrcList and return a pointer | |
| 611 ** to that SrcList. | |
| 612 ** | |
| 613 ** This routine adds a specific database name, if needed, to the target when | |
| 614 ** forming the SrcList. This prevents a trigger in one database from | |
| 615 ** referring to a target in another database. An exception is when the | |
| 616 ** trigger is in TEMP in which case it can refer to any other database it | |
| 617 ** wants. | |
| 618 */ | |
| 619 static SrcList *targetSrcList( | |
| 620 Parse *pParse, /* The parsing context */ | |
| 621 TriggerStep *pStep /* The trigger containing the target token */ | |
| 622 ){ | |
| 623 Token sDb; /* Dummy database name token */ | |
| 624 int iDb; /* Index of the database to use */ | |
| 625 SrcList *pSrc; /* SrcList to be returned */ | |
| 626 | |
| 627 iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema); | |
| 628 if( iDb==0 || iDb>=2 ){ | |
| 629 assert( iDb<pParse->db->nDb ); | |
| 630 sDb.z = (u8*)pParse->db->aDb[iDb].zName; | |
| 631 sDb.n = strlen((char*)sDb.z); | |
| 632 pSrc = sqlite3SrcListAppend(0, &sDb, &pStep->target); | |
| 633 } else { | |
| 634 pSrc = sqlite3SrcListAppend(0, &pStep->target, 0); | |
| 635 } | |
| 636 return pSrc; | |
| 637 } | |
| 638 | |
| 639 /* | |
| 640 ** Generate VDBE code for zero or more statements inside the body of a | |
| 641 ** trigger. | |
| 642 */ | |
| 643 static int codeTriggerProgram( | |
| 644 Parse *pParse, /* The parser context */ | |
| 645 TriggerStep *pStepList, /* List of statements inside the trigger body */ | |
| 646 int orconfin /* Conflict algorithm. (OE_Abort, etc) */ | |
| 647 ){ | |
| 648 TriggerStep * pTriggerStep = pStepList; | |
| 649 int orconf; | |
| 650 Vdbe *v = pParse->pVdbe; | |
| 651 | |
| 652 assert( pTriggerStep!=0 ); | |
| 653 assert( v!=0 ); | |
| 654 sqlite3VdbeAddOp(v, OP_ContextPush, 0, 0); | |
| 655 VdbeComment((v, "# begin trigger %s", pStepList->pTrig->name)); | |
| 656 while( pTriggerStep ){ | |
| 657 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; | |
| 658 pParse->trigStack->orconf = orconf; | |
| 659 switch( pTriggerStep->op ){ | |
| 660 case TK_SELECT: { | |
| 661 Select * ss = sqlite3SelectDup(pTriggerStep->pSelect); | |
| 662 assert(ss); | |
| 663 assert(ss->pSrc); | |
| 664 sqlite3SelectResolve(pParse, ss, 0); | |
| 665 sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0); | |
| 666 sqlite3SelectDelete(ss); | |
| 667 break; | |
| 668 } | |
| 669 case TK_UPDATE: { | |
| 670 SrcList *pSrc; | |
| 671 pSrc = targetSrcList(pParse, pTriggerStep); | |
| 672 sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); | |
| 673 sqlite3Update(pParse, pSrc, | |
| 674 sqlite3ExprListDup(pTriggerStep->pExprList), | |
| 675 sqlite3ExprDup(pTriggerStep->pWhere), orconf); | |
| 676 sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); | |
| 677 break; | |
| 678 } | |
| 679 case TK_INSERT: { | |
| 680 SrcList *pSrc; | |
| 681 pSrc = targetSrcList(pParse, pTriggerStep); | |
| 682 sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); | |
| 683 sqlite3Insert(pParse, pSrc, | |
| 684 sqlite3ExprListDup(pTriggerStep->pExprList), | |
| 685 sqlite3SelectDup(pTriggerStep->pSelect), | |
| 686 sqlite3IdListDup(pTriggerStep->pIdList), orconf); | |
| 687 sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); | |
| 688 break; | |
| 689 } | |
| 690 case TK_DELETE: { | |
| 691 SrcList *pSrc; | |
| 692 sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); | |
| 693 pSrc = targetSrcList(pParse, pTriggerStep); | |
| 694 sqlite3DeleteFrom(pParse, pSrc, sqlite3ExprDup(pTriggerStep->pWhere)); | |
| 695 sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); | |
| 696 break; | |
| 697 } | |
| 698 default: | |
| 699 assert(0); | |
| 700 } | |
| 701 pTriggerStep = pTriggerStep->pNext; | |
| 702 } | |
| 703 sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0); | |
| 704 VdbeComment((v, "# end trigger %s", pStepList->pTrig->name)); | |
| 705 | |
| 706 return 0; | |
| 707 } | |
| 708 | |
| 709 /* | |
| 710 ** This is called to code FOR EACH ROW triggers. | |
| 711 ** | |
| 712 ** When the code that this function generates is executed, the following | |
| 713 ** must be true: | |
| 714 ** | |
| 715 ** 1. No cursors may be open in the main database. (But newIdx and oldIdx | |
| 716 ** can be indices of cursors in temporary tables. See below.) | |
| 717 ** | |
| 718 ** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then | |
| 719 ** a temporary vdbe cursor (index newIdx) must be open and pointing at | |
| 720 ** a row containing values to be substituted for new.* expressions in the | |
| 721 ** trigger program(s). | |
| 722 ** | |
| 723 ** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then | |
| 724 ** a temporary vdbe cursor (index oldIdx) must be open and pointing at | |
| 725 ** a row containing values to be substituted for old.* expressions in the | |
| 726 ** trigger program(s). | |
| 727 ** | |
| 728 */ | |
| 729 int sqlite3CodeRowTrigger( | |
| 730 Parse *pParse, /* Parse context */ | |
| 731 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ | |
| 732 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ | |
| 733 int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ | |
| 734 Table *pTab, /* The table to code triggers from */ | |
| 735 int newIdx, /* The indice of the "new" row to access */ | |
| 736 int oldIdx, /* The indice of the "old" row to access */ | |
| 737 int orconf, /* ON CONFLICT policy */ | |
| 738 int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ | |
| 739 ){ | |
| 740 Trigger *p; | |
| 741 TriggerStack trigStackEntry; | |
| 742 | |
| 743 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE); | |
| 744 assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER ); | |
| 745 | |
| 746 assert(newIdx != -1 || oldIdx != -1); | |
| 747 | |
| 748 for(p=pTab->pTrigger; p; p=p->pNext){ | |
| 749 int fire_this = 0; | |
| 750 | |
| 751 /* Determine whether we should code this trigger */ | |
| 752 if( | |
| 753 p->op==op && | |
| 754 p->tr_tm==tr_tm && | |
| 755 (p->pSchema==p->pTabSchema || p->pSchema==pParse->db->aDb[1].pSchema) && | |
| 756 (op!=TK_UPDATE||!p->pColumns||checkColumnOverLap(p->pColumns,pChanges)) | |
| 757 ){ | |
| 758 TriggerStack *pS; /* Pointer to trigger-stack entry */ | |
| 759 for(pS=pParse->trigStack; pS && p!=pS->pTrigger; pS=pS->pNext){} | |
| 760 if( !pS ){ | |
| 761 fire_this = 1; | |
| 762 } | |
| 763 #if 0 /* Give no warning for recursive triggers. Just do not do them */ | |
| 764 else{ | |
| 765 sqlite3ErrorMsg(pParse, "recursive triggers not supported (%s)", | |
| 766 p->name); | |
| 767 return SQLITE_ERROR; | |
| 768 } | |
| 769 #endif | |
| 770 } | |
| 771 | |
| 772 if( fire_this ){ | |
| 773 int endTrigger; | |
| 774 Expr * whenExpr; | |
| 775 AuthContext sContext; | |
| 776 NameContext sNC; | |
| 777 | |
| 778 memset(&sNC, 0, sizeof(sNC)); | |
| 779 sNC.pParse = pParse; | |
| 780 | |
| 781 /* Push an entry on to the trigger stack */ | |
| 782 trigStackEntry.pTrigger = p; | |
| 783 trigStackEntry.newIdx = newIdx; | |
| 784 trigStackEntry.oldIdx = oldIdx; | |
| 785 trigStackEntry.pTab = pTab; | |
| 786 trigStackEntry.pNext = pParse->trigStack; | |
| 787 trigStackEntry.ignoreJump = ignoreJump; | |
| 788 pParse->trigStack = &trigStackEntry; | |
| 789 sqlite3AuthContextPush(pParse, &sContext, p->name); | |
| 790 | |
| 791 /* code the WHEN clause */ | |
| 792 endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe); | |
| 793 whenExpr = sqlite3ExprDup(p->pWhen); | |
| 794 if( sqlite3ExprResolveNames(&sNC, whenExpr) ){ | |
| 795 pParse->trigStack = trigStackEntry.pNext; | |
| 796 sqlite3ExprDelete(whenExpr); | |
| 797 return 1; | |
| 798 } | |
| 799 sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1); | |
| 800 sqlite3ExprDelete(whenExpr); | |
| 801 | |
| 802 codeTriggerProgram(pParse, p->step_list, orconf); | |
| 803 | |
| 804 /* Pop the entry off the trigger stack */ | |
| 805 pParse->trigStack = trigStackEntry.pNext; | |
| 806 sqlite3AuthContextPop(&sContext); | |
| 807 | |
| 808 sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger); | |
| 809 } | |
| 810 } | |
| 811 return 0; | |
| 812 } | |
| 813 #endif /* !defined(SQLITE_OMIT_TRIGGER) */ |
