diff options
author | drh <drh@noemail.net> | 2003-05-31 16:21:12 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2003-05-31 16:21:12 +0000 |
commit | f26e09c87fd45fe3bb5aa4edacc9ea3f6325c884 (patch) | |
tree | 5f3a5c939757ced657ebcfbea9c0418fadb19677 /src/trigger.c | |
parent | 8372b8d13442ad85ab76f6b1bf89532f45fdce59 (diff) | |
download | sqlite-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.c | 61 |
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; } |