summaryrefslogtreecommitdiff
path: root/ext/pdo_sqlite/sqlite/src/trigger.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pdo_sqlite/sqlite/src/trigger.c')
-rw-r--r--ext/pdo_sqlite/sqlite/src/trigger.c122
1 files changed, 53 insertions, 69 deletions
diff --git a/ext/pdo_sqlite/sqlite/src/trigger.c b/ext/pdo_sqlite/sqlite/src/trigger.c
index bbb526f802..eccc810e9b 100644
--- a/ext/pdo_sqlite/sqlite/src/trigger.c
+++ b/ext/pdo_sqlite/sqlite/src/trigger.c
@@ -12,6 +12,7 @@
*/
#include "sqliteInt.h"
+#ifndef SQLITE_OMIT_TRIGGER
/*
** Delete a linked list of TriggerStep structures.
*/
@@ -110,9 +111,7 @@ void sqlite3BeginTrigger(
}
/* 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)
- ){
+ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
pParse->nErr++;
goto trigger_cleanup;
@@ -166,7 +165,7 @@ void sqlite3BeginTrigger(
pTrigger->iDb = iDb;
pTrigger->iTabDb = pTab->iDb;
pTrigger->op = op;
- pTrigger->tr_tm = tr_tm;
+ pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
pTrigger->pWhen = sqlite3ExprDup(pWhen);
pTrigger->pColumns = sqlite3IdListDup(pColumns);
pTrigger->foreach = foreach;
@@ -190,20 +189,20 @@ void sqlite3FinishTrigger(
TriggerStep *pStepList, /* The triggered program */
Token *pAll /* Token that describes the complete CREATE TRIGGER */
){
- Trigger *nt = 0; /* The trigger whose construction is finishing up */
+ Trigger *pTrig = 0; /* The trigger whose construction is finishing up */
sqlite3 *db = pParse->db; /* The database */
DbFixer sFix;
if( pParse->nErr || pParse->pNewTrigger==0 ) goto triggerfinish_cleanup;
- nt = pParse->pNewTrigger;
+ pTrig = pParse->pNewTrigger;
pParse->pNewTrigger = 0;
- nt->step_list = pStepList;
+ pTrig->step_list = pStepList;
while( pStepList ){
- pStepList->pTrig = nt;
+ pStepList->pTrig = pTrig;
pStepList = pStepList->pNext;
}
- if( sqlite3FixInit(&sFix, pParse, nt->iDb, "trigger", &nt->nameToken)
- && sqlite3FixTriggerStep(&sFix, nt->step_list) ){
+ if( sqlite3FixInit(&sFix, pParse, pTrig->iDb, "trigger", &pTrig->nameToken)
+ && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
goto triggerfinish_cleanup;
}
@@ -229,35 +228,32 @@ void sqlite3FinishTrigger(
/* Make an entry in the sqlite_master table */
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto triggerfinish_cleanup;
- sqlite3BeginWriteOperation(pParse, 0, nt->iDb);
- sqlite3OpenMasterTable(v, nt->iDb);
+ sqlite3BeginWriteOperation(pParse, 0, pTrig->iDb);
+ sqlite3OpenMasterTable(v, pTrig->iDb);
addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
- sqlite3VdbeChangeP3(v, addr+2, nt->name, 0);
- sqlite3VdbeChangeP3(v, addr+3, nt->table, 0);
+ sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0);
+ sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0);
sqlite3VdbeChangeP3(v, addr+6, pAll->z, pAll->n);
- if( nt->iDb!=0 ){
- sqlite3ChangeCookie(db, v, nt->iDb);
- }
+ sqlite3ChangeCookie(db, v, pTrig->iDb);
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
- sqlite3VdbeOp3(v, OP_ParseSchema, nt->iDb, 0,
- sqlite3MPrintf("type='trigger' AND name='%q'", nt->name), P3_DYNAMIC);
+ sqlite3VdbeOp3(v, OP_ParseSchema, pTrig->iDb, 0,
+ sqlite3MPrintf("type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC);
}
if( db->init.busy ){
Table *pTab;
- sqlite3HashInsert(&db->aDb[nt->iDb].trigHash,
- nt->name, strlen(nt->name)+1, nt);
- pTab = sqlite3LocateTable(pParse, nt->table, db->aDb[nt->iTabDb].zName);
+ sqlite3HashInsert(&db->aDb[pTrig->iDb].trigHash,
+ pTrig->name, strlen(pTrig->name)+1, pTrig);
+ pTab = sqlite3LocateTable(pParse,pTrig->table,db->aDb[pTrig->iTabDb].zName);
assert( pTab!=0 );
- nt->pNext = pTab->pTrigger;
- pTab->pTrigger = nt;
- nt = 0;
+ pTrig->pNext = pTab->pTrigger;
+ pTab->pTrigger = pTrig;
+ pTrig = 0;
}
triggerfinish_cleanup:
- sqlite3DeleteTrigger(nt);
- sqlite3DeleteTrigger(pParse->pNewTrigger);
- pParse->pNewTrigger = 0;
+ sqlite3DeleteTrigger(pTrig);
+ assert( !pParse->pNewTrigger );
sqlite3DeleteTriggerStep(pStepList);
}
@@ -555,52 +551,38 @@ static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
return 0;
}
-/* A global variable that is TRUE if we should always set up temp tables for
- * for triggers, even if there are no triggers to code. This is used to test
- * how much overhead the triggers algorithm is causing.
- *
- * This flag can be set or cleared using the "trigger_overhead_test" pragma.
- * The pragma is not documented since it is not really part of the interface
- * to SQLite, just the test procedure.
-*/
-int sqlite3_always_code_trigger_setup = 0;
-
/*
- * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
- * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
- * found in the list specified as pTrigger.
- */
+** Return a bit vector to indicate what kind of triggers exist for operation
+** "op" on table pTab. If pChanges is not NULL then it is a list of columns
+** that are being updated. Triggers only match if the ON clause of the
+** trigger definition overlaps the set of columns being updated.
+**
+** The returned bit vector is some combination of TRIGGER_BEFORE and
+** TRIGGER_AFTER.
+*/
int sqlite3TriggersExist(
Parse *pParse, /* Used to check for recursive triggers */
- Trigger *pTrigger, /* A list of triggers associated with a table */
+ Table *pTab, /* The table the contains the triggers */
int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
- int tr_tm, /* one of TK_BEFORE, TK_AFTER */
- int foreach, /* one of TK_ROW or TK_STATEMENT */
ExprList *pChanges /* Columns that change in an UPDATE statement */
){
- Trigger * pTriggerCursor;
+ Trigger *pTrigger = pTab->pTrigger;
+ int mask = 0;
- if( sqlite3_always_code_trigger_setup ){
- return 1;
- }
-
- pTriggerCursor = pTrigger;
- while( pTriggerCursor ){
- if( pTriggerCursor->op == op &&
- pTriggerCursor->tr_tm == tr_tm &&
- pTriggerCursor->foreach == foreach &&
- checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
- TriggerStack * ss;
+ while( pTrigger ){
+ if( pTrigger->op==op && checkColumnOverLap(pTrigger->pColumns, pChanges) ){
+ TriggerStack *ss;
ss = pParse->trigStack;
- while( ss && ss->pTrigger != pTrigger ){
+ while( ss && ss->pTrigger!=pTab->pTrigger ){
ss = ss->pNext;
}
- if( !ss )return 1;
+ if( ss==0 ){
+ mask |= pTrigger->tr_tm;
+ }
}
- pTriggerCursor = pTriggerCursor->pNext;
+ pTrigger = pTrigger->pNext;
}
-
- return 0;
+ return mask;
}
/*
@@ -658,6 +640,7 @@ static int codeTriggerProgram(
Select * ss = sqlite3SelectDup(pTriggerStep->pSelect);
assert(ss);
assert(ss->pSrc);
+ sqlite3SelectResolve(pParse, ss, 0);
sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0);
sqlite3SelectDelete(ss);
break;
@@ -726,7 +709,7 @@ int sqlite3CodeRowTrigger(
Parse *pParse, /* Parse context */
int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
- int tr_tm, /* One of TK_BEFORE, TK_AFTER */
+ int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
Table *pTab, /* The table to code triggers from */
int newIdx, /* The indice of the "new" row to access */
int oldIdx, /* The indice of the "old" row to access */
@@ -738,7 +721,7 @@ int sqlite3CodeRowTrigger(
TriggerStack trigStackEntry;
assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
- assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER );
+ assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER );
assert(newIdx != -1 || oldIdx != -1);
@@ -747,8 +730,7 @@ int sqlite3CodeRowTrigger(
int fire_this = 0;
/* determine whether we should code this trigger */
- if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
- pTrigger->foreach == TK_ROW ){
+ if( pTrigger->op == op && pTrigger->tr_tm == tr_tm ){
fire_this = 1;
for(pStack=pParse->trigStack; pStack; pStack=pStack->pNext){
if( pStack->pTrigger==pTrigger ){
@@ -763,11 +745,12 @@ int sqlite3CodeRowTrigger(
if( fire_this ){
int endTrigger;
- SrcList dummyTablist;
Expr * whenExpr;
AuthContext sContext;
+ NameContext sNC;
- dummyTablist.nSrc = 0;
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
/* Push an entry on to the trigger stack */
trigStackEntry.pTrigger = pTrigger;
@@ -782,7 +765,7 @@ int sqlite3CodeRowTrigger(
/* code the WHEN clause */
endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
whenExpr = sqlite3ExprDup(pTrigger->pWhen);
- if( sqlite3ExprResolveIds(pParse, &dummyTablist, 0, whenExpr) ){
+ if( sqlite3ExprResolveNames(&sNC, whenExpr) ){
pParse->trigStack = trigStackEntry.pNext;
sqlite3ExprDelete(whenExpr);
return 1;
@@ -802,3 +785,4 @@ int sqlite3CodeRowTrigger(
}
return 0;
}
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */