File Coverage

delete.c
Criterion Covered Total %
statement 79 146 54.1
branch 34 100 34.0
condition n/a
subroutine n/a
pod n/a
total 113 246 45.9


line stmt bran cond sub pod time code
1             /*
2             ** 2001 September 15
3             **
4             ** The author disclaims copyright to this source code. In place of
5             ** a legal notice, here is a blessing:
6             **
7             ** May you do good and not evil.
8             ** May you find forgiveness for yourself and forgive others.
9             ** May you share freely, never taking more than you give.
10             **
11             *************************************************************************
12             ** This file contains C code routines that are called by the parser
13             ** to handle DELETE FROM statements.
14             **
15             ** $Id: delete.c,v 1.1.1.1 2004/08/08 15:03:57 matt Exp $
16             */
17             #include "sqliteInt.h"
18              
19             /*
20             ** Look up every table that is named in pSrc. If any table is not found,
21             ** add an error message to pParse->zErrMsg and return NULL. If all tables
22             ** are found, return a pointer to the last table.
23             */
24 54           Table *sqliteSrcListLookup(Parse *pParse, SrcList *pSrc){
25 54           Table *pTab = 0;
26             int i;
27 108 100         for(i=0; inSrc; i++){
28 54           const char *zTab = pSrc->a[i].zName;
29 54           const char *zDb = pSrc->a[i].zDatabase;
30 54           pTab = sqliteLocateTable(pParse, zTab, zDb);
31 54           pSrc->a[i].pTab = pTab;
32             }
33 54           return pTab;
34             }
35              
36             /*
37             ** Check to make sure the given table is writable. If it is not
38             ** writable, generate an error message and return 1. If it is
39             ** writable return 0;
40             */
41 50           int sqliteIsReadOnly(Parse *pParse, Table *pTab, int viewOk){
42 50 50         if( pTab->readOnly ){
43 0           sqliteErrorMsg(pParse, "table %s may not be modified", pTab->zName);
44 0           return 1;
45             }
46 50 50         if( !viewOk && pTab->pSelect ){
    50          
47 0           sqliteErrorMsg(pParse, "cannot modify %s because it is a view",pTab->zName);
48 0           return 1;
49             }
50 50           return 0;
51             }
52              
53             /*
54             ** Process a DELETE FROM statement.
55             */
56 6           void sqliteDeleteFrom(
57             Parse *pParse, /* The parser context */
58             SrcList *pTabList, /* The table from which we should delete things */
59             Expr *pWhere /* The WHERE clause. May be null */
60             ){
61             Vdbe *v; /* The virtual database engine */
62             Table *pTab; /* The table from which records will be deleted */
63             const char *zDb; /* Name of database holding pTab */
64             int end, addr; /* A couple addresses of generated code */
65             int i; /* Loop counter */
66             WhereInfo *pWInfo; /* Information about the WHERE clause */
67             Index *pIdx; /* For looping over indices of the table */
68             int iCur; /* VDBE Cursor number for pTab */
69             sqlite *db; /* Main database structure */
70             int isView; /* True if attempting to delete from a view */
71             AuthContext sContext; /* Authorization context */
72              
73 6           int row_triggers_exist = 0; /* True if any triggers exist */
74             int before_triggers; /* True if there are BEFORE triggers */
75             int after_triggers; /* True if there are AFTER triggers */
76 6           int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */
77              
78 6           sContext.pParse = 0;
79 6 50         if( pParse->nErr || sqlite_malloc_failed ){
    50          
80 0           pTabList = 0;
81 0           goto delete_from_cleanup;
82             }
83 6           db = pParse->db;
84             assert( pTabList->nSrc==1 );
85              
86             /* Locate the table which we want to delete. This table has to be
87             ** put in an SrcList structure because some of the subroutines we
88             ** will be calling are designed to work with multiple tables and expect
89             ** an SrcList* parameter instead of just a Table* parameter.
90             */
91 6           pTab = sqliteSrcListLookup(pParse, pTabList);
92 6 50         if( pTab==0 ) goto delete_from_cleanup;
93 6           before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
94             TK_DELETE, TK_BEFORE, TK_ROW, 0);
95 6           after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
96             TK_DELETE, TK_AFTER, TK_ROW, 0);
97 6 50         row_triggers_exist = before_triggers || after_triggers;
    50          
98 6           isView = pTab->pSelect!=0;
99 6 50         if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
100 0           goto delete_from_cleanup;
101             }
102             assert( pTab->iDbnDb );
103 6           zDb = db->aDb[pTab->iDb].zName;
104 6 50         if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
105 0           goto delete_from_cleanup;
106             }
107              
108             /* If pTab is really a view, make sure it has been initialized.
109             */
110 6 50         if( isView && sqliteViewGetColumnNames(pParse, pTab) ){
    0          
111 0           goto delete_from_cleanup;
112             }
113              
114             /* Allocate a cursor used to store the old.* data for a trigger.
115             */
116 6 50         if( row_triggers_exist ){
117 0           oldIdx = pParse->nTab++;
118             }
119              
120             /* Resolve the column names in all the expressions.
121             */
122             assert( pTabList->nSrc==1 );
123 6           iCur = pTabList->a[0].iCursor = pParse->nTab++;
124 6 50         if( pWhere ){
125 6 50         if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
126 0           goto delete_from_cleanup;
127             }
128 6 50         if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
129 0           goto delete_from_cleanup;
130             }
131             }
132              
133             /* Start the view context
134             */
135 6 50         if( isView ){
136 0           sqliteAuthContextPush(pParse, &sContext, pTab->zName);
137             }
138              
139             /* Begin generating code.
140             */
141 6           v = sqliteGetVdbe(pParse);
142 6 50         if( v==0 ){
143 0           goto delete_from_cleanup;
144             }
145 6           sqliteBeginWriteOperation(pParse, row_triggers_exist, pTab->iDb);
146              
147             /* If we are trying to delete from a view, construct that view into
148             ** a temporary table.
149             */
150 6 50         if( isView ){
151 0           Select *pView = sqliteSelectDup(pTab->pSelect);
152 0           sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
153 0           sqliteSelectDelete(pView);
154             }
155              
156             /* Initialize the counter of the number of rows deleted, if
157             ** we are counting rows.
158             */
159 6 50         if( db->flags & SQLITE_CountRows ){
160 0           sqliteVdbeAddOp(v, OP_Integer, 0, 0);
161             }
162              
163             /* Special case: A DELETE without a WHERE clause deletes everything.
164             ** It is easier just to erase the whole table. Note, however, that
165             ** this means that the row change count will be incorrect.
166             */
167 6 50         if( pWhere==0 && !row_triggers_exist ){
    0          
168 0 0         if( db->flags & SQLITE_CountRows ){
169             /* If counting rows deleted, just count the total number of
170             ** entries in the table. */
171 0           int endOfLoop = sqliteVdbeMakeLabel(v);
172             int addr;
173 0 0         if( !isView ){
174 0           sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
175 0           sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
176             }
177 0           sqliteVdbeAddOp(v, OP_Rewind, iCur, sqliteVdbeCurrentAddr(v)+2);
178 0           addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
179 0           sqliteVdbeAddOp(v, OP_Next, iCur, addr);
180 0           sqliteVdbeResolveLabel(v, endOfLoop);
181 0           sqliteVdbeAddOp(v, OP_Close, iCur, 0);
182             }
183 0 0         if( !isView ){
184 0           sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb);
185 0 0         for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
186 0           sqliteVdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb);
187             }
188             }
189             }
190              
191             /* The usual case: There is a WHERE clause so we have to scan through
192             ** the table and pick which records to delete.
193             */
194             else{
195             /* Begin the database scan
196             */
197 6           pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0);
198 6 50         if( pWInfo==0 ) goto delete_from_cleanup;
199              
200             /* Remember the key of every item to be deleted.
201             */
202 6           sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
203 6 50         if( db->flags & SQLITE_CountRows ){
204 0           sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
205             }
206              
207             /* End the database scan loop.
208             */
209 6           sqliteWhereEnd(pWInfo);
210              
211             /* Open the pseudo-table used to store OLD if there are triggers.
212             */
213 6 50         if( row_triggers_exist ){
214 0           sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
215             }
216              
217             /* Delete every item whose key was written to the list during the
218             ** database scan. We have to delete items after the scan is complete
219             ** because deleting an item can change the scan order.
220             */
221 6           sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
222 6           end = sqliteVdbeMakeLabel(v);
223              
224             /* This is the beginning of the delete loop when there are
225             ** row triggers.
226             */
227 6 50         if( row_triggers_exist ){
228 0           addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
229 0           sqliteVdbeAddOp(v, OP_Dup, 0, 0);
230 0 0         if( !isView ){
231 0           sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
232 0           sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
233             }
234 0           sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
235              
236 0           sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
237 0           sqliteVdbeAddOp(v, OP_RowData, iCur, 0);
238 0           sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
239 0 0         if( !isView ){
240 0           sqliteVdbeAddOp(v, OP_Close, iCur, 0);
241             }
242              
243 0 0         sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1,
244 0           oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
245             addr);
246             }
247              
248 6 50         if( !isView ){
249             /* Open cursors for the table we are deleting from and all its
250             ** indices. If there are row triggers, this happens inside the
251             ** OP_ListRead loop because the cursor have to all be closed
252             ** before the trigger fires. If there are no row triggers, the
253             ** cursors are opened only once on the outside the loop.
254             */
255 6           pParse->nTab = iCur + 1;
256 6           sqliteOpenTableAndIndices(pParse, pTab, iCur);
257              
258             /* This is the beginning of the delete loop when there are no
259             ** row triggers */
260 6 50         if( !row_triggers_exist ){
261 6           addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
262             }
263              
264             /* Delete the row */
265 6           sqliteGenerateRowDelete(db, v, pTab, iCur, pParse->trigStack==0);
266             }
267              
268             /* If there are row triggers, close all cursors then invoke
269             ** the AFTER triggers
270             */
271 6 50         if( row_triggers_exist ){
272 0 0         if( !isView ){
273 0 0         for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
274 0           sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
275             }
276 0           sqliteVdbeAddOp(v, OP_Close, iCur, 0);
277             }
278 0 0         sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1,
279 0           oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
280             addr);
281             }
282              
283             /* End of the delete loop */
284 6           sqliteVdbeAddOp(v, OP_Goto, 0, addr);
285 6           sqliteVdbeResolveLabel(v, end);
286 6           sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
287              
288             /* Close the cursors after the loop if there are no row triggers */
289 6 50         if( !row_triggers_exist ){
290 6 50         for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
291 0           sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
292             }
293 6           sqliteVdbeAddOp(v, OP_Close, iCur, 0);
294 6           pParse->nTab = iCur;
295             }
296             }
297 6           sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
298 6           sqliteEndWriteOperation(pParse);
299              
300             /*
301             ** Return the number of rows that were deleted.
302             */
303 6 50         if( db->flags & SQLITE_CountRows ){
304 0           sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
305 0           sqliteVdbeChangeP3(v, -1, "rows deleted", P3_STATIC);
306 0           sqliteVdbeAddOp(v, OP_Callback, 1, 0);
307             }
308              
309             delete_from_cleanup:
310 6           sqliteAuthContextPop(&sContext);
311 6           sqliteSrcListDelete(pTabList);
312 6           sqliteExprDelete(pWhere);
313 6           return;
314             }
315              
316             /*
317             ** This routine generates VDBE code that causes a single row of a
318             ** single table to be deleted.
319             **
320             ** The VDBE must be in a particular state when this routine is called.
321             ** These are the requirements:
322             **
323             ** 1. A read/write cursor pointing to pTab, the table containing the row
324             ** to be deleted, must be opened as cursor number "base".
325             **
326             ** 2. Read/write cursors for all indices of pTab must be open as
327             ** cursor number base+i for the i-th index.
328             **
329             ** 3. The record number of the row to be deleted must be on the top
330             ** of the stack.
331             **
332             ** This routine pops the top of the stack to remove the record number
333             ** and then generates code to remove both the table record and all index
334             ** entries that point to that record.
335             */
336 6           void sqliteGenerateRowDelete(
337             sqlite *db, /* The database containing the index */
338             Vdbe *v, /* Generate code into this VDBE */
339             Table *pTab, /* Table containing the row to be deleted */
340             int iCur, /* Cursor number for the table */
341             int count /* Increment the row change counter */
342             ){
343             int addr;
344 6           addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0);
345 6           sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0);
346 6 50         sqliteVdbeAddOp(v, OP_Delete, iCur,
347             (count?OPFLAG_NCHANGE:0) | OPFLAG_CSCHANGE);
348 6           sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
349 6           }
350              
351             /*
352             ** This routine generates VDBE code that causes the deletion of all
353             ** index entries associated with a single row of a single table.
354             **
355             ** The VDBE must be in a particular state when this routine is called.
356             ** These are the requirements:
357             **
358             ** 1. A read/write cursor pointing to pTab, the table containing the row
359             ** to be deleted, must be opened as cursor number "iCur".
360             **
361             ** 2. Read/write cursors for all indices of pTab must be open as
362             ** cursor number iCur+i for the i-th index.
363             **
364             ** 3. The "iCur" cursor must be pointing to the row that is to be
365             ** deleted.
366             */
367 6           void sqliteGenerateRowIndexDelete(
368             sqlite *db, /* The database containing the index */
369             Vdbe *v, /* Generate code into this VDBE */
370             Table *pTab, /* Table containing the row to be deleted */
371             int iCur, /* Cursor number for the table */
372             char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
373             ){
374             int i;
375             Index *pIdx;
376              
377 6 50         for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
378             int j;
379 0 0         if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
    0          
380 0           sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
381 0 0         for(j=0; jnColumn; j++){
382 0           int idx = pIdx->aiColumn[j];
383 0 0         if( idx==pTab->iPKey ){
384 0           sqliteVdbeAddOp(v, OP_Dup, j, 0);
385             }else{
386 0           sqliteVdbeAddOp(v, OP_Column, iCur, idx);
387             }
388             }
389 0           sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
390 0 0         if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
391 0           sqliteVdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
392             }
393 6           }