aboutsummaryrefslogtreecommitdiff
path: root/src/trigger.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2003-05-31 16:21:12 +0000
committerdrh <drh@noemail.net>2003-05-31 16:21:12 +0000
commitf26e09c87fd45fe3bb5aa4edacc9ea3f6325c884 (patch)
tree5f3a5c939757ced657ebcfbea9c0418fadb19677 /src/trigger.c
parent8372b8d13442ad85ab76f6b1bf89532f45fdce59 (diff)
downloadsqlite-f26e09c87fd45fe3bb5aa4edacc9ea3f6325c884.tar.gz
sqlite-f26e09c87fd45fe3bb5aa4edacc9ea3f6325c884.zip
Tighter binding of views, triggers, and indices to their respective
databases. Ticket #323. Much more testing needs to be done to the sqliteFix...() routines in attach.c. (CVS 990) FossilOrigin-Name: 7202d4f1a8853368954a967b7ccca9d8a6645a2e
Diffstat (limited to 'src/trigger.c')
-rw-r--r--src/trigger.c61
1 files changed, 50 insertions, 11 deletions
diff --git a/src/trigger.c b/src/trigger.c
index 6ac45fc23..eec48e0ff 100644
--- a/src/trigger.c
+++ b/src/trigger.c
@@ -64,7 +64,12 @@ void sqliteBeginTrigger(
*/
if( sqlite_malloc_failed ) goto trigger_cleanup;
assert( pTableName->nSrc==1 );
+ assert( pTableName->a[0].zDatabase==0 );
+ if( pParse->initFlag ){
+ pTableName->a[0].zDatabase = db->aDb[pParse->iDb].zName;
+ }
tab = sqliteSrcListLookup(pParse, pTableName);
+ pTableName->a[0].zDatabase = 0;
if( !tab ){
goto trigger_cleanup;
}
@@ -133,6 +138,7 @@ void sqliteBeginTrigger(
nt->pWhen = sqliteExprDup(pWhen);
nt->pColumns = sqliteIdListDup(pColumns);
nt->foreach = foreach;
+ nt->pNameToken = pName;
assert( pParse->pNewTrigger==0 );
pParse->pNewTrigger = nt;
@@ -152,8 +158,9 @@ void sqliteFinishTrigger(
TriggerStep *pStepList, /* The triggered program */
Token *pAll /* Token that describes the complete CREATE TRIGGER */
){
- Trigger *nt; /* The trigger whose construction is finishing up */
+ Trigger *nt = 0; /* The trigger whose construction is finishing up */
sqlite *db = pParse->db; /* The database */
+ DbFixer sFix;
if( pParse->nErr || pParse->pNewTrigger==0 ) goto triggerfinish_cleanup;
nt = pParse->pNewTrigger;
@@ -163,6 +170,11 @@ void sqliteFinishTrigger(
pStepList->pTrig = nt;
pStepList = pStepList->pNext;
}
+ if( sqliteFixInit(&sFix, pParse, nt->iDb, "trigger", nt->pNameToken)
+ && sqliteFixTriggerStep(&sFix, nt->step_list) ){
+ goto triggerfinish_cleanup;
+ }
+ nt->pNameToken = 0;
/* if we are not initializing, and this trigger is not on a TEMP table,
** build the sqlite_master entry
@@ -201,15 +213,15 @@ void sqliteFinishTrigger(
Table *pTab;
sqliteHashInsert(&db->aDb[nt->iDb].trigHash,
nt->name, strlen(nt->name)+1, nt);
- pTab = sqliteLocateTable(pParse, nt->table, 0);
+ pTab = sqliteLocateTable(pParse, nt->table, db->aDb[nt->iTabDb].zName);
assert( pTab!=0 );
nt->pNext = pTab->pTrigger;
pTab->pTrigger = nt;
- }else{
- sqliteDeleteTrigger(nt);
+ nt = 0;
}
triggerfinish_cleanup:
+ sqliteDeleteTrigger(nt);
sqliteDeleteTrigger(pParse->pNewTrigger);
pParse->pNewTrigger = 0;
sqliteDeleteTriggerStep(pStepList);
@@ -548,6 +560,36 @@ int sqliteTriggersExist(
}
/*
+** Convert the pStep->target token into a SrcList and return a pointer
+** to that SrcList.
+**
+** This routine adds a specific database name, if needed, to the target when
+** forming the SrcList. This prevents a trigger in one database from
+** referring to a target in another database. An exception is when the
+** trigger is in TEMP in which case it can refer to any other database it
+** wants.
+*/
+static SrcList *targetSrcList(
+ Parse *pParse, /* The parsing context */
+ TriggerStep *pStep /* The trigger containing the target token */
+){
+ Token sDb; /* Dummy database name token */
+ int iDb; /* Index of the database to use */
+ SrcList *pSrc; /* SrcList to be returned */
+
+ iDb = pStep->pTrig->iDb;
+ if( iDb==0 || iDb>=2 ){
+ assert( iDb<pParse->db->nDb );
+ sDb.z = pParse->db->aDb[iDb].zName;
+ sDb.n = strlen(sDb.z);
+ pSrc = sqliteSrcListAppend(0, &sDb, &pStep->target);
+ } else {
+ pSrc = sqliteSrcListAppend(0, &pStep->target, 0);
+ }
+ return pSrc;
+}
+
+/*
** Generate VDBE code for zero or more statements inside the body of a
** trigger.
*/
@@ -561,11 +603,9 @@ static int codeTriggerProgram(
while( pTriggerStep ){
int saveNTab = pParse->nTab;
- int saveUseDb = pParse->useDb;
+
orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
pParse->trigStack->orconf = orconf;
- pParse->useDb = pTriggerStep->pTrig->iDb;
- if( pParse->useDb==1 ) pParse->useDb = -1;
switch( pTriggerStep->op ){
case TK_SELECT: {
Select * ss = sqliteSelectDup(pTriggerStep->pSelect);
@@ -577,7 +617,7 @@ static int codeTriggerProgram(
}
case TK_UPDATE: {
SrcList *pSrc;
- pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
+ pSrc = targetSrcList(pParse, pTriggerStep);
sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
sqliteUpdate(pParse, pSrc,
sqliteExprListDup(pTriggerStep->pExprList),
@@ -587,7 +627,7 @@ static int codeTriggerProgram(
}
case TK_INSERT: {
SrcList *pSrc;
- pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
+ pSrc = targetSrcList(pParse, pTriggerStep);
sqliteInsert(pParse, pSrc,
sqliteExprListDup(pTriggerStep->pExprList),
sqliteSelectDup(pTriggerStep->pSelect),
@@ -597,7 +637,7 @@ static int codeTriggerProgram(
case TK_DELETE: {
SrcList *pSrc;
sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
- pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
+ pSrc = targetSrcList(pParse, pTriggerStep);
sqliteDeleteFrom(pParse, pSrc, sqliteExprDup(pTriggerStep->pWhere));
sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
break;
@@ -606,7 +646,6 @@ static int codeTriggerProgram(
assert(0);
}
pParse->nTab = saveNTab;
- pParse->useDb = saveUseDb;
pTriggerStep = pTriggerStep->pNext;
}