Annotation of embedaddon/php/ext/sqlite/libsqlite/src/delete.c, revision 1.1.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: ** to handle DELETE FROM statements.
                     14: **
                     15: ** $Id: delete.c 195361 2005-09-07 15:11:33Z iliaa $
                     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 *sqliteSrcListLookup(Parse *pParse, SrcList *pSrc){
                     25:   Table *pTab = 0;
                     26:   int i;
                     27:   for(i=0; i<pSrc->nSrc; i++){
                     28:     const char *zTab = pSrc->a[i].zName;
                     29:     const char *zDb = pSrc->a[i].zDatabase;
                     30:     pTab = sqliteLocateTable(pParse, zTab, zDb);
                     31:     pSrc->a[i].pTab = pTab;
                     32:   }
                     33:   return pTab;
                     34: }
                     35: 
                     36: /*
                     37: ** Check to make sure the given table is writable.  If it is not
                     38: ** writable, generate an error message and return 1.  If it is
                     39: ** writable return 0;
                     40: */
                     41: int sqliteIsReadOnly(Parse *pParse, Table *pTab, int viewOk){
                     42:   if( pTab->readOnly ){
                     43:     sqliteErrorMsg(pParse, "table %s may not be modified", pTab->zName);
                     44:     return 1;
                     45:   }
                     46:   if( !viewOk && pTab->pSelect ){
                     47:     sqliteErrorMsg(pParse, "cannot modify %s because it is a view",pTab->zName);
                     48:     return 1;
                     49:   }
                     50:   return 0;
                     51: }
                     52: 
                     53: /*
                     54: ** Process a DELETE FROM statement.
                     55: */
                     56: void sqliteDeleteFrom(
                     57:   Parse *pParse,         /* The parser context */
                     58:   SrcList *pTabList,     /* The table from which we should delete things */
                     59:   Expr *pWhere           /* The WHERE clause.  May be null */
                     60: ){
                     61:   Vdbe *v;               /* The virtual database engine */
                     62:   Table *pTab;           /* The table from which records will be deleted */
                     63:   const char *zDb;       /* Name of database holding pTab */
                     64:   int end, addr;         /* A couple addresses of generated code */
                     65:   int i;                 /* Loop counter */
                     66:   WhereInfo *pWInfo;     /* Information about the WHERE clause */
                     67:   Index *pIdx;           /* For looping over indices of the table */
                     68:   int iCur;              /* VDBE Cursor number for pTab */
                     69:   sqlite *db;            /* Main database structure */
                     70:   int isView;            /* True if attempting to delete from a view */
                     71:   AuthContext sContext;  /* Authorization context */
                     72: 
                     73:   int row_triggers_exist = 0;  /* True if any triggers exist */
                     74:   int before_triggers;         /* True if there are BEFORE triggers */
                     75:   int after_triggers;          /* True if there are AFTER triggers */
                     76:   int oldIdx = -1;             /* Cursor for the OLD table of AFTER triggers */
                     77: 
                     78:   sContext.pParse = 0;
                     79:   if( pParse->nErr || sqlite_malloc_failed ){
                     80:     pTabList = 0;
                     81:     goto delete_from_cleanup;
                     82:   }
                     83:   db = pParse->db;
                     84:   assert( pTabList->nSrc==1 );
                     85: 
                     86:   /* Locate the table which we want to delete.  This table has to be
                     87:   ** put in an SrcList structure because some of the subroutines we
                     88:   ** will be calling are designed to work with multiple tables and expect
                     89:   ** an SrcList* parameter instead of just a Table* parameter.
                     90:   */
                     91:   pTab = sqliteSrcListLookup(pParse, pTabList);
                     92:   if( pTab==0 )  goto delete_from_cleanup;
                     93:   before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, 
                     94:                          TK_DELETE, TK_BEFORE, TK_ROW, 0);
                     95:   after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger, 
                     96:                          TK_DELETE, TK_AFTER, TK_ROW, 0);
                     97:   row_triggers_exist = before_triggers || after_triggers;
                     98:   isView = pTab->pSelect!=0;
                     99:   if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
                    100:     goto delete_from_cleanup;
                    101:   }
                    102:   assert( pTab->iDb<db->nDb );
                    103:   zDb = db->aDb[pTab->iDb].zName;
                    104:   if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
                    105:     goto delete_from_cleanup;
                    106:   }
                    107: 
                    108:   /* If pTab is really a view, make sure it has been initialized.
                    109:   */
                    110:   if( isView && sqliteViewGetColumnNames(pParse, pTab) ){
                    111:     goto delete_from_cleanup;
                    112:   }
                    113: 
                    114:   /* Allocate a cursor used to store the old.* data for a trigger.
                    115:   */
                    116:   if( row_triggers_exist ){ 
                    117:     oldIdx = pParse->nTab++;
                    118:   }
                    119: 
                    120:   /* Resolve the column names in all the expressions.
                    121:   */
                    122:   assert( pTabList->nSrc==1 );
                    123:   iCur = pTabList->a[0].iCursor = pParse->nTab++;
                    124:   if( pWhere ){
                    125:     if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
                    126:       goto delete_from_cleanup;
                    127:     }
                    128:     if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
                    129:       goto delete_from_cleanup;
                    130:     }
                    131:   }
                    132: 
                    133:   /* Start the view context
                    134:   */
                    135:   if( isView ){
                    136:     sqliteAuthContextPush(pParse, &sContext, pTab->zName);
                    137:   }
                    138: 
                    139:   /* Begin generating code.
                    140:   */
                    141:   v = sqliteGetVdbe(pParse);
                    142:   if( v==0 ){
                    143:     goto delete_from_cleanup;
                    144:   }
                    145:   sqliteBeginWriteOperation(pParse, row_triggers_exist, pTab->iDb);
                    146: 
                    147:   /* If we are trying to delete from a view, construct that view into
                    148:   ** a temporary table.
                    149:   */
                    150:   if( isView ){
                    151:     Select *pView = sqliteSelectDup(pTab->pSelect);
                    152:     sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
                    153:     sqliteSelectDelete(pView);
                    154:   }
                    155: 
                    156:   /* Initialize the counter of the number of rows deleted, if
                    157:   ** we are counting rows.
                    158:   */
                    159:   if( db->flags & SQLITE_CountRows ){
                    160:     sqliteVdbeAddOp(v, OP_Integer, 0, 0);
                    161:   }
                    162: 
                    163:   /* Special case: A DELETE without a WHERE clause deletes everything.
                    164:   ** It is easier just to erase the whole table.  Note, however, that
                    165:   ** this means that the row change count will be incorrect.
                    166:   */
                    167:   if( pWhere==0 && !row_triggers_exist ){
                    168:     if( db->flags & SQLITE_CountRows ){
                    169:       /* If counting rows deleted, just count the total number of
                    170:       ** entries in the table. */
                    171:       int endOfLoop = sqliteVdbeMakeLabel(v);
                    172:       int addr;
                    173:       if( !isView ){
                    174:         sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
                    175:         sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
                    176:       }
                    177:       sqliteVdbeAddOp(v, OP_Rewind, iCur, sqliteVdbeCurrentAddr(v)+2);
                    178:       addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
                    179:       sqliteVdbeAddOp(v, OP_Next, iCur, addr);
                    180:       sqliteVdbeResolveLabel(v, endOfLoop);
                    181:       sqliteVdbeAddOp(v, OP_Close, iCur, 0);
                    182:     }
                    183:     if( !isView ){
                    184:       sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb);
                    185:       for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
                    186:         sqliteVdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb);
                    187:       }
                    188:     }
                    189:   }
                    190: 
                    191:   /* The usual case: There is a WHERE clause so we have to scan through
                    192:   ** the table and pick which records to delete.
                    193:   */
                    194:   else{
                    195:     /* Begin the database scan
                    196:     */
                    197:     pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0);
                    198:     if( pWInfo==0 ) goto delete_from_cleanup;
                    199: 
                    200:     /* Remember the key of every item to be deleted.
                    201:     */
                    202:     sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
                    203:     if( db->flags & SQLITE_CountRows ){
                    204:       sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
                    205:     }
                    206: 
                    207:     /* End the database scan loop.
                    208:     */
                    209:     sqliteWhereEnd(pWInfo);
                    210: 
                    211:     /* Open the pseudo-table used to store OLD if there are triggers.
                    212:     */
                    213:     if( row_triggers_exist ){
                    214:       sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
                    215:     }
                    216: 
                    217:     /* Delete every item whose key was written to the list during the
                    218:     ** database scan.  We have to delete items after the scan is complete
                    219:     ** because deleting an item can change the scan order.
                    220:     */
                    221:     sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
                    222:     end = sqliteVdbeMakeLabel(v);
                    223: 
                    224:     /* This is the beginning of the delete loop when there are
                    225:     ** row triggers.
                    226:     */
                    227:     if( row_triggers_exist ){
                    228:       addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
                    229:       sqliteVdbeAddOp(v, OP_Dup, 0, 0);
                    230:       if( !isView ){
                    231:         sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
                    232:         sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
                    233:       }
                    234:       sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
                    235: 
                    236:       sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
                    237:       sqliteVdbeAddOp(v, OP_RowData, iCur, 0);
                    238:       sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
                    239:       if( !isView ){
                    240:         sqliteVdbeAddOp(v, OP_Close, iCur, 0);
                    241:       }
                    242: 
                    243:       sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, 
                    244:           oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
                    245:          addr);
                    246:     }
                    247: 
                    248:     if( !isView ){
                    249:       /* Open cursors for the table we are deleting from and all its
                    250:       ** indices.  If there are row triggers, this happens inside the
                    251:       ** OP_ListRead loop because the cursor have to all be closed
                    252:       ** before the trigger fires.  If there are no row triggers, the
                    253:       ** cursors are opened only once on the outside the loop.
                    254:       */
                    255:       pParse->nTab = iCur + 1;
                    256:       sqliteOpenTableAndIndices(pParse, pTab, iCur);
                    257: 
                    258:       /* This is the beginning of the delete loop when there are no
                    259:       ** row triggers */
                    260:       if( !row_triggers_exist ){ 
                    261:         addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
                    262:       }
                    263: 
                    264:       /* Delete the row */
                    265:       sqliteGenerateRowDelete(db, v, pTab, iCur, pParse->trigStack==0);
                    266:     }
                    267: 
                    268:     /* If there are row triggers, close all cursors then invoke
                    269:     ** the AFTER triggers
                    270:     */
                    271:     if( row_triggers_exist ){
                    272:       if( !isView ){
                    273:         for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
                    274:           sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
                    275:         }
                    276:         sqliteVdbeAddOp(v, OP_Close, iCur, 0);
                    277:       }
                    278:       sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, 
                    279:           oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
                    280:          addr);
                    281:     }
                    282: 
                    283:     /* End of the delete loop */
                    284:     sqliteVdbeAddOp(v, OP_Goto, 0, addr);
                    285:     sqliteVdbeResolveLabel(v, end);
                    286:     sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
                    287: 
                    288:     /* Close the cursors after the loop if there are no row triggers */
                    289:     if( !row_triggers_exist ){
                    290:       for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
                    291:         sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
                    292:       }
                    293:       sqliteVdbeAddOp(v, OP_Close, iCur, 0);
                    294:       pParse->nTab = iCur;
                    295:     }
                    296:   }
                    297:   sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
                    298:   sqliteEndWriteOperation(pParse);
                    299: 
                    300:   /*
                    301:   ** Return the number of rows that were deleted.
                    302:   */
                    303:   if( db->flags & SQLITE_CountRows ){
                    304:     sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
                    305:     sqliteVdbeChangeP3(v, -1, "rows deleted", P3_STATIC);
                    306:     sqliteVdbeAddOp(v, OP_Callback, 1, 0);
                    307:   }
                    308: 
                    309: delete_from_cleanup:
                    310:   sqliteAuthContextPop(&sContext);
                    311:   sqliteSrcListDelete(pTabList);
                    312:   sqliteExprDelete(pWhere);
                    313:   return;
                    314: }
                    315: 
                    316: /*
                    317: ** This routine generates VDBE code that causes a single row of a
                    318: ** single table to be deleted.
                    319: **
                    320: ** The VDBE must be in a particular state when this routine is called.
                    321: ** These are the requirements:
                    322: **
                    323: **   1.  A read/write cursor pointing to pTab, the table containing the row
                    324: **       to be deleted, must be opened as cursor number "base".
                    325: **
                    326: **   2.  Read/write cursors for all indices of pTab must be open as
                    327: **       cursor number base+i for the i-th index.
                    328: **
                    329: **   3.  The record number of the row to be deleted must be on the top
                    330: **       of the stack.
                    331: **
                    332: ** This routine pops the top of the stack to remove the record number
                    333: ** and then generates code to remove both the table record and all index
                    334: ** entries that point to that record.
                    335: */
                    336: void sqliteGenerateRowDelete(
                    337:   sqlite *db,        /* The database containing the index */
                    338:   Vdbe *v,           /* Generate code into this VDBE */
                    339:   Table *pTab,       /* Table containing the row to be deleted */
                    340:   int iCur,          /* Cursor number for the table */
                    341:   int count          /* Increment the row change counter */
                    342: ){
                    343:   int addr;
                    344:   addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0);
                    345:   sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0);
                    346:   sqliteVdbeAddOp(v, OP_Delete, iCur,
                    347:     (count?OPFLAG_NCHANGE:0) | OPFLAG_CSCHANGE);
                    348:   sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
                    349: }
                    350: 
                    351: /*
                    352: ** This routine generates VDBE code that causes the deletion of all
                    353: ** index entries associated with a single row of a single table.
                    354: **
                    355: ** The VDBE must be in a particular state when this routine is called.
                    356: ** These are the requirements:
                    357: **
                    358: **   1.  A read/write cursor pointing to pTab, the table containing the row
                    359: **       to be deleted, must be opened as cursor number "iCur".
                    360: **
                    361: **   2.  Read/write cursors for all indices of pTab must be open as
                    362: **       cursor number iCur+i for the i-th index.
                    363: **
                    364: **   3.  The "iCur" cursor must be pointing to the row that is to be
                    365: **       deleted.
                    366: */
                    367: void sqliteGenerateRowIndexDelete(
                    368:   sqlite *db,        /* The database containing the index */
                    369:   Vdbe *v,           /* Generate code into this VDBE */
                    370:   Table *pTab,       /* Table containing the row to be deleted */
                    371:   int iCur,          /* Cursor number for the table */
                    372:   char *aIdxUsed     /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
                    373: ){
                    374:   int i;
                    375:   Index *pIdx;
                    376: 
                    377:   for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
                    378:     int j;
                    379:     if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
                    380:     sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
                    381:     for(j=0; j<pIdx->nColumn; j++){
                    382:       int idx = pIdx->aiColumn[j];
                    383:       if( idx==pTab->iPKey ){
                    384:         sqliteVdbeAddOp(v, OP_Dup, j, 0);
                    385:       }else{
                    386:         sqliteVdbeAddOp(v, OP_Column, iCur, idx);
                    387:       }
                    388:     }
                    389:     sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
                    390:     if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
                    391:     sqliteVdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
                    392:   }
                    393: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>