File Coverage

update.c
Criterion Covered Total %
statement 0 199 0.0
branch 0 156 0.0
condition n/a
subroutine n/a
pod n/a
total 0 355 0.0


line stmt bran cond sub pod time code
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 UPDATE statements.
14             **
15             ** $Id: update.c,v 1.1.1.1 2004/08/08 15:03:58 matt Exp $
16             */
17             #include "sqliteInt.h"
18              
19             /*
20             ** Process an UPDATE statement.
21             **
22             ** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
23             ** \_______/ \________/ \______/ \________________/
24             * onError pTabList pChanges pWhere
25             */
26 0           void sqliteUpdate(
27             Parse *pParse, /* The parser context */
28             SrcList *pTabList, /* The table in which we should change things */
29             ExprList *pChanges, /* Things to be changed */
30             Expr *pWhere, /* The WHERE clause. May be null */
31             int onError /* How to handle constraint errors */
32             ){
33             int i, j; /* Loop counters */
34             Table *pTab; /* The table to be updated */
35             int loopStart; /* VDBE instruction address of the start of the loop */
36             int jumpInst; /* Addr of VDBE instruction to jump out of loop */
37             WhereInfo *pWInfo; /* Information about the WHERE clause */
38             Vdbe *v; /* The virtual database engine */
39             Index *pIdx; /* For looping over indices */
40             int nIdx; /* Number of indices that need updating */
41             int nIdxTotal; /* Total number of indices */
42             int iCur; /* VDBE Cursor number of pTab */
43             sqlite *db; /* The database structure */
44 0           Index **apIdx = 0; /* An array of indices that need updating too */
45 0           char *aIdxUsed = 0; /* aIdxUsed[i]==1 if the i-th index is used */
46 0           int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
47             ** an expression for the i-th column of the table.
48             ** aXRef[i]==-1 if the i-th column is not changed. */
49             int chngRecno; /* True if the record number is being changed */
50             Expr *pRecnoExpr; /* Expression defining the new record number */
51             int openAll; /* True if all indices need to be opened */
52             int isView; /* Trying to update a view */
53             int iStackDepth; /* Index of memory cell holding stack depth */
54             AuthContext sContext; /* The authorization context */
55              
56             int before_triggers; /* True if there are any BEFORE triggers */
57             int after_triggers; /* True if there are any AFTER triggers */
58 0           int row_triggers_exist = 0; /* True if any row triggers exist */
59              
60 0           int newIdx = -1; /* index of trigger "new" temp table */
61 0           int oldIdx = -1; /* index of trigger "old" temp table */
62              
63 0           sContext.pParse = 0;
64 0 0         if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;
    0          
65 0           db = pParse->db;
66             assert( pTabList->nSrc==1 );
67 0           iStackDepth = pParse->nMem++;
68              
69             /* Locate the table which we want to update.
70             */
71 0           pTab = sqliteSrcListLookup(pParse, pTabList);
72 0 0         if( pTab==0 ) goto update_cleanup;
73 0           before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
74             TK_UPDATE, TK_BEFORE, TK_ROW, pChanges);
75 0           after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
76             TK_UPDATE, TK_AFTER, TK_ROW, pChanges);
77 0 0         row_triggers_exist = before_triggers || after_triggers;
    0          
78 0           isView = pTab->pSelect!=0;
79 0 0         if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
80 0           goto update_cleanup;
81             }
82 0 0         if( isView ){
83 0 0         if( sqliteViewGetColumnNames(pParse, pTab) ){
84 0           goto update_cleanup;
85             }
86             }
87 0           aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
88 0 0         if( aXRef==0 ) goto update_cleanup;
89 0 0         for(i=0; inCol; i++) aXRef[i] = -1;
90              
91             /* If there are FOR EACH ROW triggers, allocate cursors for the
92             ** special OLD and NEW tables
93             */
94 0 0         if( row_triggers_exist ){
95 0           newIdx = pParse->nTab++;
96 0           oldIdx = pParse->nTab++;
97             }
98              
99             /* Allocate a cursors for the main database table and for all indices.
100             ** The index cursors might not be used, but if they are used they
101             ** need to occur right after the database cursor. So go ahead and
102             ** allocate enough space, just in case.
103             */
104 0           pTabList->a[0].iCursor = iCur = pParse->nTab++;
105 0 0         for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
106 0           pParse->nTab++;
107             }
108              
109             /* Resolve the column names in all the expressions of the
110             ** of the UPDATE statement. Also find the column index
111             ** for each column to be updated in the pChanges array. For each
112             ** column to be updated, make sure we have authorization to change
113             ** that column.
114             */
115 0           chngRecno = 0;
116 0 0         for(i=0; inExpr; i++){
117 0 0         if( sqliteExprResolveIds(pParse, pTabList, 0, pChanges->a[i].pExpr) ){
118 0           goto update_cleanup;
119             }
120 0 0         if( sqliteExprCheck(pParse, pChanges->a[i].pExpr, 0, 0) ){
121 0           goto update_cleanup;
122             }
123 0 0         for(j=0; jnCol; j++){
124 0 0         if( sqliteStrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
125 0 0         if( j==pTab->iPKey ){
126 0           chngRecno = 1;
127 0           pRecnoExpr = pChanges->a[i].pExpr;
128             }
129 0           aXRef[j] = i;
130 0           break;
131             }
132             }
133 0 0         if( j>=pTab->nCol ){
134 0 0         if( sqliteIsRowid(pChanges->a[i].zName) ){
135 0           chngRecno = 1;
136 0           pRecnoExpr = pChanges->a[i].pExpr;
137             }else{
138 0           sqliteErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
139 0           goto update_cleanup;
140             }
141             }
142             #ifndef SQLITE_OMIT_AUTHORIZATION
143             {
144             int rc;
145 0           rc = sqliteAuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
146 0           pTab->aCol[j].zName, db->aDb[pTab->iDb].zName);
147 0 0         if( rc==SQLITE_DENY ){
148 0           goto update_cleanup;
149 0 0         }else if( rc==SQLITE_IGNORE ){
150 0           aXRef[j] = -1;
151             }
152             }
153             #endif
154             }
155              
156             /* Allocate memory for the array apIdx[] and fill it with pointers to every
157             ** index that needs to be updated. Indices only need updating if their
158             ** key includes one of the columns named in pChanges or if the record
159             ** number of the original table entry is changing.
160             */
161 0 0         for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){
162 0 0         if( chngRecno ){
163 0           i = 0;
164             }else {
165 0 0         for(i=0; inColumn; i++){
166 0 0         if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
167             }
168             }
169 0 0         if( inColumn ) nIdx++;
170             }
171 0 0         if( nIdxTotal>0 ){
172 0           apIdx = sqliteMalloc( sizeof(Index*) * nIdx + nIdxTotal );
173 0 0         if( apIdx==0 ) goto update_cleanup;
174 0           aIdxUsed = (char*)&apIdx[nIdx];
175             }
176 0 0         for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
177 0 0         if( chngRecno ){
178 0           i = 0;
179             }else{
180 0 0         for(i=0; inColumn; i++){
181 0 0         if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
182             }
183             }
184 0 0         if( inColumn ){
185 0           apIdx[nIdx++] = pIdx;
186 0           aIdxUsed[j] = 1;
187             }else{
188 0           aIdxUsed[j] = 0;
189             }
190             }
191              
192             /* Resolve the column names in all the expressions in the
193             ** WHERE clause.
194             */
195 0 0         if( pWhere ){
196 0 0         if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
197 0           goto update_cleanup;
198             }
199 0 0         if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
200 0           goto update_cleanup;
201             }
202             }
203              
204             /* Start the view context
205             */
206 0 0         if( isView ){
207 0           sqliteAuthContextPush(pParse, &sContext, pTab->zName);
208             }
209              
210             /* Begin generating code.
211             */
212 0           v = sqliteGetVdbe(pParse);
213 0 0         if( v==0 ) goto update_cleanup;
214 0           sqliteBeginWriteOperation(pParse, 1, pTab->iDb);
215              
216             /* If we are trying to update a view, construct that view into
217             ** a temporary table.
218             */
219 0 0         if( isView ){
220             Select *pView;
221 0           pView = sqliteSelectDup(pTab->pSelect);
222 0           sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
223 0           sqliteSelectDelete(pView);
224             }
225              
226             /* Begin the database scan
227             */
228 0           pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0);
229 0 0         if( pWInfo==0 ) goto update_cleanup;
230              
231             /* Remember the index of every item to be updated.
232             */
233 0           sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
234              
235             /* End the database scan loop.
236             */
237 0           sqliteWhereEnd(pWInfo);
238              
239             /* Initialize the count of updated rows
240             */
241 0 0         if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
    0          
242 0           sqliteVdbeAddOp(v, OP_Integer, 0, 0);
243             }
244              
245 0 0         if( row_triggers_exist ){
246             /* Create pseudo-tables for NEW and OLD
247             */
248 0           sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
249 0           sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
250              
251             /* The top of the update loop for when there are triggers.
252             */
253 0           sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
254 0           sqliteVdbeAddOp(v, OP_StackDepth, 0, 0);
255 0           sqliteVdbeAddOp(v, OP_MemStore, iStackDepth, 1);
256 0           loopStart = sqliteVdbeAddOp(v, OP_MemLoad, iStackDepth, 0);
257 0           sqliteVdbeAddOp(v, OP_StackReset, 0, 0);
258 0           jumpInst = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
259 0           sqliteVdbeAddOp(v, OP_Dup, 0, 0);
260              
261             /* Open a cursor and make it point to the record that is
262             ** being updated.
263             */
264 0           sqliteVdbeAddOp(v, OP_Dup, 0, 0);
265 0 0         if( !isView ){
266 0           sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
267 0           sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
268             }
269 0           sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
270              
271             /* Generate the OLD table
272             */
273 0           sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
274 0           sqliteVdbeAddOp(v, OP_RowData, iCur, 0);
275 0           sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
276              
277             /* Generate the NEW table
278             */
279 0 0         if( chngRecno ){
280 0           sqliteExprCode(pParse, pRecnoExpr);
281             }else{
282 0           sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
283             }
284 0 0         for(i=0; inCol; i++){
285 0 0         if( i==pTab->iPKey ){
286 0           sqliteVdbeAddOp(v, OP_String, 0, 0);
287 0           continue;
288             }
289 0           j = aXRef[i];
290 0 0         if( j<0 ){
291 0           sqliteVdbeAddOp(v, OP_Column, iCur, i);
292             }else{
293 0           sqliteExprCode(pParse, pChanges->a[j].pExpr);
294             }
295             }
296 0           sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
297 0           sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
298 0 0         if( !isView ){
299 0           sqliteVdbeAddOp(v, OP_Close, iCur, 0);
300             }
301              
302             /* Fire the BEFORE and INSTEAD OF triggers
303             */
304 0 0         if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab,
305             newIdx, oldIdx, onError, loopStart) ){
306 0           goto update_cleanup;
307             }
308             }
309              
310 0 0         if( !isView ){
311             /*
312             ** Open every index that needs updating. Note that if any
313             ** index could potentially invoke a REPLACE conflict resolution
314             ** action, then we need to open all indices because we might need
315             ** to be deleting some records.
316             */
317 0           sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
318 0           sqliteVdbeAddOp(v, OP_OpenWrite, iCur, pTab->tnum);
319 0 0         if( onError==OE_Replace ){
320 0           openAll = 1;
321             }else{
322 0           openAll = 0;
323 0 0         for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
324 0 0         if( pIdx->onError==OE_Replace ){
325 0           openAll = 1;
326 0           break;
327             }
328             }
329             }
330 0 0         for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
331 0 0         if( openAll || aIdxUsed[i] ){
    0          
332 0           sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
333 0           sqliteVdbeAddOp(v, OP_OpenWrite, iCur+i+1, pIdx->tnum);
334             assert( pParse->nTab>iCur+i+1 );
335             }
336             }
337              
338             /* Loop over every record that needs updating. We have to load
339             ** the old data for each record to be updated because some columns
340             ** might not change and we will need to copy the old value.
341             ** Also, the old data is needed to delete the old index entires.
342             ** So make the cursor point at the old record.
343             */
344 0 0         if( !row_triggers_exist ){
345 0           sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
346 0           jumpInst = loopStart = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
347 0           sqliteVdbeAddOp(v, OP_Dup, 0, 0);
348             }
349 0           sqliteVdbeAddOp(v, OP_NotExists, iCur, loopStart);
350              
351             /* If the record number will change, push the record number as it
352             ** will be after the update. (The old record number is currently
353             ** on top of the stack.)
354             */
355 0 0         if( chngRecno ){
356 0           sqliteExprCode(pParse, pRecnoExpr);
357 0           sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
358             }
359              
360             /* Compute new data for this record.
361             */
362 0 0         for(i=0; inCol; i++){
363 0 0         if( i==pTab->iPKey ){
364 0           sqliteVdbeAddOp(v, OP_String, 0, 0);
365 0           continue;
366             }
367 0           j = aXRef[i];
368 0 0         if( j<0 ){
369 0           sqliteVdbeAddOp(v, OP_Column, iCur, i);
370             }else{
371 0           sqliteExprCode(pParse, pChanges->a[j].pExpr);
372             }
373             }
374              
375             /* Do constraint checks
376             */
377 0           sqliteGenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRecno, 1,
378             onError, loopStart);
379              
380             /* Delete the old indices for the current record.
381             */
382 0           sqliteGenerateRowIndexDelete(db, v, pTab, iCur, aIdxUsed);
383              
384             /* If changing the record number, delete the old record.
385             */
386 0 0         if( chngRecno ){
387 0           sqliteVdbeAddOp(v, OP_Delete, iCur, 0);
388             }
389              
390             /* Create the new index entries and the new record.
391             */
392 0           sqliteCompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRecno, 1, -1);
393             }
394              
395             /* Increment the row counter
396             */
397 0 0         if( db->flags & SQLITE_CountRows && !pParse->trigStack){
    0          
398 0           sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
399             }
400              
401             /* If there are triggers, close all the cursors after each iteration
402             ** through the loop. The fire the after triggers.
403             */
404 0 0         if( row_triggers_exist ){
405 0 0         if( !isView ){
406 0 0         for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
407 0 0         if( openAll || aIdxUsed[i] )
    0          
408 0           sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0);
409             }
410 0           sqliteVdbeAddOp(v, OP_Close, iCur, 0);
411 0           pParse->nTab = iCur;
412             }
413 0 0         if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab,
414             newIdx, oldIdx, onError, loopStart) ){
415 0           goto update_cleanup;
416             }
417             }
418              
419             /* Repeat the above with the next record to be updated, until
420             ** all record selected by the WHERE clause have been updated.
421             */
422 0           sqliteVdbeAddOp(v, OP_Goto, 0, loopStart);
423 0           sqliteVdbeChangeP2(v, jumpInst, sqliteVdbeCurrentAddr(v));
424 0           sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
425              
426             /* Close all tables if there were no FOR EACH ROW triggers */
427 0 0         if( !row_triggers_exist ){
428 0 0         for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
429 0 0         if( openAll || aIdxUsed[i] ){
    0          
430 0           sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0);
431             }
432             }
433 0           sqliteVdbeAddOp(v, OP_Close, iCur, 0);
434 0           pParse->nTab = iCur;
435             }else{
436 0           sqliteVdbeAddOp(v, OP_Close, newIdx, 0);
437 0           sqliteVdbeAddOp(v, OP_Close, oldIdx, 0);
438             }
439              
440 0           sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
441 0           sqliteEndWriteOperation(pParse);
442              
443             /*
444             ** Return the number of rows that were changed.
445             */
446 0 0         if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
    0          
447 0           sqliteVdbeOp3(v, OP_ColumnName, 0, 1, "rows updated", P3_STATIC);
448 0           sqliteVdbeAddOp(v, OP_Callback, 1, 0);
449             }
450              
451             update_cleanup:
452 0           sqliteAuthContextPop(&sContext);
453 0           sqliteFree(apIdx);
454 0           sqliteFree(aXRef);
455 0           sqliteSrcListDelete(pTabList);
456 0           sqliteExprListDelete(pChanges);
457 0           sqliteExprDelete(pWhere);
458 0           return;
459             }