1cce7d176Sdrh /* 2b19a2bc6Sdrh ** 2001 September 15 3cce7d176Sdrh ** 4b19a2bc6Sdrh ** The author disclaims copyright to this source code. In place of 5b19a2bc6Sdrh ** a legal notice, here is a blessing: 6cce7d176Sdrh ** 7b19a2bc6Sdrh ** May you do good and not evil. 8b19a2bc6Sdrh ** May you find forgiveness for yourself and forgive others. 9b19a2bc6Sdrh ** May you share freely, never taking more than you give. 10cce7d176Sdrh ** 11cce7d176Sdrh ************************************************************************* 12cce7d176Sdrh ** This file contains C code routines that are called by the parser 1323bf66d6Sdrh ** in order to generate code for DELETE FROM statements. 14cce7d176Sdrh ** 15*cc6bd383Sdanielk1977 ** $Id: delete.c,v 1.95 2005/01/10 02:48:49 danielk1977 Exp $ 16cce7d176Sdrh */ 17cce7d176Sdrh #include "sqliteInt.h" 18cce7d176Sdrh 19a76b5dfcSdrh /* 20812d7a21Sdrh ** Look up every table that is named in pSrc. If any table is not found, 21812d7a21Sdrh ** add an error message to pParse->zErrMsg and return NULL. If all tables 22812d7a21Sdrh ** are found, return a pointer to the last table. 23a76b5dfcSdrh */ 244adee20fSdanielk1977 Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ 25812d7a21Sdrh Table *pTab = 0; 26812d7a21Sdrh int i; 27855eb1cfSdrh struct SrcList_item *pItem; 28855eb1cfSdrh for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){ 29855eb1cfSdrh pTab = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase); 30855eb1cfSdrh pItem->pTab = pTab; 31a76b5dfcSdrh } 32a76b5dfcSdrh return pTab; 33a76b5dfcSdrh } 34a76b5dfcSdrh 35a76b5dfcSdrh /* 36812d7a21Sdrh ** Check to make sure the given table is writable. If it is not 37812d7a21Sdrh ** writable, generate an error message and return 1. If it is 38812d7a21Sdrh ** writable return 0; 39812d7a21Sdrh */ 404adee20fSdanielk1977 int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ 41205f48e6Sdrh if( pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0 42205f48e6Sdrh && pParse->nested==0 ){ 434adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); 445cf590c1Sdrh return 1; 455cf590c1Sdrh } 465cf590c1Sdrh if( !viewOk && pTab->pSelect ){ 474adee20fSdanielk1977 sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); 48812d7a21Sdrh return 1; 49812d7a21Sdrh } 50812d7a21Sdrh return 0; 51812d7a21Sdrh } 52812d7a21Sdrh 53812d7a21Sdrh /* 54ad6d9460Sdrh ** Generate code that will open a table for reading. 55ad6d9460Sdrh */ 56ad6d9460Sdrh void sqlite3OpenTableForReading( 57ad6d9460Sdrh Vdbe *v, /* Generate code into this VDBE */ 58ad6d9460Sdrh int iCur, /* The cursor number of the table */ 59ad6d9460Sdrh Table *pTab /* The table to be opened */ 60ad6d9460Sdrh ){ 61ad6d9460Sdrh sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); 62ad6d9460Sdrh sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum); 63ad6d9460Sdrh VdbeComment((v, "# %s", pTab->zName)); 64ad6d9460Sdrh sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol); 65ad6d9460Sdrh } 66ad6d9460Sdrh 67299b187dSdanielk1977 68ad6d9460Sdrh /* 6923bf66d6Sdrh ** Generate code for a DELETE FROM statement. 7023bf66d6Sdrh ** 7123bf66d6Sdrh ** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL; 7223bf66d6Sdrh ** \________/ \________________/ 7323bf66d6Sdrh ** pTabList pWhere 74cce7d176Sdrh */ 754adee20fSdanielk1977 void sqlite3DeleteFrom( 76cce7d176Sdrh Parse *pParse, /* The parser context */ 77113088ecSdrh SrcList *pTabList, /* The table from which we should delete things */ 78cce7d176Sdrh Expr *pWhere /* The WHERE clause. May be null */ 79cce7d176Sdrh ){ 80cce7d176Sdrh Vdbe *v; /* The virtual database engine */ 81cce7d176Sdrh Table *pTab; /* The table from which records will be deleted */ 82e22a334bSdrh const char *zDb; /* Name of database holding pTab */ 83299b187dSdanielk1977 int end, addr = 0; /* A couple addresses of generated code */ 84cce7d176Sdrh int i; /* Loop counter */ 85cce7d176Sdrh WhereInfo *pWInfo; /* Information about the WHERE clause */ 86cce7d176Sdrh Index *pIdx; /* For looping over indices of the table */ 876a3ea0e6Sdrh int iCur; /* VDBE Cursor number for pTab */ 889bb575fdSdrh sqlite3 *db; /* Main database structure */ 8985e2096fSdrh AuthContext sContext; /* Authorization context */ 90798da52cSdrh int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */ 911bee3d7bSdrh 92798da52cSdrh #ifndef SQLITE_OMIT_TRIGGER 93798da52cSdrh int isView; /* True if attempting to delete from a view */ 94dca76841Sdrh int triggers_exist = 0; /* True if any triggers exist */ 95798da52cSdrh #endif 96cce7d176Sdrh 9785e2096fSdrh sContext.pParse = 0; 9824b03fd0Sdanielk1977 if( pParse->nErr || sqlite3_malloc_failed ){ 99daffd0e5Sdrh pTabList = 0; 100daffd0e5Sdrh goto delete_from_cleanup; 101daffd0e5Sdrh } 102ecdc7530Sdrh db = pParse->db; 103113088ecSdrh assert( pTabList->nSrc==1 ); 104daffd0e5Sdrh 1051ccde15dSdrh /* Locate the table which we want to delete. This table has to be 106ad3cab52Sdrh ** put in an SrcList structure because some of the subroutines we 107cce7d176Sdrh ** will be calling are designed to work with multiple tables and expect 108ad3cab52Sdrh ** an SrcList* parameter instead of just a Table* parameter. 109cce7d176Sdrh */ 1104adee20fSdanielk1977 pTab = sqlite3SrcListLookup(pParse, pTabList); 111a69d9168Sdrh if( pTab==0 ) goto delete_from_cleanup; 112b7f9164eSdrh 113b7f9164eSdrh /* Figure out if we have any triggers and if the table being 114b7f9164eSdrh ** deleted from is a view 115b7f9164eSdrh */ 116b7f9164eSdrh #ifndef SQLITE_OMIT_TRIGGER 117dca76841Sdrh triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0); 1185cf590c1Sdrh isView = pTab->pSelect!=0; 119b7f9164eSdrh #else 120dca76841Sdrh # define triggers_exist 0 121b7f9164eSdrh # define isView 0 122b7f9164eSdrh #endif 123b7f9164eSdrh #ifdef SQLITE_OMIT_VIEW 124b7f9164eSdrh # undef isView 125b7f9164eSdrh # define isView 0 126b7f9164eSdrh #endif 127b7f9164eSdrh 128dca76841Sdrh if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ 1295cf590c1Sdrh goto delete_from_cleanup; 130113088ecSdrh } 131e22a334bSdrh assert( pTab->iDb<db->nDb ); 132e22a334bSdrh zDb = db->aDb[pTab->iDb].zName; 1334adee20fSdanielk1977 if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ 134e5f9c644Sdrh goto delete_from_cleanup; 135e5f9c644Sdrh } 136cce7d176Sdrh 1375cf590c1Sdrh /* If pTab is really a view, make sure it has been initialized. 1385cf590c1Sdrh */ 1394adee20fSdanielk1977 if( isView && sqlite3ViewGetColumnNames(pParse, pTab) ){ 1405cf590c1Sdrh goto delete_from_cleanup; 1415cf590c1Sdrh } 1425cf590c1Sdrh 143c977f7f5Sdrh /* Allocate a cursor used to store the old.* data for a trigger. 144c977f7f5Sdrh */ 145dca76841Sdrh if( triggers_exist ){ 146c3f9bad2Sdanielk1977 oldIdx = pParse->nTab++; 147f29ce559Sdanielk1977 } 148c3f9bad2Sdanielk1977 149299b187dSdanielk1977 /* Resolve the column names in all the expressions. 150cce7d176Sdrh */ 1516a3ea0e6Sdrh assert( pTabList->nSrc==1 ); 1526a3ea0e6Sdrh iCur = pTabList->a[0].iCursor = pParse->nTab++; 153290c1948Sdrh if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pWhere, 0, 0) ){ 154cce7d176Sdrh goto delete_from_cleanup; 155cce7d176Sdrh } 156cce7d176Sdrh 15785e2096fSdrh /* Start the view context 15885e2096fSdrh */ 15985e2096fSdrh if( isView ){ 1604adee20fSdanielk1977 sqlite3AuthContextPush(pParse, &sContext, pTab->zName); 16185e2096fSdrh } 16285e2096fSdrh 163cce7d176Sdrh /* Begin generating code. 164cce7d176Sdrh */ 1654adee20fSdanielk1977 v = sqlite3GetVdbe(pParse); 166f29ce559Sdanielk1977 if( v==0 ){ 167f29ce559Sdanielk1977 goto delete_from_cleanup; 168f29ce559Sdanielk1977 } 1694794f735Sdrh if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); 170dca76841Sdrh sqlite3BeginWriteOperation(pParse, triggers_exist, pTab->iDb); 1715e00f6c7Sdrh 1725cf590c1Sdrh /* If we are trying to delete from a view, construct that view into 1735cf590c1Sdrh ** a temporary table. 1745cf590c1Sdrh */ 1755cf590c1Sdrh if( isView ){ 1764adee20fSdanielk1977 Select *pView = sqlite3SelectDup(pTab->pSelect); 17784ac9d02Sdanielk1977 sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0, 0); 1784adee20fSdanielk1977 sqlite3SelectDelete(pView); 1795cf590c1Sdrh } 1805cf590c1Sdrh 1811bee3d7bSdrh /* Initialize the counter of the number of rows deleted, if 1821bee3d7bSdrh ** we are counting rows. 1831bee3d7bSdrh */ 1841bee3d7bSdrh if( db->flags & SQLITE_CountRows ){ 1854adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Integer, 0, 0); 1861bee3d7bSdrh } 187cce7d176Sdrh 1880353ceddSdrh /* Special case: A DELETE without a WHERE clause deletes everything. 189c977f7f5Sdrh ** It is easier just to erase the whole table. Note, however, that 190c977f7f5Sdrh ** this means that the row change count will be incorrect. 1910353ceddSdrh */ 192dca76841Sdrh if( pWhere==0 && !triggers_exist ){ 1931bee3d7bSdrh if( db->flags & SQLITE_CountRows ){ 1941bee3d7bSdrh /* If counting rows deleted, just count the total number of 1951bee3d7bSdrh ** entries in the table. */ 1964adee20fSdanielk1977 int endOfLoop = sqlite3VdbeMakeLabel(v); 1971bee3d7bSdrh int addr; 1985cf590c1Sdrh if( !isView ){ 199ad6d9460Sdrh sqlite3OpenTableForReading(v, iCur, pTab); 2005cf590c1Sdrh } 2014adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2); 2024adee20fSdanielk1977 addr = sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); 2034adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Next, iCur, addr); 2044adee20fSdanielk1977 sqlite3VdbeResolveLabel(v, endOfLoop); 2054adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Close, iCur, 0); 2061bee3d7bSdrh } 2075cf590c1Sdrh if( !isView ){ 2084adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb); 2090353ceddSdrh for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ 2104adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb); 2110353ceddSdrh } 2120353ceddSdrh } 2135cf590c1Sdrh } 2140353ceddSdrh 2150353ceddSdrh /* The usual case: There is a WHERE clause so we have to scan through 2168bc03a7aSjplyon ** the table and pick which records to delete. 2170353ceddSdrh */ 2180353ceddSdrh else{ 2197cedc8d4Sdanielk1977 /* Ensure all required collation sequences are available. */ 2207cedc8d4Sdanielk1977 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ 2217cedc8d4Sdanielk1977 if( sqlite3CheckIndexCollSeq(pParse, pIdx) ){ 2227cedc8d4Sdanielk1977 goto delete_from_cleanup; 2237cedc8d4Sdanielk1977 } 2247cedc8d4Sdanielk1977 } 2257cedc8d4Sdanielk1977 226299b187dSdanielk1977 /* Begin the database scan 227299b187dSdanielk1977 */ 228e6f85e71Sdrh pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0); 229299b187dSdanielk1977 if( pWInfo==0 ) goto delete_from_cleanup; 230299b187dSdanielk1977 231e6f85e71Sdrh /* Remember the rowid of every item to be deleted. 232299b187dSdanielk1977 */ 233e6f85e71Sdrh sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); 234299b187dSdanielk1977 sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0); 235299b187dSdanielk1977 if( db->flags & SQLITE_CountRows ){ 236299b187dSdanielk1977 sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); 237299b187dSdanielk1977 } 238299b187dSdanielk1977 239299b187dSdanielk1977 /* End the database scan loop. 240299b187dSdanielk1977 */ 241299b187dSdanielk1977 sqlite3WhereEnd(pWInfo); 242299b187dSdanielk1977 24370ce3f0cSdrh /* Open the pseudo-table used to store OLD if there are triggers. 24470ce3f0cSdrh */ 245dca76841Sdrh if( triggers_exist ){ 2464adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0); 24784ac9d02Sdanielk1977 sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol); 24870ce3f0cSdrh } 24970ce3f0cSdrh 250299b187dSdanielk1977 /* Delete every item whose key was written to the list during the 251299b187dSdanielk1977 ** database scan. We have to delete items after the scan is complete 252299b187dSdanielk1977 ** because deleting an item can change the scan order. 253ed326d70Sdanielk1977 */ 254299b187dSdanielk1977 sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0); 255299b187dSdanielk1977 end = sqlite3VdbeMakeLabel(v); 256ed326d70Sdanielk1977 257299b187dSdanielk1977 /* This is the beginning of the delete loop when there are 258299b187dSdanielk1977 ** row triggers. 259c977f7f5Sdrh */ 260dca76841Sdrh if( triggers_exist ){ 261299b187dSdanielk1977 addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end); 262299b187dSdanielk1977 sqlite3VdbeAddOp(v, OP_Dup, 0, 0); 263299b187dSdanielk1977 if( !isView ){ 264299b187dSdanielk1977 sqlite3OpenTableForReading(v, iCur, pTab); 265299b187dSdanielk1977 } 266299b187dSdanielk1977 sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); 2674adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); 2684adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_RowData, iCur, 0); 2694adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_PutIntKey, oldIdx, 0); 270299b187dSdanielk1977 if( !isView ){ 271299b187dSdanielk1977 sqlite3VdbeAddOp(v, OP_Close, iCur, 0); 272299b187dSdanielk1977 } 273299b187dSdanielk1977 274dca76841Sdrh (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab, 275dca76841Sdrh -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, 2766f34903eSdanielk1977 addr); 277c3f9bad2Sdanielk1977 } 278c3f9bad2Sdanielk1977 279299b187dSdanielk1977 if( !isView ){ 280299b187dSdanielk1977 /* Open cursors for the table we are deleting from and all its 281299b187dSdanielk1977 ** indices. If there are row triggers, this happens inside the 282299b187dSdanielk1977 ** OP_ListRead loop because the cursor have to all be closed 283299b187dSdanielk1977 ** before the trigger fires. If there are no row triggers, the 284299b187dSdanielk1977 ** cursors are opened only once on the outside the loop. 285c977f7f5Sdrh */ 286299b187dSdanielk1977 sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite); 287c3f9bad2Sdanielk1977 288299b187dSdanielk1977 /* This is the beginning of the delete loop when there are no 289299b187dSdanielk1977 ** row triggers */ 290dca76841Sdrh if( !triggers_exist ){ 291299b187dSdanielk1977 addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end); 292299b187dSdanielk1977 } 293299b187dSdanielk1977 294299b187dSdanielk1977 /* Delete the row */ 295299b187dSdanielk1977 sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0); 296299b187dSdanielk1977 } 297299b187dSdanielk1977 298299b187dSdanielk1977 /* If there are row triggers, close all cursors then invoke 299299b187dSdanielk1977 ** the AFTER triggers 300299b187dSdanielk1977 */ 301dca76841Sdrh if( triggers_exist ){ 302299b187dSdanielk1977 if( !isView ){ 303299b187dSdanielk1977 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ 304299b187dSdanielk1977 sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); 305299b187dSdanielk1977 } 306299b187dSdanielk1977 sqlite3VdbeAddOp(v, OP_Close, iCur, 0); 307299b187dSdanielk1977 } 308dca76841Sdrh (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1, 3096f34903eSdanielk1977 oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, 3106f34903eSdanielk1977 addr); 311c3f9bad2Sdanielk1977 } 312c3f9bad2Sdanielk1977 313299b187dSdanielk1977 /* End of the delete loop */ 314299b187dSdanielk1977 sqlite3VdbeAddOp(v, OP_Goto, 0, addr); 315299b187dSdanielk1977 sqlite3VdbeResolveLabel(v, end); 316299b187dSdanielk1977 sqlite3VdbeAddOp(v, OP_ListReset, 0, 0); 317299b187dSdanielk1977 318299b187dSdanielk1977 /* Close the cursors after the loop if there are no row triggers */ 319dca76841Sdrh if( !triggers_exist ){ 320c3f9bad2Sdanielk1977 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ 3214adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); 322c3f9bad2Sdanielk1977 } 323299b187dSdanielk1977 sqlite3VdbeAddOp(v, OP_Close, iCur, 0); 324299b187dSdanielk1977 } 3250353ceddSdrh } 3265e00f6c7Sdrh 3271bee3d7bSdrh /* 328e7de6f25Sdanielk1977 ** Return the number of rows that were deleted. If this routine is 329e7de6f25Sdanielk1977 ** generating code because of a call to sqlite3NestedParse(), do not 330e7de6f25Sdanielk1977 ** invoke the callback function. 3311bee3d7bSdrh */ 332*cc6bd383Sdanielk1977 if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ 3334adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Callback, 1, 0); 33422322fd4Sdanielk1977 sqlite3VdbeSetNumCols(v, 1); 3353cf86063Sdanielk1977 sqlite3VdbeSetColName(v, 0, "rows deleted", P3_STATIC); 3361bee3d7bSdrh } 337cce7d176Sdrh 338cce7d176Sdrh delete_from_cleanup: 3394adee20fSdanielk1977 sqlite3AuthContextPop(&sContext); 3404adee20fSdanielk1977 sqlite3SrcListDelete(pTabList); 3414adee20fSdanielk1977 sqlite3ExprDelete(pWhere); 342cce7d176Sdrh return; 343cce7d176Sdrh } 3449cfcf5d4Sdrh 3459cfcf5d4Sdrh /* 3469cfcf5d4Sdrh ** This routine generates VDBE code that causes a single row of a 3479cfcf5d4Sdrh ** single table to be deleted. 3489cfcf5d4Sdrh ** 3499cfcf5d4Sdrh ** The VDBE must be in a particular state when this routine is called. 3509cfcf5d4Sdrh ** These are the requirements: 3519cfcf5d4Sdrh ** 3529cfcf5d4Sdrh ** 1. A read/write cursor pointing to pTab, the table containing the row 3539cfcf5d4Sdrh ** to be deleted, must be opened as cursor number "base". 3549cfcf5d4Sdrh ** 3559cfcf5d4Sdrh ** 2. Read/write cursors for all indices of pTab must be open as 3569cfcf5d4Sdrh ** cursor number base+i for the i-th index. 3579cfcf5d4Sdrh ** 3589cfcf5d4Sdrh ** 3. The record number of the row to be deleted must be on the top 3599cfcf5d4Sdrh ** of the stack. 3609cfcf5d4Sdrh ** 3619cfcf5d4Sdrh ** This routine pops the top of the stack to remove the record number 3629cfcf5d4Sdrh ** and then generates code to remove both the table record and all index 3639cfcf5d4Sdrh ** entries that point to that record. 3649cfcf5d4Sdrh */ 3654adee20fSdanielk1977 void sqlite3GenerateRowDelete( 3669bb575fdSdrh sqlite3 *db, /* The database containing the index */ 3679cfcf5d4Sdrh Vdbe *v, /* Generate code into this VDBE */ 3689cfcf5d4Sdrh Table *pTab, /* Table containing the row to be deleted */ 3696a3ea0e6Sdrh int iCur, /* Cursor number for the table */ 370c8d30ac1Sdrh int count /* Increment the row change counter */ 3719cfcf5d4Sdrh ){ 37207d6e3a7Sdrh int addr; 3734adee20fSdanielk1977 addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0); 3744adee20fSdanielk1977 sqlite3GenerateRowIndexDelete(db, v, pTab, iCur, 0); 375b28af71aSdanielk1977 sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); 3764adee20fSdanielk1977 sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v)); 3770ca3e24bSdrh } 3780ca3e24bSdrh 3790ca3e24bSdrh /* 3800ca3e24bSdrh ** This routine generates VDBE code that causes the deletion of all 3810ca3e24bSdrh ** index entries associated with a single row of a single table. 3820ca3e24bSdrh ** 3830ca3e24bSdrh ** The VDBE must be in a particular state when this routine is called. 3840ca3e24bSdrh ** These are the requirements: 3850ca3e24bSdrh ** 3860ca3e24bSdrh ** 1. A read/write cursor pointing to pTab, the table containing the row 3876a3ea0e6Sdrh ** to be deleted, must be opened as cursor number "iCur". 3880ca3e24bSdrh ** 3890ca3e24bSdrh ** 2. Read/write cursors for all indices of pTab must be open as 3906a3ea0e6Sdrh ** cursor number iCur+i for the i-th index. 3910ca3e24bSdrh ** 3926a3ea0e6Sdrh ** 3. The "iCur" cursor must be pointing to the row that is to be 3930ca3e24bSdrh ** deleted. 3940ca3e24bSdrh */ 3954adee20fSdanielk1977 void sqlite3GenerateRowIndexDelete( 3969bb575fdSdrh sqlite3 *db, /* The database containing the index */ 3970ca3e24bSdrh Vdbe *v, /* Generate code into this VDBE */ 3980ca3e24bSdrh Table *pTab, /* Table containing the row to be deleted */ 3996a3ea0e6Sdrh int iCur, /* Cursor number for the table */ 4000ca3e24bSdrh char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */ 4010ca3e24bSdrh ){ 4029cfcf5d4Sdrh int i; 4039cfcf5d4Sdrh Index *pIdx; 4049cfcf5d4Sdrh 4059cfcf5d4Sdrh for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ 4060ca3e24bSdrh if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue; 40751846b56Sdrh sqlite3GenerateIndexKey(v, pIdx, iCur); 40851846b56Sdrh sqlite3VdbeAddOp(v, OP_IdxDelete, iCur+i, 0); 40951846b56Sdrh } 41051846b56Sdrh } 41151846b56Sdrh 41251846b56Sdrh /* 41351846b56Sdrh ** Generate code that will assemble an index key and put it on the top 41451846b56Sdrh ** of the tack. The key with be for index pIdx which is an index on pTab. 41551846b56Sdrh ** iCur is the index of a cursor open on the pTab table and pointing to 41651846b56Sdrh ** the entry that needs indexing. 41751846b56Sdrh */ 41851846b56Sdrh void sqlite3GenerateIndexKey( 41951846b56Sdrh Vdbe *v, /* Generate code into this VDBE */ 42051846b56Sdrh Index *pIdx, /* The index for which to generate a key */ 42151846b56Sdrh int iCur /* Cursor number for the pIdx->pTable table */ 42251846b56Sdrh ){ 42351846b56Sdrh int j; 42451846b56Sdrh Table *pTab = pIdx->pTable; 42551846b56Sdrh 4264adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Recno, iCur, 0); 4279cfcf5d4Sdrh for(j=0; j<pIdx->nColumn; j++){ 4289cfcf5d4Sdrh int idx = pIdx->aiColumn[j]; 4299cfcf5d4Sdrh if( idx==pTab->iPKey ){ 4304adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Dup, j, 0); 4319cfcf5d4Sdrh }else{ 4324adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Column, iCur, idx); 4339cfcf5d4Sdrh } 4349cfcf5d4Sdrh } 435ededfd5eSdanielk1977 sqlite3VdbeAddOp(v, OP_MakeRecord, pIdx->nColumn, (1<<24)); 436a37cdde0Sdanielk1977 sqlite3IndexAffinityStr(v, pIdx); 4379cfcf5d4Sdrh } 438