xref: /titanic_44/usr/src/lib/libsqlite/src/delete.c (revision c5c4113dfcabb1eed3d4bdf7609de5170027a794)
1*c5c4113dSnw141292 
2*c5c4113dSnw141292 #pragma ident	"%Z%%M%	%I%	%E% SMI"
3*c5c4113dSnw141292 
4*c5c4113dSnw141292 /*
5*c5c4113dSnw141292 ** 2001 September 15
6*c5c4113dSnw141292 **
7*c5c4113dSnw141292 ** The author disclaims copyright to this source code.  In place of
8*c5c4113dSnw141292 ** a legal notice, here is a blessing:
9*c5c4113dSnw141292 **
10*c5c4113dSnw141292 **    May you do good and not evil.
11*c5c4113dSnw141292 **    May you find forgiveness for yourself and forgive others.
12*c5c4113dSnw141292 **    May you share freely, never taking more than you give.
13*c5c4113dSnw141292 **
14*c5c4113dSnw141292 *************************************************************************
15*c5c4113dSnw141292 ** This file contains C code routines that are called by the parser
16*c5c4113dSnw141292 ** to handle DELETE FROM statements.
17*c5c4113dSnw141292 **
18*c5c4113dSnw141292 ** $Id: delete.c,v 1.61 2004/02/24 01:05:32 drh Exp $
19*c5c4113dSnw141292 */
20*c5c4113dSnw141292 #include "sqliteInt.h"
21*c5c4113dSnw141292 
22*c5c4113dSnw141292 /*
23*c5c4113dSnw141292 ** Look up every table that is named in pSrc.  If any table is not found,
24*c5c4113dSnw141292 ** add an error message to pParse->zErrMsg and return NULL.  If all tables
25*c5c4113dSnw141292 ** are found, return a pointer to the last table.
26*c5c4113dSnw141292 */
sqliteSrcListLookup(Parse * pParse,SrcList * pSrc)27*c5c4113dSnw141292 Table *sqliteSrcListLookup(Parse *pParse, SrcList *pSrc){
28*c5c4113dSnw141292   Table *pTab = 0;
29*c5c4113dSnw141292   int i;
30*c5c4113dSnw141292   for(i=0; i<pSrc->nSrc; i++){
31*c5c4113dSnw141292     const char *zTab = pSrc->a[i].zName;
32*c5c4113dSnw141292     const char *zDb = pSrc->a[i].zDatabase;
33*c5c4113dSnw141292     pTab = sqliteLocateTable(pParse, zTab, zDb);
34*c5c4113dSnw141292     pSrc->a[i].pTab = pTab;
35*c5c4113dSnw141292   }
36*c5c4113dSnw141292   return pTab;
37*c5c4113dSnw141292 }
38*c5c4113dSnw141292 
39*c5c4113dSnw141292 /*
40*c5c4113dSnw141292 ** Check to make sure the given table is writable.  If it is not
41*c5c4113dSnw141292 ** writable, generate an error message and return 1.  If it is
42*c5c4113dSnw141292 ** writable return 0;
43*c5c4113dSnw141292 */
sqliteIsReadOnly(Parse * pParse,Table * pTab,int viewOk)44*c5c4113dSnw141292 int sqliteIsReadOnly(Parse *pParse, Table *pTab, int viewOk){
45*c5c4113dSnw141292   if( pTab->readOnly ){
46*c5c4113dSnw141292     sqliteErrorMsg(pParse, "table %s may not be modified", pTab->zName);
47*c5c4113dSnw141292     return 1;
48*c5c4113dSnw141292   }
49*c5c4113dSnw141292   if( !viewOk && pTab->pSelect ){
50*c5c4113dSnw141292     sqliteErrorMsg(pParse, "cannot modify %s because it is a view",pTab->zName);
51*c5c4113dSnw141292     return 1;
52*c5c4113dSnw141292   }
53*c5c4113dSnw141292   return 0;
54*c5c4113dSnw141292 }
55*c5c4113dSnw141292 
56*c5c4113dSnw141292 /*
57*c5c4113dSnw141292 ** Process a DELETE FROM statement.
58*c5c4113dSnw141292 */
sqliteDeleteFrom(Parse * pParse,SrcList * pTabList,Expr * pWhere)59*c5c4113dSnw141292 void sqliteDeleteFrom(
60*c5c4113dSnw141292   Parse *pParse,         /* The parser context */
61*c5c4113dSnw141292   SrcList *pTabList,     /* The table from which we should delete things */
62*c5c4113dSnw141292   Expr *pWhere           /* The WHERE clause.  May be null */
63*c5c4113dSnw141292 ){
64*c5c4113dSnw141292   Vdbe *v;               /* The virtual database engine */
65*c5c4113dSnw141292   Table *pTab;           /* The table from which records will be deleted */
66*c5c4113dSnw141292   const char *zDb;       /* Name of database holding pTab */
67*c5c4113dSnw141292   int end, addr;         /* A couple addresses of generated code */
68*c5c4113dSnw141292   int i;                 /* Loop counter */
69*c5c4113dSnw141292   WhereInfo *pWInfo;     /* Information about the WHERE clause */
70*c5c4113dSnw141292   Index *pIdx;           /* For looping over indices of the table */
71*c5c4113dSnw141292   int iCur;              /* VDBE Cursor number for pTab */
72*c5c4113dSnw141292   sqlite *db;            /* Main database structure */
73*c5c4113dSnw141292   int isView;            /* True if attempting to delete from a view */
74*c5c4113dSnw141292   AuthContext sContext;  /* Authorization context */
75*c5c4113dSnw141292 
76*c5c4113dSnw141292   int row_triggers_exist = 0;  /* True if any triggers exist */
77*c5c4113dSnw141292   int before_triggers;         /* True if there are BEFORE triggers */
78*c5c4113dSnw141292   int after_triggers;          /* True if there are AFTER triggers */
79*c5c4113dSnw141292   int oldIdx = -1;             /* Cursor for the OLD table of AFTER triggers */
80*c5c4113dSnw141292 
81*c5c4113dSnw141292   sContext.pParse = 0;
82*c5c4113dSnw141292   if( pParse->nErr || sqlite_malloc_failed ){
83*c5c4113dSnw141292     pTabList = 0;
84*c5c4113dSnw141292     goto delete_from_cleanup;
85*c5c4113dSnw141292   }
86*c5c4113dSnw141292   db = pParse->db;
87*c5c4113dSnw141292   assert( pTabList->nSrc==1 );
88*c5c4113dSnw141292 
89*c5c4113dSnw141292   /* Locate the table which we want to delete.  This table has to be
90*c5c4113dSnw141292   ** put in an SrcList structure because some of the subroutines we
91*c5c4113dSnw141292   ** will be calling are designed to work with multiple tables and expect
92*c5c4113dSnw141292   ** an SrcList* parameter instead of just a Table* parameter.
93*c5c4113dSnw141292   */
94*c5c4113dSnw141292   pTab = sqliteSrcListLookup(pParse, pTabList);
95*c5c4113dSnw141292   if( pTab==0 )  goto delete_from_cleanup;
96*c5c4113dSnw141292   before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
97*c5c4113dSnw141292                          TK_DELETE, TK_BEFORE, TK_ROW, 0);
98*c5c4113dSnw141292   after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
99*c5c4113dSnw141292                          TK_DELETE, TK_AFTER, TK_ROW, 0);
100*c5c4113dSnw141292   row_triggers_exist = before_triggers || after_triggers;
101*c5c4113dSnw141292   isView = pTab->pSelect!=0;
102*c5c4113dSnw141292   if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
103*c5c4113dSnw141292     goto delete_from_cleanup;
104*c5c4113dSnw141292   }
105*c5c4113dSnw141292   assert( pTab->iDb<db->nDb );
106*c5c4113dSnw141292   zDb = db->aDb[pTab->iDb].zName;
107*c5c4113dSnw141292   if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
108*c5c4113dSnw141292     goto delete_from_cleanup;
109*c5c4113dSnw141292   }
110*c5c4113dSnw141292 
111*c5c4113dSnw141292   /* If pTab is really a view, make sure it has been initialized.
112*c5c4113dSnw141292   */
113*c5c4113dSnw141292   if( isView && sqliteViewGetColumnNames(pParse, pTab) ){
114*c5c4113dSnw141292     goto delete_from_cleanup;
115*c5c4113dSnw141292   }
116*c5c4113dSnw141292 
117*c5c4113dSnw141292   /* Allocate a cursor used to store the old.* data for a trigger.
118*c5c4113dSnw141292   */
119*c5c4113dSnw141292   if( row_triggers_exist ){
120*c5c4113dSnw141292     oldIdx = pParse->nTab++;
121*c5c4113dSnw141292   }
122*c5c4113dSnw141292 
123*c5c4113dSnw141292   /* Resolve the column names in all the expressions.
124*c5c4113dSnw141292   */
125*c5c4113dSnw141292   assert( pTabList->nSrc==1 );
126*c5c4113dSnw141292   iCur = pTabList->a[0].iCursor = pParse->nTab++;
127*c5c4113dSnw141292   if( pWhere ){
128*c5c4113dSnw141292     if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
129*c5c4113dSnw141292       goto delete_from_cleanup;
130*c5c4113dSnw141292     }
131*c5c4113dSnw141292     if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
132*c5c4113dSnw141292       goto delete_from_cleanup;
133*c5c4113dSnw141292     }
134*c5c4113dSnw141292   }
135*c5c4113dSnw141292 
136*c5c4113dSnw141292   /* Start the view context
137*c5c4113dSnw141292   */
138*c5c4113dSnw141292   if( isView ){
139*c5c4113dSnw141292     sqliteAuthContextPush(pParse, &sContext, pTab->zName);
140*c5c4113dSnw141292   }
141*c5c4113dSnw141292 
142*c5c4113dSnw141292   /* Begin generating code.
143*c5c4113dSnw141292   */
144*c5c4113dSnw141292   v = sqliteGetVdbe(pParse);
145*c5c4113dSnw141292   if( v==0 ){
146*c5c4113dSnw141292     goto delete_from_cleanup;
147*c5c4113dSnw141292   }
148*c5c4113dSnw141292   sqliteBeginWriteOperation(pParse, row_triggers_exist, pTab->iDb);
149*c5c4113dSnw141292 
150*c5c4113dSnw141292   /* If we are trying to delete from a view, construct that view into
151*c5c4113dSnw141292   ** a temporary table.
152*c5c4113dSnw141292   */
153*c5c4113dSnw141292   if( isView ){
154*c5c4113dSnw141292     Select *pView = sqliteSelectDup(pTab->pSelect);
155*c5c4113dSnw141292     sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
156*c5c4113dSnw141292     sqliteSelectDelete(pView);
157*c5c4113dSnw141292   }
158*c5c4113dSnw141292 
159*c5c4113dSnw141292   /* Initialize the counter of the number of rows deleted, if
160*c5c4113dSnw141292   ** we are counting rows.
161*c5c4113dSnw141292   */
162*c5c4113dSnw141292   if( db->flags & SQLITE_CountRows ){
163*c5c4113dSnw141292     sqliteVdbeAddOp(v, OP_Integer, 0, 0);
164*c5c4113dSnw141292   }
165*c5c4113dSnw141292 
166*c5c4113dSnw141292   /* Special case: A DELETE without a WHERE clause deletes everything.
167*c5c4113dSnw141292   ** It is easier just to erase the whole table.  Note, however, that
168*c5c4113dSnw141292   ** this means that the row change count will be incorrect.
169*c5c4113dSnw141292   */
170*c5c4113dSnw141292   if( pWhere==0 && !row_triggers_exist ){
171*c5c4113dSnw141292     if( db->flags & SQLITE_CountRows ){
172*c5c4113dSnw141292       /* If counting rows deleted, just count the total number of
173*c5c4113dSnw141292       ** entries in the table. */
174*c5c4113dSnw141292       int endOfLoop = sqliteVdbeMakeLabel(v);
175*c5c4113dSnw141292       int addr;
176*c5c4113dSnw141292       if( !isView ){
177*c5c4113dSnw141292         sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
178*c5c4113dSnw141292         sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
179*c5c4113dSnw141292       }
180*c5c4113dSnw141292       sqliteVdbeAddOp(v, OP_Rewind, iCur, sqliteVdbeCurrentAddr(v)+2);
181*c5c4113dSnw141292       addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
182*c5c4113dSnw141292       sqliteVdbeAddOp(v, OP_Next, iCur, addr);
183*c5c4113dSnw141292       sqliteVdbeResolveLabel(v, endOfLoop);
184*c5c4113dSnw141292       sqliteVdbeAddOp(v, OP_Close, iCur, 0);
185*c5c4113dSnw141292     }
186*c5c4113dSnw141292     if( !isView ){
187*c5c4113dSnw141292       sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb);
188*c5c4113dSnw141292       for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
189*c5c4113dSnw141292         sqliteVdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb);
190*c5c4113dSnw141292       }
191*c5c4113dSnw141292     }
192*c5c4113dSnw141292   }
193*c5c4113dSnw141292 
194*c5c4113dSnw141292   /* The usual case: There is a WHERE clause so we have to scan through
195*c5c4113dSnw141292   ** the table and pick which records to delete.
196*c5c4113dSnw141292   */
197*c5c4113dSnw141292   else{
198*c5c4113dSnw141292     /* Begin the database scan
199*c5c4113dSnw141292     */
200*c5c4113dSnw141292     pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0);
201*c5c4113dSnw141292     if( pWInfo==0 ) goto delete_from_cleanup;
202*c5c4113dSnw141292 
203*c5c4113dSnw141292     /* Remember the key of every item to be deleted.
204*c5c4113dSnw141292     */
205*c5c4113dSnw141292     sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
206*c5c4113dSnw141292     if( db->flags & SQLITE_CountRows ){
207*c5c4113dSnw141292       sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
208*c5c4113dSnw141292     }
209*c5c4113dSnw141292 
210*c5c4113dSnw141292     /* End the database scan loop.
211*c5c4113dSnw141292     */
212*c5c4113dSnw141292     sqliteWhereEnd(pWInfo);
213*c5c4113dSnw141292 
214*c5c4113dSnw141292     /* Open the pseudo-table used to store OLD if there are triggers.
215*c5c4113dSnw141292     */
216*c5c4113dSnw141292     if( row_triggers_exist ){
217*c5c4113dSnw141292       sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
218*c5c4113dSnw141292     }
219*c5c4113dSnw141292 
220*c5c4113dSnw141292     /* Delete every item whose key was written to the list during the
221*c5c4113dSnw141292     ** database scan.  We have to delete items after the scan is complete
222*c5c4113dSnw141292     ** because deleting an item can change the scan order.
223*c5c4113dSnw141292     */
224*c5c4113dSnw141292     sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
225*c5c4113dSnw141292     end = sqliteVdbeMakeLabel(v);
226*c5c4113dSnw141292 
227*c5c4113dSnw141292     /* This is the beginning of the delete loop when there are
228*c5c4113dSnw141292     ** row triggers.
229*c5c4113dSnw141292     */
230*c5c4113dSnw141292     if( row_triggers_exist ){
231*c5c4113dSnw141292       addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
232*c5c4113dSnw141292       sqliteVdbeAddOp(v, OP_Dup, 0, 0);
233*c5c4113dSnw141292       if( !isView ){
234*c5c4113dSnw141292         sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
235*c5c4113dSnw141292         sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
236*c5c4113dSnw141292       }
237*c5c4113dSnw141292       sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
238*c5c4113dSnw141292 
239*c5c4113dSnw141292       sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
240*c5c4113dSnw141292       sqliteVdbeAddOp(v, OP_RowData, iCur, 0);
241*c5c4113dSnw141292       sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
242*c5c4113dSnw141292       if( !isView ){
243*c5c4113dSnw141292         sqliteVdbeAddOp(v, OP_Close, iCur, 0);
244*c5c4113dSnw141292       }
245*c5c4113dSnw141292 
246*c5c4113dSnw141292       sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1,
247*c5c4113dSnw141292           oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
248*c5c4113dSnw141292 	  addr);
249*c5c4113dSnw141292     }
250*c5c4113dSnw141292 
251*c5c4113dSnw141292     if( !isView ){
252*c5c4113dSnw141292       /* Open cursors for the table we are deleting from and all its
253*c5c4113dSnw141292       ** indices.  If there are row triggers, this happens inside the
254*c5c4113dSnw141292       ** OP_ListRead loop because the cursor have to all be closed
255*c5c4113dSnw141292       ** before the trigger fires.  If there are no row triggers, the
256*c5c4113dSnw141292       ** cursors are opened only once on the outside the loop.
257*c5c4113dSnw141292       */
258*c5c4113dSnw141292       pParse->nTab = iCur + 1;
259*c5c4113dSnw141292       sqliteOpenTableAndIndices(pParse, pTab, iCur);
260*c5c4113dSnw141292 
261*c5c4113dSnw141292       /* This is the beginning of the delete loop when there are no
262*c5c4113dSnw141292       ** row triggers */
263*c5c4113dSnw141292       if( !row_triggers_exist ){
264*c5c4113dSnw141292         addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
265*c5c4113dSnw141292       }
266*c5c4113dSnw141292 
267*c5c4113dSnw141292       /* Delete the row */
268*c5c4113dSnw141292       sqliteGenerateRowDelete(db, v, pTab, iCur, pParse->trigStack==0);
269*c5c4113dSnw141292     }
270*c5c4113dSnw141292 
271*c5c4113dSnw141292     /* If there are row triggers, close all cursors then invoke
272*c5c4113dSnw141292     ** the AFTER triggers
273*c5c4113dSnw141292     */
274*c5c4113dSnw141292     if( row_triggers_exist ){
275*c5c4113dSnw141292       if( !isView ){
276*c5c4113dSnw141292         for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
277*c5c4113dSnw141292           sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
278*c5c4113dSnw141292         }
279*c5c4113dSnw141292         sqliteVdbeAddOp(v, OP_Close, iCur, 0);
280*c5c4113dSnw141292       }
281*c5c4113dSnw141292       sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1,
282*c5c4113dSnw141292           oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
283*c5c4113dSnw141292 	  addr);
284*c5c4113dSnw141292     }
285*c5c4113dSnw141292 
286*c5c4113dSnw141292     /* End of the delete loop */
287*c5c4113dSnw141292     sqliteVdbeAddOp(v, OP_Goto, 0, addr);
288*c5c4113dSnw141292     sqliteVdbeResolveLabel(v, end);
289*c5c4113dSnw141292     sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
290*c5c4113dSnw141292 
291*c5c4113dSnw141292     /* Close the cursors after the loop if there are no row triggers */
292*c5c4113dSnw141292     if( !row_triggers_exist ){
293*c5c4113dSnw141292       for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
294*c5c4113dSnw141292         sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
295*c5c4113dSnw141292       }
296*c5c4113dSnw141292       sqliteVdbeAddOp(v, OP_Close, iCur, 0);
297*c5c4113dSnw141292       pParse->nTab = iCur;
298*c5c4113dSnw141292     }
299*c5c4113dSnw141292   }
300*c5c4113dSnw141292   sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
301*c5c4113dSnw141292   sqliteEndWriteOperation(pParse);
302*c5c4113dSnw141292 
303*c5c4113dSnw141292   /*
304*c5c4113dSnw141292   ** Return the number of rows that were deleted.
305*c5c4113dSnw141292   */
306*c5c4113dSnw141292   if( db->flags & SQLITE_CountRows ){
307*c5c4113dSnw141292     sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
308*c5c4113dSnw141292     sqliteVdbeChangeP3(v, -1, "rows deleted", P3_STATIC);
309*c5c4113dSnw141292     sqliteVdbeAddOp(v, OP_Callback, 1, 0);
310*c5c4113dSnw141292   }
311*c5c4113dSnw141292 
312*c5c4113dSnw141292 delete_from_cleanup:
313*c5c4113dSnw141292   sqliteAuthContextPop(&sContext);
314*c5c4113dSnw141292   sqliteSrcListDelete(pTabList);
315*c5c4113dSnw141292   sqliteExprDelete(pWhere);
316*c5c4113dSnw141292   return;
317*c5c4113dSnw141292 }
318*c5c4113dSnw141292 
319*c5c4113dSnw141292 /*
320*c5c4113dSnw141292 ** This routine generates VDBE code that causes a single row of a
321*c5c4113dSnw141292 ** single table to be deleted.
322*c5c4113dSnw141292 **
323*c5c4113dSnw141292 ** The VDBE must be in a particular state when this routine is called.
324*c5c4113dSnw141292 ** These are the requirements:
325*c5c4113dSnw141292 **
326*c5c4113dSnw141292 **   1.  A read/write cursor pointing to pTab, the table containing the row
327*c5c4113dSnw141292 **       to be deleted, must be opened as cursor number "base".
328*c5c4113dSnw141292 **
329*c5c4113dSnw141292 **   2.  Read/write cursors for all indices of pTab must be open as
330*c5c4113dSnw141292 **       cursor number base+i for the i-th index.
331*c5c4113dSnw141292 **
332*c5c4113dSnw141292 **   3.  The record number of the row to be deleted must be on the top
333*c5c4113dSnw141292 **       of the stack.
334*c5c4113dSnw141292 **
335*c5c4113dSnw141292 ** This routine pops the top of the stack to remove the record number
336*c5c4113dSnw141292 ** and then generates code to remove both the table record and all index
337*c5c4113dSnw141292 ** entries that point to that record.
338*c5c4113dSnw141292 */
sqliteGenerateRowDelete(sqlite * db,Vdbe * v,Table * pTab,int iCur,int count)339*c5c4113dSnw141292 void sqliteGenerateRowDelete(
340*c5c4113dSnw141292   sqlite *db,        /* The database containing the index */
341*c5c4113dSnw141292   Vdbe *v,           /* Generate code into this VDBE */
342*c5c4113dSnw141292   Table *pTab,       /* Table containing the row to be deleted */
343*c5c4113dSnw141292   int iCur,          /* Cursor number for the table */
344*c5c4113dSnw141292   int count          /* Increment the row change counter */
345*c5c4113dSnw141292 ){
346*c5c4113dSnw141292   int addr;
347*c5c4113dSnw141292   addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0);
348*c5c4113dSnw141292   sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0);
349*c5c4113dSnw141292   sqliteVdbeAddOp(v, OP_Delete, iCur,
350*c5c4113dSnw141292     (count?OPFLAG_NCHANGE:0) | OPFLAG_CSCHANGE);
351*c5c4113dSnw141292   sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
352*c5c4113dSnw141292 }
353*c5c4113dSnw141292 
354*c5c4113dSnw141292 /*
355*c5c4113dSnw141292 ** This routine generates VDBE code that causes the deletion of all
356*c5c4113dSnw141292 ** index entries associated with a single row of a single table.
357*c5c4113dSnw141292 **
358*c5c4113dSnw141292 ** The VDBE must be in a particular state when this routine is called.
359*c5c4113dSnw141292 ** These are the requirements:
360*c5c4113dSnw141292 **
361*c5c4113dSnw141292 **   1.  A read/write cursor pointing to pTab, the table containing the row
362*c5c4113dSnw141292 **       to be deleted, must be opened as cursor number "iCur".
363*c5c4113dSnw141292 **
364*c5c4113dSnw141292 **   2.  Read/write cursors for all indices of pTab must be open as
365*c5c4113dSnw141292 **       cursor number iCur+i for the i-th index.
366*c5c4113dSnw141292 **
367*c5c4113dSnw141292 **   3.  The "iCur" cursor must be pointing to the row that is to be
368*c5c4113dSnw141292 **       deleted.
369*c5c4113dSnw141292 */
sqliteGenerateRowIndexDelete(sqlite * db,Vdbe * v,Table * pTab,int iCur,char * aIdxUsed)370*c5c4113dSnw141292 void sqliteGenerateRowIndexDelete(
371*c5c4113dSnw141292   sqlite *db,        /* The database containing the index */
372*c5c4113dSnw141292   Vdbe *v,           /* Generate code into this VDBE */
373*c5c4113dSnw141292   Table *pTab,       /* Table containing the row to be deleted */
374*c5c4113dSnw141292   int iCur,          /* Cursor number for the table */
375*c5c4113dSnw141292   char *aIdxUsed     /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
376*c5c4113dSnw141292 ){
377*c5c4113dSnw141292   int i;
378*c5c4113dSnw141292   Index *pIdx;
379*c5c4113dSnw141292 
380*c5c4113dSnw141292   for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
381*c5c4113dSnw141292     int j;
382*c5c4113dSnw141292     if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
383*c5c4113dSnw141292     sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
384*c5c4113dSnw141292     for(j=0; j<pIdx->nColumn; j++){
385*c5c4113dSnw141292       int idx = pIdx->aiColumn[j];
386*c5c4113dSnw141292       if( idx==pTab->iPKey ){
387*c5c4113dSnw141292         sqliteVdbeAddOp(v, OP_Dup, j, 0);
388*c5c4113dSnw141292       }else{
389*c5c4113dSnw141292         sqliteVdbeAddOp(v, OP_Column, iCur, idx);
390*c5c4113dSnw141292       }
391*c5c4113dSnw141292     }
392*c5c4113dSnw141292     sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
393*c5c4113dSnw141292     if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
394*c5c4113dSnw141292     sqliteVdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
395*c5c4113dSnw141292   }
396*c5c4113dSnw141292 }
397