2N/A#
pragma ident "%Z%%M% %I% %E% SMI" 2N/A** The author disclaims copyright to this source code. In place of 2N/A** a legal notice, here is a blessing: 2N/A** May you do good and not evil. 2N/A** May you find forgiveness for yourself and forgive others. 2N/A** May you share freely, never taking more than you give. 2N/A************************************************************************* 2N/A** This file contains C code routines that are called by the parser 2N/A** to handle UPDATE statements. 2N/A** $Id: update.c,v 1.70.2.1 2004/04/29 16:16:29 drh Exp $ 2N/A** Process an UPDATE statement. 2N/A** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; 2N/A** \_______/ \________/ \______/ \________________/ 2N/A* onError pTabList pChanges pWhere 2N/A int i, j;
/* Loop counters */ 2N/A int loopStart;
/* VDBE instruction address of the start of the loop */ 2N/A int jumpInst;
/* Addr of VDBE instruction to jump out of loop */ 2N/A Vdbe *v;
/* The virtual database engine */ 2N/A int nIdx;
/* Number of indices that need updating */ 2N/A int iCur;
/* VDBE Cursor number of pTab */ 2N/A Index **
apIdx = 0;
/* An array of indices that need updating too */ 2N/A char *
aIdxUsed = 0;
/* aIdxUsed[i]==1 if the i-th index is used */ 2N/A int *
aXRef = 0;
/* aXRef[i] is the index in pChanges->a[] of the 2N/A ** an expression for the i-th column of the table. 2N/A ** aXRef[i]==-1 if the i-th column is not changed. */ 2N/A int chngRecno;
/* True if the record number is being changed */ 2N/A int openAll;
/* True if all indices need to be opened */ 2N/A int newIdx = -
1;
/* index of trigger "new" temp table */ 2N/A int oldIdx = -
1;
/* index of trigger "old" temp table */ 2N/A /* Locate the table which we want to update. 2N/A /* If there are FOR EACH ROW triggers, allocate cursors for the 2N/A ** special OLD and NEW tables 2N/A /* Allocate a cursors for the main database table and for all indices. 2N/A ** The index cursors might not be used, but if they are used they 2N/A ** need to occur right after the database cursor. So go ahead and 2N/A ** allocate enough space, just in case. 2N/A /* Resolve the column names in all the expressions of the 2N/A ** of the UPDATE statement. Also find the column index 2N/A ** for each column to be updated in the pChanges array. For each 2N/A ** column to be updated, make sure we have authorization to change 2N/A /* Allocate memory for the array apIdx[] and fill it with pointers to every 2N/A ** index that needs to be updated. Indices only need updating if their 2N/A ** key includes one of the columns named in pChanges or if the record 2N/A ** number of the original table entry is changing. 2N/A /* Resolve the column names in all the expressions in the 2N/A /* Start the view context 2N/A /* Begin generating code. 2N/A /* If we are trying to update a view, construct that view into 2N/A ** a temporary table. 2N/A /* Begin the database scan 2N/A /* Remember the index of every item to be updated. 2N/A /* End the database scan loop. 2N/A /* Initialize the count of updated rows 2N/A /* Create pseudo-tables for NEW and OLD 2N/A /* The top of the update loop for when there are triggers. 2N/A /* Open a cursor and make it point to the record that is 2N/A /* Generate the OLD table 2N/A /* Generate the NEW table 2N/A /* Fire the BEFORE and INSTEAD OF triggers 2N/A ** Open every index that needs updating. Note that if any 2N/A ** index could potentially invoke a REPLACE conflict resolution 2N/A ** action, then we need to open all indices because we might need 2N/A ** to be deleting some records. 2N/A /* Loop over every record that needs updating. We have to load 2N/A ** the old data for each record to be updated because some columns 2N/A ** might not change and we will need to copy the old value. 2N/A ** Also, the old data is needed to delete the old index entires. 2N/A ** So make the cursor point at the old record. 2N/A /* If the record number will change, push the record number as it 2N/A ** will be after the update. (The old record number is currently 2N/A ** on top of the stack.) 2N/A /* Compute new data for this record. 2N/A /* Do constraint checks 2N/A /* Delete the old indices for the current record. 2N/A /* If changing the record number, delete the old record. 2N/A /* Create the new index entries and the new record. 2N/A /* Increment the row counter 2N/A /* If there are triggers, close all the cursors after each iteration 2N/A ** through the loop. The fire the after triggers. 2N/A /* Repeat the above with the next record to be updated, until 2N/A ** all record selected by the WHERE clause have been updated. 2N/A /* Close all tables if there were no FOR EACH ROW triggers */ 2N/A ** Return the number of rows that were changed.