00001 /* 00002 ** 2001 September 15 00003 ** 00004 ** The author disclaims copyright to this source code. In place of 00005 ** a legal notice, here is a blessing: 00006 ** 00007 ** May you do good and not evil. 00008 ** May you find forgiveness for yourself and forgive others. 00009 ** May you share freely, never taking more than you give. 00010 ** 00011 ************************************************************************* 00012 ** This file contains C code routines that are called by the parser 00013 ** in order to generate code for DELETE FROM statements. 00014 ** 00015 ** $Id: delete.c,v 1.186 2008/10/31 10:53:23 danielk1977 Exp $ 00016 */ 00017 #include "sqliteInt.h" 00018 00019 /* 00020 ** Look up every table that is named in pSrc. If any table is not found, 00021 ** add an error message to pParse->zErrMsg and return NULL. If all tables 00022 ** are found, return a pointer to the last table. 00023 */ 00024 Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ 00025 struct SrcList_item *pItem = pSrc->a; 00026 Table *pTab; 00027 assert( pItem && pSrc->nSrc==1 ); 00028 pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase); 00029 sqlite3DeleteTable(pItem->pTab); 00030 pItem->pTab = pTab; 00031 if( pTab ){ 00032 pTab->nRef++; 00033 } 00034 if( sqlite3IndexedByLookup(pParse, pItem) ){ 00035 pTab = 0; 00036 } 00037 return pTab; 00038 } 00039 00040 /* 00041 ** Check to make sure the given table is writable. If it is not 00042 ** writable, generate an error message and return 1. If it is 00043 ** writable return 0; 00044 */ 00045 int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ 00046 if( ((pTab->tabFlags & TF_Readonly)!=0 00047 && (pParse->db->flags & SQLITE_WriteSchema)==0 00048 && pParse->nested==0) 00049 #ifndef SQLITE_OMIT_VIRTUALTABLE 00050 || (pTab->pMod && pTab->pMod->pModule->xUpdate==0) 00051 #endif 00052 ){ 00053 sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); 00054 return 1; 00055 } 00056 #ifndef SQLITE_OMIT_VIEW 00057 if( !viewOk && pTab->pSelect ){ 00058 sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); 00059 return 1; 00060 } 00061 #endif 00062 return 0; 00063 } 00064 00065 /* 00066 ** Generate code that will open a table for reading. 00067 */ 00068 void sqlite3OpenTable( 00069 Parse *p, /* Generate code into this VDBE */ 00070 int iCur, /* The cursor number of the table */ 00071 int iDb, /* The database index in sqlite3.aDb[] */ 00072 Table *pTab, /* The table to be opened */ 00073 int opcode /* OP_OpenRead or OP_OpenWrite */ 00074 ){ 00075 Vdbe *v; 00076 if( IsVirtual(pTab) ) return; 00077 v = sqlite3GetVdbe(p); 00078 assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); 00079 sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName); 00080 sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); 00081 sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb); 00082 VdbeComment((v, "%s", pTab->zName)); 00083 } 00084 00085 00086 #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) 00087 /* 00088 ** Evaluate a view and store its result in an ephemeral table. The 00089 ** pWhere argument is an optional WHERE clause that restricts the 00090 ** set of rows in the view that are to be added to the ephemeral table. 00091 */ 00092 void sqlite3MaterializeView( 00093 Parse *pParse, /* Parsing context */ 00094 Table *pView, /* View definition */ 00095 Expr *pWhere, /* Optional WHERE clause to be added */ 00096 int iCur /* Cursor number for ephemerial table */ 00097 ){ 00098 SelectDest dest; 00099 Select *pDup; 00100 sqlite3 *db = pParse->db; 00101 00102 pDup = sqlite3SelectDup(db, pView->pSelect); 00103 if( pWhere ){ 00104 SrcList *pFrom; 00105 Token viewName; 00106 00107 pWhere = sqlite3ExprDup(db, pWhere); 00108 viewName.z = (u8*)pView->zName; 00109 viewName.n = (unsigned int)strlen((const char*)viewName.z); 00110 pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &viewName, pDup, 0,0); 00111 pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0); 00112 } 00113 sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); 00114 sqlite3Select(pParse, pDup, &dest); 00115 sqlite3SelectDelete(db, pDup); 00116 } 00117 #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */ 00118 00119 #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) 00120 /* 00121 ** Generate an expression tree to implement the WHERE, ORDER BY, 00122 ** and LIMIT/OFFSET portion of DELETE and UPDATE statements. 00123 ** 00124 ** DELETE FROM table_wxyz WHERE a<5 ORDER BY a LIMIT 1; 00125 ** \__________________________/ 00126 ** pLimitWhere (pInClause) 00127 */ 00128 Expr *sqlite3LimitWhere( 00129 Parse *pParse, /* The parser context */ 00130 SrcList *pSrc, /* the FROM clause -- which tables to scan */ 00131 Expr *pWhere, /* The WHERE clause. May be null */ 00132 ExprList *pOrderBy, /* The ORDER BY clause. May be null */ 00133 Expr *pLimit, /* The LIMIT clause. May be null */ 00134 Expr *pOffset, /* The OFFSET clause. May be null */ 00135 char *zStmtType /* Either DELETE or UPDATE. For error messages. */ 00136 ){ 00137 Expr *pWhereRowid = NULL; /* WHERE rowid .. */ 00138 Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */ 00139 Expr *pSelectRowid = NULL; /* SELECT rowid ... */ 00140 ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */ 00141 SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */ 00142 Select *pSelect = NULL; /* Complete SELECT tree */ 00143 00144 /* Check that there isn't an ORDER BY without a LIMIT clause. 00145 */ 00146 if( pOrderBy && (pLimit == 0) ) { 00147 sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType); 00148 pParse->parseError = 1; 00149 goto limit_where_cleanup_2; 00150 } 00151 00152 /* We only need to generate a select expression if there 00153 ** is a limit/offset term to enforce. 00154 */ 00155 if( pLimit == 0 ) { 00156 /* if pLimit is null, pOffset will always be null as well. */ 00157 assert( pOffset == 0 ); 00158 return pWhere; 00159 } 00160 00161 /* Generate a select expression tree to enforce the limit/offset 00162 ** term for the DELETE or UPDATE statement. For example: 00163 ** DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 00164 ** becomes: 00165 ** DELETE FROM table_a WHERE rowid IN ( 00166 ** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 00167 ** ); 00168 */ 00169 00170 pSelectRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0); 00171 if( pSelectRowid == 0 ) goto limit_where_cleanup_2; 00172 pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid, 0); 00173 if( pEList == 0 ) goto limit_where_cleanup_2; 00174 00175 /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree 00176 ** and the SELECT subtree. */ 00177 pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc); 00178 if( pSelectSrc == 0 ) { 00179 sqlite3ExprListDelete(pParse->db, pEList); 00180 goto limit_where_cleanup_2; 00181 } 00182 00183 /* generate the SELECT expression tree. */ 00184 pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0,pOrderBy,0,pLimit,pOffset); 00185 if( pSelect == 0 ) return 0; 00186 00187 /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ 00188 pWhereRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0); 00189 if( pWhereRowid == 0 ) goto limit_where_cleanup_1; 00190 pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0); 00191 if( pInClause == 0 ) goto limit_where_cleanup_1; 00192 00193 pInClause->pSelect = pSelect; 00194 sqlite3ExprSetHeight(pParse, pInClause); 00195 return pInClause; 00196 00197 /* something went wrong. clean up anything allocated. */ 00198 limit_where_cleanup_1: 00199 sqlite3SelectDelete(pParse->db, pSelect); 00200 return 0; 00201 00202 limit_where_cleanup_2: 00203 sqlite3ExprDelete(pParse->db, pWhere); 00204 sqlite3ExprListDelete(pParse->db, pOrderBy); 00205 sqlite3ExprDelete(pParse->db, pLimit); 00206 sqlite3ExprDelete(pParse->db, pOffset); 00207 return 0; 00208 } 00209 #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */ 00210 00211 /* 00212 ** Generate code for a DELETE FROM statement. 00213 ** 00214 ** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL; 00215 ** \________/ \________________/ 00216 ** pTabList pWhere 00217 */ 00218 void sqlite3DeleteFrom( 00219 Parse *pParse, /* The parser context */ 00220 SrcList *pTabList, /* The table from which we should delete things */ 00221 Expr *pWhere /* The WHERE clause. May be null */ 00222 ){ 00223 Vdbe *v; /* The virtual database engine */ 00224 Table *pTab; /* The table from which records will be deleted */ 00225 const char *zDb; /* Name of database holding pTab */ 00226 int end, addr = 0; /* A couple addresses of generated code */ 00227 int i; /* Loop counter */ 00228 WhereInfo *pWInfo; /* Information about the WHERE clause */ 00229 Index *pIdx; /* For looping over indices of the table */ 00230 int iCur; /* VDBE Cursor number for pTab */ 00231 sqlite3 *db; /* Main database structure */ 00232 AuthContext sContext; /* Authorization context */ 00233 int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */ 00234 NameContext sNC; /* Name context to resolve expressions in */ 00235 int iDb; /* Database number */ 00236 int memCnt = -1; /* Memory cell used for change counting */ 00237 int rcauth; /* Value returned by authorization callback */ 00238 00239 #ifndef SQLITE_OMIT_TRIGGER 00240 int isView; /* True if attempting to delete from a view */ 00241 int triggers_exist = 0; /* True if any triggers exist */ 00242 #endif 00243 int iBeginAfterTrigger; /* Address of after trigger program */ 00244 int iEndAfterTrigger; /* Exit of after trigger program */ 00245 int iBeginBeforeTrigger; /* Address of before trigger program */ 00246 int iEndBeforeTrigger; /* Exit of before trigger program */ 00247 u32 old_col_mask = 0; /* Mask of OLD.* columns in use */ 00248 00249 sContext.pParse = 0; 00250 db = pParse->db; 00251 if( pParse->nErr || db->mallocFailed ){ 00252 goto delete_from_cleanup; 00253 } 00254 assert( pTabList->nSrc==1 ); 00255 00256 /* Locate the table which we want to delete. This table has to be 00257 ** put in an SrcList structure because some of the subroutines we 00258 ** will be calling are designed to work with multiple tables and expect 00259 ** an SrcList* parameter instead of just a Table* parameter. 00260 */ 00261 pTab = sqlite3SrcListLookup(pParse, pTabList); 00262 if( pTab==0 ) goto delete_from_cleanup; 00263 00264 /* Figure out if we have any triggers and if the table being 00265 ** deleted from is a view 00266 */ 00267 #ifndef SQLITE_OMIT_TRIGGER 00268 triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0); 00269 isView = pTab->pSelect!=0; 00270 #else 00271 # define triggers_exist 0 00272 # define isView 0 00273 #endif 00274 #ifdef SQLITE_OMIT_VIEW 00275 # undef isView 00276 # define isView 0 00277 #endif 00278 00279 if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ 00280 goto delete_from_cleanup; 00281 } 00282 iDb = sqlite3SchemaToIndex(db, pTab->pSchema); 00283 assert( iDb<db->nDb ); 00284 zDb = db->aDb[iDb].zName; 00285 rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb); 00286 assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); 00287 if( rcauth==SQLITE_DENY ){ 00288 goto delete_from_cleanup; 00289 } 00290 assert(!isView || triggers_exist); 00291 00292 /* If pTab is really a view, make sure it has been initialized. 00293 */ 00294 if( sqlite3ViewGetColumnNames(pParse, pTab) ){ 00295 goto delete_from_cleanup; 00296 } 00297 00298 /* Allocate a cursor used to store the old.* data for a trigger. 00299 */ 00300 if( triggers_exist ){ 00301 oldIdx = pParse->nTab++; 00302 } 00303 00304 /* Assign cursor number to the table and all its indices. 00305 */ 00306 assert( pTabList->nSrc==1 ); 00307 iCur = pTabList->a[0].iCursor = pParse->nTab++; 00308 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ 00309 pParse->nTab++; 00310 } 00311 00312 /* Start the view context 00313 */ 00314 if( isView ){ 00315 sqlite3AuthContextPush(pParse, &sContext, pTab->zName); 00316 } 00317 00318 /* Begin generating code. 00319 */ 00320 v = sqlite3GetVdbe(pParse); 00321 if( v==0 ){ 00322 goto delete_from_cleanup; 00323 } 00324 if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); 00325 sqlite3BeginWriteOperation(pParse, triggers_exist, iDb); 00326 00327 if( triggers_exist ){ 00328 int orconf = ((pParse->trigStack)?pParse->trigStack->orconf:OE_Default); 00329 int iGoto = sqlite3VdbeAddOp0(v, OP_Goto); 00330 addr = sqlite3VdbeMakeLabel(v); 00331 00332 iBeginBeforeTrigger = sqlite3VdbeCurrentAddr(v); 00333 (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab, 00334 -1, oldIdx, orconf, addr, &old_col_mask, 0); 00335 iEndBeforeTrigger = sqlite3VdbeAddOp0(v, OP_Goto); 00336 00337 iBeginAfterTrigger = sqlite3VdbeCurrentAddr(v); 00338 (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1, 00339 oldIdx, orconf, addr, &old_col_mask, 0); 00340 iEndAfterTrigger = sqlite3VdbeAddOp0(v, OP_Goto); 00341 00342 sqlite3VdbeJumpHere(v, iGoto); 00343 } 00344 00345 /* If we are trying to delete from a view, realize that view into 00346 ** a ephemeral table. 00347 */ 00348 #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) 00349 if( isView ){ 00350 sqlite3MaterializeView(pParse, pTab, pWhere, iCur); 00351 } 00352 #endif 00353 00354 /* Resolve the column names in the WHERE clause. 00355 */ 00356 memset(&sNC, 0, sizeof(sNC)); 00357 sNC.pParse = pParse; 00358 sNC.pSrcList = pTabList; 00359 if( sqlite3ResolveExprNames(&sNC, pWhere) ){ 00360 goto delete_from_cleanup; 00361 } 00362 00363 /* Initialize the counter of the number of rows deleted, if 00364 ** we are counting rows. 00365 */ 00366 if( db->flags & SQLITE_CountRows ){ 00367 memCnt = ++pParse->nMem; 00368 sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt); 00369 } 00370 00371 #ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION 00372 /* Special case: A DELETE without a WHERE clause deletes everything. 00373 ** It is easier just to erase the whole table. Note, however, that 00374 ** this means that the row change count will be incorrect. 00375 */ 00376 if( rcauth==SQLITE_OK && pWhere==0 && !triggers_exist && !IsVirtual(pTab) ){ 00377 assert( !isView ); 00378 sqlite3VdbeAddOp3(v, OP_Clear, pTab->tnum, iDb, memCnt); 00379 if( !pParse->nested ){ 00380 sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); 00381 } 00382 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ 00383 assert( pIdx->pSchema==pTab->pSchema ); 00384 sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); 00385 } 00386 }else 00387 #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ 00388 /* The usual case: There is a WHERE clause so we have to scan through 00389 ** the table and pick which records to delete. 00390 */ 00391 { 00392 int iRowid = ++pParse->nMem; /* Used for storing rowid values. */ 00393 00394 /* Begin the database scan 00395 */ 00396 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0); 00397 if( pWInfo==0 ) goto delete_from_cleanup; 00398 00399 /* Remember the rowid of every item to be deleted. 00400 */ 00401 sqlite3VdbeAddOp2(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, iRowid); 00402 sqlite3VdbeAddOp1(v, OP_FifoWrite, iRowid); 00403 if( db->flags & SQLITE_CountRows ){ 00404 sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); 00405 } 00406 00407 /* End the database scan loop. 00408 */ 00409 sqlite3WhereEnd(pWInfo); 00410 00411 /* Open the pseudo-table used to store OLD if there are triggers. 00412 */ 00413 if( triggers_exist ){ 00414 sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); 00415 sqlite3VdbeAddOp1(v, OP_OpenPseudo, oldIdx); 00416 } 00417 00418 /* Delete every item whose key was written to the list during the 00419 ** database scan. We have to delete items after the scan is complete 00420 ** because deleting an item can change the scan order. 00421 */ 00422 end = sqlite3VdbeMakeLabel(v); 00423 00424 if( !isView ){ 00425 /* Open cursors for the table we are deleting from and 00426 ** all its indices. 00427 */ 00428 sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite); 00429 } 00430 00431 /* This is the beginning of the delete loop. If a trigger encounters 00432 ** an IGNORE constraint, it jumps back to here. 00433 */ 00434 if( triggers_exist ){ 00435 sqlite3VdbeResolveLabel(v, addr); 00436 } 00437 addr = sqlite3VdbeAddOp2(v, OP_FifoRead, iRowid, end); 00438 00439 if( triggers_exist ){ 00440 int iData = ++pParse->nMem; /* For storing row data of OLD table */ 00441 00442 /* If the record is no longer present in the table, jump to the 00443 ** next iteration of the loop through the contents of the fifo. 00444 */ 00445 sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid); 00446 00447 /* Populate the OLD.* pseudo-table */ 00448 if( old_col_mask ){ 00449 sqlite3VdbeAddOp2(v, OP_RowData, iCur, iData); 00450 }else{ 00451 sqlite3VdbeAddOp2(v, OP_Null, 0, iData); 00452 } 00453 sqlite3VdbeAddOp3(v, OP_Insert, oldIdx, iData, iRowid); 00454 00455 /* Jump back and run the BEFORE triggers */ 00456 sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger); 00457 sqlite3VdbeJumpHere(v, iEndBeforeTrigger); 00458 } 00459 00460 if( !isView ){ 00461 /* Delete the row */ 00462 #ifndef SQLITE_OMIT_VIRTUALTABLE 00463 if( IsVirtual(pTab) ){ 00464 const char *pVtab = (const char *)pTab->pVtab; 00465 sqlite3VtabMakeWritable(pParse, pTab); 00466 sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVtab, P4_VTAB); 00467 }else 00468 #endif 00469 { 00470 sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, pParse->nested==0); 00471 } 00472 } 00473 00474 /* If there are row triggers, close all cursors then invoke 00475 ** the AFTER triggers 00476 */ 00477 if( triggers_exist ){ 00478 /* Jump back and run the AFTER triggers */ 00479 sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginAfterTrigger); 00480 sqlite3VdbeJumpHere(v, iEndAfterTrigger); 00481 } 00482 00483 /* End of the delete loop */ 00484 sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); 00485 sqlite3VdbeResolveLabel(v, end); 00486 00487 /* Close the cursors after the loop if there are no row triggers */ 00488 if( !isView && !IsVirtual(pTab) ){ 00489 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ 00490 sqlite3VdbeAddOp2(v, OP_Close, iCur + i, pIdx->tnum); 00491 } 00492 sqlite3VdbeAddOp1(v, OP_Close, iCur); 00493 } 00494 } 00495 00496 /* 00497 ** Return the number of rows that were deleted. If this routine is 00498 ** generating code because of a call to sqlite3NestedParse(), do not 00499 ** invoke the callback function. 00500 */ 00501 if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ 00502 sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1); 00503 sqlite3VdbeSetNumCols(v, 1); 00504 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC); 00505 } 00506 00507 delete_from_cleanup: 00508 sqlite3AuthContextPop(&sContext); 00509 sqlite3SrcListDelete(db, pTabList); 00510 sqlite3ExprDelete(db, pWhere); 00511 return; 00512 } 00513 00514 /* 00515 ** This routine generates VDBE code that causes a single row of a 00516 ** single table to be deleted. 00517 ** 00518 ** The VDBE must be in a particular state when this routine is called. 00519 ** These are the requirements: 00520 ** 00521 ** 1. A read/write cursor pointing to pTab, the table containing the row 00522 ** to be deleted, must be opened as cursor number "base". 00523 ** 00524 ** 2. Read/write cursors for all indices of pTab must be open as 00525 ** cursor number base+i for the i-th index. 00526 ** 00527 ** 3. The record number of the row to be deleted must be stored in 00528 ** memory cell iRowid. 00529 ** 00530 ** This routine pops the top of the stack to remove the record number 00531 ** and then generates code to remove both the table record and all index 00532 ** entries that point to that record. 00533 */ 00534 void sqlite3GenerateRowDelete( 00535 Parse *pParse, /* Parsing context */ 00536 Table *pTab, /* Table containing the row to be deleted */ 00537 int iCur, /* Cursor number for the table */ 00538 int iRowid, /* Memory cell that contains the rowid to delete */ 00539 int count /* Increment the row change counter */ 00540 ){ 00541 int addr; 00542 Vdbe *v; 00543 00544 v = pParse->pVdbe; 00545 addr = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowid); 00546 sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0); 00547 sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); 00548 if( count ){ 00549 sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); 00550 } 00551 sqlite3VdbeJumpHere(v, addr); 00552 } 00553 00554 /* 00555 ** This routine generates VDBE code that causes the deletion of all 00556 ** index entries associated with a single row of a single table. 00557 ** 00558 ** The VDBE must be in a particular state when this routine is called. 00559 ** These are the requirements: 00560 ** 00561 ** 1. A read/write cursor pointing to pTab, the table containing the row 00562 ** to be deleted, must be opened as cursor number "iCur". 00563 ** 00564 ** 2. Read/write cursors for all indices of pTab must be open as 00565 ** cursor number iCur+i for the i-th index. 00566 ** 00567 ** 3. The "iCur" cursor must be pointing to the row that is to be 00568 ** deleted. 00569 */ 00570 void sqlite3GenerateRowIndexDelete( 00571 Parse *pParse, /* Parsing and code generating context */ 00572 Table *pTab, /* Table containing the row to be deleted */ 00573 int iCur, /* Cursor number for the table */ 00574 int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */ 00575 ){ 00576 int i; 00577 Index *pIdx; 00578 int r1; 00579 00580 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ 00581 if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue; 00582 r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0); 00583 sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1); 00584 } 00585 } 00586 00587 /* 00588 ** Generate code that will assemble an index key and put it in register 00589 ** regOut. The key with be for index pIdx which is an index on pTab. 00590 ** iCur is the index of a cursor open on the pTab table and pointing to 00591 ** the entry that needs indexing. 00592 ** 00593 ** Return a register number which is the first in a block of 00594 ** registers that holds the elements of the index key. The 00595 ** block of registers has already been deallocated by the time 00596 ** this routine returns. 00597 */ 00598 int sqlite3GenerateIndexKey( 00599 Parse *pParse, /* Parsing context */ 00600 Index *pIdx, /* The index for which to generate a key */ 00601 int iCur, /* Cursor number for the pIdx->pTable table */ 00602 int regOut, /* Write the new index key to this register */ 00603 int doMakeRec /* Run the OP_MakeRecord instruction if true */ 00604 ){ 00605 Vdbe *v = pParse->pVdbe; 00606 int j; 00607 Table *pTab = pIdx->pTable; 00608 int regBase; 00609 int nCol; 00610 00611 nCol = pIdx->nColumn; 00612 regBase = sqlite3GetTempRange(pParse, nCol+1); 00613 sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol); 00614 for(j=0; j<nCol; j++){ 00615 int idx = pIdx->aiColumn[j]; 00616 if( idx==pTab->iPKey ){ 00617 sqlite3VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j); 00618 }else{ 00619 sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j); 00620 sqlite3ColumnDefault(v, pTab, idx); 00621 } 00622 } 00623 if( doMakeRec ){ 00624 sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut); 00625 sqlite3IndexAffinityStr(v, pIdx); 00626 sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1); 00627 } 00628 sqlite3ReleaseTempRange(pParse, regBase, nCol+1); 00629 return regBase; 00630 } 00631 00632 /* Make sure "isView" gets undefined in case this file becomes part of 00633 ** the amalgamation - so that subsequent files do not see isView as a 00634 ** macro. */ 00635 #undef isView
ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:52 2011 by Doxygen 1.6.1