diff options
author | drh <drh@noemail.net> | 2002-05-21 11:38:11 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2002-05-21 11:38:11 +0000 |
commit | c977f7f5968fcffbb8f35986059f396b830e40a3 (patch) | |
tree | c545a581fea4656189fe654b5824129fc33fffcb /src/delete.c | |
parent | f29ce5595883df5c035b5c6b97bf07f73eef5bc5 (diff) | |
download | sqlite-c977f7f5968fcffbb8f35986059f396b830e40a3.tar.gz sqlite-c977f7f5968fcffbb8f35986059f396b830e40a3.zip |
Additional code cleanup resulting from a review of the new trigger code. (CVS 572)
FossilOrigin-Name: 37dbdd551e88440933066133ec9cc1e10b03fc1a
Diffstat (limited to 'src/delete.c')
-rw-r--r-- | src/delete.c | 76 |
1 files changed, 44 insertions, 32 deletions
diff --git a/src/delete.c b/src/delete.c index 417ed2fd6..bcbe5ea81 100644 --- a/src/delete.c +++ b/src/delete.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle DELETE FROM statements. ** -** $Id: delete.c,v 1.33 2002/05/19 23:43:14 danielk1977 Exp $ +** $Id: delete.c,v 1.34 2002/05/21 11:38:11 drh Exp $ */ #include "sqliteInt.h" @@ -75,6 +75,7 @@ void sqliteDeleteFrom( ){ Vdbe *v; /* The virtual database engine */ Table *pTab; /* The table from which records will be deleted */ + char *zTab; /* Name of the table from which we are deleting */ IdList *pTabList; /* An ID list holding pTab and nothing else */ int end, addr; /* A couple addresses of generated code */ int i; /* Loop counter */ @@ -96,32 +97,28 @@ void sqliteDeleteFrom( /* Check for the special case of a VIEW with one or more ON DELETE triggers ** defined */ - { - Table *pTab; - char *zTab = sqliteTableNameFromToken(pTableName); - - if( zTab != 0 ){ - pTab = sqliteFindTable(pParse->db, zTab); - if( pTab ){ - row_triggers_exist = - sqliteTriggersExist(pParse, pTab->pTrigger, - TK_DELETE, TK_BEFORE, TK_ROW, 0) || - sqliteTriggersExist(pParse, pTab->pTrigger, - TK_DELETE, TK_AFTER, TK_ROW, 0); - } - sqliteFree(zTab); - if( row_triggers_exist && pTab->pSelect ){ - /* Just fire VIEW triggers */ - sqliteViewTriggers(pParse, pTab, pWhere, OE_Replace, 0); - return; - } + zTab = sqliteTableNameFromToken(pTableName); + if( zTab != 0 ){ + pTab = sqliteFindTable(pParse->db, zTab); + if( pTab ){ + row_triggers_exist = + sqliteTriggersExist(pParse, pTab->pTrigger, + TK_DELETE, TK_BEFORE, TK_ROW, 0) || + sqliteTriggersExist(pParse, pTab->pTrigger, + TK_DELETE, TK_AFTER, TK_ROW, 0); + } + sqliteFree(zTab); + if( row_triggers_exist && pTab->pSelect ){ + /* Just fire VIEW triggers */ + sqliteViewTriggers(pParse, pTab, pWhere, OE_Replace, 0); + return; } } /* Locate the table which we want to delete. This table has to be ** put in an IdList structure because some of the subroutines we ** will be calling are designed to work with multiple tables and expect - ** an IdList* parameter instead of just a Table* parameger. + ** an IdList* parameter instead of just a Table* parameter. */ pTabList = sqliteTableTokenToIdList(pParse, pTableName); if( pTabList==0 ) goto delete_from_cleanup; @@ -129,6 +126,8 @@ void sqliteDeleteFrom( pTab = pTabList->a[0].pTab; assert( pTab->pSelect==0 ); /* This table is not a view */ + /* Allocate a cursor used to store the old.* data for a trigger. + */ if( row_triggers_exist ){ oldIdx = pParse->nTab++; } @@ -151,11 +150,7 @@ void sqliteDeleteFrom( if( v==0 ){ goto delete_from_cleanup; } - if( row_triggers_exist ){ - sqliteBeginMultiWriteOperation(pParse); - } else { - sqliteBeginWriteOperation(pParse); - } + sqliteBeginWriteOperation(pParse, row_triggers_exist); /* Initialize the counter of the number of rows deleted, if ** we are counting rows. @@ -165,7 +160,8 @@ void sqliteDeleteFrom( } /* Special case: A DELETE without a WHERE clause deletes everything. - ** It is easier just to erase the whole table. + ** It is easier just to erase the whole table. Note, however, that + ** this means that the row change count will be incorrect. */ if( pWhere==0 && !row_triggers_exist ){ if( db->flags & SQLITE_CountRows ){ @@ -215,8 +211,10 @@ void sqliteDeleteFrom( sqliteVdbeAddOp(v, OP_ListRewind, 0, 0); end = sqliteVdbeMakeLabel(v); + /* This is the beginning of the delete loop when there are + ** row triggers. + */ if( row_triggers_exist ){ - int ii; addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end); sqliteVdbeAddOp(v, OP_Dup, 0, 0); @@ -226,11 +224,11 @@ void sqliteDeleteFrom( sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0); sqliteVdbeAddOp(v, OP_Integer, 13, 0); - for(ii = 0; ii<pTab->nCol; ii++){ - if( ii==pTab->iPKey ){ + for(i = 0; i<pTab->nCol; i++){ + if( i==pTab->iPKey ){ sqliteVdbeAddOp(v, OP_Recno, base, 0); } else { - sqliteVdbeAddOp(v, OP_Column, base, ii); + sqliteVdbeAddOp(v, OP_Column, base, i); } } sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); @@ -242,6 +240,12 @@ void sqliteDeleteFrom( oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default); } + /* Open cursors for the table we are deleting from and all its + ** indices. If there are row triggers, this happens inside the + ** OP_ListRead loop because the cursor have to all be closed + ** before the trigger fires. If there are no row triggers, the + ** cursors are opened only once on the outside the loop. + */ pParse->nTab = base + 1; openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite; sqliteVdbeAddOp(v, openOp, base, pTab->tnum); @@ -249,12 +253,18 @@ void sqliteDeleteFrom( sqliteVdbeAddOp(v, openOp, pParse->nTab++, pIdx->tnum); } + /* This is the beginning of the delete loop when there are no + ** row triggers */ if( !row_triggers_exist ){ addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end); } - sqliteGenerateRowDelete(v, pTab, base, pParse->trigStack?0:1); + /* Delete the row */ + sqliteGenerateRowDelete(v, pTab, base, pParse->trigStack==0); + /* If there are row triggers, close all cursors then invoke + ** the AFTER triggers + */ if( row_triggers_exist ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqliteVdbeAddOp(v, OP_Close, base + i, pIdx->tnum); @@ -264,10 +274,12 @@ void sqliteDeleteFrom( oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default); } + /* End of the delete loop */ sqliteVdbeAddOp(v, OP_Goto, 0, addr); sqliteVdbeResolveLabel(v, end); sqliteVdbeAddOp(v, OP_ListReset, 0, 0); + /* Close the cursors after the loop if there are no row triggers */ if( !row_triggers_exist ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqliteVdbeAddOp(v, OP_Close, base + i, pIdx->tnum); |