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