Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: third_party/sqlite/src/src/update.c

Issue 2751253002: [sql] Import SQLite 3.17.0. (Closed)
Patch Set: also clang on Linux i386 Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/sqlite/src/src/trigger.c ('k') | third_party/sqlite/src/src/utf.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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 */
OLDNEW
« no previous file with comments | « third_party/sqlite/src/src/trigger.c ('k') | third_party/sqlite/src/src/utf.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698