00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "sqliteInt.h"
00018
00019
00020
00021
00022
00023
00024 Table *sqliteSrcListLookup(Parse *pParse, SrcList *pSrc){
00025 Table *pTab = 0;
00026 int i;
00027 for(i=0; i<pSrc->nSrc; i++){
00028 const char *zTab = pSrc->a[i].zName;
00029 const char *zDb = pSrc->a[i].zDatabase;
00030 pTab = sqliteLocateTable(pParse, zTab, zDb);
00031 pSrc->a[i].pTab = pTab;
00032 }
00033 return pTab;
00034 }
00035
00036
00037
00038
00039
00040
00041 int sqliteIsReadOnly(Parse *pParse, Table *pTab, int viewOk){
00042 if( pTab->readOnly ){
00043 sqliteErrorMsg(pParse, "table %s may not be modified", pTab->zName);
00044 return 1;
00045 }
00046 if( !viewOk && pTab->pSelect ){
00047 sqliteErrorMsg(pParse, "cannot modify %s because it is a view",pTab->zName);
00048 return 1;
00049 }
00050 return 0;
00051 }
00052
00053
00054
00055
00056 void sqliteDeleteFrom(
00057 Parse *pParse,
00058 SrcList *pTabList,
00059 Expr *pWhere
00060 ){
00061 Vdbe *v;
00062 Table *pTab;
00063 const char *zDb;
00064 int end, addr;
00065 int i;
00066 WhereInfo *pWInfo;
00067 Index *pIdx;
00068 int iCur;
00069 sqlite *db;
00070 int isView;
00071 AuthContext sContext;
00072
00073 int row_triggers_exist = 0;
00074 int before_triggers;
00075 int after_triggers;
00076 int oldIdx = -1;
00077
00078 sContext.pParse = 0;
00079 if( pParse->nErr || sqlite_malloc_failed ){
00080 pTabList = 0;
00081 goto delete_from_cleanup;
00082 }
00083 db = pParse->db;
00084 assert( pTabList->nSrc==1 );
00085
00086
00087
00088
00089
00090
00091 pTab = sqliteSrcListLookup(pParse, pTabList);
00092 if( pTab==0 ) goto delete_from_cleanup;
00093 before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
00094 TK_DELETE, TK_BEFORE, TK_ROW, 0);
00095 after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
00096 TK_DELETE, TK_AFTER, TK_ROW, 0);
00097 row_triggers_exist = before_triggers || after_triggers;
00098 isView = pTab->pSelect!=0;
00099 if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
00100 goto delete_from_cleanup;
00101 }
00102 assert( pTab->iDb<db->nDb );
00103 zDb = db->aDb[pTab->iDb].zName;
00104 if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
00105 goto delete_from_cleanup;
00106 }
00107
00108
00109
00110 if( isView && sqliteViewGetColumnNames(pParse, pTab) ){
00111 goto delete_from_cleanup;
00112 }
00113
00114
00115
00116 if( row_triggers_exist ){
00117 oldIdx = pParse->nTab++;
00118 }
00119
00120
00121
00122 assert( pTabList->nSrc==1 );
00123 iCur = pTabList->a[0].iCursor = pParse->nTab++;
00124 if( pWhere ){
00125 if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
00126 goto delete_from_cleanup;
00127 }
00128 if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
00129 goto delete_from_cleanup;
00130 }
00131 }
00132
00133
00134
00135 if( isView ){
00136 sqliteAuthContextPush(pParse, &sContext, pTab->zName);
00137 }
00138
00139
00140
00141 v = sqliteGetVdbe(pParse);
00142 if( v==0 ){
00143 goto delete_from_cleanup;
00144 }
00145 sqliteBeginWriteOperation(pParse, row_triggers_exist, pTab->iDb);
00146
00147
00148
00149
00150 if( isView ){
00151 Select *pView = sqliteSelectDup(pTab->pSelect);
00152 sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
00153 sqliteSelectDelete(pView);
00154 }
00155
00156
00157
00158
00159 if( db->flags & SQLITE_CountRows ){
00160 sqliteVdbeAddOp(v, OP_Integer, 0, 0);
00161 }
00162
00163
00164
00165
00166
00167 if( pWhere==0 && !row_triggers_exist ){
00168 if( db->flags & SQLITE_CountRows ){
00169
00170
00171 int endOfLoop = sqliteVdbeMakeLabel(v);
00172 int addr;
00173 if( !isView ){
00174 sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
00175 sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
00176 }
00177 sqliteVdbeAddOp(v, OP_Rewind, iCur, sqliteVdbeCurrentAddr(v)+2);
00178 addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
00179 sqliteVdbeAddOp(v, OP_Next, iCur, addr);
00180 sqliteVdbeResolveLabel(v, endOfLoop);
00181 sqliteVdbeAddOp(v, OP_Close, iCur, 0);
00182 }
00183 if( !isView ){
00184 sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb);
00185 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
00186 sqliteVdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb);
00187 }
00188 }
00189 }
00190
00191
00192
00193
00194 else{
00195
00196
00197 pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0);
00198 if( pWInfo==0 ) goto delete_from_cleanup;
00199
00200
00201
00202 sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
00203 if( db->flags & SQLITE_CountRows ){
00204 sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
00205 }
00206
00207
00208
00209 sqliteWhereEnd(pWInfo);
00210
00211
00212
00213 if( row_triggers_exist ){
00214 sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
00215 }
00216
00217
00218
00219
00220
00221 sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
00222 end = sqliteVdbeMakeLabel(v);
00223
00224
00225
00226
00227 if( row_triggers_exist ){
00228 addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
00229 sqliteVdbeAddOp(v, OP_Dup, 0, 0);
00230 if( !isView ){
00231 sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
00232 sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
00233 }
00234 sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
00235
00236 sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
00237 sqliteVdbeAddOp(v, OP_RowData, iCur, 0);
00238 sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
00239 if( !isView ){
00240 sqliteVdbeAddOp(v, OP_Close, iCur, 0);
00241 }
00242
00243 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1,
00244 oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
00245 addr);
00246 }
00247
00248 if( !isView ){
00249
00250
00251
00252
00253
00254
00255 pParse->nTab = iCur + 1;
00256 sqliteOpenTableAndIndices(pParse, pTab, iCur);
00257
00258
00259
00260 if( !row_triggers_exist ){
00261 addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
00262 }
00263
00264
00265 sqliteGenerateRowDelete(db, v, pTab, iCur, pParse->trigStack==0);
00266 }
00267
00268
00269
00270
00271 if( row_triggers_exist ){
00272 if( !isView ){
00273 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
00274 sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
00275 }
00276 sqliteVdbeAddOp(v, OP_Close, iCur, 0);
00277 }
00278 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1,
00279 oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
00280 addr);
00281 }
00282
00283
00284 sqliteVdbeAddOp(v, OP_Goto, 0, addr);
00285 sqliteVdbeResolveLabel(v, end);
00286 sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
00287
00288
00289 if( !row_triggers_exist ){
00290 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
00291 sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
00292 }
00293 sqliteVdbeAddOp(v, OP_Close, iCur, 0);
00294 pParse->nTab = iCur;
00295 }
00296 }
00297 sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
00298 sqliteEndWriteOperation(pParse);
00299
00300
00301
00302
00303 if( db->flags & SQLITE_CountRows ){
00304 sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
00305 sqliteVdbeChangeP3(v, -1, "rows deleted", P3_STATIC);
00306 sqliteVdbeAddOp(v, OP_Callback, 1, 0);
00307 }
00308
00309 delete_from_cleanup:
00310 sqliteAuthContextPop(&sContext);
00311 sqliteSrcListDelete(pTabList);
00312 sqliteExprDelete(pWhere);
00313 return;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 void sqliteGenerateRowDelete(
00337 sqlite *db,
00338 Vdbe *v,
00339 Table *pTab,
00340 int iCur,
00341 int count
00342 ){
00343 int addr;
00344 addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0);
00345 sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0);
00346 sqliteVdbeAddOp(v, OP_Delete, iCur,
00347 (count?OPFLAG_NCHANGE:0) | OPFLAG_CSCHANGE);
00348 sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 void sqliteGenerateRowIndexDelete(
00368 sqlite *db,
00369 Vdbe *v,
00370 Table *pTab,
00371 int iCur,
00372 char *aIdxUsed
00373 ){
00374 int i;
00375 Index *pIdx;
00376
00377 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
00378 int j;
00379 if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
00380 sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
00381 for(j=0; j<pIdx->nColumn; j++){
00382 int idx = pIdx->aiColumn[j];
00383 if( idx==pTab->iPKey ){
00384 sqliteVdbeAddOp(v, OP_Dup, j, 0);
00385 }else{
00386 sqliteVdbeAddOp(v, OP_Column, iCur, idx);
00387 }
00388 }
00389 sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
00390 if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
00391 sqliteVdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
00392 }
00393 }