source: trunk/src/3rdparty/sqlite/delete.c@ 205

Last change on this file since 205 was 205, checked in by rudi, 14 years ago

Added SQLite 2.8.17 sources. This allows to build at least one of the sql drivers / plugins.

File size: 12.9 KB
Line 
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.61 2004/02/24 01:05:32 drh 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*/
24Table *sqliteSrcListLookup(Parse *pParse, SrcList *pSrc){
25 Table *pTab = 0;
26 int i;
27 for(i=0; i<pSrc->nSrc; i++){
28 const char *zTab = pSrc->a[i].zName;
29 const char *zDb = pSrc->a[i].zDatabase;
30 pTab = sqliteLocateTable(pParse, zTab, zDb);
31 pSrc->a[i].pTab = pTab;
32 }
33 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*/
41int sqliteIsReadOnly(Parse *pParse, Table *pTab, int viewOk){
42 if( pTab->readOnly ){
43 sqliteErrorMsg(pParse, "table %s may not be modified", pTab->zName);
44 return 1;
45 }
46 if( !viewOk && pTab->pSelect ){
47 sqliteErrorMsg(pParse, "cannot modify %s because it is a view",pTab->zName);
48 return 1;
49 }
50 return 0;
51}
52
53/*
54** Process a DELETE FROM statement.
55*/
56void 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 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 int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */
77
78 sContext.pParse = 0;
79 if( pParse->nErr || sqlite_malloc_failed ){
80 pTabList = 0;
81 goto delete_from_cleanup;
82 }
83 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 pTab = sqliteSrcListLookup(pParse, pTabList);
92 if( pTab==0 ) goto delete_from_cleanup;
93 before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
94 TK_DELETE, TK_BEFORE, TK_ROW, 0);
95 after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
96 TK_DELETE, TK_AFTER, TK_ROW, 0);
97 row_triggers_exist = before_triggers || after_triggers;
98 isView = pTab->pSelect!=0;
99 if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
100 goto delete_from_cleanup;
101 }
102 assert( pTab->iDb<db->nDb );
103 zDb = db->aDb[pTab->iDb].zName;
104 if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
105 goto delete_from_cleanup;
106 }
107
108 /* If pTab is really a view, make sure it has been initialized.
109 */
110 if( isView && sqliteViewGetColumnNames(pParse, pTab) ){
111 goto delete_from_cleanup;
112 }
113
114 /* Allocate a cursor used to store the old.* data for a trigger.
115 */
116 if( row_triggers_exist ){
117 oldIdx = pParse->nTab++;
118 }
119
120 /* Resolve the column names in all the expressions.
121 */
122 assert( pTabList->nSrc==1 );
123 iCur = pTabList->a[0].iCursor = pParse->nTab++;
124 if( pWhere ){
125 if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
126 goto delete_from_cleanup;
127 }
128 if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
129 goto delete_from_cleanup;
130 }
131 }
132
133 /* Start the view context
134 */
135 if( isView ){
136 sqliteAuthContextPush(pParse, &sContext, pTab->zName);
137 }
138
139 /* Begin generating code.
140 */
141 v = sqliteGetVdbe(pParse);
142 if( v==0 ){
143 goto delete_from_cleanup;
144 }
145 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 if( isView ){
151 Select *pView = sqliteSelectDup(pTab->pSelect);
152 sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
153 sqliteSelectDelete(pView);
154 }
155
156 /* Initialize the counter of the number of rows deleted, if
157 ** we are counting rows.
158 */
159 if( db->flags & SQLITE_CountRows ){
160 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 if( pWhere==0 && !row_triggers_exist ){
168 if( db->flags & SQLITE_CountRows ){
169 /* If counting rows deleted, just count the total number of
170 ** entries in the table. */
171 int endOfLoop = sqliteVdbeMakeLabel(v);
172 int addr;
173 if( !isView ){
174 sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
175 sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
176 }
177 sqliteVdbeAddOp(v, OP_Rewind, iCur, sqliteVdbeCurrentAddr(v)+2);
178 addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
179 sqliteVdbeAddOp(v, OP_Next, iCur, addr);
180 sqliteVdbeResolveLabel(v, endOfLoop);
181 sqliteVdbeAddOp(v, OP_Close, iCur, 0);
182 }
183 if( !isView ){
184 sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb);
185 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
186 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 pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0);
198 if( pWInfo==0 ) goto delete_from_cleanup;
199
200 /* Remember the key of every item to be deleted.
201 */
202 sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
203 if( db->flags & SQLITE_CountRows ){
204 sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
205 }
206
207 /* End the database scan loop.
208 */
209 sqliteWhereEnd(pWInfo);
210
211 /* Open the pseudo-table used to store OLD if there are triggers.
212 */
213 if( row_triggers_exist ){
214 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 sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
222 end = sqliteVdbeMakeLabel(v);
223
224 /* This is the beginning of the delete loop when there are
225 ** row triggers.
226 */
227 if( row_triggers_exist ){
228 addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
229 sqliteVdbeAddOp(v, OP_Dup, 0, 0);
230 if( !isView ){
231 sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
232 sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
233 }
234 sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
235
236 sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
237 sqliteVdbeAddOp(v, OP_RowData, iCur, 0);
238 sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
239 if( !isView ){
240 sqliteVdbeAddOp(v, OP_Close, iCur, 0);
241 }
242
243 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1,
244 oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
245 addr);
246 }
247
248 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 pParse->nTab = iCur + 1;
256 sqliteOpenTableAndIndices(pParse, pTab, iCur);
257
258 /* This is the beginning of the delete loop when there are no
259 ** row triggers */
260 if( !row_triggers_exist ){
261 addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
262 }
263
264 /* Delete the row */
265 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 if( row_triggers_exist ){
272 if( !isView ){
273 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
274 sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
275 }
276 sqliteVdbeAddOp(v, OP_Close, iCur, 0);
277 }
278 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1,
279 oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
280 addr);
281 }
282
283 /* End of the delete loop */
284 sqliteVdbeAddOp(v, OP_Goto, 0, addr);
285 sqliteVdbeResolveLabel(v, end);
286 sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
287
288 /* Close the cursors after the loop if there are no row triggers */
289 if( !row_triggers_exist ){
290 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
291 sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
292 }
293 sqliteVdbeAddOp(v, OP_Close, iCur, 0);
294 pParse->nTab = iCur;
295 }
296 }
297 sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
298 sqliteEndWriteOperation(pParse);
299
300 /*
301 ** Return the number of rows that were deleted.
302 */
303 if( db->flags & SQLITE_CountRows ){
304 sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
305 sqliteVdbeChangeP3(v, -1, "rows deleted", P3_STATIC);
306 sqliteVdbeAddOp(v, OP_Callback, 1, 0);
307 }
308
309delete_from_cleanup:
310 sqliteAuthContextPop(&sContext);
311 sqliteSrcListDelete(pTabList);
312 sqliteExprDelete(pWhere);
313 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*/
336void 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 addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0);
345 sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0);
346 sqliteVdbeAddOp(v, OP_Delete, iCur,
347 (count?OPFLAG_NCHANGE:0) | OPFLAG_CSCHANGE);
348 sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
349}
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*/
367void 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 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
378 int j;
379 if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
380 sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
381 for(j=0; j<pIdx->nColumn; j++){
382 int idx = pIdx->aiColumn[j];
383 if( idx==pTab->iPKey ){
384 sqliteVdbeAddOp(v, OP_Dup, j, 0);
385 }else{
386 sqliteVdbeAddOp(v, OP_Column, iCur, idx);
387 }
388 }
389 sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
390 if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
391 sqliteVdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
392 }
393}
Note: See TracBrowser for help on using the repository browser.