~ubuntu-branches/ubuntu/intrepid/digikam/intrepid

« back to all changes in this revision

Viewing changes to digikam/libs/sqlite2/delete.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Purcell
  • Date: 2008-07-17 20:25:39 UTC
  • mfrom: (1.3.2 upstream) (37 hardy)
  • mto: This revision was merged to the branch mainline in revision 39.
  • Revision ID: james.westby@ubuntu.com-20080717202539-1bw3w3nrsso7yj4z
* New upstream release
  - digiKam 0.9.4 Release Plan (KDE3) ~ 13 July 08 (Closes: #490144)
* DEB_CONFIGURE_EXTRA_FLAGS := --without-included-sqlite3
* Debhelper compatibility level V7
* Install pixmaps in debian/*.install
* Add debian/digikam.lintian-overrides

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 326789 2004-07-07 21:25:56Z pahlibar $
 
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
Table *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
*/
 
41
int 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
*/
 
56
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
  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
 
 
309
delete_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
*/
 
336
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
  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
*/
 
367
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
  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
}