1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-11 01:42:22 +03:00

Instead of linking temporary triggers on non-temporary tables into the Table.pTrigger list, search the temp schema for them on demand. Fix for #3688. (CVS 6329)

FossilOrigin-Name: 3befe1ef7e6ebddedfa69579553a1b85b411ee98
This commit is contained in:
danielk1977
2009-02-28 10:47:41 +00:00
parent 02b4e3b34e
commit 2f886d1d53
11 changed files with 357 additions and 133 deletions

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.259 2009/02/20 10:58:42 danielk1977 Exp $
** $Id: insert.c,v 1.260 2009/02/28 10:47:42 danielk1977 Exp $
*/
#include "sqliteInt.h"
@@ -401,7 +401,8 @@ void sqlite3Insert(
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to insert into a view */
int triggers_exist = 0; /* True if there are FOR EACH ROW triggers */
Trigger *pTrigger; /* List of triggers on pTab, if required */
int tmask; /* Mask of trigger times */
#endif
db = pParse->db;
@@ -431,22 +432,24 @@ void sqlite3Insert(
** inserted into is a view
*/
#ifndef SQLITE_OMIT_TRIGGER
triggers_exist = sqlite3TriggersExist(pTab, TK_INSERT, 0);
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask);
isView = pTab->pSelect!=0;
#else
# define triggers_exist 0
# define pTrigger 0
# define tmask 0
# define isView 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif
assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) );
/* Ensure that:
* (a) the table is not read-only,
* (b) that if it is a view then ON INSERT triggers exist
*/
if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
goto insert_cleanup;
}
assert( pTab!=0 );
@@ -464,10 +467,10 @@ void sqlite3Insert(
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto insert_cleanup;
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
sqlite3BeginWriteOperation(pParse, pSelect || triggers_exist, iDb);
sqlite3BeginWriteOperation(pParse, pSelect || pTrigger, iDb);
/* if there are row triggers, allocate a temp table for new.* references. */
if( triggers_exist ){
if( pTrigger ){
newIdx = pParse->nTab++;
}
@@ -482,7 +485,7 @@ void sqlite3Insert(
** This is the 2nd template.
*/
if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){
assert( !triggers_exist );
assert( !pTrigger );
assert( pList==0 );
goto insert_cleanup;
}
@@ -557,7 +560,7 @@ void sqlite3Insert(
** of the tables being read by the SELECT statement. Also use a
** temp table in the case of row triggers.
*/
if( triggers_exist || readsTable(v, addrSelect, iDb, pTab) ){
if( pTrigger || readsTable(v, addrSelect, iDb, pTab) ){
useTempTable = 1;
}
@@ -676,7 +679,7 @@ void sqlite3Insert(
/* Open the temp table for FOR EACH ROW triggers
*/
if( triggers_exist ){
if( pTrigger ){
sqlite3VdbeAddOp3(v, OP_OpenPseudo, newIdx, 0, pTab->nCol);
}
@@ -744,7 +747,7 @@ void sqlite3Insert(
/* Run the BEFORE and INSTEAD OF triggers, if there are any
*/
endOfLoop = sqlite3VdbeMakeLabel(v);
if( triggers_exist & TRIGGER_BEFORE ){
if( tmask & TRIGGER_BEFORE ){
int regTrigRowid;
int regCols;
int regRec;
@@ -812,8 +815,8 @@ void sqlite3Insert(
sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol);
/* Fire BEFORE or INSTEAD OF triggers */
if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_BEFORE, pTab,
newIdx, -1, onError, endOfLoop, 0, 0) ){
if( sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE,
pTab, newIdx, -1, onError, endOfLoop, 0, 0) ){
goto insert_cleanup;
}
}
@@ -935,7 +938,7 @@ void sqlite3Insert(
regIns,
aRegIdx,
0,
(triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1,
(tmask&TRIGGER_AFTER) ? newIdx : -1,
appendFlag
);
}
@@ -947,10 +950,10 @@ void sqlite3Insert(
sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
}
if( triggers_exist ){
if( pTrigger ){
/* Code AFTER triggers */
if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_AFTER, pTab,
newIdx, -1, onError, endOfLoop, 0, 0) ){
if( sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER,
pTab, newIdx, -1, onError, endOfLoop, 0, 0) ){
goto insert_cleanup;
}
}
@@ -1530,7 +1533,7 @@ static int xferOptimization(
if( pSelect==0 ){
return 0; /* Must be of the form INSERT INTO ... SELECT ... */
}
if( pDest->pTrigger ){
if( sqlite3TriggerList(pParse, pDest) ){
return 0; /* tab1 must not have triggers */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE