xref: /sqlite-3.40.0/src/delete.c (revision cc6bd383)
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