xref: /sqlite-3.40.0/src/delete.c (revision bbb5e4e0)
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*bbb5e4e0Sdrh ** $Id: delete.c,v 1.200 2009/04/30 00:11:10 drh 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){
25b1c685b0Sdanielk1977   struct SrcList_item *pItem = pSrc->a;
26b1c685b0Sdanielk1977   Table *pTab;
27b1c685b0Sdanielk1977   assert( pItem && pSrc->nSrc==1 );
28ca424114Sdrh   pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
29a04a34ffSdanielk1977   sqlite3DeleteTable(pItem->pTab);
30855eb1cfSdrh   pItem->pTab = pTab;
31ed8a3bb1Sdrh   if( pTab ){
32ed8a3bb1Sdrh     pTab->nRef++;
33ed8a3bb1Sdrh   }
34b1c685b0Sdanielk1977   if( sqlite3IndexedByLookup(pParse, pItem) ){
35b1c685b0Sdanielk1977     pTab = 0;
36a76b5dfcSdrh   }
37a76b5dfcSdrh   return pTab;
38a76b5dfcSdrh }
39a76b5dfcSdrh 
40a76b5dfcSdrh /*
41812d7a21Sdrh ** Check to make sure the given table is writable.  If it is not
42812d7a21Sdrh ** writable, generate an error message and return 1.  If it is
43812d7a21Sdrh ** writable return 0;
44812d7a21Sdrh */
454adee20fSdanielk1977 int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
467d10d5a6Sdrh   if( ((pTab->tabFlags & TF_Readonly)!=0
477d10d5a6Sdrh         && (pParse->db->flags & SQLITE_WriteSchema)==0
484cbdda9eSdrh         && pParse->nested==0)
494cbdda9eSdrh #ifndef SQLITE_OMIT_VIRTUALTABLE
50d1ab1ba5Sdanielk1977       || (pTab->pMod && pTab->pMod->pModule->xUpdate==0)
514cbdda9eSdrh #endif
524cbdda9eSdrh   ){
534adee20fSdanielk1977     sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
545cf590c1Sdrh     return 1;
555cf590c1Sdrh   }
56b84f96f8Sdanielk1977 #ifndef SQLITE_OMIT_VIEW
575cf590c1Sdrh   if( !viewOk && pTab->pSelect ){
584adee20fSdanielk1977     sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
59812d7a21Sdrh     return 1;
60812d7a21Sdrh   }
61b84f96f8Sdanielk1977 #endif
62812d7a21Sdrh   return 0;
63812d7a21Sdrh }
64812d7a21Sdrh 
65299b187dSdanielk1977 
660f35a6b5Sdrh #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
670f35a6b5Sdrh /*
680f35a6b5Sdrh ** Evaluate a view and store its result in an ephemeral table.  The
690f35a6b5Sdrh ** pWhere argument is an optional WHERE clause that restricts the
700f35a6b5Sdrh ** set of rows in the view that are to be added to the ephemeral table.
710f35a6b5Sdrh */
720f35a6b5Sdrh void sqlite3MaterializeView(
730f35a6b5Sdrh   Parse *pParse,       /* Parsing context */
742a5d825eSdrh   Table *pView,        /* View definition */
750f35a6b5Sdrh   Expr *pWhere,        /* Optional WHERE clause to be added */
760f35a6b5Sdrh   int iCur             /* Cursor number for ephemerial table */
770f35a6b5Sdrh ){
780f35a6b5Sdrh   SelectDest dest;
790f35a6b5Sdrh   Select *pDup;
800f35a6b5Sdrh   sqlite3 *db = pParse->db;
810f35a6b5Sdrh 
826ab3a2ecSdanielk1977   pDup = sqlite3SelectDup(db, pView->pSelect, 0);
830f35a6b5Sdrh   if( pWhere ){
840f35a6b5Sdrh     SrcList *pFrom;
852a5d825eSdrh     Token viewName;
860f35a6b5Sdrh 
876ab3a2ecSdanielk1977     pWhere = sqlite3ExprDup(db, pWhere, 0);
888b213899Sdrh     viewName.z = (u8*)pView->zName;
89ea678832Sdrh     viewName.n = (unsigned int)sqlite3Strlen30((const char*)viewName.z);
90b1c685b0Sdanielk1977     pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &viewName, pDup, 0,0);
910f35a6b5Sdrh     pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
920f35a6b5Sdrh   }
930f35a6b5Sdrh   sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
947d10d5a6Sdrh   sqlite3Select(pParse, pDup, &dest);
95633e6d57Sdrh   sqlite3SelectDelete(db, pDup);
960f35a6b5Sdrh }
970f35a6b5Sdrh #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
980f35a6b5Sdrh 
99273f619bSshane #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
1004281bd42Sshane /*
1014281bd42Sshane ** Generate an expression tree to implement the WHERE, ORDER BY,
1024281bd42Sshane ** and LIMIT/OFFSET portion of DELETE and UPDATE statements.
1034281bd42Sshane **
1044281bd42Sshane **     DELETE FROM table_wxyz WHERE a<5 ORDER BY a LIMIT 1;
1054281bd42Sshane **                            \__________________________/
1064281bd42Sshane **                               pLimitWhere (pInClause)
1074281bd42Sshane */
1084281bd42Sshane Expr *sqlite3LimitWhere(
1094281bd42Sshane   Parse *pParse,               /* The parser context */
1104281bd42Sshane   SrcList *pSrc,               /* the FROM clause -- which tables to scan */
1114281bd42Sshane   Expr *pWhere,                /* The WHERE clause.  May be null */
1124281bd42Sshane   ExprList *pOrderBy,          /* The ORDER BY clause.  May be null */
1134281bd42Sshane   Expr *pLimit,                /* The LIMIT clause.  May be null */
11449ffdbf4Sshane   Expr *pOffset,               /* The OFFSET clause.  May be null */
11549ffdbf4Sshane   char *zStmtType              /* Either DELETE or UPDATE.  For error messages. */
1164281bd42Sshane ){
11749ffdbf4Sshane   Expr *pWhereRowid = NULL;    /* WHERE rowid .. */
11849ffdbf4Sshane   Expr *pInClause = NULL;      /* WHERE rowid IN ( select ) */
11949ffdbf4Sshane   Expr *pSelectRowid = NULL;   /* SELECT rowid ... */
12049ffdbf4Sshane   ExprList *pEList = NULL;     /* Expression list contaning only pSelectRowid */
12149ffdbf4Sshane   SrcList *pSelectSrc = NULL;  /* SELECT rowid FROM x ... (dup of pSrc) */
12249ffdbf4Sshane   Select *pSelect = NULL;      /* Complete SELECT tree */
12349ffdbf4Sshane 
12449ffdbf4Sshane   /* Check that there isn't an ORDER BY without a LIMIT clause.
12549ffdbf4Sshane   */
12649ffdbf4Sshane   if( pOrderBy && (pLimit == 0) ) {
12749ffdbf4Sshane     sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType);
12849ffdbf4Sshane     pParse->parseError = 1;
12949ffdbf4Sshane     goto limit_where_cleanup_2;
13049ffdbf4Sshane   }
131273f619bSshane 
132273f619bSshane   /* We only need to generate a select expression if there
133273f619bSshane   ** is a limit/offset term to enforce.
134273f619bSshane   */
13549ffdbf4Sshane   if( pLimit == 0 ) {
13649ffdbf4Sshane     /* if pLimit is null, pOffset will always be null as well. */
13749ffdbf4Sshane     assert( pOffset == 0 );
13849ffdbf4Sshane     return pWhere;
13949ffdbf4Sshane   }
140273f619bSshane 
141273f619bSshane   /* Generate a select expression tree to enforce the limit/offset
142273f619bSshane   ** term for the DELETE or UPDATE statement.  For example:
143273f619bSshane   **   DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
144273f619bSshane   ** becomes:
145273f619bSshane   **   DELETE FROM table_a WHERE rowid IN (
146b235db9cSshane   **     SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
147273f619bSshane   **   );
148273f619bSshane   */
149b235db9cSshane 
150273f619bSshane   pSelectRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0);
15149ffdbf4Sshane   if( pSelectRowid == 0 ) goto limit_where_cleanup_2;
152273f619bSshane   pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid, 0);
15349ffdbf4Sshane   if( pEList == 0 ) goto limit_where_cleanup_2;
154b235db9cSshane 
155273f619bSshane   /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
156b235db9cSshane   ** and the SELECT subtree. */
1576ab3a2ecSdanielk1977   pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0);
158b235db9cSshane   if( pSelectSrc == 0 ) {
159b235db9cSshane     sqlite3ExprListDelete(pParse->db, pEList);
16049ffdbf4Sshane     goto limit_where_cleanup_2;
161b235db9cSshane   }
162b235db9cSshane 
163b235db9cSshane   /* generate the SELECT expression tree. */
16418209cd6Sdrh   pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0,
16518209cd6Sdrh                              pOrderBy,0,pLimit,pOffset);
166b235db9cSshane   if( pSelect == 0 ) return 0;
167b235db9cSshane 
16849ffdbf4Sshane   /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
169273f619bSshane   pWhereRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0);
17049ffdbf4Sshane   if( pWhereRowid == 0 ) goto limit_where_cleanup_1;
171273f619bSshane   pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0);
17249ffdbf4Sshane   if( pInClause == 0 ) goto limit_where_cleanup_1;
173b235db9cSshane 
17418209cd6Sdrh   pInClause->x.pSelect = pSelect;
17518209cd6Sdrh   pInClause->flags |= EP_xIsSelect;
1764281bd42Sshane   sqlite3ExprSetHeight(pParse, pInClause);
1774281bd42Sshane   return pInClause;
178273f619bSshane 
179273f619bSshane   /* something went wrong. clean up anything allocated. */
18049ffdbf4Sshane limit_where_cleanup_1:
181b235db9cSshane   sqlite3SelectDelete(pParse->db, pSelect);
1824281bd42Sshane   return 0;
18349ffdbf4Sshane 
18449ffdbf4Sshane limit_where_cleanup_2:
18549ffdbf4Sshane   sqlite3ExprDelete(pParse->db, pWhere);
18649ffdbf4Sshane   sqlite3ExprListDelete(pParse->db, pOrderBy);
18749ffdbf4Sshane   sqlite3ExprDelete(pParse->db, pLimit);
18849ffdbf4Sshane   sqlite3ExprDelete(pParse->db, pOffset);
18949ffdbf4Sshane   return 0;
1904281bd42Sshane }
191273f619bSshane #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
1920f35a6b5Sdrh 
193ad6d9460Sdrh /*
19423bf66d6Sdrh ** Generate code for a DELETE FROM statement.
19523bf66d6Sdrh **
19623bf66d6Sdrh **     DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
19723bf66d6Sdrh **                 \________/       \________________/
19823bf66d6Sdrh **                  pTabList              pWhere
199cce7d176Sdrh */
2004adee20fSdanielk1977 void sqlite3DeleteFrom(
201cce7d176Sdrh   Parse *pParse,         /* The parser context */
202113088ecSdrh   SrcList *pTabList,     /* The table from which we should delete things */
203cce7d176Sdrh   Expr *pWhere           /* The WHERE clause.  May be null */
204cce7d176Sdrh ){
205cce7d176Sdrh   Vdbe *v;               /* The virtual database engine */
206cce7d176Sdrh   Table *pTab;           /* The table from which records will be deleted */
207e22a334bSdrh   const char *zDb;       /* Name of database holding pTab */
208299b187dSdanielk1977   int end, addr = 0;     /* A couple addresses of generated code */
209cce7d176Sdrh   int i;                 /* Loop counter */
210cce7d176Sdrh   WhereInfo *pWInfo;     /* Information about the WHERE clause */
211cce7d176Sdrh   Index *pIdx;           /* For looping over indices of the table */
2126a3ea0e6Sdrh   int iCur;              /* VDBE Cursor number for pTab */
2139bb575fdSdrh   sqlite3 *db;           /* Main database structure */
21485e2096fSdrh   AuthContext sContext;  /* Authorization context */
215798da52cSdrh   int oldIdx = -1;       /* Cursor for the OLD table of AFTER triggers */
216b3bce662Sdanielk1977   NameContext sNC;       /* Name context to resolve expressions in */
21753a67774Sdrh   int iDb;               /* Database number */
218c7af484bSdanielk1977   int memCnt = -1;       /* Memory cell used for change counting */
21952bd7912Sdanielk1977   int rcauth;            /* Value returned by authorization callback */
2201bee3d7bSdrh 
221798da52cSdrh #ifndef SQLITE_OMIT_TRIGGER
222798da52cSdrh   int isView;                  /* True if attempting to delete from a view */
2232f886d1dSdanielk1977   Trigger *pTrigger;           /* List of table triggers, if required */
224798da52cSdrh #endif
2251bd10f8aSdrh   int iBeginAfterTrigger = 0;  /* Address of after trigger program */
2261bd10f8aSdrh   int iEndAfterTrigger = 0;    /* Exit of after trigger program */
2271bd10f8aSdrh   int iBeginBeforeTrigger = 0; /* Address of before trigger program */
2281bd10f8aSdrh   int iEndBeforeTrigger = 0;   /* Exit of before trigger program */
2298f2c54e6Sdanielk1977   u32 old_col_mask = 0;        /* Mask of OLD.* columns in use */
230cce7d176Sdrh 
23185e2096fSdrh   sContext.pParse = 0;
23217435752Sdrh   db = pParse->db;
23317435752Sdrh   if( pParse->nErr || db->mallocFailed ){
234daffd0e5Sdrh     goto delete_from_cleanup;
235daffd0e5Sdrh   }
236113088ecSdrh   assert( pTabList->nSrc==1 );
237daffd0e5Sdrh 
2381ccde15dSdrh   /* Locate the table which we want to delete.  This table has to be
239ad3cab52Sdrh   ** put in an SrcList structure because some of the subroutines we
240cce7d176Sdrh   ** will be calling are designed to work with multiple tables and expect
241ad3cab52Sdrh   ** an SrcList* parameter instead of just a Table* parameter.
242cce7d176Sdrh   */
2434adee20fSdanielk1977   pTab = sqlite3SrcListLookup(pParse, pTabList);
244a69d9168Sdrh   if( pTab==0 )  goto delete_from_cleanup;
245b7f9164eSdrh 
246b7f9164eSdrh   /* Figure out if we have any triggers and if the table being
247b7f9164eSdrh   ** deleted from is a view
248b7f9164eSdrh   */
249b7f9164eSdrh #ifndef SQLITE_OMIT_TRIGGER
2502f886d1dSdanielk1977   pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
2515cf590c1Sdrh   isView = pTab->pSelect!=0;
252b7f9164eSdrh #else
2532f886d1dSdanielk1977 # define pTrigger 0
254b7f9164eSdrh # define isView 0
255b7f9164eSdrh #endif
256b7f9164eSdrh #ifdef SQLITE_OMIT_VIEW
257b7f9164eSdrh # undef isView
258b7f9164eSdrh # define isView 0
259b7f9164eSdrh #endif
260b7f9164eSdrh 
2612f886d1dSdanielk1977   if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){
2625cf590c1Sdrh     goto delete_from_cleanup;
263113088ecSdrh   }
264da184236Sdanielk1977   iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
265da184236Sdanielk1977   assert( iDb<db->nDb );
266da184236Sdanielk1977   zDb = db->aDb[iDb].zName;
26752bd7912Sdanielk1977   rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb);
26852bd7912Sdanielk1977   assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE );
26952bd7912Sdanielk1977   if( rcauth==SQLITE_DENY ){
270e5f9c644Sdrh     goto delete_from_cleanup;
271e5f9c644Sdrh   }
2722f886d1dSdanielk1977   assert(!isView || pTrigger);
273cce7d176Sdrh 
2745cf590c1Sdrh   /* If pTab is really a view, make sure it has been initialized.
2755cf590c1Sdrh   */
276b3d24bf8Sdanielk1977   if( sqlite3ViewGetColumnNames(pParse, pTab) ){
2775cf590c1Sdrh     goto delete_from_cleanup;
2785cf590c1Sdrh   }
2795cf590c1Sdrh 
280c977f7f5Sdrh   /* Allocate a cursor used to store the old.* data for a trigger.
281c977f7f5Sdrh   */
2822f886d1dSdanielk1977   if( pTrigger ){
283c3f9bad2Sdanielk1977     oldIdx = pParse->nTab++;
284f29ce559Sdanielk1977   }
285c3f9bad2Sdanielk1977 
2860f35a6b5Sdrh   /* Assign  cursor number to the table and all its indices.
287cce7d176Sdrh   */
2886a3ea0e6Sdrh   assert( pTabList->nSrc==1 );
2896a3ea0e6Sdrh   iCur = pTabList->a[0].iCursor = pParse->nTab++;
290e448dc4aSdanielk1977   for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
291e448dc4aSdanielk1977     pParse->nTab++;
292e448dc4aSdanielk1977   }
293cce7d176Sdrh 
29485e2096fSdrh   /* Start the view context
29585e2096fSdrh   */
29685e2096fSdrh   if( isView ){
2974adee20fSdanielk1977     sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
29885e2096fSdrh   }
29985e2096fSdrh 
300cce7d176Sdrh   /* Begin generating code.
301cce7d176Sdrh   */
3024adee20fSdanielk1977   v = sqlite3GetVdbe(pParse);
303f29ce559Sdanielk1977   if( v==0 ){
304f29ce559Sdanielk1977     goto delete_from_cleanup;
305f29ce559Sdanielk1977   }
3064794f735Sdrh   if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
3072f886d1dSdanielk1977   sqlite3BeginWriteOperation(pParse, (pTrigger?1:0), iDb);
3085e00f6c7Sdrh 
3092f886d1dSdanielk1977   if( pTrigger ){
310dd2fb29bSdanielk1977     int orconf = ((pParse->trigStack)?pParse->trigStack->orconf:OE_Default);
31166a5167bSdrh     int iGoto = sqlite3VdbeAddOp0(v, OP_Goto);
3128f2c54e6Sdanielk1977     addr = sqlite3VdbeMakeLabel(v);
313dd2fb29bSdanielk1977 
3148f2c54e6Sdanielk1977     iBeginBeforeTrigger = sqlite3VdbeCurrentAddr(v);
3152f886d1dSdanielk1977     (void)sqlite3CodeRowTrigger(pParse, pTrigger, TK_DELETE, 0,
3162f886d1dSdanielk1977         TRIGGER_BEFORE, pTab, -1, oldIdx, orconf, addr, &old_col_mask, 0);
31766a5167bSdrh     iEndBeforeTrigger = sqlite3VdbeAddOp0(v, OP_Goto);
318dd2fb29bSdanielk1977 
3198f2c54e6Sdanielk1977     iBeginAfterTrigger = sqlite3VdbeCurrentAddr(v);
3202f886d1dSdanielk1977     (void)sqlite3CodeRowTrigger(pParse, pTrigger, TK_DELETE, 0,
3212f886d1dSdanielk1977         TRIGGER_AFTER, pTab, -1, oldIdx, orconf, addr, &old_col_mask, 0);
32266a5167bSdrh     iEndAfterTrigger = sqlite3VdbeAddOp0(v, OP_Goto);
323dd2fb29bSdanielk1977 
3248f2c54e6Sdanielk1977     sqlite3VdbeJumpHere(v, iGoto);
3258f2c54e6Sdanielk1977   }
3268f2c54e6Sdanielk1977 
3279d2985c7Sdrh   /* If we are trying to delete from a view, realize that view into
3289d2985c7Sdrh   ** a ephemeral table.
3295cf590c1Sdrh   */
330fa4e62f3Sshane #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
3315cf590c1Sdrh   if( isView ){
3322a5d825eSdrh     sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
3330f35a6b5Sdrh   }
334fa4e62f3Sshane #endif
3351013c932Sdrh 
3360f35a6b5Sdrh   /* Resolve the column names in the WHERE clause.
3370f35a6b5Sdrh   */
3380f35a6b5Sdrh   memset(&sNC, 0, sizeof(sNC));
3390f35a6b5Sdrh   sNC.pParse = pParse;
3400f35a6b5Sdrh   sNC.pSrcList = pTabList;
3417d10d5a6Sdrh   if( sqlite3ResolveExprNames(&sNC, pWhere) ){
3420f35a6b5Sdrh     goto delete_from_cleanup;
3435cf590c1Sdrh   }
3445cf590c1Sdrh 
3451bee3d7bSdrh   /* Initialize the counter of the number of rows deleted, if
3461bee3d7bSdrh   ** we are counting rows.
3471bee3d7bSdrh   */
3481bee3d7bSdrh   if( db->flags & SQLITE_CountRows ){
3490a07c107Sdrh     memCnt = ++pParse->nMem;
3504c583128Sdrh     sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt);
3511bee3d7bSdrh   }
352cce7d176Sdrh 
353f8cecdabSdrh #ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
3540353ceddSdrh   /* Special case: A DELETE without a WHERE clause deletes everything.
355c977f7f5Sdrh   ** It is easier just to erase the whole table.  Note, however, that
356c977f7f5Sdrh   ** this means that the row change count will be incorrect.
3570353ceddSdrh   */
3582f886d1dSdanielk1977   if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) ){
3599a02fb44Sdanielk1977     assert( !isView );
360*bbb5e4e0Sdrh     sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
361*bbb5e4e0Sdrh                       pTab->zName, P4_STATIC);
3620353ceddSdrh     for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
363da184236Sdanielk1977       assert( pIdx->pSchema==pTab->pSchema );
36466a5167bSdrh       sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
3650353ceddSdrh     }
366f8cecdabSdrh   }else
367f8cecdabSdrh #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
3680353ceddSdrh   /* The usual case: There is a WHERE clause so we have to scan through
3698bc03a7aSjplyon   ** the table and pick which records to delete.
3700353ceddSdrh   */
371f8cecdabSdrh   {
372dd2fb29bSdanielk1977     int iRowid = ++pParse->nMem;    /* Used for storing rowid values. */
3733d4501e5Sdrh     int iRowSet = ++pParse->nMem;   /* Register for rowset of rows to delete */
374336a5300Sdrh     int regRowid;                   /* Actual register containing rowids */
37596cb76fcSdanielk1977 
37623d04d5aSdrh     /* Collect rowids of every row to be deleted.
377299b187dSdanielk1977     */
37823d04d5aSdrh     sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
379336a5300Sdrh     pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK);
380299b187dSdanielk1977     if( pWInfo==0 ) goto delete_from_cleanup;
381336a5300Sdrh     regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0);
382336a5300Sdrh     sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
383299b187dSdanielk1977     if( db->flags & SQLITE_CountRows ){
3848558cde1Sdrh       sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
385299b187dSdanielk1977     }
386299b187dSdanielk1977     sqlite3WhereEnd(pWInfo);
387299b187dSdanielk1977 
38870ce3f0cSdrh     /* Open the pseudo-table used to store OLD if there are triggers.
38970ce3f0cSdrh     */
3902f886d1dSdanielk1977     if( pTrigger ){
391d336e222Sdanielk1977       sqlite3VdbeAddOp3(v, OP_OpenPseudo, oldIdx, 0, pTab->nCol);
39270ce3f0cSdrh     }
39370ce3f0cSdrh 
394299b187dSdanielk1977     /* Delete every item whose key was written to the list during the
395299b187dSdanielk1977     ** database scan.  We have to delete items after the scan is complete
396299b187dSdanielk1977     ** because deleting an item can change the scan order.
397ed326d70Sdanielk1977     */
398299b187dSdanielk1977     end = sqlite3VdbeMakeLabel(v);
399ed326d70Sdanielk1977 
400e448dc4aSdanielk1977     if( !isView ){
401e448dc4aSdanielk1977       /* Open cursors for the table we are deleting from and
402e448dc4aSdanielk1977       ** all its indices.
403e448dc4aSdanielk1977       */
404e448dc4aSdanielk1977       sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
405e448dc4aSdanielk1977     }
406e448dc4aSdanielk1977 
407e448dc4aSdanielk1977     /* This is the beginning of the delete loop. If a trigger encounters
408e448dc4aSdanielk1977     ** an IGNORE constraint, it jumps back to here.
409c977f7f5Sdrh     */
4102f886d1dSdanielk1977     if( pTrigger ){
4118f2c54e6Sdanielk1977       sqlite3VdbeResolveLabel(v, addr);
412e448dc4aSdanielk1977     }
4133d4501e5Sdrh     addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);
414e448dc4aSdanielk1977 
4152f886d1dSdanielk1977     if( pTrigger ){
41696cb76fcSdanielk1977       int iData = ++pParse->nMem;   /* For storing row data of OLD table */
41796cb76fcSdanielk1977 
41896cb76fcSdanielk1977       /* If the record is no longer present in the table, jump to the
41996cb76fcSdanielk1977       ** next iteration of the loop through the contents of the fifo.
42096cb76fcSdanielk1977       */
42196cb76fcSdanielk1977       sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid);
42296cb76fcSdanielk1977 
42396cb76fcSdanielk1977       /* Populate the OLD.* pseudo-table */
4248f2c54e6Sdanielk1977       if( old_col_mask ){
42598757157Sdrh         sqlite3VdbeAddOp2(v, OP_RowData, iCur, iData);
4268f2c54e6Sdanielk1977       }else{
4274c583128Sdrh         sqlite3VdbeAddOp2(v, OP_Null, 0, iData);
4288f2c54e6Sdanielk1977       }
42996cb76fcSdanielk1977       sqlite3VdbeAddOp3(v, OP_Insert, oldIdx, iData, iRowid);
430299b187dSdanielk1977 
4318f2c54e6Sdanielk1977       /* Jump back and run the BEFORE triggers */
43266a5167bSdrh       sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger);
4338f2c54e6Sdanielk1977       sqlite3VdbeJumpHere(v, iEndBeforeTrigger);
434c3f9bad2Sdanielk1977     }
435c3f9bad2Sdanielk1977 
436299b187dSdanielk1977     if( !isView ){
437299b187dSdanielk1977       /* Delete the row */
4384cbdda9eSdrh #ifndef SQLITE_OMIT_VIRTUALTABLE
4394cbdda9eSdrh       if( IsVirtual(pTab) ){
44096cb76fcSdanielk1977         const char *pVtab = (const char *)pTab->pVtab;
4414f3dd150Sdrh         sqlite3VtabMakeWritable(pParse, pTab);
44296cb76fcSdanielk1977         sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVtab, P4_VTAB);
4434cbdda9eSdrh       }else
4444cbdda9eSdrh #endif
4454cbdda9eSdrh       {
4462d401ab8Sdrh         sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, pParse->nested==0);
447299b187dSdanielk1977       }
4484cbdda9eSdrh     }
449299b187dSdanielk1977 
450299b187dSdanielk1977     /* If there are row triggers, close all cursors then invoke
451299b187dSdanielk1977     ** the AFTER triggers
452299b187dSdanielk1977     */
4532f886d1dSdanielk1977     if( pTrigger ){
4548f2c54e6Sdanielk1977       /* Jump back and run the AFTER triggers */
45566a5167bSdrh       sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginAfterTrigger);
4568f2c54e6Sdanielk1977       sqlite3VdbeJumpHere(v, iEndAfterTrigger);
457c3f9bad2Sdanielk1977     }
458c3f9bad2Sdanielk1977 
459299b187dSdanielk1977     /* End of the delete loop */
46066a5167bSdrh     sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
461299b187dSdanielk1977     sqlite3VdbeResolveLabel(v, end);
462299b187dSdanielk1977 
463299b187dSdanielk1977     /* Close the cursors after the loop if there are no row triggers */
464e448dc4aSdanielk1977     if( !isView  && !IsVirtual(pTab) ){
465c3f9bad2Sdanielk1977       for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
46666a5167bSdrh         sqlite3VdbeAddOp2(v, OP_Close, iCur + i, pIdx->tnum);
467c3f9bad2Sdanielk1977       }
46866a5167bSdrh       sqlite3VdbeAddOp1(v, OP_Close, iCur);
469299b187dSdanielk1977     }
4700353ceddSdrh   }
4715e00f6c7Sdrh 
4721bee3d7bSdrh   /*
473e7de6f25Sdanielk1977   ** Return the number of rows that were deleted. If this routine is
474e7de6f25Sdanielk1977   ** generating code because of a call to sqlite3NestedParse(), do not
475e7de6f25Sdanielk1977   ** invoke the callback function.
4761bee3d7bSdrh   */
477cc6bd383Sdanielk1977   if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
47866a5167bSdrh     sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1);
47922322fd4Sdanielk1977     sqlite3VdbeSetNumCols(v, 1);
48010fb749bSdanielk1977     sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC);
4811bee3d7bSdrh   }
482cce7d176Sdrh 
483cce7d176Sdrh delete_from_cleanup:
4844adee20fSdanielk1977   sqlite3AuthContextPop(&sContext);
485633e6d57Sdrh   sqlite3SrcListDelete(db, pTabList);
486633e6d57Sdrh   sqlite3ExprDelete(db, pWhere);
487cce7d176Sdrh   return;
488cce7d176Sdrh }
4899cfcf5d4Sdrh 
4909cfcf5d4Sdrh /*
4919cfcf5d4Sdrh ** This routine generates VDBE code that causes a single row of a
4929cfcf5d4Sdrh ** single table to be deleted.
4939cfcf5d4Sdrh **
4949cfcf5d4Sdrh ** The VDBE must be in a particular state when this routine is called.
4959cfcf5d4Sdrh ** These are the requirements:
4969cfcf5d4Sdrh **
4979cfcf5d4Sdrh **   1.  A read/write cursor pointing to pTab, the table containing the row
4989cfcf5d4Sdrh **       to be deleted, must be opened as cursor number "base".
4999cfcf5d4Sdrh **
5009cfcf5d4Sdrh **   2.  Read/write cursors for all indices of pTab must be open as
5019cfcf5d4Sdrh **       cursor number base+i for the i-th index.
5029cfcf5d4Sdrh **
50396cb76fcSdanielk1977 **   3.  The record number of the row to be deleted must be stored in
50496cb76fcSdanielk1977 **       memory cell iRowid.
5059cfcf5d4Sdrh **
5069cfcf5d4Sdrh ** This routine pops the top of the stack to remove the record number
5079cfcf5d4Sdrh ** and then generates code to remove both the table record and all index
5089cfcf5d4Sdrh ** entries that point to that record.
5099cfcf5d4Sdrh */
5104adee20fSdanielk1977 void sqlite3GenerateRowDelete(
5112d401ab8Sdrh   Parse *pParse,     /* Parsing context */
5129cfcf5d4Sdrh   Table *pTab,       /* Table containing the row to be deleted */
5136a3ea0e6Sdrh   int iCur,          /* Cursor number for the table */
51496cb76fcSdanielk1977   int iRowid,        /* Memory cell that contains the rowid to delete */
515c8d30ac1Sdrh   int count          /* Increment the row change counter */
5169cfcf5d4Sdrh ){
51707d6e3a7Sdrh   int addr;
5182d401ab8Sdrh   Vdbe *v;
5192d401ab8Sdrh 
5202d401ab8Sdrh   v = pParse->pVdbe;
52196cb76fcSdanielk1977   addr = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowid);
5222d401ab8Sdrh   sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0);
52366a5167bSdrh   sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
52494eb6a14Sdanielk1977   if( count ){
52566a5167bSdrh     sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
52694eb6a14Sdanielk1977   }
527d654be80Sdrh   sqlite3VdbeJumpHere(v, addr);
5280ca3e24bSdrh }
5290ca3e24bSdrh 
5300ca3e24bSdrh /*
5310ca3e24bSdrh ** This routine generates VDBE code that causes the deletion of all
5320ca3e24bSdrh ** index entries associated with a single row of a single table.
5330ca3e24bSdrh **
5340ca3e24bSdrh ** The VDBE must be in a particular state when this routine is called.
5350ca3e24bSdrh ** These are the requirements:
5360ca3e24bSdrh **
5370ca3e24bSdrh **   1.  A read/write cursor pointing to pTab, the table containing the row
5386a3ea0e6Sdrh **       to be deleted, must be opened as cursor number "iCur".
5390ca3e24bSdrh **
5400ca3e24bSdrh **   2.  Read/write cursors for all indices of pTab must be open as
5416a3ea0e6Sdrh **       cursor number iCur+i for the i-th index.
5420ca3e24bSdrh **
5436a3ea0e6Sdrh **   3.  The "iCur" cursor must be pointing to the row that is to be
5440ca3e24bSdrh **       deleted.
5450ca3e24bSdrh */
5464adee20fSdanielk1977 void sqlite3GenerateRowIndexDelete(
5472d401ab8Sdrh   Parse *pParse,     /* Parsing and code generating context */
5480ca3e24bSdrh   Table *pTab,       /* Table containing the row to be deleted */
5496a3ea0e6Sdrh   int iCur,          /* Cursor number for the table */
550aa9b8963Sdrh   int *aRegIdx       /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
5510ca3e24bSdrh ){
5529cfcf5d4Sdrh   int i;
5539cfcf5d4Sdrh   Index *pIdx;
5549cbf3425Sdrh   int r1;
5559cfcf5d4Sdrh 
5569cfcf5d4Sdrh   for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
557aa9b8963Sdrh     if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
5583a200e0aSdrh     r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0);
559e14006d0Sdrh     sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1);
56051846b56Sdrh   }
56151846b56Sdrh }
56251846b56Sdrh 
56351846b56Sdrh /*
564e14006d0Sdrh ** Generate code that will assemble an index key and put it in register
565e14006d0Sdrh ** regOut.  The key with be for index pIdx which is an index on pTab.
56651846b56Sdrh ** iCur is the index of a cursor open on the pTab table and pointing to
56751846b56Sdrh ** the entry that needs indexing.
5682d401ab8Sdrh **
5692d401ab8Sdrh ** Return a register number which is the first in a block of
5702d401ab8Sdrh ** registers that holds the elements of the index key.  The
5712d401ab8Sdrh ** block of registers has already been deallocated by the time
5722d401ab8Sdrh ** this routine returns.
57351846b56Sdrh */
5742d401ab8Sdrh int sqlite3GenerateIndexKey(
5752d401ab8Sdrh   Parse *pParse,     /* Parsing context */
57651846b56Sdrh   Index *pIdx,       /* The index for which to generate a key */
5772d401ab8Sdrh   int iCur,          /* Cursor number for the pIdx->pTable table */
578e14006d0Sdrh   int regOut,        /* Write the new index key to this register */
579e14006d0Sdrh   int doMakeRec      /* Run the OP_MakeRecord instruction if true */
58051846b56Sdrh ){
5812d401ab8Sdrh   Vdbe *v = pParse->pVdbe;
58251846b56Sdrh   int j;
58351846b56Sdrh   Table *pTab = pIdx->pTable;
5842d401ab8Sdrh   int regBase;
5852d401ab8Sdrh   int nCol;
58651846b56Sdrh 
5872d401ab8Sdrh   nCol = pIdx->nColumn;
5882d401ab8Sdrh   regBase = sqlite3GetTempRange(pParse, nCol+1);
5892d401ab8Sdrh   sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol);
5902d401ab8Sdrh   for(j=0; j<nCol; j++){
5919cfcf5d4Sdrh     int idx = pIdx->aiColumn[j];
5929cfcf5d4Sdrh     if( idx==pTab->iPKey ){
5932d401ab8Sdrh       sqlite3VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j);
5949cfcf5d4Sdrh     }else{
5952d401ab8Sdrh       sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
596aee18ef8Sdanielk1977       sqlite3ColumnDefault(v, pTab, idx);
5979cfcf5d4Sdrh     }
5989cfcf5d4Sdrh   }
599e14006d0Sdrh   if( doMakeRec ){
6001db639ceSdrh     sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
601a37cdde0Sdanielk1977     sqlite3IndexAffinityStr(v, pIdx);
602da250ea5Sdrh     sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1);
603e14006d0Sdrh   }
6042d401ab8Sdrh   sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
6052d401ab8Sdrh   return regBase;
6069cfcf5d4Sdrh }
607f39d9588Sdrh 
608f39d9588Sdrh /* Make sure "isView" gets undefined in case this file becomes part of
609f39d9588Sdrh ** the amalgamation - so that subsequent files do not see isView as a
610f39d9588Sdrh ** macro. */
611f39d9588Sdrh #undef isView
612