Annotation of embedaddon/sqlite3/src/delete.c, revision 1.1
1.1 ! misho 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: #include "sqliteInt.h"
! 16:
! 17: /*
! 18: ** While a SrcList can in general represent multiple tables and subqueries
! 19: ** (as in the FROM clause of a SELECT statement) in this case it contains
! 20: ** the name of a single table, as one might find in an INSERT, DELETE,
! 21: ** or UPDATE statement. Look up that table in the symbol table and
! 22: ** return a pointer. Set an error message and return NULL if the table
! 23: ** name is not found or if any other error occurs.
! 24: **
! 25: ** The following fields are initialized appropriate in pSrc:
! 26: **
! 27: ** pSrc->a[0].pTab Pointer to the Table object
! 28: ** pSrc->a[0].pIndex Pointer to the INDEXED BY index, if there is one
! 29: **
! 30: */
! 31: Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
! 32: struct SrcList_item *pItem = pSrc->a;
! 33: Table *pTab;
! 34: assert( pItem && pSrc->nSrc==1 );
! 35: pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
! 36: sqlite3DeleteTable(pParse->db, pItem->pTab);
! 37: pItem->pTab = pTab;
! 38: if( pTab ){
! 39: pTab->nRef++;
! 40: }
! 41: if( sqlite3IndexedByLookup(pParse, pItem) ){
! 42: pTab = 0;
! 43: }
! 44: return pTab;
! 45: }
! 46:
! 47: /*
! 48: ** Check to make sure the given table is writable. If it is not
! 49: ** writable, generate an error message and return 1. If it is
! 50: ** writable return 0;
! 51: */
! 52: int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
! 53: /* A table is not writable under the following circumstances:
! 54: **
! 55: ** 1) It is a virtual table and no implementation of the xUpdate method
! 56: ** has been provided, or
! 57: ** 2) It is a system table (i.e. sqlite_master), this call is not
! 58: ** part of a nested parse and writable_schema pragma has not
! 59: ** been specified.
! 60: **
! 61: ** In either case leave an error message in pParse and return non-zero.
! 62: */
! 63: if( ( IsVirtual(pTab)
! 64: && sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 )
! 65: || ( (pTab->tabFlags & TF_Readonly)!=0
! 66: && (pParse->db->flags & SQLITE_WriteSchema)==0
! 67: && pParse->nested==0 )
! 68: ){
! 69: sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
! 70: return 1;
! 71: }
! 72:
! 73: #ifndef SQLITE_OMIT_VIEW
! 74: if( !viewOk && pTab->pSelect ){
! 75: sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
! 76: return 1;
! 77: }
! 78: #endif
! 79: return 0;
! 80: }
! 81:
! 82:
! 83: #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
! 84: /*
! 85: ** Evaluate a view and store its result in an ephemeral table. The
! 86: ** pWhere argument is an optional WHERE clause that restricts the
! 87: ** set of rows in the view that are to be added to the ephemeral table.
! 88: */
! 89: void sqlite3MaterializeView(
! 90: Parse *pParse, /* Parsing context */
! 91: Table *pView, /* View definition */
! 92: Expr *pWhere, /* Optional WHERE clause to be added */
! 93: int iCur /* Cursor number for ephemerial table */
! 94: ){
! 95: SelectDest dest;
! 96: Select *pDup;
! 97: sqlite3 *db = pParse->db;
! 98:
! 99: pDup = sqlite3SelectDup(db, pView->pSelect, 0);
! 100: if( pWhere ){
! 101: SrcList *pFrom;
! 102:
! 103: pWhere = sqlite3ExprDup(db, pWhere, 0);
! 104: pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
! 105: if( pFrom ){
! 106: assert( pFrom->nSrc==1 );
! 107: pFrom->a[0].zAlias = sqlite3DbStrDup(db, pView->zName);
! 108: pFrom->a[0].pSelect = pDup;
! 109: assert( pFrom->a[0].pOn==0 );
! 110: assert( pFrom->a[0].pUsing==0 );
! 111: }else{
! 112: sqlite3SelectDelete(db, pDup);
! 113: }
! 114: pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
! 115: }
! 116: sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
! 117: sqlite3Select(pParse, pDup, &dest);
! 118: sqlite3SelectDelete(db, pDup);
! 119: }
! 120: #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
! 121:
! 122: #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
! 123: /*
! 124: ** Generate an expression tree to implement the WHERE, ORDER BY,
! 125: ** and LIMIT/OFFSET portion of DELETE and UPDATE statements.
! 126: **
! 127: ** DELETE FROM table_wxyz WHERE a<5 ORDER BY a LIMIT 1;
! 128: ** \__________________________/
! 129: ** pLimitWhere (pInClause)
! 130: */
! 131: Expr *sqlite3LimitWhere(
! 132: Parse *pParse, /* The parser context */
! 133: SrcList *pSrc, /* the FROM clause -- which tables to scan */
! 134: Expr *pWhere, /* The WHERE clause. May be null */
! 135: ExprList *pOrderBy, /* The ORDER BY clause. May be null */
! 136: Expr *pLimit, /* The LIMIT clause. May be null */
! 137: Expr *pOffset, /* The OFFSET clause. May be null */
! 138: char *zStmtType /* Either DELETE or UPDATE. For error messages. */
! 139: ){
! 140: Expr *pWhereRowid = NULL; /* WHERE rowid .. */
! 141: Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */
! 142: Expr *pSelectRowid = NULL; /* SELECT rowid ... */
! 143: ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */
! 144: SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */
! 145: Select *pSelect = NULL; /* Complete SELECT tree */
! 146:
! 147: /* Check that there isn't an ORDER BY without a LIMIT clause.
! 148: */
! 149: if( pOrderBy && (pLimit == 0) ) {
! 150: sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType);
! 151: goto limit_where_cleanup_2;
! 152: }
! 153:
! 154: /* We only need to generate a select expression if there
! 155: ** is a limit/offset term to enforce.
! 156: */
! 157: if( pLimit == 0 ) {
! 158: /* if pLimit is null, pOffset will always be null as well. */
! 159: assert( pOffset == 0 );
! 160: return pWhere;
! 161: }
! 162:
! 163: /* Generate a select expression tree to enforce the limit/offset
! 164: ** term for the DELETE or UPDATE statement. For example:
! 165: ** DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
! 166: ** becomes:
! 167: ** DELETE FROM table_a WHERE rowid IN (
! 168: ** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
! 169: ** );
! 170: */
! 171:
! 172: pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
! 173: if( pSelectRowid == 0 ) goto limit_where_cleanup_2;
! 174: pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid);
! 175: if( pEList == 0 ) goto limit_where_cleanup_2;
! 176:
! 177: /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
! 178: ** and the SELECT subtree. */
! 179: pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0);
! 180: if( pSelectSrc == 0 ) {
! 181: sqlite3ExprListDelete(pParse->db, pEList);
! 182: goto limit_where_cleanup_2;
! 183: }
! 184:
! 185: /* generate the SELECT expression tree. */
! 186: pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0,
! 187: pOrderBy,0,pLimit,pOffset);
! 188: if( pSelect == 0 ) return 0;
! 189:
! 190: /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
! 191: pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
! 192: if( pWhereRowid == 0 ) goto limit_where_cleanup_1;
! 193: pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0);
! 194: if( pInClause == 0 ) goto limit_where_cleanup_1;
! 195:
! 196: pInClause->x.pSelect = pSelect;
! 197: pInClause->flags |= EP_xIsSelect;
! 198: sqlite3ExprSetHeight(pParse, pInClause);
! 199: return pInClause;
! 200:
! 201: /* something went wrong. clean up anything allocated. */
! 202: limit_where_cleanup_1:
! 203: sqlite3SelectDelete(pParse->db, pSelect);
! 204: return 0;
! 205:
! 206: limit_where_cleanup_2:
! 207: sqlite3ExprDelete(pParse->db, pWhere);
! 208: sqlite3ExprListDelete(pParse->db, pOrderBy);
! 209: sqlite3ExprDelete(pParse->db, pLimit);
! 210: sqlite3ExprDelete(pParse->db, pOffset);
! 211: return 0;
! 212: }
! 213: #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
! 214:
! 215: /*
! 216: ** Generate code for a DELETE FROM statement.
! 217: **
! 218: ** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
! 219: ** \________/ \________________/
! 220: ** pTabList pWhere
! 221: */
! 222: void sqlite3DeleteFrom(
! 223: Parse *pParse, /* The parser context */
! 224: SrcList *pTabList, /* The table from which we should delete things */
! 225: Expr *pWhere /* The WHERE clause. May be null */
! 226: ){
! 227: Vdbe *v; /* The virtual database engine */
! 228: Table *pTab; /* The table from which records will be deleted */
! 229: const char *zDb; /* Name of database holding pTab */
! 230: int end, addr = 0; /* A couple addresses of generated code */
! 231: int i; /* Loop counter */
! 232: WhereInfo *pWInfo; /* Information about the WHERE clause */
! 233: Index *pIdx; /* For looping over indices of the table */
! 234: int iCur; /* VDBE Cursor number for pTab */
! 235: sqlite3 *db; /* Main database structure */
! 236: AuthContext sContext; /* Authorization context */
! 237: NameContext sNC; /* Name context to resolve expressions in */
! 238: int iDb; /* Database number */
! 239: int memCnt = -1; /* Memory cell used for change counting */
! 240: int rcauth; /* Value returned by authorization callback */
! 241:
! 242: #ifndef SQLITE_OMIT_TRIGGER
! 243: int isView; /* True if attempting to delete from a view */
! 244: Trigger *pTrigger; /* List of table triggers, if required */
! 245: #endif
! 246:
! 247: memset(&sContext, 0, sizeof(sContext));
! 248: db = pParse->db;
! 249: if( pParse->nErr || db->mallocFailed ){
! 250: goto delete_from_cleanup;
! 251: }
! 252: assert( pTabList->nSrc==1 );
! 253:
! 254: /* Locate the table which we want to delete. This table has to be
! 255: ** put in an SrcList structure because some of the subroutines we
! 256: ** will be calling are designed to work with multiple tables and expect
! 257: ** an SrcList* parameter instead of just a Table* parameter.
! 258: */
! 259: pTab = sqlite3SrcListLookup(pParse, pTabList);
! 260: if( pTab==0 ) goto delete_from_cleanup;
! 261:
! 262: /* Figure out if we have any triggers and if the table being
! 263: ** deleted from is a view
! 264: */
! 265: #ifndef SQLITE_OMIT_TRIGGER
! 266: pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
! 267: isView = pTab->pSelect!=0;
! 268: #else
! 269: # define pTrigger 0
! 270: # define isView 0
! 271: #endif
! 272: #ifdef SQLITE_OMIT_VIEW
! 273: # undef isView
! 274: # define isView 0
! 275: #endif
! 276:
! 277: /* If pTab is really a view, make sure it has been initialized.
! 278: */
! 279: if( sqlite3ViewGetColumnNames(pParse, pTab) ){
! 280: goto delete_from_cleanup;
! 281: }
! 282:
! 283: if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){
! 284: goto delete_from_cleanup;
! 285: }
! 286: iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
! 287: assert( iDb<db->nDb );
! 288: zDb = db->aDb[iDb].zName;
! 289: rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb);
! 290: assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE );
! 291: if( rcauth==SQLITE_DENY ){
! 292: goto delete_from_cleanup;
! 293: }
! 294: assert(!isView || pTrigger);
! 295:
! 296: /* Assign cursor number to the table and all its indices.
! 297: */
! 298: assert( pTabList->nSrc==1 );
! 299: iCur = pTabList->a[0].iCursor = pParse->nTab++;
! 300: for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
! 301: pParse->nTab++;
! 302: }
! 303:
! 304: /* Start the view context
! 305: */
! 306: if( isView ){
! 307: sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
! 308: }
! 309:
! 310: /* Begin generating code.
! 311: */
! 312: v = sqlite3GetVdbe(pParse);
! 313: if( v==0 ){
! 314: goto delete_from_cleanup;
! 315: }
! 316: if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
! 317: sqlite3BeginWriteOperation(pParse, 1, iDb);
! 318:
! 319: /* If we are trying to delete from a view, realize that view into
! 320: ** a ephemeral table.
! 321: */
! 322: #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
! 323: if( isView ){
! 324: sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
! 325: }
! 326: #endif
! 327:
! 328: /* Resolve the column names in the WHERE clause.
! 329: */
! 330: memset(&sNC, 0, sizeof(sNC));
! 331: sNC.pParse = pParse;
! 332: sNC.pSrcList = pTabList;
! 333: if( sqlite3ResolveExprNames(&sNC, pWhere) ){
! 334: goto delete_from_cleanup;
! 335: }
! 336:
! 337: /* Initialize the counter of the number of rows deleted, if
! 338: ** we are counting rows.
! 339: */
! 340: if( db->flags & SQLITE_CountRows ){
! 341: memCnt = ++pParse->nMem;
! 342: sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt);
! 343: }
! 344:
! 345: #ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
! 346: /* Special case: A DELETE without a WHERE clause deletes everything.
! 347: ** It is easier just to erase the whole table. Prior to version 3.6.5,
! 348: ** this optimization caused the row change count (the value returned by
! 349: ** API function sqlite3_count_changes) to be set incorrectly. */
! 350: if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab)
! 351: && 0==sqlite3FkRequired(pParse, pTab, 0, 0)
! 352: ){
! 353: assert( !isView );
! 354: sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
! 355: pTab->zName, P4_STATIC);
! 356: for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
! 357: assert( pIdx->pSchema==pTab->pSchema );
! 358: sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
! 359: }
! 360: }else
! 361: #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
! 362: /* The usual case: There is a WHERE clause so we have to scan through
! 363: ** the table and pick which records to delete.
! 364: */
! 365: {
! 366: int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */
! 367: int iRowid = ++pParse->nMem; /* Used for storing rowid values. */
! 368: int regRowid; /* Actual register containing rowids */
! 369:
! 370: /* Collect rowids of every row to be deleted.
! 371: */
! 372: sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
! 373: pWInfo = sqlite3WhereBegin(
! 374: pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
! 375: );
! 376: if( pWInfo==0 ) goto delete_from_cleanup;
! 377: regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
! 378: sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
! 379: if( db->flags & SQLITE_CountRows ){
! 380: sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
! 381: }
! 382: sqlite3WhereEnd(pWInfo);
! 383:
! 384: /* Delete every item whose key was written to the list during the
! 385: ** database scan. We have to delete items after the scan is complete
! 386: ** because deleting an item can change the scan order. */
! 387: end = sqlite3VdbeMakeLabel(v);
! 388:
! 389: /* Unless this is a view, open cursors for the table we are
! 390: ** deleting from and all its indices. If this is a view, then the
! 391: ** only effect this statement has is to fire the INSTEAD OF
! 392: ** triggers. */
! 393: if( !isView ){
! 394: sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
! 395: }
! 396:
! 397: addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);
! 398:
! 399: /* Delete the row */
! 400: #ifndef SQLITE_OMIT_VIRTUALTABLE
! 401: if( IsVirtual(pTab) ){
! 402: const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
! 403: sqlite3VtabMakeWritable(pParse, pTab);
! 404: sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB);
! 405: sqlite3VdbeChangeP5(v, OE_Abort);
! 406: sqlite3MayAbort(pParse);
! 407: }else
! 408: #endif
! 409: {
! 410: int count = (pParse->nested==0); /* True to count changes */
! 411: sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, count, pTrigger, OE_Default);
! 412: }
! 413:
! 414: /* End of the delete loop */
! 415: sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
! 416: sqlite3VdbeResolveLabel(v, end);
! 417:
! 418: /* Close the cursors open on the table and its indexes. */
! 419: if( !isView && !IsVirtual(pTab) ){
! 420: for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
! 421: sqlite3VdbeAddOp2(v, OP_Close, iCur + i, pIdx->tnum);
! 422: }
! 423: sqlite3VdbeAddOp1(v, OP_Close, iCur);
! 424: }
! 425: }
! 426:
! 427: /* Update the sqlite_sequence table by storing the content of the
! 428: ** maximum rowid counter values recorded while inserting into
! 429: ** autoincrement tables.
! 430: */
! 431: if( pParse->nested==0 && pParse->pTriggerTab==0 ){
! 432: sqlite3AutoincrementEnd(pParse);
! 433: }
! 434:
! 435: /* Return the number of rows that were deleted. If this routine is
! 436: ** generating code because of a call to sqlite3NestedParse(), do not
! 437: ** invoke the callback function.
! 438: */
! 439: if( (db->flags&SQLITE_CountRows) && !pParse->nested && !pParse->pTriggerTab ){
! 440: sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1);
! 441: sqlite3VdbeSetNumCols(v, 1);
! 442: sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC);
! 443: }
! 444:
! 445: delete_from_cleanup:
! 446: sqlite3AuthContextPop(&sContext);
! 447: sqlite3SrcListDelete(db, pTabList);
! 448: sqlite3ExprDelete(db, pWhere);
! 449: return;
! 450: }
! 451: /* Make sure "isView" and other macros defined above are undefined. Otherwise
! 452: ** thely may interfere with compilation of other functions in this file
! 453: ** (or in another file, if this file becomes part of the amalgamation). */
! 454: #ifdef isView
! 455: #undef isView
! 456: #endif
! 457: #ifdef pTrigger
! 458: #undef pTrigger
! 459: #endif
! 460:
! 461: /*
! 462: ** This routine generates VDBE code that causes a single row of a
! 463: ** single table to be deleted.
! 464: **
! 465: ** The VDBE must be in a particular state when this routine is called.
! 466: ** These are the requirements:
! 467: **
! 468: ** 1. A read/write cursor pointing to pTab, the table containing the row
! 469: ** to be deleted, must be opened as cursor number $iCur.
! 470: **
! 471: ** 2. Read/write cursors for all indices of pTab must be open as
! 472: ** cursor number base+i for the i-th index.
! 473: **
! 474: ** 3. The record number of the row to be deleted must be stored in
! 475: ** memory cell iRowid.
! 476: **
! 477: ** This routine generates code to remove both the table record and all
! 478: ** index entries that point to that record.
! 479: */
! 480: void sqlite3GenerateRowDelete(
! 481: Parse *pParse, /* Parsing context */
! 482: Table *pTab, /* Table containing the row to be deleted */
! 483: int iCur, /* Cursor number for the table */
! 484: int iRowid, /* Memory cell that contains the rowid to delete */
! 485: int count, /* If non-zero, increment the row change counter */
! 486: Trigger *pTrigger, /* List of triggers to (potentially) fire */
! 487: int onconf /* Default ON CONFLICT policy for triggers */
! 488: ){
! 489: Vdbe *v = pParse->pVdbe; /* Vdbe */
! 490: int iOld = 0; /* First register in OLD.* array */
! 491: int iLabel; /* Label resolved to end of generated code */
! 492:
! 493: /* Vdbe is guaranteed to have been allocated by this stage. */
! 494: assert( v );
! 495:
! 496: /* Seek cursor iCur to the row to delete. If this row no longer exists
! 497: ** (this can happen if a trigger program has already deleted it), do
! 498: ** not attempt to delete it or fire any DELETE triggers. */
! 499: iLabel = sqlite3VdbeMakeLabel(v);
! 500: sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);
! 501:
! 502: /* If there are any triggers to fire, allocate a range of registers to
! 503: ** use for the old.* references in the triggers. */
! 504: if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){
! 505: u32 mask; /* Mask of OLD.* columns in use */
! 506: int iCol; /* Iterator used while populating OLD.* */
! 507:
! 508: /* TODO: Could use temporary registers here. Also could attempt to
! 509: ** avoid copying the contents of the rowid register. */
! 510: mask = sqlite3TriggerColmask(
! 511: pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf
! 512: );
! 513: mask |= sqlite3FkOldmask(pParse, pTab);
! 514: iOld = pParse->nMem+1;
! 515: pParse->nMem += (1 + pTab->nCol);
! 516:
! 517: /* Populate the OLD.* pseudo-table register array. These values will be
! 518: ** used by any BEFORE and AFTER triggers that exist. */
! 519: sqlite3VdbeAddOp2(v, OP_Copy, iRowid, iOld);
! 520: for(iCol=0; iCol<pTab->nCol; iCol++){
! 521: if( mask==0xffffffff || mask&(1<<iCol) ){
! 522: sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, iOld+iCol+1);
! 523: }
! 524: }
! 525:
! 526: /* Invoke BEFORE DELETE trigger programs. */
! 527: sqlite3CodeRowTrigger(pParse, pTrigger,
! 528: TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
! 529: );
! 530:
! 531: /* Seek the cursor to the row to be deleted again. It may be that
! 532: ** the BEFORE triggers coded above have already removed the row
! 533: ** being deleted. Do not attempt to delete the row a second time, and
! 534: ** do not fire AFTER triggers. */
! 535: sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);
! 536:
! 537: /* Do FK processing. This call checks that any FK constraints that
! 538: ** refer to this table (i.e. constraints attached to other tables)
! 539: ** are not violated by deleting this row. */
! 540: sqlite3FkCheck(pParse, pTab, iOld, 0);
! 541: }
! 542:
! 543: /* Delete the index and table entries. Skip this step if pTab is really
! 544: ** a view (in which case the only effect of the DELETE statement is to
! 545: ** fire the INSTEAD OF triggers). */
! 546: if( pTab->pSelect==0 ){
! 547: sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0);
! 548: sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
! 549: if( count ){
! 550: sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT);
! 551: }
! 552: }
! 553:
! 554: /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
! 555: ** handle rows (possibly in other tables) that refer via a foreign key
! 556: ** to the row just deleted. */
! 557: sqlite3FkActions(pParse, pTab, 0, iOld);
! 558:
! 559: /* Invoke AFTER DELETE trigger programs. */
! 560: sqlite3CodeRowTrigger(pParse, pTrigger,
! 561: TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel
! 562: );
! 563:
! 564: /* Jump here if the row had already been deleted before any BEFORE
! 565: ** trigger programs were invoked. Or if a trigger program throws a
! 566: ** RAISE(IGNORE) exception. */
! 567: sqlite3VdbeResolveLabel(v, iLabel);
! 568: }
! 569:
! 570: /*
! 571: ** This routine generates VDBE code that causes the deletion of all
! 572: ** index entries associated with a single row of a single table.
! 573: **
! 574: ** The VDBE must be in a particular state when this routine is called.
! 575: ** These are the requirements:
! 576: **
! 577: ** 1. A read/write cursor pointing to pTab, the table containing the row
! 578: ** to be deleted, must be opened as cursor number "iCur".
! 579: **
! 580: ** 2. Read/write cursors for all indices of pTab must be open as
! 581: ** cursor number iCur+i for the i-th index.
! 582: **
! 583: ** 3. The "iCur" cursor must be pointing to the row that is to be
! 584: ** deleted.
! 585: */
! 586: void sqlite3GenerateRowIndexDelete(
! 587: Parse *pParse, /* Parsing and code generating context */
! 588: Table *pTab, /* Table containing the row to be deleted */
! 589: int iCur, /* Cursor number for the table */
! 590: int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
! 591: ){
! 592: int i;
! 593: Index *pIdx;
! 594: int r1;
! 595:
! 596: for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
! 597: if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
! 598: r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0);
! 599: sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1);
! 600: }
! 601: }
! 602:
! 603: /*
! 604: ** Generate code that will assemble an index key and put it in register
! 605: ** regOut. The key with be for index pIdx which is an index on pTab.
! 606: ** iCur is the index of a cursor open on the pTab table and pointing to
! 607: ** the entry that needs indexing.
! 608: **
! 609: ** Return a register number which is the first in a block of
! 610: ** registers that holds the elements of the index key. The
! 611: ** block of registers has already been deallocated by the time
! 612: ** this routine returns.
! 613: */
! 614: int sqlite3GenerateIndexKey(
! 615: Parse *pParse, /* Parsing context */
! 616: Index *pIdx, /* The index for which to generate a key */
! 617: int iCur, /* Cursor number for the pIdx->pTable table */
! 618: int regOut, /* Write the new index key to this register */
! 619: int doMakeRec /* Run the OP_MakeRecord instruction if true */
! 620: ){
! 621: Vdbe *v = pParse->pVdbe;
! 622: int j;
! 623: Table *pTab = pIdx->pTable;
! 624: int regBase;
! 625: int nCol;
! 626:
! 627: nCol = pIdx->nColumn;
! 628: regBase = sqlite3GetTempRange(pParse, nCol+1);
! 629: sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol);
! 630: for(j=0; j<nCol; j++){
! 631: int idx = pIdx->aiColumn[j];
! 632: if( idx==pTab->iPKey ){
! 633: sqlite3VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j);
! 634: }else{
! 635: sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
! 636: sqlite3ColumnDefault(v, pTab, idx, -1);
! 637: }
! 638: }
! 639: if( doMakeRec ){
! 640: const char *zAff;
! 641: if( pTab->pSelect || (pParse->db->flags & SQLITE_IdxRealAsInt)!=0 ){
! 642: zAff = 0;
! 643: }else{
! 644: zAff = sqlite3IndexAffinityStr(v, pIdx);
! 645: }
! 646: sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
! 647: sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
! 648: }
! 649: sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
! 650: return regBase;
! 651: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>