mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Check in implementation of foreign key constraints.
FossilOrigin-Name: d5d399811876391642937edeb9e8434dd9e356f5
This commit is contained in:
@@ -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;
|
||||
|
Reference in New Issue
Block a user