Back to index

lightning-sunbird  0.9+nobinonly
delete.c
Go to the documentation of this file.
00001 /*
00002 ** 2001 September 15
00003 **
00004 ** The author disclaims copyright to this source code.  In place of
00005 ** a legal notice, here is a blessing:
00006 **
00007 **    May you do good and not evil.
00008 **    May you find forgiveness for yourself and forgive others.
00009 **    May you share freely, never taking more than you give.
00010 **
00011 *************************************************************************
00012 ** This file contains C code routines that are called by the parser
00013 ** in order to generate code for DELETE FROM statements.
00014 **
00015 ** $Id: delete.c,v 1.122 2006/02/24 02:53:50 drh Exp $
00016 */
00017 #include "sqliteInt.h"
00018 
00019 /*
00020 ** Look up every table that is named in pSrc.  If any table is not found,
00021 ** add an error message to pParse->zErrMsg and return NULL.  If all tables
00022 ** are found, return a pointer to the last table.
00023 */
00024 Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
00025   Table *pTab = 0;
00026   int i;
00027   struct SrcList_item *pItem;
00028   for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
00029     pTab = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase);
00030     sqlite3DeleteTable(pParse->db, pItem->pTab);
00031     pItem->pTab = pTab;
00032     if( pTab ){
00033       pTab->nRef++;
00034     }
00035   }
00036   return pTab;
00037 }
00038 
00039 /*
00040 ** Check to make sure the given table is writable.  If it is not
00041 ** writable, generate an error message and return 1.  If it is
00042 ** writable return 0;
00043 */
00044 int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
00045   if( pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0
00046         && pParse->nested==0 ){
00047     sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
00048     return 1;
00049   }
00050 #ifndef SQLITE_OMIT_VIEW
00051   if( !viewOk && pTab->pSelect ){
00052     sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
00053     return 1;
00054   }
00055 #endif
00056   return 0;
00057 }
00058 
00059 /*
00060 ** Generate code that will open a table for reading.
00061 */
00062 void sqlite3OpenTable(
00063   Parse *p,       /* Generate code into this VDBE */
00064   int iCur,       /* The cursor number of the table */
00065   int iDb,        /* The database index in sqlite3.aDb[] */
00066   Table *pTab,    /* The table to be opened */
00067   int opcode      /* OP_OpenRead or OP_OpenWrite */
00068 ){
00069   Vdbe *v = sqlite3GetVdbe(p);
00070   assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
00071   sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName);
00072   sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
00073   VdbeComment((v, "# %s", pTab->zName));
00074   sqlite3VdbeAddOp(v, opcode, iCur, pTab->tnum);
00075   sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol);
00076 }
00077 
00078 
00079 /*
00080 ** Generate code for a DELETE FROM statement.
00081 **
00082 **     DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
00083 **                 \________/       \________________/
00084 **                  pTabList              pWhere
00085 */
00086 void sqlite3DeleteFrom(
00087   Parse *pParse,         /* The parser context */
00088   SrcList *pTabList,     /* The table from which we should delete things */
00089   Expr *pWhere           /* The WHERE clause.  May be null */
00090 ){
00091   Vdbe *v;               /* The virtual database engine */
00092   Table *pTab;           /* The table from which records will be deleted */
00093   const char *zDb;       /* Name of database holding pTab */
00094   int end, addr = 0;     /* A couple addresses of generated code */
00095   int i;                 /* Loop counter */
00096   WhereInfo *pWInfo;     /* Information about the WHERE clause */
00097   Index *pIdx;           /* For looping over indices of the table */
00098   int iCur;              /* VDBE Cursor number for pTab */
00099   sqlite3 *db;           /* Main database structure */
00100   AuthContext sContext;  /* Authorization context */
00101   int oldIdx = -1;       /* Cursor for the OLD table of AFTER triggers */
00102   NameContext sNC;       /* Name context to resolve expressions in */
00103   int iDb;
00104 
00105 #ifndef SQLITE_OMIT_TRIGGER
00106   int isView;                  /* True if attempting to delete from a view */
00107   int triggers_exist = 0;      /* True if any triggers exist */
00108 #endif
00109 
00110   sContext.pParse = 0;
00111   if( pParse->nErr || sqlite3MallocFailed() ){
00112     goto delete_from_cleanup;
00113   }
00114   db = pParse->db;
00115   assert( pTabList->nSrc==1 );
00116 
00117   /* Locate the table which we want to delete.  This table has to be
00118   ** put in an SrcList structure because some of the subroutines we
00119   ** will be calling are designed to work with multiple tables and expect
00120   ** an SrcList* parameter instead of just a Table* parameter.
00121   */
00122   pTab = sqlite3SrcListLookup(pParse, pTabList);
00123   if( pTab==0 )  goto delete_from_cleanup;
00124 
00125   /* Figure out if we have any triggers and if the table being
00126   ** deleted from is a view
00127   */
00128 #ifndef SQLITE_OMIT_TRIGGER
00129   triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0);
00130   isView = pTab->pSelect!=0;
00131 #else
00132 # define triggers_exist 0
00133 # define isView 0
00134 #endif
00135 #ifdef SQLITE_OMIT_VIEW
00136 # undef isView
00137 # define isView 0
00138 #endif
00139 
00140   if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
00141     goto delete_from_cleanup;
00142   }
00143   iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
00144   assert( iDb<db->nDb );
00145   zDb = db->aDb[iDb].zName;
00146   if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
00147     goto delete_from_cleanup;
00148   }
00149 
00150   /* If pTab is really a view, make sure it has been initialized.
00151   */
00152   if( isView && sqlite3ViewGetColumnNames(pParse, pTab) ){
00153     goto delete_from_cleanup;
00154   }
00155 
00156   /* Allocate a cursor used to store the old.* data for a trigger.
00157   */
00158   if( triggers_exist ){ 
00159     oldIdx = pParse->nTab++;
00160   }
00161 
00162   /* Resolve the column names in the WHERE clause.
00163   */
00164   assert( pTabList->nSrc==1 );
00165   iCur = pTabList->a[0].iCursor = pParse->nTab++;
00166   memset(&sNC, 0, sizeof(sNC));
00167   sNC.pParse = pParse;
00168   sNC.pSrcList = pTabList;
00169   if( sqlite3ExprResolveNames(&sNC, pWhere) ){
00170     goto delete_from_cleanup;
00171   }
00172 
00173   /* Start the view context
00174   */
00175   if( isView ){
00176     sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
00177   }
00178 
00179   /* Begin generating code.
00180   */
00181   v = sqlite3GetVdbe(pParse);
00182   if( v==0 ){
00183     goto delete_from_cleanup;
00184   }
00185   if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
00186   sqlite3BeginWriteOperation(pParse, triggers_exist, iDb);
00187 
00188   /* If we are trying to delete from a view, realize that view into
00189   ** a ephemeral table.
00190   */
00191   if( isView ){
00192     Select *pView = sqlite3SelectDup(pTab->pSelect);
00193     sqlite3Select(pParse, pView, SRT_VirtualTab, iCur, 0, 0, 0, 0);
00194     sqlite3SelectDelete(pView);
00195   }
00196 
00197   /* Initialize the counter of the number of rows deleted, if
00198   ** we are counting rows.
00199   */
00200   if( db->flags & SQLITE_CountRows ){
00201     sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
00202   }
00203 
00204   /* Special case: A DELETE without a WHERE clause deletes everything.
00205   ** It is easier just to erase the whole table.  Note, however, that
00206   ** this means that the row change count will be incorrect.
00207   */
00208   if( pWhere==0 && !triggers_exist ){
00209     if( db->flags & SQLITE_CountRows ){
00210       /* If counting rows deleted, just count the total number of
00211       ** entries in the table. */
00212       int endOfLoop = sqlite3VdbeMakeLabel(v);
00213       int addr2;
00214       if( !isView ){
00215         sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
00216       }
00217       sqlite3VdbeAddOp(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2);
00218       addr2 = sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
00219       sqlite3VdbeAddOp(v, OP_Next, iCur, addr2);
00220       sqlite3VdbeResolveLabel(v, endOfLoop);
00221       sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
00222     }
00223     if( !isView ){
00224       sqlite3VdbeAddOp(v, OP_Clear, pTab->tnum, iDb);
00225       if( !pParse->nested ){
00226         sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
00227       }
00228       for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
00229         assert( pIdx->pSchema==pTab->pSchema );
00230         sqlite3VdbeAddOp(v, OP_Clear, pIdx->tnum, iDb);
00231       }
00232     }
00233   }
00234 
00235   /* The usual case: There is a WHERE clause so we have to scan through
00236   ** the table and pick which records to delete.
00237   */
00238   else{
00239     /* Begin the database scan
00240     */
00241     pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
00242     if( pWInfo==0 ) goto delete_from_cleanup;
00243 
00244     /* Remember the rowid of every item to be deleted.
00245     */
00246     sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
00247     sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
00248     if( db->flags & SQLITE_CountRows ){
00249       sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
00250     }
00251 
00252     /* End the database scan loop.
00253     */
00254     sqlite3WhereEnd(pWInfo);
00255 
00256     /* Open the pseudo-table used to store OLD if there are triggers.
00257     */
00258     if( triggers_exist ){
00259       sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
00260       sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
00261     }
00262 
00263     /* Delete every item whose key was written to the list during the
00264     ** database scan.  We have to delete items after the scan is complete
00265     ** because deleting an item can change the scan order.
00266     */
00267     end = sqlite3VdbeMakeLabel(v);
00268 
00269     /* This is the beginning of the delete loop when there are
00270     ** row triggers.
00271     */
00272     if( triggers_exist ){
00273       addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
00274       if( !isView ){
00275         sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
00276         sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
00277       }
00278       sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
00279       sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
00280       sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
00281       sqlite3VdbeAddOp(v, OP_Insert, oldIdx, 0);
00282       if( !isView ){
00283         sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
00284       }
00285 
00286       (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab,
00287           -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
00288           addr);
00289     }
00290 
00291     if( !isView ){
00292       /* Open cursors for the table we are deleting from and all its
00293       ** indices.  If there are row triggers, this happens inside the
00294       ** OP_FifoRead loop because the cursor have to all be closed
00295       ** before the trigger fires.  If there are no row triggers, the
00296       ** cursors are opened only once on the outside the loop.
00297       */
00298       sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
00299 
00300       /* This is the beginning of the delete loop when there are no
00301       ** row triggers */
00302       if( !triggers_exist ){ 
00303         addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
00304       }
00305 
00306       /* Delete the row */
00307       sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0);
00308     }
00309 
00310     /* If there are row triggers, close all cursors then invoke
00311     ** the AFTER triggers
00312     */
00313     if( triggers_exist ){
00314       if( !isView ){
00315         for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
00316           sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
00317         }
00318         sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
00319       }
00320       (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1,
00321           oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
00322           addr);
00323     }
00324 
00325     /* End of the delete loop */
00326     sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
00327     sqlite3VdbeResolveLabel(v, end);
00328 
00329     /* Close the cursors after the loop if there are no row triggers */
00330     if( !triggers_exist ){
00331       for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
00332         sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
00333       }
00334       sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
00335     }
00336   }
00337 
00338   /*
00339   ** Return the number of rows that were deleted. If this routine is 
00340   ** generating code because of a call to sqlite3NestedParse(), do not
00341   ** invoke the callback function.
00342   */
00343   if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
00344     sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
00345     sqlite3VdbeSetNumCols(v, 1);
00346     sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", P3_STATIC);
00347   }
00348 
00349 delete_from_cleanup:
00350   sqlite3AuthContextPop(&sContext);
00351   sqlite3SrcListDelete(pTabList);
00352   sqlite3ExprDelete(pWhere);
00353   return;
00354 }
00355 
00356 /*
00357 ** This routine generates VDBE code that causes a single row of a
00358 ** single table to be deleted.
00359 **
00360 ** The VDBE must be in a particular state when this routine is called.
00361 ** These are the requirements:
00362 **
00363 **   1.  A read/write cursor pointing to pTab, the table containing the row
00364 **       to be deleted, must be opened as cursor number "base".
00365 **
00366 **   2.  Read/write cursors for all indices of pTab must be open as
00367 **       cursor number base+i for the i-th index.
00368 **
00369 **   3.  The record number of the row to be deleted must be on the top
00370 **       of the stack.
00371 **
00372 ** This routine pops the top of the stack to remove the record number
00373 ** and then generates code to remove both the table record and all index
00374 ** entries that point to that record.
00375 */
00376 void sqlite3GenerateRowDelete(
00377   sqlite3 *db,       /* The database containing the index */
00378   Vdbe *v,           /* Generate code into this VDBE */
00379   Table *pTab,       /* Table containing the row to be deleted */
00380   int iCur,          /* Cursor number for the table */
00381   int count          /* Increment the row change counter */
00382 ){
00383   int addr;
00384   addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0);
00385   sqlite3GenerateRowIndexDelete(v, pTab, iCur, 0);
00386   sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
00387   if( count ){
00388     sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
00389   }
00390   sqlite3VdbeJumpHere(v, addr);
00391 }
00392 
00393 /*
00394 ** This routine generates VDBE code that causes the deletion of all
00395 ** index entries associated with a single row of a single table.
00396 **
00397 ** The VDBE must be in a particular state when this routine is called.
00398 ** These are the requirements:
00399 **
00400 **   1.  A read/write cursor pointing to pTab, the table containing the row
00401 **       to be deleted, must be opened as cursor number "iCur".
00402 **
00403 **   2.  Read/write cursors for all indices of pTab must be open as
00404 **       cursor number iCur+i for the i-th index.
00405 **
00406 **   3.  The "iCur" cursor must be pointing to the row that is to be
00407 **       deleted.
00408 */
00409 void sqlite3GenerateRowIndexDelete(
00410   Vdbe *v,           /* Generate code into this VDBE */
00411   Table *pTab,       /* Table containing the row to be deleted */
00412   int iCur,          /* Cursor number for the table */
00413   char *aIdxUsed     /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
00414 ){
00415   int i;
00416   Index *pIdx;
00417 
00418   for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
00419     if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
00420     sqlite3GenerateIndexKey(v, pIdx, iCur);
00421     sqlite3VdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
00422   }
00423 }
00424 
00425 /*
00426 ** Generate code that will assemble an index key and put it on the top
00427 ** of the tack.  The key with be for index pIdx which is an index on pTab.
00428 ** iCur is the index of a cursor open on the pTab table and pointing to
00429 ** the entry that needs indexing.
00430 */
00431 void sqlite3GenerateIndexKey(
00432   Vdbe *v,           /* Generate code into this VDBE */
00433   Index *pIdx,       /* The index for which to generate a key */
00434   int iCur           /* Cursor number for the pIdx->pTable table */
00435 ){
00436   int j;
00437   Table *pTab = pIdx->pTable;
00438 
00439   sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
00440   for(j=0; j<pIdx->nColumn; j++){
00441     int idx = pIdx->aiColumn[j];
00442     if( idx==pTab->iPKey ){
00443       sqlite3VdbeAddOp(v, OP_Dup, j, 0);
00444     }else{
00445       sqlite3VdbeAddOp(v, OP_Column, iCur, idx);
00446       sqlite3ColumnDefault(v, pTab, idx);
00447     }
00448   }
00449   sqlite3VdbeAddOp(v, OP_MakeIdxRec, pIdx->nColumn, 0);
00450   sqlite3IndexAffinityStr(v, pIdx);
00451 }