1434
|
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.123 2006/02/24 02:53:50 drh Exp $
|
|
16 */
|
|
17 #include "sqliteInt.h"
|
|
18
|
|
19 /*
|
|
20 ** The most recently coded instruction was an OP_Column to retrieve the
|
|
21 ** i-th column of table pTab. This routine sets the P3 parameter of the
|
|
22 ** OP_Column to the default value, if any.
|
|
23 **
|
|
24 ** The default value of a column is specified by a DEFAULT clause in the
|
|
25 ** column definition. This was either supplied by the user when the table
|
|
26 ** was created, or added later to the table definition by an ALTER TABLE
|
|
27 ** command. If the latter, then the row-records in the table btree on disk
|
|
28 ** may not contain a value for the column and the default value, taken
|
|
29 ** from the P3 parameter of the OP_Column instruction, is returned instead.
|
|
30 ** If the former, then all row-records are guaranteed to include a value
|
|
31 ** for the column and the P3 value is not required.
|
|
32 **
|
|
33 ** Column definitions created by an ALTER TABLE command may only have
|
|
34 ** literal default values specified: a number, null or a string. (If a more
|
|
35 ** complicated default expression value was provided, it is evaluated
|
|
36 ** when the ALTER TABLE is executed and one of the literal values written
|
|
37 ** into the sqlite_master table.)
|
|
38 **
|
|
39 ** Therefore, the P3 parameter is only required if the default value for
|
|
40 ** the column is a literal number, string or null. The sqlite3ValueFromExpr()
|
|
41 ** function is capable of transforming these types of expressions into
|
|
42 ** sqlite3_value objects.
|
|
43 */
|
|
44 void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){
|
|
45 if( pTab && !pTab->pSelect ){
|
|
46 sqlite3_value *pValue;
|
|
47 u8 enc = ENC(sqlite3VdbeDb(v));
|
|
48 Column *pCol = &pTab->aCol[i];
|
|
49 sqlite3ValueFromExpr(pCol->pDflt, enc, pCol->affinity, &pValue);
|
|
50 if( pValue ){
|
|
51 sqlite3VdbeChangeP3(v, -1, (const char *)pValue, P3_MEM);
|
|
52 }else{
|
|
53 VdbeComment((v, "# %s.%s", pTab->zName, pCol->zName));
|
|
54 }
|
|
55 }
|
|
56 }
|
|
57
|
|
58 /*
|
|
59 ** Process an UPDATE statement.
|
|
60 **
|
|
61 ** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
|
|
62 ** \_______/ \________/ \______/ \________________/
|
|
63 * onError pTabList pChanges pWhere
|
|
64 */
|
|
65 void sqlite3Update(
|
|
66 Parse *pParse, /* The parser context */
|
|
67 SrcList *pTabList, /* The table in which we should change things */
|
|
68 ExprList *pChanges, /* Things to be changed */
|
|
69 Expr *pWhere, /* The WHERE clause. May be null */
|
|
70 int onError /* How to handle constraint errors */
|
|
71 ){
|
|
72 int i, j; /* Loop counters */
|
|
73 Table *pTab; /* The table to be updated */
|
|
74 int addr = 0; /* VDBE instruction address of the start of the loop */
|
|
75 WhereInfo *pWInfo; /* Information about the WHERE clause */
|
|
76 Vdbe *v; /* The virtual database engine */
|
|
77 Index *pIdx; /* For looping over indices */
|
|
78 int nIdx; /* Number of indices that need updating */
|
|
79 int nIdxTotal; /* Total number of indices */
|
|
80 int iCur; /* VDBE Cursor number of pTab */
|
|
81 sqlite3 *db; /* The database structure */
|
|
82 Index **apIdx = 0; /* An array of indices that need updating too */
|
|
83 char *aIdxUsed = 0; /* aIdxUsed[i]==1 if the i-th index is used */
|
|
84 int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
|
|
85 ** an expression for the i-th column of the table.
|
|
86 ** aXRef[i]==-1 if the i-th column is not changed. */
|
|
87 int chngRowid; /* True if the record number is being changed */
|
|
88 Expr *pRowidExpr = 0; /* Expression defining the new record number */
|
|
89 int openAll = 0; /* True if all indices need to be opened */
|
|
90 AuthContext sContext; /* The authorization context */
|
|
91 NameContext sNC; /* The name-context to resolve expressions in */
|
|
92 int iDb; /* Database containing the table being updated */
|
|
93
|
|
94 #ifndef SQLITE_OMIT_TRIGGER
|
|
95 int isView; /* Trying to update a view */
|
|
96 int triggers_exist = 0; /* True if any row triggers exist */
|
|
97 #endif
|
|
98
|
|
99 int newIdx = -1; /* index of trigger "new" temp table */
|
|
100 int oldIdx = -1; /* index of trigger "old" temp table */
|
|
101
|
|
102 sContext.pParse = 0;
|
|
103 if( pParse->nErr || sqlite3MallocFailed() ){
|
|
104 goto update_cleanup;
|
|
105 }
|
|
106 db = pParse->db;
|
|
107 assert( pTabList->nSrc==1 );
|
|
108
|
|
109 /* Locate the table which we want to update.
|
|
110 */
|
|
111 pTab = sqlite3SrcListLookup(pParse, pTabList);
|
|
112 if( pTab==0 ) goto update_cleanup;
|
|
113 iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
|
114
|
|
115 /* Figure out if we have any triggers and if the table being
|
|
116 ** updated is a view
|
|
117 */
|
|
118 #ifndef SQLITE_OMIT_TRIGGER
|
|
119 triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges);
|
|
120 isView = pTab->pSelect!=0;
|
|
121 #else
|
|
122 # define triggers_exist 0
|
|
123 # define isView 0
|
|
124 #endif
|
|
125 #ifdef SQLITE_OMIT_VIEW
|
|
126 # undef isView
|
|
127 # define isView 0
|
|
128 #endif
|
|
129
|
|
130 if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
|
|
131 goto update_cleanup;
|
|
132 }
|
|
133 if( isView ){
|
|
134 if( sqlite3ViewGetColumnNames(pParse, pTab) ){
|
|
135 goto update_cleanup;
|
|
136 }
|
|
137 }
|
|
138 aXRef = sqliteMallocRaw( sizeof(int) * pTab->nCol );
|
|
139 if( aXRef==0 ) goto update_cleanup;
|
|
140 for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
|
|
141
|
|
142 /* If there are FOR EACH ROW triggers, allocate cursors for the
|
|
143 ** special OLD and NEW tables
|
|
144 */
|
|
145 if( triggers_exist ){
|
|
146 newIdx = pParse->nTab++;
|
|
147 oldIdx = pParse->nTab++;
|
|
148 }
|
|
149
|
|
150 /* Allocate a cursors for the main database table and for all indices.
|
|
151 ** The index cursors might not be used, but if they are used they
|
|
152 ** need to occur right after the database cursor. So go ahead and
|
|
153 ** allocate enough space, just in case.
|
|
154 */
|
|
155 pTabList->a[0].iCursor = iCur = pParse->nTab++;
|
|
156 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
|
157 pParse->nTab++;
|
|
158 }
|
|
159
|
|
160 /* Initialize the name-context */
|
|
161 memset(&sNC, 0, sizeof(sNC));
|
|
162 sNC.pParse = pParse;
|
|
163 sNC.pSrcList = pTabList;
|
|
164
|
|
165 /* Resolve the column names in all the expressions of the
|
|
166 ** of the UPDATE statement. Also find the column index
|
|
167 ** for each column to be updated in the pChanges array. For each
|
|
168 ** column to be updated, make sure we have authorization to change
|
|
169 ** that column.
|
|
170 */
|
|
171 chngRowid = 0;
|
|
172 for(i=0; i<pChanges->nExpr; i++){
|
|
173 if( sqlite3ExprResolveNames(&sNC, pChanges->a[i].pExpr) ){
|
|
174 goto update_cleanup;
|
|
175 }
|
|
176 for(j=0; j<pTab->nCol; j++){
|
|
177 if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
|
|
178 if( j==pTab->iPKey ){
|
|
179 chngRowid = 1;
|
|
180 pRowidExpr = pChanges->a[i].pExpr;
|
|
181 }
|
|
182 aXRef[j] = i;
|
|
183 break;
|
|
184 }
|
|
185 }
|
|
186 if( j>=pTab->nCol ){
|
|
187 if( sqlite3IsRowid(pChanges->a[i].zName) ){
|
|
188 chngRowid = 1;
|
|
189 pRowidExpr = pChanges->a[i].pExpr;
|
|
190 }else{
|
|
191 sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
|
|
192 goto update_cleanup;
|
|
193 }
|
|
194 }
|
|
195 #ifndef SQLITE_OMIT_AUTHORIZATION
|
|
196 {
|
|
197 int rc;
|
|
198 rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
|
|
199 pTab->aCol[j].zName, db->aDb[iDb].zName);
|
|
200 if( rc==SQLITE_DENY ){
|
|
201 goto update_cleanup;
|
|
202 }else if( rc==SQLITE_IGNORE ){
|
|
203 aXRef[j] = -1;
|
|
204 }
|
|
205 }
|
|
206 #endif
|
|
207 }
|
|
208
|
|
209 /* Allocate memory for the array apIdx[] and fill it with pointers to every
|
|
210 ** index that needs to be updated. Indices only need updating if their
|
|
211 ** key includes one of the columns named in pChanges or if the record
|
|
212 ** number of the original table entry is changing.
|
|
213 */
|
|
214 for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){
|
|
215 if( chngRowid ){
|
|
216 i = 0;
|
|
217 }else {
|
|
218 for(i=0; i<pIdx->nColumn; i++){
|
|
219 if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
|
|
220 }
|
|
221 }
|
|
222 if( i<pIdx->nColumn ) nIdx++;
|
|
223 }
|
|
224 if( nIdxTotal>0 ){
|
|
225 apIdx = sqliteMallocRaw( sizeof(Index*) * nIdx + nIdxTotal );
|
|
226 if( apIdx==0 ) goto update_cleanup;
|
|
227 aIdxUsed = (char*)&apIdx[nIdx];
|
|
228 }
|
|
229 for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
|
230 if( chngRowid ){
|
|
231 i = 0;
|
|
232 }else{
|
|
233 for(i=0; i<pIdx->nColumn; i++){
|
|
234 if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
|
|
235 }
|
|
236 }
|
|
237 if( i<pIdx->nColumn ){
|
|
238 apIdx[nIdx++] = pIdx;
|
|
239 aIdxUsed[j] = 1;
|
|
240 }else{
|
|
241 aIdxUsed[j] = 0;
|
|
242 }
|
|
243 }
|
|
244
|
|
245 /* Resolve the column names in all the expressions in the
|
|
246 ** WHERE clause.
|
|
247 */
|
|
248 if( sqlite3ExprResolveNames(&sNC, pWhere) ){
|
|
249 goto update_cleanup;
|
|
250 }
|
|
251
|
|
252 /* Start the view context
|
|
253 */
|
|
254 if( isView ){
|
|
255 sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
|
|
256 }
|
|
257
|
|
258 /* Begin generating code.
|
|
259 */
|
|
260 v = sqlite3GetVdbe(pParse);
|
|
261 if( v==0 ) goto update_cleanup;
|
|
262 if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
|
|
263 sqlite3BeginWriteOperation(pParse, 1, iDb);
|
|
264
|
|
265 /* If we are trying to update a view, realize that view into
|
|
266 ** a ephemeral table.
|
|
267 */
|
|
268 if( isView ){
|
|
269 Select *pView;
|
|
270 pView = sqlite3SelectDup(pTab->pSelect);
|
|
271 sqlite3Select(pParse, pView, SRT_VirtualTab, iCur, 0, 0, 0, 0);
|
|
272 sqlite3SelectDelete(pView);
|
|
273 }
|
|
274
|
|
275 /* Begin the database scan
|
|
276 */
|
|
277 pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
|
|
278 if( pWInfo==0 ) goto update_cleanup;
|
|
279
|
|
280 /* Remember the index of every item to be updated.
|
|
281 */
|
|
282 sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
|
|
283 sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
|
|
284
|
|
285 /* End the database scan loop.
|
|
286 */
|
|
287 sqlite3WhereEnd(pWInfo);
|
|
288
|
|
289 /* Initialize the count of updated rows
|
|
290 */
|
|
291 if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
|
|
292 sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
|
|
293 }
|
|
294
|
|
295 if( triggers_exist ){
|
|
296 /* Create pseudo-tables for NEW and OLD
|
|
297 */
|
|
298 sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
|
|
299 sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
|
|
300 sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
|
|
301 sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol);
|
|
302
|
|
303 /* The top of the update loop for when there are triggers.
|
|
304 */
|
|
305 addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
|
|
306
|
|
307 if( !isView ){
|
|
308 sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
|
|
309 sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
|
|
310 /* Open a cursor and make it point to the record that is
|
|
311 ** being updated.
|
|
312 */
|
|
313 sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
|
|
314 }
|
|
315 sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
|
|
316
|
|
317 /* Generate the OLD table
|
|
318 */
|
|
319 sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
|
|
320 sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
|
|
321 sqlite3VdbeAddOp(v, OP_Insert, oldIdx, 0);
|
|
322
|
|
323 /* Generate the NEW table
|
|
324 */
|
|
325 if( chngRowid ){
|
|
326 sqlite3ExprCodeAndCache(pParse, pRowidExpr);
|
|
327 }else{
|
|
328 sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
|
|
329 }
|
|
330 for(i=0; i<pTab->nCol; i++){
|
|
331 if( i==pTab->iPKey ){
|
|
332 sqlite3VdbeAddOp(v, OP_Null, 0, 0);
|
|
333 continue;
|
|
334 }
|
|
335 j = aXRef[i];
|
|
336 if( j<0 ){
|
|
337 sqlite3VdbeAddOp(v, OP_Column, iCur, i);
|
|
338 sqlite3ColumnDefault(v, pTab, i);
|
|
339 }else{
|
|
340 sqlite3ExprCodeAndCache(pParse, pChanges->a[j].pExpr);
|
|
341 }
|
|
342 }
|
|
343 sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
|
|
344 if( !isView ){
|
|
345 sqlite3TableAffinityStr(v, pTab);
|
|
346 }
|
|
347 if( pParse->nErr ) goto update_cleanup;
|
|
348 sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);
|
|
349 if( !isView ){
|
|
350 sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
|
|
351 }
|
|
352
|
|
353 /* Fire the BEFORE and INSTEAD OF triggers
|
|
354 */
|
|
355 if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab,
|
|
356 newIdx, oldIdx, onError, addr) ){
|
|
357 goto update_cleanup;
|
|
358 }
|
|
359 }
|
|
360
|
|
361 if( !isView ){
|
|
362 /*
|
|
363 ** Open every index that needs updating. Note that if any
|
|
364 ** index could potentially invoke a REPLACE conflict resolution
|
|
365 ** action, then we need to open all indices because we might need
|
|
366 ** to be deleting some records.
|
|
367 */
|
|
368 sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
|
|
369 if( onError==OE_Replace ){
|
|
370 openAll = 1;
|
|
371 }else{
|
|
372 openAll = 0;
|
|
373 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
|
374 if( pIdx->onError==OE_Replace ){
|
|
375 openAll = 1;
|
|
376 break;
|
|
377 }
|
|
378 }
|
|
379 }
|
|
380 for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
|
381 if( openAll || aIdxUsed[i] ){
|
|
382 KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
|
|
383 sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
|
|
384 sqlite3VdbeOp3(v, OP_OpenWrite, iCur+i+1, pIdx->tnum,
|
|
385 (char*)pKey, P3_KEYINFO_HANDOFF);
|
|
386 assert( pParse->nTab>iCur+i+1 );
|
|
387 }
|
|
388 }
|
|
389
|
|
390 /* Loop over every record that needs updating. We have to load
|
|
391 ** the old data for each record to be updated because some columns
|
|
392 ** might not change and we will need to copy the old value.
|
|
393 ** Also, the old data is needed to delete the old index entires.
|
|
394 ** So make the cursor point at the old record.
|
|
395 */
|
|
396 if( !triggers_exist ){
|
|
397 addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
|
|
398 sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
|
|
399 }
|
|
400 sqlite3VdbeAddOp(v, OP_NotExists, iCur, addr);
|
|
401
|
|
402 /* If the record number will change, push the record number as it
|
|
403 ** will be after the update. (The old record number is currently
|
|
404 ** on top of the stack.)
|
|
405 */
|
|
406 if( chngRowid ){
|
|
407 sqlite3ExprCode(pParse, pRowidExpr);
|
|
408 sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
|
|
409 }
|
|
410
|
|
411 /* Compute new data for this record.
|
|
412 */
|
|
413 for(i=0; i<pTab->nCol; i++){
|
|
414 if( i==pTab->iPKey ){
|
|
415 sqlite3VdbeAddOp(v, OP_Null, 0, 0);
|
|
416 continue;
|
|
417 }
|
|
418 j = aXRef[i];
|
|
419 if( j<0 ){
|
|
420 sqlite3VdbeAddOp(v, OP_Column, iCur, i);
|
|
421 sqlite3ColumnDefault(v, pTab, i);
|
|
422 }else{
|
|
423 sqlite3ExprCode(pParse, pChanges->a[j].pExpr);
|
|
424 }
|
|
425 }
|
|
426
|
|
427 /* Do constraint checks
|
|
428 */
|
|
429 sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRowid, 1,
|
|
430 onError, addr);
|
|
431
|
|
432 /* Delete the old indices for the current record.
|
|
433 */
|
|
434 sqlite3GenerateRowIndexDelete(v, pTab, iCur, aIdxUsed);
|
|
435
|
|
436 /* If changing the record number, delete the old record.
|
|
437 */
|
|
438 if( chngRowid ){
|
|
439 sqlite3VdbeAddOp(v, OP_Delete, iCur, 0);
|
|
440 }
|
|
441
|
|
442 /* Create the new index entries and the new record.
|
|
443 */
|
|
444 sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRowid, 1, -1);
|
|
445 }
|
|
446
|
|
447 /* Increment the row counter
|
|
448 */
|
|
449 if( db->flags & SQLITE_CountRows && !pParse->trigStack){
|
|
450 sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
|
|
451 }
|
|
452
|
|
453 /* If there are triggers, close all the cursors after each iteration
|
|
454 ** through the loop. The fire the after triggers.
|
|
455 */
|
|
456 if( triggers_exist ){
|
|
457 if( !isView ){
|
|
458 for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
|
459 if( openAll || aIdxUsed[i] )
|
|
460 sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0);
|
|
461 }
|
|
462 sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
|
|
463 }
|
|
464 if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_AFTER, pTab,
|
|
465 newIdx, oldIdx, onError, addr) ){
|
|
466 goto update_cleanup;
|
|
467 }
|
|
468 }
|
|
469
|
|
470 /* Repeat the above with the next record to be updated, until
|
|
471 ** all record selected by the WHERE clause have been updated.
|
|
472 */
|
|
473 sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
|
|
474 sqlite3VdbeJumpHere(v, addr);
|
|
475
|
|
476 /* Close all tables if there were no FOR EACH ROW triggers */
|
|
477 if( !triggers_exist ){
|
|
478 for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
|
479 if( openAll || aIdxUsed[i] ){
|
|
480 sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0);
|
|
481 }
|
|
482 }
|
|
483 sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
|
|
484 }else{
|
|
485 sqlite3VdbeAddOp(v, OP_Close, newIdx, 0);
|
|
486 sqlite3VdbeAddOp(v, OP_Close, oldIdx, 0);
|
|
487 }
|
|
488
|
|
489 /*
|
|
490 ** Return the number of rows that were changed. If this routine is
|
|
491 ** generating code because of a call to sqlite3NestedParse(), do not
|
|
492 ** invoke the callback function.
|
|
493 */
|
|
494 if( db->flags & SQLITE_CountRows && !pParse->trigStack && pParse->nested==0 ){
|
|
495 sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
|
|
496 sqlite3VdbeSetNumCols(v, 1);
|
|
497 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", P3_STATIC);
|
|
498 }
|
|
499
|
|
500 update_cleanup:
|
|
501 sqlite3AuthContextPop(&sContext);
|
|
502 sqliteFree(apIdx);
|
|
503 sqliteFree(aXRef);
|
|
504 sqlite3SrcListDelete(pTabList);
|
|
505 sqlite3ExprListDelete(pChanges);
|
|
506 sqlite3ExprDelete(pWhere);
|
|
507 return;
|
|
508 }
|