1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

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
This commit is contained in:
drh
2003-05-31 16:21:12 +00:00
parent 8372b8d134
commit f26e09c87f
13 changed files with 373 additions and 72 deletions

View File

@@ -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);
@@ -547,6 +559,36 @@ int sqliteTriggersExist(
return 0;
}
/*
** 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;
}