| OLD | NEW |
| 1 /* | 1 /* |
| 2 ** | 2 ** |
| 3 ** The author disclaims copyright to this source code. In place of | 3 ** The author disclaims copyright to this source code. In place of |
| 4 ** a legal notice, here is a blessing: | 4 ** a legal notice, here is a blessing: |
| 5 ** | 5 ** |
| 6 ** May you do good and not evil. | 6 ** May you do good and not evil. |
| 7 ** May you find forgiveness for yourself and forgive others. | 7 ** May you find forgiveness for yourself and forgive others. |
| 8 ** May you share freely, never taking more than you give. | 8 ** May you share freely, never taking more than you give. |
| 9 ** | 9 ** |
| 10 ************************************************************************* | 10 ************************************************************************* |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 int isTemp, /* True if the TEMPORARY keyword is present */ | 89 int isTemp, /* True if the TEMPORARY keyword is present */ |
| 90 int noErr /* Suppress errors if the trigger already exists */ | 90 int noErr /* Suppress errors if the trigger already exists */ |
| 91 ){ | 91 ){ |
| 92 Trigger *pTrigger = 0; /* The new trigger */ | 92 Trigger *pTrigger = 0; /* The new trigger */ |
| 93 Table *pTab; /* Table that the trigger fires off of */ | 93 Table *pTab; /* Table that the trigger fires off of */ |
| 94 char *zName = 0; /* Name of the trigger */ | 94 char *zName = 0; /* Name of the trigger */ |
| 95 sqlite3 *db = pParse->db; /* The database connection */ | 95 sqlite3 *db = pParse->db; /* The database connection */ |
| 96 int iDb; /* The database to store the trigger in */ | 96 int iDb; /* The database to store the trigger in */ |
| 97 Token *pName; /* The unqualified db name */ | 97 Token *pName; /* The unqualified db name */ |
| 98 DbFixer sFix; /* State vector for the DB fixer */ | 98 DbFixer sFix; /* State vector for the DB fixer */ |
| 99 int iTabDb; /* Index of the database holding pTab */ | |
| 100 | 99 |
| 101 assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */ | 100 assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */ |
| 102 assert( pName2!=0 ); | 101 assert( pName2!=0 ); |
| 103 assert( op==TK_INSERT || op==TK_UPDATE || op==TK_DELETE ); | 102 assert( op==TK_INSERT || op==TK_UPDATE || op==TK_DELETE ); |
| 104 assert( op>0 && op<0xff ); | 103 assert( op>0 && op<0xff ); |
| 105 if( isTemp ){ | 104 if( isTemp ){ |
| 106 /* If TEMP was specified, then the trigger name may not be qualified. */ | 105 /* If TEMP was specified, then the trigger name may not be qualified. */ |
| 107 if( pName2->n>0 ){ | 106 if( pName2->n>0 ){ |
| 108 sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name"); | 107 sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name"); |
| 109 goto trigger_cleanup; | 108 goto trigger_cleanup; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 if( pTab->pSelect && tr_tm!=TK_INSTEAD ){ | 201 if( pTab->pSelect && tr_tm!=TK_INSTEAD ){ |
| 203 sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", | 202 sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", |
| 204 (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0); | 203 (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0); |
| 205 goto trigger_cleanup; | 204 goto trigger_cleanup; |
| 206 } | 205 } |
| 207 if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ | 206 if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ |
| 208 sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" | 207 sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" |
| 209 " trigger on table: %S", pTableName, 0); | 208 " trigger on table: %S", pTableName, 0); |
| 210 goto trigger_cleanup; | 209 goto trigger_cleanup; |
| 211 } | 210 } |
| 212 iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); | |
| 213 | 211 |
| 214 #ifndef SQLITE_OMIT_AUTHORIZATION | 212 #ifndef SQLITE_OMIT_AUTHORIZATION |
| 215 { | 213 { |
| 214 int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
| 216 int code = SQLITE_CREATE_TRIGGER; | 215 int code = SQLITE_CREATE_TRIGGER; |
| 217 const char *zDb = db->aDb[iTabDb].zName; | 216 const char *zDb = db->aDb[iTabDb].zDbSName; |
| 218 const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; | 217 const char *zDbTrig = isTemp ? db->aDb[1].zDbSName : zDb; |
| 219 if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; | 218 if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; |
| 220 if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ | 219 if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ |
| 221 goto trigger_cleanup; | 220 goto trigger_cleanup; |
| 222 } | 221 } |
| 223 if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){ | 222 if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){ |
| 224 goto trigger_cleanup; | 223 goto trigger_cleanup; |
| 225 } | 224 } |
| 226 } | 225 } |
| 227 #endif | 226 #endif |
| 228 | 227 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 | 279 |
| 281 pParse->pNewTrigger = 0; | 280 pParse->pNewTrigger = 0; |
| 282 if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; | 281 if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; |
| 283 zName = pTrig->zName; | 282 zName = pTrig->zName; |
| 284 iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); | 283 iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); |
| 285 pTrig->step_list = pStepList; | 284 pTrig->step_list = pStepList; |
| 286 while( pStepList ){ | 285 while( pStepList ){ |
| 287 pStepList->pTrig = pTrig; | 286 pStepList->pTrig = pTrig; |
| 288 pStepList = pStepList->pNext; | 287 pStepList = pStepList->pNext; |
| 289 } | 288 } |
| 290 nameToken.z = pTrig->zName; | 289 sqlite3TokenInit(&nameToken, pTrig->zName); |
| 291 nameToken.n = sqlite3Strlen30(nameToken.z); | |
| 292 sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken); | 290 sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken); |
| 293 if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) | 291 if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) |
| 294 || sqlite3FixExpr(&sFix, pTrig->pWhen) | 292 || sqlite3FixExpr(&sFix, pTrig->pWhen) |
| 295 ){ | 293 ){ |
| 296 goto triggerfinish_cleanup; | 294 goto triggerfinish_cleanup; |
| 297 } | 295 } |
| 298 | 296 |
| 299 /* if we are not initializing, | 297 /* if we are not initializing, |
| 300 ** build the sqlite_master entry | 298 ** build the sqlite_master entry |
| 301 */ | 299 */ |
| 302 if( !db->init.busy ){ | 300 if( !db->init.busy ){ |
| 303 Vdbe *v; | 301 Vdbe *v; |
| 304 char *z; | 302 char *z; |
| 305 | 303 |
| 306 /* Make an entry in the sqlite_master table */ | 304 /* Make an entry in the sqlite_master table */ |
| 307 v = sqlite3GetVdbe(pParse); | 305 v = sqlite3GetVdbe(pParse); |
| 308 if( v==0 ) goto triggerfinish_cleanup; | 306 if( v==0 ) goto triggerfinish_cleanup; |
| 309 sqlite3BeginWriteOperation(pParse, 0, iDb); | 307 sqlite3BeginWriteOperation(pParse, 0, iDb); |
| 310 z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n); | 308 z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n); |
| 311 sqlite3NestedParse(pParse, | 309 sqlite3NestedParse(pParse, |
| 312 "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", | 310 "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", |
| 313 db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zName, | 311 db->aDb[iDb].zDbSName, MASTER_NAME, zName, |
| 314 pTrig->table, z); | 312 pTrig->table, z); |
| 315 sqlite3DbFree(db, z); | 313 sqlite3DbFree(db, z); |
| 316 sqlite3ChangeCookie(pParse, iDb); | 314 sqlite3ChangeCookie(pParse, iDb); |
| 317 sqlite3VdbeAddParseSchemaOp(v, iDb, | 315 sqlite3VdbeAddParseSchemaOp(v, iDb, |
| 318 sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName)); | 316 sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName)); |
| 319 } | 317 } |
| 320 | 318 |
| 321 if( db->init.busy ){ | 319 if( db->init.busy ){ |
| 322 Trigger *pLink = pTrig; | 320 Trigger *pLink = pTrig; |
| 323 Hash *pHash = &db->aDb[iDb].pSchema->trigHash; | 321 Hash *pHash = &db->aDb[iDb].pSchema->trigHash; |
| 324 assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); | 322 assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); |
| 325 pTrig = sqlite3HashInsert(pHash, zName, pTrig); | 323 pTrig = sqlite3HashInsert(pHash, zName, pTrig); |
| 326 if( pTrig ){ | 324 if( pTrig ){ |
| 327 db->mallocFailed = 1; | 325 sqlite3OomFault(db); |
| 328 }else if( pLink->pSchema==pLink->pTabSchema ){ | 326 }else if( pLink->pSchema==pLink->pTabSchema ){ |
| 329 Table *pTab; | 327 Table *pTab; |
| 330 pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table); | 328 pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table); |
| 331 assert( pTab!=0 ); | 329 assert( pTab!=0 ); |
| 332 pLink->pNext = pTab->pTrigger; | 330 pLink->pNext = pTab->pTrigger; |
| 333 pTab->pTrigger = pLink; | 331 pTab->pTrigger = pLink; |
| 334 } | 332 } |
| 335 } | 333 } |
| 336 | 334 |
| 337 triggerfinish_cleanup: | 335 triggerfinish_cleanup: |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ | 490 if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ |
| 493 goto drop_trigger_cleanup; | 491 goto drop_trigger_cleanup; |
| 494 } | 492 } |
| 495 | 493 |
| 496 assert( pName->nSrc==1 ); | 494 assert( pName->nSrc==1 ); |
| 497 zDb = pName->a[0].zDatabase; | 495 zDb = pName->a[0].zDatabase; |
| 498 zName = pName->a[0].zName; | 496 zName = pName->a[0].zName; |
| 499 assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); | 497 assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); |
| 500 for(i=OMIT_TEMPDB; i<db->nDb; i++){ | 498 for(i=OMIT_TEMPDB; i<db->nDb; i++){ |
| 501 int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ | 499 int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ |
| 502 if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; | 500 if( zDb && sqlite3StrICmp(db->aDb[j].zDbSName, zDb) ) continue; |
| 503 assert( sqlite3SchemaMutexHeld(db, j, 0) ); | 501 assert( sqlite3SchemaMutexHeld(db, j, 0) ); |
| 504 pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName); | 502 pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName); |
| 505 if( pTrigger ) break; | 503 if( pTrigger ) break; |
| 506 } | 504 } |
| 507 if( !pTrigger ){ | 505 if( !pTrigger ){ |
| 508 if( !noErr ){ | 506 if( !noErr ){ |
| 509 sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); | 507 sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); |
| 510 }else{ | 508 }else{ |
| 511 sqlite3CodeVerifyNamedSchema(pParse, zDb); | 509 sqlite3CodeVerifyNamedSchema(pParse, zDb); |
| 512 } | 510 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 538 int iDb; | 536 int iDb; |
| 539 | 537 |
| 540 iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema); | 538 iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema); |
| 541 assert( iDb>=0 && iDb<db->nDb ); | 539 assert( iDb>=0 && iDb<db->nDb ); |
| 542 pTable = tableOfTrigger(pTrigger); | 540 pTable = tableOfTrigger(pTrigger); |
| 543 assert( pTable ); | 541 assert( pTable ); |
| 544 assert( pTable->pSchema==pTrigger->pSchema || iDb==1 ); | 542 assert( pTable->pSchema==pTrigger->pSchema || iDb==1 ); |
| 545 #ifndef SQLITE_OMIT_AUTHORIZATION | 543 #ifndef SQLITE_OMIT_AUTHORIZATION |
| 546 { | 544 { |
| 547 int code = SQLITE_DROP_TRIGGER; | 545 int code = SQLITE_DROP_TRIGGER; |
| 548 const char *zDb = db->aDb[iDb].zName; | 546 const char *zDb = db->aDb[iDb].zDbSName; |
| 549 const char *zTab = SCHEMA_TABLE(iDb); | 547 const char *zTab = SCHEMA_TABLE(iDb); |
| 550 if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; | 548 if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; |
| 551 if( sqlite3AuthCheck(pParse, code, pTrigger->zName, pTable->zName, zDb) || | 549 if( sqlite3AuthCheck(pParse, code, pTrigger->zName, pTable->zName, zDb) || |
| 552 sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ | 550 sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ |
| 553 return; | 551 return; |
| 554 } | 552 } |
| 555 } | 553 } |
| 556 #endif | 554 #endif |
| 557 | 555 |
| 558 /* Generate code to destroy the database record of the trigger. | 556 /* Generate code to destroy the database record of the trigger. |
| 559 */ | 557 */ |
| 560 assert( pTable!=0 ); | 558 assert( pTable!=0 ); |
| 561 if( (v = sqlite3GetVdbe(pParse))!=0 ){ | 559 if( (v = sqlite3GetVdbe(pParse))!=0 ){ |
| 562 sqlite3NestedParse(pParse, | 560 sqlite3NestedParse(pParse, |
| 563 "DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'", | 561 "DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'", |
| 564 db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrigger->zName | 562 db->aDb[iDb].zDbSName, MASTER_NAME, pTrigger->zName |
| 565 ); | 563 ); |
| 566 sqlite3ChangeCookie(pParse, iDb); | 564 sqlite3ChangeCookie(pParse, iDb); |
| 567 sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0); | 565 sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0); |
| 568 } | 566 } |
| 569 } | 567 } |
| 570 | 568 |
| 571 /* | 569 /* |
| 572 ** Remove a trigger from the hash tables of the sqlite* pointer. | 570 ** Remove a trigger from the hash tables of the sqlite* pointer. |
| 573 */ | 571 */ |
| 574 void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ | 572 void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 sqlite3 *db = pParse->db; | 655 sqlite3 *db = pParse->db; |
| 658 int iDb; /* Index of the database to use */ | 656 int iDb; /* Index of the database to use */ |
| 659 SrcList *pSrc; /* SrcList to be returned */ | 657 SrcList *pSrc; /* SrcList to be returned */ |
| 660 | 658 |
| 661 pSrc = sqlite3SrcListAppend(db, 0, 0, 0); | 659 pSrc = sqlite3SrcListAppend(db, 0, 0, 0); |
| 662 if( pSrc ){ | 660 if( pSrc ){ |
| 663 assert( pSrc->nSrc>0 ); | 661 assert( pSrc->nSrc>0 ); |
| 664 pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget); | 662 pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget); |
| 665 iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema); | 663 iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema); |
| 666 if( iDb==0 || iDb>=2 ){ | 664 if( iDb==0 || iDb>=2 ){ |
| 665 const char *zDb; |
| 667 assert( iDb<db->nDb ); | 666 assert( iDb<db->nDb ); |
| 668 pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); | 667 zDb = db->aDb[iDb].zDbSName; |
| 668 pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, zDb); |
| 669 } | 669 } |
| 670 } | 670 } |
| 671 return pSrc; | 671 return pSrc; |
| 672 } | 672 } |
| 673 | 673 |
| 674 /* | 674 /* |
| 675 ** Generate VDBE code for the statements inside the body of a single | 675 ** Generate VDBE code for the statements inside the body of a single |
| 676 ** trigger. | 676 ** trigger. |
| 677 */ | 677 */ |
| 678 static int codeTriggerProgram( | 678 static int codeTriggerProgram( |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 872 } | 872 } |
| 873 sqlite3VdbeAddOp0(v, OP_Halt); | 873 sqlite3VdbeAddOp0(v, OP_Halt); |
| 874 VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf))); | 874 VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf))); |
| 875 | 875 |
| 876 transferParseError(pParse, pSubParse); | 876 transferParseError(pParse, pSubParse); |
| 877 if( db->mallocFailed==0 ){ | 877 if( db->mallocFailed==0 ){ |
| 878 pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); | 878 pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); |
| 879 } | 879 } |
| 880 pProgram->nMem = pSubParse->nMem; | 880 pProgram->nMem = pSubParse->nMem; |
| 881 pProgram->nCsr = pSubParse->nTab; | 881 pProgram->nCsr = pSubParse->nTab; |
| 882 pProgram->nOnce = pSubParse->nOnce; | |
| 883 pProgram->token = (void *)pTrigger; | 882 pProgram->token = (void *)pTrigger; |
| 884 pPrg->aColmask[0] = pSubParse->oldmask; | 883 pPrg->aColmask[0] = pSubParse->oldmask; |
| 885 pPrg->aColmask[1] = pSubParse->newmask; | 884 pPrg->aColmask[1] = pSubParse->newmask; |
| 886 sqlite3VdbeDelete(v); | 885 sqlite3VdbeDelete(v); |
| 887 } | 886 } |
| 888 | 887 |
| 889 assert( !pSubParse->pAinc && !pSubParse->pZombieTab ); | 888 assert( !pSubParse->pAinc && !pSubParse->pZombieTab ); |
| 890 assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg ); | 889 assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg ); |
| 891 sqlite3ParserReset(pSubParse); | 890 sqlite3ParserReset(pSubParse); |
| 892 sqlite3StackFree(db, pSubParse); | 891 sqlite3StackFree(db, pSubParse); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 945 Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */ | 944 Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */ |
| 946 TriggerPrg *pPrg; | 945 TriggerPrg *pPrg; |
| 947 pPrg = getRowTrigger(pParse, p, pTab, orconf); | 946 pPrg = getRowTrigger(pParse, p, pTab, orconf); |
| 948 assert( pPrg || pParse->nErr || pParse->db->mallocFailed ); | 947 assert( pPrg || pParse->nErr || pParse->db->mallocFailed ); |
| 949 | 948 |
| 950 /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program | 949 /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program |
| 951 ** is a pointer to the sub-vdbe containing the trigger program. */ | 950 ** is a pointer to the sub-vdbe containing the trigger program. */ |
| 952 if( pPrg ){ | 951 if( pPrg ){ |
| 953 int bRecursive = (p->zName && 0==(pParse->db->flags&SQLITE_RecTriggers)); | 952 int bRecursive = (p->zName && 0==(pParse->db->flags&SQLITE_RecTriggers)); |
| 954 | 953 |
| 955 sqlite3VdbeAddOp3(v, OP_Program, reg, ignoreJump, ++pParse->nMem); | 954 sqlite3VdbeAddOp4(v, OP_Program, reg, ignoreJump, ++pParse->nMem, |
| 956 sqlite3VdbeChangeP4(v, -1, (const char *)pPrg->pProgram, P4_SUBPROGRAM); | 955 (const char *)pPrg->pProgram, P4_SUBPROGRAM); |
| 957 VdbeComment( | 956 VdbeComment( |
| 958 (v, "Call: %s.%s", (p->zName?p->zName:"fkey"), onErrorText(orconf))); | 957 (v, "Call: %s.%s", (p->zName?p->zName:"fkey"), onErrorText(orconf))); |
| 959 | 958 |
| 960 /* Set the P5 operand of the OP_Program instruction to non-zero if | 959 /* Set the P5 operand of the OP_Program instruction to non-zero if |
| 961 ** recursive invocation of this trigger program is disallowed. Recursive | 960 ** recursive invocation of this trigger program is disallowed. Recursive |
| 962 ** invocation is disallowed if (a) the sub-program is really a trigger, | 961 ** invocation is disallowed if (a) the sub-program is really a trigger, |
| 963 ** not a foreign key action, and (b) the flag to enable recursive triggers | 962 ** not a foreign key action, and (b) the flag to enable recursive triggers |
| 964 ** is clear. */ | 963 ** is clear. */ |
| 965 sqlite3VdbeChangeP5(v, (u8)bRecursive); | 964 sqlite3VdbeChangeP5(v, (u8)bRecursive); |
| 966 } | 965 } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1091 if( pPrg ){ | 1090 if( pPrg ){ |
| 1092 mask |= pPrg->aColmask[isNew]; | 1091 mask |= pPrg->aColmask[isNew]; |
| 1093 } | 1092 } |
| 1094 } | 1093 } |
| 1095 } | 1094 } |
| 1096 | 1095 |
| 1097 return mask; | 1096 return mask; |
| 1098 } | 1097 } |
| 1099 | 1098 |
| 1100 #endif /* !defined(SQLITE_OMIT_TRIGGER) */ | 1099 #endif /* !defined(SQLITE_OMIT_TRIGGER) */ |
| OLD | NEW |