Mercurial > audlegacy
comparison sqlite/delete.c @ 1434:b6b61becdf4e trunk
[svn] - add sqlite/ directory
| author | nenolod |
|---|---|
| date | Thu, 27 Jul 2006 22:41:31 -0700 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1433:3cbe3d14ea68 | 1434:b6b61becdf4e |
|---|---|
| 1 /* | |
| 2 ** 2001 September 15 | |
| 3 ** | |
| 4 ** The author disclaims copyright to this source code. In place of | |
| 5 ** a legal notice, here is a blessing: | |
| 6 ** | |
| 7 ** May you do good and not evil. | |
| 8 ** May you find forgiveness for yourself and forgive others. | |
| 9 ** May you share freely, never taking more than you give. | |
| 10 ** | |
| 11 ************************************************************************* | |
| 12 ** This file contains C code routines that are called by the parser | |
| 13 ** in order to generate code for DELETE FROM statements. | |
| 14 ** | |
| 15 ** $Id: delete.c,v 1.122 2006/02/24 02:53:50 drh Exp $ | |
| 16 */ | |
| 17 #include "sqliteInt.h" | |
| 18 | |
| 19 /* | |
| 20 ** Look up every table that is named in pSrc. If any table is not found, | |
| 21 ** add an error message to pParse->zErrMsg and return NULL. If all tables | |
| 22 ** are found, return a pointer to the last table. | |
| 23 */ | |
| 24 Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ | |
| 25 Table *pTab = 0; | |
| 26 int i; | |
| 27 struct SrcList_item *pItem; | |
| 28 for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){ | |
| 29 pTab = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase); | |
| 30 sqlite3DeleteTable(pParse->db, pItem->pTab); | |
| 31 pItem->pTab = pTab; | |
| 32 if( pTab ){ | |
| 33 pTab->nRef++; | |
| 34 } | |
| 35 } | |
| 36 return pTab; | |
| 37 } | |
| 38 | |
| 39 /* | |
| 40 ** Check to make sure the given table is writable. If it is not | |
| 41 ** writable, generate an error message and return 1. If it is | |
| 42 ** writable return 0; | |
| 43 */ | |
| 44 int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ | |
| 45 if( pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0 | |
| 46 && pParse->nested==0 ){ | |
| 47 sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); | |
| 48 return 1; | |
| 49 } | |
| 50 #ifndef SQLITE_OMIT_VIEW | |
| 51 if( !viewOk && pTab->pSelect ){ | |
| 52 sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); | |
| 53 return 1; | |
| 54 } | |
| 55 #endif | |
| 56 return 0; | |
| 57 } | |
| 58 | |
| 59 /* | |
| 60 ** Generate code that will open a table for reading. | |
| 61 */ | |
| 62 void sqlite3OpenTable( | |
| 63 Parse *p, /* Generate code into this VDBE */ | |
| 64 int iCur, /* The cursor number of the table */ | |
| 65 int iDb, /* The database index in sqlite3.aDb[] */ | |
| 66 Table *pTab, /* The table to be opened */ | |
| 67 int opcode /* OP_OpenRead or OP_OpenWrite */ | |
| 68 ){ | |
| 69 Vdbe *v = sqlite3GetVdbe(p); | |
| 70 assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); | |
| 71 sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName); | |
| 72 sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); | |
| 73 VdbeComment((v, "# %s", pTab->zName)); | |
| 74 sqlite3VdbeAddOp(v, opcode, iCur, pTab->tnum); | |
| 75 sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol); | |
| 76 } | |
| 77 | |
| 78 | |
| 79 /* | |
| 80 ** Generate code for a DELETE FROM statement. | |
| 81 ** | |
| 82 ** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL; | |
| 83 ** \________/ \________________/ | |
| 84 ** pTabList pWhere | |
| 85 */ | |
| 86 void sqlite3DeleteFrom( | |
| 87 Parse *pParse, /* The parser context */ | |
| 88 SrcList *pTabList, /* The table from which we should delete things */ | |
| 89 Expr *pWhere /* The WHERE clause. May be null */ | |
| 90 ){ | |
| 91 Vdbe *v; /* The virtual database engine */ | |
| 92 Table *pTab; /* The table from which records will be deleted */ | |
| 93 const char *zDb; /* Name of database holding pTab */ | |
| 94 int end, addr = 0; /* A couple addresses of generated code */ | |
| 95 int i; /* Loop counter */ | |
| 96 WhereInfo *pWInfo; /* Information about the WHERE clause */ | |
| 97 Index *pIdx; /* For looping over indices of the table */ | |
| 98 int iCur; /* VDBE Cursor number for pTab */ | |
| 99 sqlite3 *db; /* Main database structure */ | |
| 100 AuthContext sContext; /* Authorization context */ | |
| 101 int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */ | |
| 102 NameContext sNC; /* Name context to resolve expressions in */ | |
| 103 int iDb; | |
| 104 | |
| 105 #ifndef SQLITE_OMIT_TRIGGER | |
| 106 int isView; /* True if attempting to delete from a view */ | |
| 107 int triggers_exist = 0; /* True if any triggers exist */ | |
| 108 #endif | |
| 109 | |
| 110 sContext.pParse = 0; | |
| 111 if( pParse->nErr || sqlite3MallocFailed() ){ | |
| 112 goto delete_from_cleanup; | |
| 113 } | |
| 114 db = pParse->db; | |
| 115 assert( pTabList->nSrc==1 ); | |
| 116 | |
| 117 /* Locate the table which we want to delete. This table has to be | |
| 118 ** put in an SrcList structure because some of the subroutines we | |
| 119 ** will be calling are designed to work with multiple tables and expect | |
| 120 ** an SrcList* parameter instead of just a Table* parameter. | |
| 121 */ | |
| 122 pTab = sqlite3SrcListLookup(pParse, pTabList); | |
| 123 if( pTab==0 ) goto delete_from_cleanup; | |
| 124 | |
| 125 /* Figure out if we have any triggers and if the table being | |
| 126 ** deleted from is a view | |
| 127 */ | |
| 128 #ifndef SQLITE_OMIT_TRIGGER | |
| 129 triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0); | |
| 130 isView = pTab->pSelect!=0; | |
| 131 #else | |
| 132 # define triggers_exist 0 | |
| 133 # define isView 0 | |
| 134 #endif | |
| 135 #ifdef SQLITE_OMIT_VIEW | |
| 136 # undef isView | |
| 137 # define isView 0 | |
| 138 #endif | |
| 139 | |
| 140 if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ | |
| 141 goto delete_from_cleanup; | |
| 142 } | |
| 143 iDb = sqlite3SchemaToIndex(db, pTab->pSchema); | |
| 144 assert( iDb<db->nDb ); | |
| 145 zDb = db->aDb[iDb].zName; | |
| 146 if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ | |
| 147 goto delete_from_cleanup; | |
| 148 } | |
| 149 | |
| 150 /* If pTab is really a view, make sure it has been initialized. | |
| 151 */ | |
| 152 if( isView && sqlite3ViewGetColumnNames(pParse, pTab) ){ | |
| 153 goto delete_from_cleanup; | |
| 154 } | |
| 155 | |
| 156 /* Allocate a cursor used to store the old.* data for a trigger. | |
| 157 */ | |
| 158 if( triggers_exist ){ | |
| 159 oldIdx = pParse->nTab++; | |
| 160 } | |
| 161 | |
| 162 /* Resolve the column names in the WHERE clause. | |
| 163 */ | |
| 164 assert( pTabList->nSrc==1 ); | |
| 165 iCur = pTabList->a[0].iCursor = pParse->nTab++; | |
| 166 memset(&sNC, 0, sizeof(sNC)); | |
| 167 sNC.pParse = pParse; | |
| 168 sNC.pSrcList = pTabList; | |
| 169 if( sqlite3ExprResolveNames(&sNC, pWhere) ){ | |
| 170 goto delete_from_cleanup; | |
| 171 } | |
| 172 | |
| 173 /* Start the view context | |
| 174 */ | |
| 175 if( isView ){ | |
| 176 sqlite3AuthContextPush(pParse, &sContext, pTab->zName); | |
| 177 } | |
| 178 | |
| 179 /* Begin generating code. | |
| 180 */ | |
| 181 v = sqlite3GetVdbe(pParse); | |
| 182 if( v==0 ){ | |
| 183 goto delete_from_cleanup; | |
| 184 } | |
| 185 if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); | |
| 186 sqlite3BeginWriteOperation(pParse, triggers_exist, iDb); | |
| 187 | |
| 188 /* If we are trying to delete from a view, realize that view into | |
| 189 ** a ephemeral table. | |
| 190 */ | |
| 191 if( isView ){ | |
| 192 Select *pView = sqlite3SelectDup(pTab->pSelect); | |
| 193 sqlite3Select(pParse, pView, SRT_VirtualTab, iCur, 0, 0, 0, 0); | |
| 194 sqlite3SelectDelete(pView); | |
| 195 } | |
| 196 | |
| 197 /* Initialize the counter of the number of rows deleted, if | |
| 198 ** we are counting rows. | |
| 199 */ | |
| 200 if( db->flags & SQLITE_CountRows ){ | |
| 201 sqlite3VdbeAddOp(v, OP_Integer, 0, 0); | |
| 202 } | |
| 203 | |
| 204 /* Special case: A DELETE without a WHERE clause deletes everything. | |
| 205 ** It is easier just to erase the whole table. Note, however, that | |
| 206 ** this means that the row change count will be incorrect. | |
| 207 */ | |
| 208 if( pWhere==0 && !triggers_exist ){ | |
| 209 if( db->flags & SQLITE_CountRows ){ | |
| 210 /* If counting rows deleted, just count the total number of | |
| 211 ** entries in the table. */ | |
| 212 int endOfLoop = sqlite3VdbeMakeLabel(v); | |
| 213 int addr2; | |
| 214 if( !isView ){ | |
| 215 sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); | |
| 216 } | |
| 217 sqlite3VdbeAddOp(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2); | |
| 218 addr2 = sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); | |
| 219 sqlite3VdbeAddOp(v, OP_Next, iCur, addr2); | |
| 220 sqlite3VdbeResolveLabel(v, endOfLoop); | |
| 221 sqlite3VdbeAddOp(v, OP_Close, iCur, 0); | |
| 222 } | |
| 223 if( !isView ){ | |
| 224 sqlite3VdbeAddOp(v, OP_Clear, pTab->tnum, iDb); | |
| 225 if( !pParse->nested ){ | |
| 226 sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC); | |
| 227 } | |
| 228 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ | |
| 229 assert( pIdx->pSchema==pTab->pSchema ); | |
| 230 sqlite3VdbeAddOp(v, OP_Clear, pIdx->tnum, iDb); | |
| 231 } | |
| 232 } | |
| 233 } | |
| 234 | |
| 235 /* The usual case: There is a WHERE clause so we have to scan through | |
| 236 ** the table and pick which records to delete. | |
| 237 */ | |
| 238 else{ | |
| 239 /* Begin the database scan | |
| 240 */ | |
| 241 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0); | |
| 242 if( pWInfo==0 ) goto delete_from_cleanup; | |
| 243 | |
| 244 /* Remember the rowid of every item to be deleted. | |
| 245 */ | |
| 246 sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0); | |
| 247 sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0); | |
| 248 if( db->flags & SQLITE_CountRows ){ | |
| 249 sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); | |
| 250 } | |
| 251 | |
| 252 /* End the database scan loop. | |
| 253 */ | |
| 254 sqlite3WhereEnd(pWInfo); | |
| 255 | |
| 256 /* Open the pseudo-table used to store OLD if there are triggers. | |
| 257 */ | |
| 258 if( triggers_exist ){ | |
| 259 sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0); | |
| 260 sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol); | |
| 261 } | |
| 262 | |
| 263 /* Delete every item whose key was written to the list during the | |
| 264 ** database scan. We have to delete items after the scan is complete | |
| 265 ** because deleting an item can change the scan order. | |
| 266 */ | |
| 267 end = sqlite3VdbeMakeLabel(v); | |
| 268 | |
| 269 /* This is the beginning of the delete loop when there are | |
| 270 ** row triggers. | |
| 271 */ | |
| 272 if( triggers_exist ){ | |
| 273 addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end); | |
| 274 if( !isView ){ | |
| 275 sqlite3VdbeAddOp(v, OP_Dup, 0, 0); | |
| 276 sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); | |
| 277 } | |
| 278 sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0); | |
| 279 sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0); | |
| 280 sqlite3VdbeAddOp(v, OP_RowData, iCur, 0); | |
| 281 sqlite3VdbeAddOp(v, OP_Insert, oldIdx, 0); | |
| 282 if( !isView ){ | |
| 283 sqlite3VdbeAddOp(v, OP_Close, iCur, 0); | |
| 284 } | |
| 285 | |
| 286 (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab, | |
| 287 -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, | |
| 288 addr); | |
| 289 } | |
| 290 | |
| 291 if( !isView ){ | |
| 292 /* Open cursors for the table we are deleting from and all its | |
| 293 ** indices. If there are row triggers, this happens inside the | |
| 294 ** OP_FifoRead loop because the cursor have to all be closed | |
| 295 ** before the trigger fires. If there are no row triggers, the | |
| 296 ** cursors are opened only once on the outside the loop. | |
| 297 */ | |
| 298 sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite); | |
| 299 | |
| 300 /* This is the beginning of the delete loop when there are no | |
| 301 ** row triggers */ | |
| 302 if( !triggers_exist ){ | |
| 303 addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end); | |
| 304 } | |
| 305 | |
| 306 /* Delete the row */ | |
| 307 sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0); | |
| 308 } | |
| 309 | |
| 310 /* If there are row triggers, close all cursors then invoke | |
| 311 ** the AFTER triggers | |
| 312 */ | |
| 313 if( triggers_exist ){ | |
| 314 if( !isView ){ | |
| 315 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ | |
| 316 sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); | |
| 317 } | |
| 318 sqlite3VdbeAddOp(v, OP_Close, iCur, 0); | |
| 319 } | |
| 320 (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1, | |
| 321 oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, | |
| 322 addr); | |
| 323 } | |
| 324 | |
| 325 /* End of the delete loop */ | |
| 326 sqlite3VdbeAddOp(v, OP_Goto, 0, addr); | |
| 327 sqlite3VdbeResolveLabel(v, end); | |
| 328 | |
| 329 /* Close the cursors after the loop if there are no row triggers */ | |
| 330 if( !triggers_exist ){ | |
| 331 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ | |
| 332 sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); | |
| 333 } | |
| 334 sqlite3VdbeAddOp(v, OP_Close, iCur, 0); | |
| 335 } | |
| 336 } | |
| 337 | |
| 338 /* | |
| 339 ** Return the number of rows that were deleted. If this routine is | |
| 340 ** generating code because of a call to sqlite3NestedParse(), do not | |
| 341 ** invoke the callback function. | |
| 342 */ | |
| 343 if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ | |
| 344 sqlite3VdbeAddOp(v, OP_Callback, 1, 0); | |
| 345 sqlite3VdbeSetNumCols(v, 1); | |
| 346 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", P3_STATIC); | |
| 347 } | |
| 348 | |
| 349 delete_from_cleanup: | |
| 350 sqlite3AuthContextPop(&sContext); | |
| 351 sqlite3SrcListDelete(pTabList); | |
| 352 sqlite3ExprDelete(pWhere); | |
| 353 return; | |
| 354 } | |
| 355 | |
| 356 /* | |
| 357 ** This routine generates VDBE code that causes a single row of a | |
| 358 ** single table to be deleted. | |
| 359 ** | |
| 360 ** The VDBE must be in a particular state when this routine is called. | |
| 361 ** These are the requirements: | |
| 362 ** | |
| 363 ** 1. A read/write cursor pointing to pTab, the table containing the row | |
| 364 ** to be deleted, must be opened as cursor number "base". | |
| 365 ** | |
| 366 ** 2. Read/write cursors for all indices of pTab must be open as | |
| 367 ** cursor number base+i for the i-th index. | |
| 368 ** | |
| 369 ** 3. The record number of the row to be deleted must be on the top | |
| 370 ** of the stack. | |
| 371 ** | |
| 372 ** This routine pops the top of the stack to remove the record number | |
| 373 ** and then generates code to remove both the table record and all index | |
| 374 ** entries that point to that record. | |
| 375 */ | |
| 376 void sqlite3GenerateRowDelete( | |
| 377 sqlite3 *db, /* The database containing the index */ | |
| 378 Vdbe *v, /* Generate code into this VDBE */ | |
| 379 Table *pTab, /* Table containing the row to be deleted */ | |
| 380 int iCur, /* Cursor number for the table */ | |
| 381 int count /* Increment the row change counter */ | |
| 382 ){ | |
| 383 int addr; | |
| 384 addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0); | |
| 385 sqlite3GenerateRowIndexDelete(v, pTab, iCur, 0); | |
| 386 sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); | |
| 387 if( count ){ | |
| 388 sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC); | |
| 389 } | |
| 390 sqlite3VdbeJumpHere(v, addr); | |
| 391 } | |
| 392 | |
| 393 /* | |
| 394 ** This routine generates VDBE code that causes the deletion of all | |
| 395 ** index entries associated with a single row of a single table. | |
| 396 ** | |
| 397 ** The VDBE must be in a particular state when this routine is called. | |
| 398 ** These are the requirements: | |
| 399 ** | |
| 400 ** 1. A read/write cursor pointing to pTab, the table containing the row | |
| 401 ** to be deleted, must be opened as cursor number "iCur". | |
| 402 ** | |
| 403 ** 2. Read/write cursors for all indices of pTab must be open as | |
| 404 ** cursor number iCur+i for the i-th index. | |
| 405 ** | |
| 406 ** 3. The "iCur" cursor must be pointing to the row that is to be | |
| 407 ** deleted. | |
| 408 */ | |
| 409 void sqlite3GenerateRowIndexDelete( | |
| 410 Vdbe *v, /* Generate code into this VDBE */ | |
| 411 Table *pTab, /* Table containing the row to be deleted */ | |
| 412 int iCur, /* Cursor number for the table */ | |
| 413 char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */ | |
| 414 ){ | |
| 415 int i; | |
| 416 Index *pIdx; | |
| 417 | |
| 418 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ | |
| 419 if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue; | |
| 420 sqlite3GenerateIndexKey(v, pIdx, iCur); | |
| 421 sqlite3VdbeAddOp(v, OP_IdxDelete, iCur+i, 0); | |
| 422 } | |
| 423 } | |
| 424 | |
| 425 /* | |
| 426 ** Generate code that will assemble an index key and put it on the top | |
| 427 ** of the tack. The key with be for index pIdx which is an index on pTab. | |
| 428 ** iCur is the index of a cursor open on the pTab table and pointing to | |
| 429 ** the entry that needs indexing. | |
| 430 */ | |
| 431 void sqlite3GenerateIndexKey( | |
| 432 Vdbe *v, /* Generate code into this VDBE */ | |
| 433 Index *pIdx, /* The index for which to generate a key */ | |
| 434 int iCur /* Cursor number for the pIdx->pTable table */ | |
| 435 ){ | |
| 436 int j; | |
| 437 Table *pTab = pIdx->pTable; | |
| 438 | |
| 439 sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0); | |
| 440 for(j=0; j<pIdx->nColumn; j++){ | |
| 441 int idx = pIdx->aiColumn[j]; | |
| 442 if( idx==pTab->iPKey ){ | |
| 443 sqlite3VdbeAddOp(v, OP_Dup, j, 0); | |
| 444 }else{ | |
| 445 sqlite3VdbeAddOp(v, OP_Column, iCur, idx); | |
| 446 sqlite3ColumnDefault(v, pTab, idx); | |
| 447 } | |
| 448 } | |
| 449 sqlite3VdbeAddOp(v, OP_MakeIdxRec, pIdx->nColumn, 0); | |
| 450 sqlite3IndexAffinityStr(v, pIdx); | |
| 451 } |
