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
00025
00026 void sqliteUpdate(
00027 Parse *pParse,
00028 SrcList *pTabList,
00029 ExprList *pChanges,
00030 Expr *pWhere,
00031 int onError
00032 ){
00033 int i, j;
00034 Table *pTab;
00035 int loopStart;
00036 int jumpInst;
00037 WhereInfo *pWInfo;
00038 Vdbe *v;
00039 Index *pIdx;
00040 int nIdx;
00041 int nIdxTotal;
00042 int iCur;
00043 sqlite *db;
00044 Index **apIdx = 0;
00045 char *aIdxUsed = 0;
00046 int *aXRef = 0;
00047
00048
00049 int chngRecno;
00050 Expr *pRecnoExpr;
00051 int openAll;
00052 int isView;
00053 int iStackDepth;
00054 AuthContext sContext;
00055
00056 int before_triggers;
00057 int after_triggers;
00058 int row_triggers_exist = 0;
00059
00060 int newIdx = -1;
00061 int oldIdx = -1;
00062
00063 sContext.pParse = 0;
00064 if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;
00065 db = pParse->db;
00066 assert( pTabList->nSrc==1 );
00067 iStackDepth = pParse->nMem++;
00068
00069
00070
00071 pTab = sqliteSrcListLookup(pParse, pTabList);
00072 if( pTab==0 ) goto update_cleanup;
00073 before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
00074 TK_UPDATE, TK_BEFORE, TK_ROW, pChanges);
00075 after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
00076 TK_UPDATE, TK_AFTER, TK_ROW, pChanges);
00077 row_triggers_exist = before_triggers || after_triggers;
00078 isView = pTab->pSelect!=0;
00079 if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
00080 goto update_cleanup;
00081 }
00082 if( isView ){
00083 if( sqliteViewGetColumnNames(pParse, pTab) ){
00084 goto update_cleanup;
00085 }
00086 }
00087 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
00088 if( aXRef==0 ) goto update_cleanup;
00089 for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
00090
00091
00092
00093
00094 if( row_triggers_exist ){
00095 newIdx = pParse->nTab++;
00096 oldIdx = pParse->nTab++;
00097 }
00098
00099
00100
00101
00102
00103
00104 pTabList->a[0].iCursor = iCur = pParse->nTab++;
00105 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
00106 pParse->nTab++;
00107 }
00108
00109
00110
00111
00112
00113
00114
00115 chngRecno = 0;
00116 for(i=0; i<pChanges->nExpr; i++){
00117 if( sqliteExprResolveIds(pParse, pTabList, 0, pChanges->a[i].pExpr) ){
00118 goto update_cleanup;
00119 }
00120 if( sqliteExprCheck(pParse, pChanges->a[i].pExpr, 0, 0) ){
00121 goto update_cleanup;
00122 }
00123 for(j=0; j<pTab->nCol; j++){
00124 if( sqliteStrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
00125 if( j==pTab->iPKey ){
00126 chngRecno = 1;
00127 pRecnoExpr = pChanges->a[i].pExpr;
00128 }
00129 aXRef[j] = i;
00130 break;
00131 }
00132 }
00133 if( j>=pTab->nCol ){
00134 if( sqliteIsRowid(pChanges->a[i].zName) ){
00135 chngRecno = 1;
00136 pRecnoExpr = pChanges->a[i].pExpr;
00137 }else{
00138 sqliteErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
00139 goto update_cleanup;
00140 }
00141 }
00142 #ifndef SQLITE_OMIT_AUTHORIZATION
00143 {
00144 int rc;
00145 rc = sqliteAuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
00146 pTab->aCol[j].zName, db->aDb[pTab->iDb].zName);
00147 if( rc==SQLITE_DENY ){
00148 goto update_cleanup;
00149 }else if( rc==SQLITE_IGNORE ){
00150 aXRef[j] = -1;
00151 }
00152 }
00153 #endif
00154 }
00155
00156
00157
00158
00159
00160
00161 for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){
00162 if( chngRecno ){
00163 i = 0;
00164 }else {
00165 for(i=0; i<pIdx->nColumn; i++){
00166 if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
00167 }
00168 }
00169 if( i<pIdx->nColumn ) nIdx++;
00170 }
00171 if( nIdxTotal>0 ){
00172 apIdx = sqliteMalloc( sizeof(Index*) * nIdx + nIdxTotal );
00173 if( apIdx==0 ) goto update_cleanup;
00174 aIdxUsed = (char*)&apIdx[nIdx];
00175 }
00176 for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
00177 if( chngRecno ){
00178 i = 0;
00179 }else{
00180 for(i=0; i<pIdx->nColumn; i++){
00181 if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
00182 }
00183 }
00184 if( i<pIdx->nColumn ){
00185 apIdx[nIdx++] = pIdx;
00186 aIdxUsed[j] = 1;
00187 }else{
00188 aIdxUsed[j] = 0;
00189 }
00190 }
00191
00192
00193
00194
00195 if( pWhere ){
00196 if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
00197 goto update_cleanup;
00198 }
00199 if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
00200 goto update_cleanup;
00201 }
00202 }
00203
00204
00205
00206 if( isView ){
00207 sqliteAuthContextPush(pParse, &sContext, pTab->zName);
00208 }
00209
00210
00211
00212 v = sqliteGetVdbe(pParse);
00213 if( v==0 ) goto update_cleanup;
00214 sqliteBeginWriteOperation(pParse, 1, pTab->iDb);
00215
00216
00217
00218
00219 if( isView ){
00220 Select *pView;
00221 pView = sqliteSelectDup(pTab->pSelect);
00222 sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
00223 sqliteSelectDelete(pView);
00224 }
00225
00226
00227
00228 pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0);
00229 if( pWInfo==0 ) goto update_cleanup;
00230
00231
00232
00233 sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
00234
00235
00236
00237 sqliteWhereEnd(pWInfo);
00238
00239
00240
00241 if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
00242 sqliteVdbeAddOp(v, OP_Integer, 0, 0);
00243 }
00244
00245 if( row_triggers_exist ){
00246
00247
00248 sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
00249 sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
00250
00251
00252
00253 sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
00254 sqliteVdbeAddOp(v, OP_StackDepth, 0, 0);
00255 sqliteVdbeAddOp(v, OP_MemStore, iStackDepth, 1);
00256 loopStart = sqliteVdbeAddOp(v, OP_MemLoad, iStackDepth, 0);
00257 sqliteVdbeAddOp(v, OP_StackReset, 0, 0);
00258 jumpInst = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
00259 sqliteVdbeAddOp(v, OP_Dup, 0, 0);
00260
00261
00262
00263
00264 sqliteVdbeAddOp(v, OP_Dup, 0, 0);
00265 if( !isView ){
00266 sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
00267 sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
00268 }
00269 sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
00270
00271
00272
00273 sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
00274 sqliteVdbeAddOp(v, OP_RowData, iCur, 0);
00275 sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
00276
00277
00278
00279 if( chngRecno ){
00280 sqliteExprCode(pParse, pRecnoExpr);
00281 }else{
00282 sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
00283 }
00284 for(i=0; i<pTab->nCol; i++){
00285 if( i==pTab->iPKey ){
00286 sqliteVdbeAddOp(v, OP_String, 0, 0);
00287 continue;
00288 }
00289 j = aXRef[i];
00290 if( j<0 ){
00291 sqliteVdbeAddOp(v, OP_Column, iCur, i);
00292 }else{
00293 sqliteExprCode(pParse, pChanges->a[j].pExpr);
00294 }
00295 }
00296 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
00297 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
00298 if( !isView ){
00299 sqliteVdbeAddOp(v, OP_Close, iCur, 0);
00300 }
00301
00302
00303
00304 if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab,
00305 newIdx, oldIdx, onError, loopStart) ){
00306 goto update_cleanup;
00307 }
00308 }
00309
00310 if( !isView ){
00311
00312
00313
00314
00315
00316
00317 sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
00318 sqliteVdbeAddOp(v, OP_OpenWrite, iCur, pTab->tnum);
00319 if( onError==OE_Replace ){
00320 openAll = 1;
00321 }else{
00322 openAll = 0;
00323 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
00324 if( pIdx->onError==OE_Replace ){
00325 openAll = 1;
00326 break;
00327 }
00328 }
00329 }
00330 for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
00331 if( openAll || aIdxUsed[i] ){
00332 sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
00333 sqliteVdbeAddOp(v, OP_OpenWrite, iCur+i+1, pIdx->tnum);
00334 assert( pParse->nTab>iCur+i+1 );
00335 }
00336 }
00337
00338
00339
00340
00341
00342
00343
00344 if( !row_triggers_exist ){
00345 sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
00346 jumpInst = loopStart = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
00347 sqliteVdbeAddOp(v, OP_Dup, 0, 0);
00348 }
00349 sqliteVdbeAddOp(v, OP_NotExists, iCur, loopStart);
00350
00351
00352
00353
00354
00355 if( chngRecno ){
00356 sqliteExprCode(pParse, pRecnoExpr);
00357 sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
00358 }
00359
00360
00361
00362 for(i=0; i<pTab->nCol; i++){
00363 if( i==pTab->iPKey ){
00364 sqliteVdbeAddOp(v, OP_String, 0, 0);
00365 continue;
00366 }
00367 j = aXRef[i];
00368 if( j<0 ){
00369 sqliteVdbeAddOp(v, OP_Column, iCur, i);
00370 }else{
00371 sqliteExprCode(pParse, pChanges->a[j].pExpr);
00372 }
00373 }
00374
00375
00376
00377 sqliteGenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRecno, 1,
00378 onError, loopStart);
00379
00380
00381
00382 sqliteGenerateRowIndexDelete(db, v, pTab, iCur, aIdxUsed);
00383
00384
00385
00386 if( chngRecno ){
00387 sqliteVdbeAddOp(v, OP_Delete, iCur, 0);
00388 }
00389
00390
00391
00392 sqliteCompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRecno, 1, -1);
00393 }
00394
00395
00396
00397 if( db->flags & SQLITE_CountRows && !pParse->trigStack){
00398 sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
00399 }
00400
00401
00402
00403
00404 if( row_triggers_exist ){
00405 if( !isView ){
00406 for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
00407 if( openAll || aIdxUsed[i] )
00408 sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0);
00409 }
00410 sqliteVdbeAddOp(v, OP_Close, iCur, 0);
00411 pParse->nTab = iCur;
00412 }
00413 if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab,
00414 newIdx, oldIdx, onError, loopStart) ){
00415 goto update_cleanup;
00416 }
00417 }
00418
00419
00420
00421
00422 sqliteVdbeAddOp(v, OP_Goto, 0, loopStart);
00423 sqliteVdbeChangeP2(v, jumpInst, sqliteVdbeCurrentAddr(v));
00424 sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
00425
00426
00427 if( !row_triggers_exist ){
00428 for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
00429 if( openAll || aIdxUsed[i] ){
00430 sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0);
00431 }
00432 }
00433 sqliteVdbeAddOp(v, OP_Close, iCur, 0);
00434 pParse->nTab = iCur;
00435 }else{
00436 sqliteVdbeAddOp(v, OP_Close, newIdx, 0);
00437 sqliteVdbeAddOp(v, OP_Close, oldIdx, 0);
00438 }
00439
00440 sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
00441 sqliteEndWriteOperation(pParse);
00442
00443
00444
00445
00446 if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
00447 sqliteVdbeOp3(v, OP_ColumnName, 0, 1, "rows updated", P3_STATIC);
00448 sqliteVdbeAddOp(v, OP_Callback, 1, 0);
00449 }
00450
00451 update_cleanup:
00452 sqliteAuthContextPop(&sContext);
00453 sqliteFree(apIdx);
00454 sqliteFree(aXRef);
00455 sqliteSrcListDelete(pTabList);
00456 sqliteExprListDelete(pChanges);
00457 sqliteExprDelete(pWhere);
00458 return;
00459 }