OLD | NEW |
1 /* | 1 /* |
2 ** 2001 September 15 | 2 ** 2001 September 15 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 assert( pTab!=0 ); | 62 assert( pTab!=0 ); |
63 if( !pTab->pSelect ){ | 63 if( !pTab->pSelect ){ |
64 sqlite3_value *pValue = 0; | 64 sqlite3_value *pValue = 0; |
65 u8 enc = ENC(sqlite3VdbeDb(v)); | 65 u8 enc = ENC(sqlite3VdbeDb(v)); |
66 Column *pCol = &pTab->aCol[i]; | 66 Column *pCol = &pTab->aCol[i]; |
67 VdbeComment((v, "%s.%s", pTab->zName, pCol->zName)); | 67 VdbeComment((v, "%s.%s", pTab->zName, pCol->zName)); |
68 assert( i<pTab->nCol ); | 68 assert( i<pTab->nCol ); |
69 sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc, | 69 sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc, |
70 pCol->affinity, &pValue); | 70 pCol->affinity, &pValue); |
71 if( pValue ){ | 71 if( pValue ){ |
72 sqlite3VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM); | 72 sqlite3VdbeAppendP4(v, pValue, P4_MEM); |
73 } | 73 } |
| 74 } |
74 #ifndef SQLITE_OMIT_FLOATING_POINT | 75 #ifndef SQLITE_OMIT_FLOATING_POINT |
75 if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ | 76 if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ |
76 sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); | 77 sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); |
77 } | 78 } |
78 #endif | 79 #endif |
79 } | |
80 } | 80 } |
81 | 81 |
82 /* | 82 /* |
83 ** Process an UPDATE statement. | 83 ** Process an UPDATE statement. |
84 ** | 84 ** |
85 ** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; | 85 ** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; |
86 ** \_______/ \________/ \______/ \________________/ | 86 ** \_______/ \________/ \______/ \________________/ |
87 * onError pTabList pChanges pWhere | 87 * onError pTabList pChanges pWhere |
88 */ | 88 */ |
89 void sqlite3Update( | 89 void sqlite3Update( |
90 Parse *pParse, /* The parser context */ | 90 Parse *pParse, /* The parser context */ |
91 SrcList *pTabList, /* The table in which we should change things */ | 91 SrcList *pTabList, /* The table in which we should change things */ |
92 ExprList *pChanges, /* Things to be changed */ | 92 ExprList *pChanges, /* Things to be changed */ |
93 Expr *pWhere, /* The WHERE clause. May be null */ | 93 Expr *pWhere, /* The WHERE clause. May be null */ |
94 int onError /* How to handle constraint errors */ | 94 int onError /* How to handle constraint errors */ |
95 ){ | 95 ){ |
96 int i, j; /* Loop counters */ | 96 int i, j; /* Loop counters */ |
97 Table *pTab; /* The table to be updated */ | 97 Table *pTab; /* The table to be updated */ |
98 int addrTop = 0; /* VDBE instruction address of the start of the loop */ | 98 int addrTop = 0; /* VDBE instruction address of the start of the loop */ |
99 WhereInfo *pWInfo; /* Information about the WHERE clause */ | 99 WhereInfo *pWInfo; /* Information about the WHERE clause */ |
100 Vdbe *v; /* The virtual database engine */ | 100 Vdbe *v; /* The virtual database engine */ |
101 Index *pIdx; /* For looping over indices */ | 101 Index *pIdx; /* For looping over indices */ |
102 Index *pPk; /* The PRIMARY KEY index for WITHOUT ROWID tables */ | 102 Index *pPk; /* The PRIMARY KEY index for WITHOUT ROWID tables */ |
103 int nIdx; /* Number of indices that need updating */ | 103 int nIdx; /* Number of indices that need updating */ |
104 int iBaseCur; /* Base cursor number */ | 104 int iBaseCur; /* Base cursor number */ |
105 int iDataCur; /* Cursor for the canonical data btree */ | 105 int iDataCur; /* Cursor for the canonical data btree */ |
106 int iIdxCur; /* Cursor for the first index */ | 106 int iIdxCur; /* Cursor for the first index */ |
107 sqlite3 *db; /* The database structure */ | 107 sqlite3 *db; /* The database structure */ |
108 int *aRegIdx = 0; /* One register assigned to each index to be updated */ | 108 int *aRegIdx = 0; /* First register in array assigned to each index */ |
109 int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the | 109 int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the |
110 ** an expression for the i-th column of the table. | 110 ** an expression for the i-th column of the table. |
111 ** aXRef[i]==-1 if the i-th column is not changed. */ | 111 ** aXRef[i]==-1 if the i-th column is not changed. */ |
112 u8 *aToOpen; /* 1 for tables and indices to be opened */ | 112 u8 *aToOpen; /* 1 for tables and indices to be opened */ |
113 u8 chngPk; /* PRIMARY KEY changed in a WITHOUT ROWID table */ | 113 u8 chngPk; /* PRIMARY KEY changed in a WITHOUT ROWID table */ |
114 u8 chngRowid; /* Rowid changed in a normal table */ | 114 u8 chngRowid; /* Rowid changed in a normal table */ |
115 u8 chngKey; /* Either chngPk or chngRowid */ | 115 u8 chngKey; /* Either chngPk or chngRowid */ |
116 Expr *pRowidExpr = 0; /* Expression defining the new record number */ | 116 Expr *pRowidExpr = 0; /* Expression defining the new record number */ |
117 AuthContext sContext; /* The authorization context */ | 117 AuthContext sContext; /* The authorization context */ |
118 NameContext sNC; /* The name-context to resolve expressions in */ | 118 NameContext sNC; /* The name-context to resolve expressions in */ |
119 int iDb; /* Database containing the table being updated */ | 119 int iDb; /* Database containing the table being updated */ |
120 int okOnePass; /* True for one-pass algorithm without the FIFO */ | 120 int eOnePass; /* ONEPASS_XXX value from where.c */ |
121 int hasFK; /* True if foreign key processing is required */ | 121 int hasFK; /* True if foreign key processing is required */ |
122 int labelBreak; /* Jump here to break out of UPDATE loop */ | 122 int labelBreak; /* Jump here to break out of UPDATE loop */ |
123 int labelContinue; /* Jump here to continue next step of UPDATE loop */ | 123 int labelContinue; /* Jump here to continue next step of UPDATE loop */ |
| 124 int flags; /* Flags for sqlite3WhereBegin() */ |
124 | 125 |
125 #ifndef SQLITE_OMIT_TRIGGER | 126 #ifndef SQLITE_OMIT_TRIGGER |
126 int isView; /* True when updating a view (INSTEAD OF trigger) */ | 127 int isView; /* True when updating a view (INSTEAD OF trigger) */ |
127 Trigger *pTrigger; /* List of triggers on pTab, if required */ | 128 Trigger *pTrigger; /* List of triggers on pTab, if required */ |
128 int tmask; /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ | 129 int tmask; /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ |
129 #endif | 130 #endif |
130 int newmask; /* Mask of NEW.* columns accessed by BEFORE triggers */ | 131 int newmask; /* Mask of NEW.* columns accessed by BEFORE triggers */ |
131 int iEph = 0; /* Ephemeral table holding all primary key values */ | 132 int iEph = 0; /* Ephemeral table holding all primary key values */ |
132 int nKey = 0; /* Number of elements in regKey for WITHOUT ROWID */ | 133 int nKey = 0; /* Number of elements in regKey for WITHOUT ROWID */ |
133 int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ | 134 int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ |
| 135 int addrOpen = 0; /* Address of OP_OpenEphemeral */ |
| 136 int iPk = 0; /* First of nPk cells holding PRIMARY KEY value */ |
| 137 i16 nPk = 0; /* Number of components of the PRIMARY KEY */ |
| 138 int bReplace = 0; /* True if REPLACE conflict resolution might happen */ |
134 | 139 |
135 /* Register Allocations */ | 140 /* Register Allocations */ |
136 int regRowCount = 0; /* A count of rows changed */ | 141 int regRowCount = 0; /* A count of rows changed */ |
137 int regOldRowid = 0; /* The old rowid */ | 142 int regOldRowid = 0; /* The old rowid */ |
138 int regNewRowid = 0; /* The new rowid */ | 143 int regNewRowid = 0; /* The new rowid */ |
139 int regNew = 0; /* Content of the NEW.* table in triggers */ | 144 int regNew = 0; /* Content of the NEW.* table in triggers */ |
140 int regOld = 0; /* Content of OLD.* table in triggers */ | 145 int regOld = 0; /* Content of OLD.* table in triggers */ |
141 int regRowSet = 0; /* Rowset of rows to be updated */ | 146 int regRowSet = 0; /* Rowset of rows to be updated */ |
142 int regKey = 0; /* composite PRIMARY KEY value */ | 147 int regKey = 0; /* composite PRIMARY KEY value */ |
143 | 148 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 if( IsPrimaryKeyIndex(pIdx) && pPk!=0 ){ | 195 if( IsPrimaryKeyIndex(pIdx) && pPk!=0 ){ |
191 iDataCur = pParse->nTab; | 196 iDataCur = pParse->nTab; |
192 pTabList->a[0].iCursor = iDataCur; | 197 pTabList->a[0].iCursor = iDataCur; |
193 } | 198 } |
194 pParse->nTab++; | 199 pParse->nTab++; |
195 } | 200 } |
196 | 201 |
197 /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. | 202 /* Allocate space for aXRef[], aRegIdx[], and aToOpen[]. |
198 ** Initialize aXRef[] and aToOpen[] to their default values. | 203 ** Initialize aXRef[] and aToOpen[] to their default values. |
199 */ | 204 */ |
200 aXRef = sqlite3DbMallocRaw(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 ); | 205 aXRef = sqlite3DbMallocRawNN(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 ); |
201 if( aXRef==0 ) goto update_cleanup; | 206 if( aXRef==0 ) goto update_cleanup; |
202 aRegIdx = aXRef+pTab->nCol; | 207 aRegIdx = aXRef+pTab->nCol; |
203 aToOpen = (u8*)(aRegIdx+nIdx); | 208 aToOpen = (u8*)(aRegIdx+nIdx); |
204 memset(aToOpen, 1, nIdx+1); | 209 memset(aToOpen, 1, nIdx+1); |
205 aToOpen[nIdx+1] = 0; | 210 aToOpen[nIdx+1] = 0; |
206 for(i=0; i<pTab->nCol; i++) aXRef[i] = -1; | 211 for(i=0; i<pTab->nCol; i++) aXRef[i] = -1; |
207 | 212 |
208 /* Initialize the name-context */ | 213 /* Initialize the name-context */ |
209 memset(&sNC, 0, sizeof(sNC)); | 214 memset(&sNC, 0, sizeof(sNC)); |
210 sNC.pParse = pParse; | 215 sNC.pParse = pParse; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName); | 247 sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName); |
243 pParse->checkSchema = 1; | 248 pParse->checkSchema = 1; |
244 goto update_cleanup; | 249 goto update_cleanup; |
245 } | 250 } |
246 } | 251 } |
247 #ifndef SQLITE_OMIT_AUTHORIZATION | 252 #ifndef SQLITE_OMIT_AUTHORIZATION |
248 { | 253 { |
249 int rc; | 254 int rc; |
250 rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, | 255 rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, |
251 j<0 ? "ROWID" : pTab->aCol[j].zName, | 256 j<0 ? "ROWID" : pTab->aCol[j].zName, |
252 db->aDb[iDb].zName); | 257 db->aDb[iDb].zDbSName); |
253 if( rc==SQLITE_DENY ){ | 258 if( rc==SQLITE_DENY ){ |
254 goto update_cleanup; | 259 goto update_cleanup; |
255 }else if( rc==SQLITE_IGNORE ){ | 260 }else if( rc==SQLITE_IGNORE ){ |
256 aXRef[j] = -1; | 261 aXRef[j] = -1; |
257 } | 262 } |
258 } | 263 } |
259 #endif | 264 #endif |
260 } | 265 } |
261 assert( (chngRowid & chngPk)==0 ); | 266 assert( (chngRowid & chngPk)==0 ); |
262 assert( chngRowid==0 || chngRowid==1 ); | 267 assert( chngRowid==0 || chngRowid==1 ); |
263 assert( chngPk==0 || chngPk==1 ); | 268 assert( chngPk==0 || chngPk==1 ); |
264 chngKey = chngRowid + chngPk; | 269 chngKey = chngRowid + chngPk; |
265 | 270 |
266 /* The SET expressions are not actually used inside the WHERE loop. | 271 /* The SET expressions are not actually used inside the WHERE loop. |
267 ** So reset the colUsed mask. Unless this is a virtual table. In that | 272 ** So reset the colUsed mask. Unless this is a virtual table. In that |
268 ** case, set all bits of the colUsed mask (to ensure that the virtual | 273 ** case, set all bits of the colUsed mask (to ensure that the virtual |
269 ** table implementation makes all columns available). | 274 ** table implementation makes all columns available). |
270 */ | 275 */ |
271 pTabList->a[0].colUsed = IsVirtual(pTab) ? (Bitmask)-1 : 0; | 276 pTabList->a[0].colUsed = IsVirtual(pTab) ? ALLBITS : 0; |
272 | 277 |
273 hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey); | 278 hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey); |
274 | 279 |
275 /* There is one entry in the aRegIdx[] array for each index on the table | 280 /* There is one entry in the aRegIdx[] array for each index on the table |
276 ** being updated. Fill in aRegIdx[] with a register number that will hold | 281 ** being updated. Fill in aRegIdx[] with a register number that will hold |
277 ** the key for accessing each index. | 282 ** the key for accessing each index. |
278 ** | 283 ** |
279 ** FIXME: Be smarter about omitting indexes that use expressions. | 284 ** FIXME: Be smarter about omitting indexes that use expressions. |
280 */ | 285 */ |
281 for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ | 286 for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ |
282 int reg; | 287 int reg; |
283 if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){ | 288 if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){ |
284 reg = ++pParse->nMem; | 289 reg = ++pParse->nMem; |
| 290 pParse->nMem += pIdx->nColumn; |
285 }else{ | 291 }else{ |
286 reg = 0; | 292 reg = 0; |
287 for(i=0; i<pIdx->nKeyCol; i++){ | 293 for(i=0; i<pIdx->nKeyCol; i++){ |
288 i16 iIdxCol = pIdx->aiColumn[i]; | 294 i16 iIdxCol = pIdx->aiColumn[i]; |
289 if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){ | 295 if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){ |
290 reg = ++pParse->nMem; | 296 reg = ++pParse->nMem; |
| 297 pParse->nMem += pIdx->nColumn; |
| 298 if( (onError==OE_Replace) |
| 299 || (onError==OE_Default && pIdx->onError==OE_Replace) |
| 300 ){ |
| 301 bReplace = 1; |
| 302 } |
291 break; | 303 break; |
292 } | 304 } |
293 } | 305 } |
294 } | 306 } |
295 if( reg==0 ) aToOpen[j+1] = 0; | 307 if( reg==0 ) aToOpen[j+1] = 0; |
296 aRegIdx[j] = reg; | 308 aRegIdx[j] = reg; |
297 } | 309 } |
| 310 if( bReplace ){ |
| 311 /* If REPLACE conflict resolution might be invoked, open cursors on all |
| 312 ** indexes in case they are needed to delete records. */ |
| 313 memset(aToOpen, 1, nIdx+1); |
| 314 } |
298 | 315 |
299 /* Begin generating code. */ | 316 /* Begin generating code. */ |
300 v = sqlite3GetVdbe(pParse); | 317 v = sqlite3GetVdbe(pParse); |
301 if( v==0 ) goto update_cleanup; | 318 if( v==0 ) goto update_cleanup; |
302 if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); | 319 if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); |
303 sqlite3BeginWriteOperation(pParse, 1, iDb); | 320 sqlite3BeginWriteOperation(pParse, 1, iDb); |
304 | 321 |
305 /* Allocate required registers. */ | 322 /* Allocate required registers. */ |
306 if( !IsVirtual(pTab) ){ | 323 if( !IsVirtual(pTab) ){ |
307 regRowSet = ++pParse->nMem; | 324 regRowSet = ++pParse->nMem; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 | 357 |
341 #ifndef SQLITE_OMIT_VIRTUALTABLE | 358 #ifndef SQLITE_OMIT_VIRTUALTABLE |
342 /* Virtual tables must be handled separately */ | 359 /* Virtual tables must be handled separately */ |
343 if( IsVirtual(pTab) ){ | 360 if( IsVirtual(pTab) ){ |
344 updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, | 361 updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, |
345 pWhere, onError); | 362 pWhere, onError); |
346 goto update_cleanup; | 363 goto update_cleanup; |
347 } | 364 } |
348 #endif | 365 #endif |
349 | 366 |
350 /* Begin the database scan | 367 /* Initialize the count of updated rows */ |
351 */ | 368 if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){ |
| 369 regRowCount = ++pParse->nMem; |
| 370 sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); |
| 371 } |
| 372 |
352 if( HasRowid(pTab) ){ | 373 if( HasRowid(pTab) ){ |
353 sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid); | 374 sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid); |
354 pWInfo = sqlite3WhereBegin( | |
355 pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, iIdxCur | |
356 ); | |
357 if( pWInfo==0 ) goto update_cleanup; | |
358 okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); | |
359 | |
360 /* Remember the rowid of every item to be updated. | |
361 */ | |
362 sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid); | |
363 if( !okOnePass ){ | |
364 sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid); | |
365 } | |
366 | |
367 /* End the database scan loop. | |
368 */ | |
369 sqlite3WhereEnd(pWInfo); | |
370 }else{ | 375 }else{ |
371 int iPk; /* First of nPk memory cells holding PRIMARY KEY value */ | |
372 i16 nPk; /* Number of components of the PRIMARY KEY */ | |
373 int addrOpen; /* Address of the OpenEphemeral instruction */ | |
374 | |
375 assert( pPk!=0 ); | 376 assert( pPk!=0 ); |
376 nPk = pPk->nKeyCol; | 377 nPk = pPk->nKeyCol; |
377 iPk = pParse->nMem+1; | 378 iPk = pParse->nMem+1; |
378 pParse->nMem += nPk; | 379 pParse->nMem += nPk; |
379 regKey = ++pParse->nMem; | 380 regKey = ++pParse->nMem; |
380 iEph = pParse->nTab++; | 381 iEph = pParse->nTab++; |
| 382 |
381 sqlite3VdbeAddOp2(v, OP_Null, 0, iPk); | 383 sqlite3VdbeAddOp2(v, OP_Null, 0, iPk); |
382 addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk); | 384 addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk); |
383 sqlite3VdbeSetP4KeyInfo(pParse, pPk); | 385 sqlite3VdbeSetP4KeyInfo(pParse, pPk); |
384 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, | 386 } |
385 WHERE_ONEPASS_DESIRED, iIdxCur); | 387 |
386 if( pWInfo==0 ) goto update_cleanup; | 388 /* Begin the database scan. |
387 okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); | 389 ** |
| 390 ** Do not consider a single-pass strategy for a multi-row update if |
| 391 ** there are any triggers or foreign keys to process, or rows may |
| 392 ** be deleted as a result of REPLACE conflict handling. Any of these |
| 393 ** things might disturb a cursor being used to scan through the table |
| 394 ** or index, causing a single-pass approach to malfunction. */ |
| 395 flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE; |
| 396 if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){ |
| 397 flags |= WHERE_ONEPASS_MULTIROW; |
| 398 } |
| 399 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags, iIdxCur); |
| 400 if( pWInfo==0 ) goto update_cleanup; |
| 401 |
| 402 /* A one-pass strategy that might update more than one row may not |
| 403 ** be used if any column of the index used for the scan is being |
| 404 ** updated. Otherwise, if there is an index on "b", statements like |
| 405 ** the following could create an infinite loop: |
| 406 ** |
| 407 ** UPDATE t1 SET b=b+1 WHERE b>? |
| 408 ** |
| 409 ** Fall back to ONEPASS_OFF if where.c has selected a ONEPASS_MULTI |
| 410 ** strategy that uses an index for which one or more columns are being |
| 411 ** updated. */ |
| 412 eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); |
| 413 if( eOnePass==ONEPASS_MULTI ){ |
| 414 int iCur = aiCurOnePass[1]; |
| 415 if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){ |
| 416 eOnePass = ONEPASS_OFF; |
| 417 } |
| 418 assert( iCur!=iDataCur || !HasRowid(pTab) ); |
| 419 } |
| 420 |
| 421 if( HasRowid(pTab) ){ |
| 422 /* Read the rowid of the current row of the WHERE scan. In ONEPASS_OFF |
| 423 ** mode, write the rowid into the FIFO. In either of the one-pass modes, |
| 424 ** leave it in register regOldRowid. */ |
| 425 sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid); |
| 426 if( eOnePass==ONEPASS_OFF ){ |
| 427 sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid); |
| 428 } |
| 429 }else{ |
| 430 /* Read the PK of the current row into an array of registers. In |
| 431 ** ONEPASS_OFF mode, serialize the array into a record and store it in |
| 432 ** the ephemeral table. Or, in ONEPASS_SINGLE or MULTI mode, change |
| 433 ** the OP_OpenEphemeral instruction to a Noop (the ephemeral table |
| 434 ** is not required) and leave the PK fields in the array of registers. */ |
388 for(i=0; i<nPk; i++){ | 435 for(i=0; i<nPk; i++){ |
389 assert( pPk->aiColumn[i]>=0 ); | 436 assert( pPk->aiColumn[i]>=0 ); |
390 sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pPk->aiColumn[i], | 437 sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i); |
391 iPk+i); | |
392 } | 438 } |
393 if( okOnePass ){ | 439 if( eOnePass ){ |
394 sqlite3VdbeChangeToNoop(v, addrOpen); | 440 sqlite3VdbeChangeToNoop(v, addrOpen); |
395 nKey = nPk; | 441 nKey = nPk; |
396 regKey = iPk; | 442 regKey = iPk; |
397 }else{ | 443 }else{ |
398 sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, | 444 sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey, |
399 sqlite3IndexAffinityStr(db, pPk), nPk); | 445 sqlite3IndexAffinityStr(db, pPk), nPk); |
400 sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey); | 446 sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk); |
401 } | 447 } |
402 sqlite3WhereEnd(pWInfo); | |
403 } | 448 } |
404 | 449 |
405 /* Initialize the count of updated rows | 450 if( eOnePass!=ONEPASS_MULTI ){ |
406 */ | 451 sqlite3WhereEnd(pWInfo); |
407 if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){ | |
408 regRowCount = ++pParse->nMem; | |
409 sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); | |
410 } | 452 } |
411 | 453 |
412 labelBreak = sqlite3VdbeMakeLabel(v); | 454 labelBreak = sqlite3VdbeMakeLabel(v); |
413 if( !isView ){ | 455 if( !isView ){ |
414 /* | 456 int addrOnce = 0; |
415 ** Open every index that needs updating. Note that if any | 457 |
416 ** index could potentially invoke a REPLACE conflict resolution | 458 /* Open every index that needs updating. */ |
417 ** action, then we need to open all indices because we might need | 459 if( eOnePass!=ONEPASS_OFF ){ |
418 ** to be deleting some records. | |
419 */ | |
420 if( onError==OE_Replace ){ | |
421 memset(aToOpen, 1, nIdx+1); | |
422 }else{ | |
423 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ | |
424 if( pIdx->onError==OE_Replace ){ | |
425 memset(aToOpen, 1, nIdx+1); | |
426 break; | |
427 } | |
428 } | |
429 } | |
430 if( okOnePass ){ | |
431 if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; | 460 if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0; |
432 if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; | 461 if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0; |
433 } | 462 } |
| 463 |
| 464 if( eOnePass==ONEPASS_MULTI && (nIdx-(aiCurOnePass[1]>=0))>0 ){ |
| 465 addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); |
| 466 } |
434 sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen, | 467 sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen, |
435 0, 0); | 468 0, 0); |
| 469 if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); |
436 } | 470 } |
437 | 471 |
438 /* Top of the update loop */ | 472 /* Top of the update loop */ |
439 if( okOnePass ){ | 473 if( eOnePass!=ONEPASS_OFF ){ |
440 if( aToOpen[iDataCur-iBaseCur] && !isView ){ | 474 if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){ |
441 assert( pPk ); | 475 assert( pPk ); |
442 sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); | 476 sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey); |
443 VdbeCoverageNeverTaken(v); | 477 VdbeCoverageNeverTaken(v); |
444 } | 478 } |
445 labelContinue = labelBreak; | 479 if( eOnePass==ONEPASS_SINGLE ){ |
| 480 labelContinue = labelBreak; |
| 481 }else{ |
| 482 labelContinue = sqlite3VdbeMakeLabel(v); |
| 483 } |
446 sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); | 484 sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak); |
447 VdbeCoverageIf(v, pPk==0); | 485 VdbeCoverageIf(v, pPk==0); |
448 VdbeCoverageIf(v, pPk!=0); | 486 VdbeCoverageIf(v, pPk!=0); |
449 }else if( pPk ){ | 487 }else if( pPk ){ |
450 labelContinue = sqlite3VdbeMakeLabel(v); | 488 labelContinue = sqlite3VdbeMakeLabel(v); |
451 sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); | 489 sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v); |
452 addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey); | 490 addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey); |
453 sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); | 491 sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0); |
454 VdbeCoverage(v); | 492 VdbeCoverage(v); |
455 }else{ | 493 }else{ |
456 labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak, | 494 labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak, |
457 regOldRowid); | 495 regOldRowid); |
458 VdbeCoverage(v); | 496 VdbeCoverage(v); |
459 sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); | 497 sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid); |
460 VdbeCoverage(v); | 498 VdbeCoverage(v); |
461 } | 499 } |
462 | 500 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 */ | 598 */ |
561 for(i=0; i<pTab->nCol; i++){ | 599 for(i=0; i<pTab->nCol; i++){ |
562 if( aXRef[i]<0 && i!=pTab->iPKey ){ | 600 if( aXRef[i]<0 && i!=pTab->iPKey ){ |
563 sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i); | 601 sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i); |
564 } | 602 } |
565 } | 603 } |
566 } | 604 } |
567 | 605 |
568 if( !isView ){ | 606 if( !isView ){ |
569 int addr1 = 0; /* Address of jump instruction */ | 607 int addr1 = 0; /* Address of jump instruction */ |
570 int bReplace = 0; /* True if REPLACE conflict resolution might happen */ | |
571 | 608 |
572 /* Do constraint checks. */ | 609 /* Do constraint checks. */ |
573 assert( regOldRowid>0 ); | 610 assert( regOldRowid>0 ); |
574 sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, | 611 sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, |
575 regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace); | 612 regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, |
| 613 aXRef); |
576 | 614 |
577 /* Do FK constraint checks. */ | 615 /* Do FK constraint checks. */ |
578 if( hasFK ){ | 616 if( hasFK ){ |
579 sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey); | 617 sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey); |
580 } | 618 } |
581 | 619 |
582 /* Delete the index entries associated with the current record. */ | 620 /* Delete the index entries associated with the current record. */ |
583 if( bReplace || chngKey ){ | 621 if( bReplace || chngKey ){ |
584 if( pPk ){ | 622 if( pPk ){ |
585 addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); | 623 addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); |
586 }else{ | 624 }else{ |
587 addr1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); | 625 addr1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); |
588 } | 626 } |
589 VdbeCoverageNeverTaken(v); | 627 VdbeCoverageNeverTaken(v); |
590 } | 628 } |
591 sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1); | 629 sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1); |
592 | 630 |
593 /* If changing the record number, delete the old record. */ | 631 /* If changing the rowid value, or if there are foreign key constraints |
594 if( hasFK || chngKey || pPk!=0 ){ | 632 ** to process, delete the old record. Otherwise, add a noop OP_Delete |
| 633 ** to invoke the pre-update hook. |
| 634 ** |
| 635 ** That (regNew==regnewRowid+1) is true is also important for the |
| 636 ** pre-update hook. If the caller invokes preupdate_new(), the returned |
| 637 ** value is copied from memory cell (regNewRowid+1+iCol), where iCol |
| 638 ** is the column index supplied by the user. |
| 639 */ |
| 640 assert( regNew==regNewRowid+1 ); |
| 641 #ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 642 sqlite3VdbeAddOp3(v, OP_Delete, iDataCur, |
| 643 OPFLAG_ISUPDATE | ((hasFK || chngKey) ? 0 : OPFLAG_ISNOOP), |
| 644 regNewRowid |
| 645 ); |
| 646 if( eOnePass==ONEPASS_MULTI ){ |
| 647 assert( hasFK==0 && chngKey==0 ); |
| 648 sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION); |
| 649 } |
| 650 if( !pParse->nested ){ |
| 651 sqlite3VdbeAppendP4(v, pTab, P4_TABLE); |
| 652 } |
| 653 #else |
| 654 if( hasFK || chngKey ){ |
595 sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0); | 655 sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0); |
596 } | 656 } |
| 657 #endif |
597 if( bReplace || chngKey ){ | 658 if( bReplace || chngKey ){ |
598 sqlite3VdbeJumpHere(v, addr1); | 659 sqlite3VdbeJumpHere(v, addr1); |
599 } | 660 } |
600 | 661 |
601 if( hasFK ){ | 662 if( hasFK ){ |
602 sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey); | 663 sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey); |
603 } | 664 } |
604 | 665 |
605 /* Insert the new index entries and the new record. */ | 666 /* Insert the new index entries and the new record. */ |
606 sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur, | 667 sqlite3CompleteInsertion( |
607 regNewRowid, aRegIdx, 1, 0, 0); | 668 pParse, pTab, iDataCur, iIdxCur, regNewRowid, aRegIdx, |
| 669 OPFLAG_ISUPDATE | (eOnePass==ONEPASS_MULTI ? OPFLAG_SAVEPOSITION : 0), |
| 670 0, 0 |
| 671 ); |
608 | 672 |
609 /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to | 673 /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to |
610 ** handle rows (possibly in other tables) that refer via a foreign key | 674 ** handle rows (possibly in other tables) that refer via a foreign key |
611 ** to the row just updated. */ | 675 ** to the row just updated. */ |
612 if( hasFK ){ | 676 if( hasFK ){ |
613 sqlite3FkActions(pParse, pTab, pChanges, regOldRowid, aXRef, chngKey); | 677 sqlite3FkActions(pParse, pTab, pChanges, regOldRowid, aXRef, chngKey); |
614 } | 678 } |
615 } | 679 } |
616 | 680 |
617 /* Increment the row counter | 681 /* Increment the row counter |
618 */ | 682 */ |
619 if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab){ | 683 if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab){ |
620 sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); | 684 sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); |
621 } | 685 } |
622 | 686 |
623 sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, | 687 sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, |
624 TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue); | 688 TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue); |
625 | 689 |
626 /* Repeat the above with the next record to be updated, until | 690 /* Repeat the above with the next record to be updated, until |
627 ** all record selected by the WHERE clause have been updated. | 691 ** all record selected by the WHERE clause have been updated. |
628 */ | 692 */ |
629 if( okOnePass ){ | 693 if( eOnePass==ONEPASS_SINGLE ){ |
630 /* Nothing to do at end-of-loop for a single-pass */ | 694 /* Nothing to do at end-of-loop for a single-pass */ |
| 695 }else if( eOnePass==ONEPASS_MULTI ){ |
| 696 sqlite3VdbeResolveLabel(v, labelContinue); |
| 697 sqlite3WhereEnd(pWInfo); |
631 }else if( pPk ){ | 698 }else if( pPk ){ |
632 sqlite3VdbeResolveLabel(v, labelContinue); | 699 sqlite3VdbeResolveLabel(v, labelContinue); |
633 sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v); | 700 sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v); |
634 }else{ | 701 }else{ |
635 sqlite3VdbeGoto(v, labelContinue); | 702 sqlite3VdbeGoto(v, labelContinue); |
636 } | 703 } |
637 sqlite3VdbeResolveLabel(v, labelBreak); | 704 sqlite3VdbeResolveLabel(v, labelBreak); |
638 | 705 |
639 /* Close all tables */ | |
640 for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ | |
641 assert( aRegIdx ); | |
642 if( aToOpen[i+1] ){ | |
643 sqlite3VdbeAddOp2(v, OP_Close, iIdxCur+i, 0); | |
644 } | |
645 } | |
646 if( iDataCur<iIdxCur ) sqlite3VdbeAddOp2(v, OP_Close, iDataCur, 0); | |
647 | |
648 /* Update the sqlite_sequence table by storing the content of the | 706 /* Update the sqlite_sequence table by storing the content of the |
649 ** maximum rowid counter values recorded while inserting into | 707 ** maximum rowid counter values recorded while inserting into |
650 ** autoincrement tables. | 708 ** autoincrement tables. |
651 */ | 709 */ |
652 if( pParse->nested==0 && pParse->pTriggerTab==0 ){ | 710 if( pParse->nested==0 && pParse->pTriggerTab==0 ){ |
653 sqlite3AutoincrementEnd(pParse); | 711 sqlite3AutoincrementEnd(pParse); |
654 } | 712 } |
655 | 713 |
656 /* | 714 /* |
657 ** Return the number of rows that were changed. If this routine is | 715 ** Return the number of rows that were changed. If this routine is |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
800 ** jump to here if the scan visited zero rows. */ | 858 ** jump to here if the scan visited zero rows. */ |
801 if( bOnePass==0 ){ | 859 if( bOnePass==0 ){ |
802 sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); | 860 sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); |
803 sqlite3VdbeJumpHere(v, addr); | 861 sqlite3VdbeJumpHere(v, addr); |
804 sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); | 862 sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0); |
805 }else{ | 863 }else{ |
806 sqlite3WhereEnd(pWInfo); | 864 sqlite3WhereEnd(pWInfo); |
807 } | 865 } |
808 } | 866 } |
809 #endif /* SQLITE_OMIT_VIRTUALTABLE */ | 867 #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
OLD | NEW |