diff options
author | dan <dan@noemail.net> | 2009-09-19 17:00:31 +0000 |
---|---|---|
committer | dan <dan@noemail.net> | 2009-09-19 17:00:31 +0000 |
commit | 1da40a381fcf28953cd914aa1cff2d4d2f30ffb0 (patch) | |
tree | 499fd358c9173002d540833d9a7a77c3421119d4 /src/trigger.c | |
parent | 3991bb0deec345af79e0346bc0b29a0f8a594a3a (diff) | |
download | sqlite-1da40a381fcf28953cd914aa1cff2d4d2f30ffb0.tar.gz sqlite-1da40a381fcf28953cd914aa1cff2d4d2f30ffb0.zip |
Check in implementation of foreign key constraints.
FossilOrigin-Name: d5d399811876391642937edeb9e8434dd9e356f5
Diffstat (limited to 'src/trigger.c')
-rw-r--r-- | src/trigger.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/src/trigger.c b/src/trigger.c index f06226734..79f7f486d 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -795,7 +795,7 @@ static TriggerPrg *codeRowTrigger( Parse *pSubParse; /* Parse context for sub-vdbe */ int iEndTrigger = 0; /* Label to jump to if WHEN is false */ - assert( pTab==tableOfTrigger(pTrigger) ); + assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) ); /* Allocate the TriggerPrg and SubProgram objects. To ensure that they ** are freed if an error occurs, link them into the Parse.pTriggerPrg @@ -896,7 +896,7 @@ static TriggerPrg *getRowTrigger( Parse *pRoot = sqlite3ParseToplevel(pParse); TriggerPrg *pPrg; - assert( pTab==tableOfTrigger(pTrigger) ); + assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) ); /* It may be that this trigger has already been coded (or is in the ** process of being coded). If this is the case, then an entry with @@ -915,6 +915,38 @@ static TriggerPrg *getRowTrigger( return pPrg; } +void sqlite3CodeRowTriggerDirect( + Parse *pParse, /* Parse context */ + Trigger *p, /* Trigger to code */ + Table *pTab, /* The table to code triggers from */ + int oldIdx, /* The indice of the "old" row to access */ + int orconf, /* ON CONFLICT policy */ + int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ +){ + Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */ + TriggerPrg *pPrg; + pPrg = getRowTrigger(pParse, p, pTab, orconf); + assert( pPrg || pParse->nErr || pParse->db->mallocFailed ); + + /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program + ** is a pointer to the sub-vdbe containing the trigger program. */ + if( pPrg ){ + sqlite3VdbeAddOp3(v, OP_Program, oldIdx, ignoreJump, ++pParse->nMem); + pPrg->pProgram->nRef++; + sqlite3VdbeChangeP4(v, -1, (const char *)pPrg->pProgram, P4_SUBPROGRAM); + VdbeComment( + (v, "Call: %s.%s", (p->zName?p->zName:"fkey"), onErrorText(orconf))); + + /* Set the P5 operand of the OP_Program instruction to non-zero if + ** recursive invocation of this trigger program is disallowed. Recursive + ** invocation is disallowed if (a) the sub-program is really a trigger, + ** not a foreign key action, and (b) the flag to enable recursive triggers + ** is clear. */ + sqlite3VdbeChangeP5(v, p->zName && !(pParse->db->flags&SQLITE_RecTriggers)); + + } +} + /* ** This is called to code FOR EACH ROW triggers. ** @@ -976,19 +1008,7 @@ void sqlite3CodeRowTrigger( && p->tr_tm==tr_tm && checkColumnOverlap(p->pColumns,pChanges) ){ - Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */ - TriggerPrg *pPrg; - pPrg = getRowTrigger(pParse, p, pTab, orconf); - assert( pPrg || pParse->nErr || pParse->db->mallocFailed ); - - /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program - ** is a pointer to the sub-vdbe containing the trigger program. */ - if( pPrg ){ - sqlite3VdbeAddOp3(v, OP_Program, oldIdx, ignoreJump, ++pParse->nMem); - pPrg->pProgram->nRef++; - sqlite3VdbeChangeP4(v, -1, (const char *)pPrg->pProgram, P4_SUBPROGRAM); - VdbeComment((v, "Call: %s.%s", p->zName, onErrorText(orconf))); - } + sqlite3CodeRowTriggerDirect(pParse, p, pTab, oldIdx, orconf, ignoreJump); } } } @@ -1015,15 +1035,14 @@ void sqlite3CodeRowTrigger( u32 sqlite3TriggerOldmask( Parse *pParse, /* Parse context */ Trigger *pTrigger, /* List of triggers on table pTab */ - int op, /* Either TK_UPDATE or TK_DELETE */ ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ Table *pTab, /* The table to code triggers from */ int orconf /* Default ON CONFLICT policy for trigger steps */ ){ + const int op = pChanges ? TK_UPDATE : TK_DELETE; u32 mask = 0; Trigger *p; - assert(op==TK_UPDATE || op==TK_DELETE); for(p=pTrigger; p; p=p->pNext){ if( p->op==op && checkColumnOverlap(p->pColumns,pChanges) ){ TriggerPrg *pPrg; |