blob: 6dff1fdb74e41cff31b10eefbbdd32a414dd3033 [file] [log] [blame]
drhcce7d172000-05-31 15:34:51 +00001/*
drhb19a2bc2001-09-16 00:13:26 +00002** 2001 September 15
drhcce7d172000-05-31 15:34:51 +00003**
drhb19a2bc2001-09-16 00:13:26 +00004** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
drhcce7d172000-05-31 15:34:51 +00006**
drhb19a2bc2001-09-16 00:13:26 +00007** 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.
drhcce7d172000-05-31 15:34:51 +000010**
11*************************************************************************
12** This file contains C code routines that are called by the parser
13** to handle UPDATE statements.
14**
drh0ca3e242002-01-29 23:07:02 +000015** $Id: update.c,v 1.30 2002/01/29 23:07:02 drh Exp $
drhcce7d172000-05-31 15:34:51 +000016*/
17#include "sqliteInt.h"
18
19/*
20** Process an UPDATE statement.
21*/
22void sqliteUpdate(
23 Parse *pParse, /* The parser context */
24 Token *pTableName, /* The table in which we should change things */
25 ExprList *pChanges, /* Things to be changed */
drh9cfcf5d2002-01-29 18:41:24 +000026 Expr *pWhere, /* The WHERE clause. May be null */
27 int onError /* How to handle constraint errors */
drhcce7d172000-05-31 15:34:51 +000028){
29 int i, j; /* Loop counters */
30 Table *pTab; /* The table to be updated */
31 IdList *pTabList = 0; /* List containing only pTab */
drh0ca3e242002-01-29 23:07:02 +000032 int addr; /* VDBE instruction address of the start of the loop */
drhcce7d172000-05-31 15:34:51 +000033 WhereInfo *pWInfo; /* Information about the WHERE clause */
34 Vdbe *v; /* The virtual database engine */
35 Index *pIdx; /* For looping over indices */
36 int nIdx; /* Number of indices that need updating */
drh0ca3e242002-01-29 23:07:02 +000037 int nIdxTotal; /* Total number of indices */
drh4794b982000-06-06 13:54:14 +000038 int base; /* Index of first available table cursor */
drhecdc7532001-09-23 02:35:53 +000039 sqlite *db; /* The database structure */
drhcce7d172000-05-31 15:34:51 +000040 Index **apIdx = 0; /* An array of indices that need updating too */
drh0ca3e242002-01-29 23:07:02 +000041 char *aIdxUsed = 0; /* aIdxUsed[i] if the i-th index is used */
drhcce7d172000-05-31 15:34:51 +000042 int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
drh967e8b72000-06-21 13:59:10 +000043 ** an expression for the i-th column of the table.
44 ** aXRef[i]==-1 if the i-th column is not changed. */
drhf57b3392001-10-08 13:22:32 +000045 int openOp; /* Opcode used to open tables */
drh4a324312001-12-21 14:30:42 +000046 int chngRecno; /* True if the record number is being changed */
47 Expr *pRecnoExpr; /* Expression defining the new record number */
drh0ca3e242002-01-29 23:07:02 +000048 int openAll; /* True if all indices need to be opened */
drhcce7d172000-05-31 15:34:51 +000049
drhdaffd0e2001-04-11 14:28:42 +000050 if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;
drhecdc7532001-09-23 02:35:53 +000051 db = pParse->db;
drhdaffd0e2001-04-11 14:28:42 +000052
drhcce7d172000-05-31 15:34:51 +000053 /* Locate the table which we want to update. This table has to be
drh1ccde152000-06-17 13:12:39 +000054 ** put in an IdList structure because some of the subroutines we
drhcce7d172000-05-31 15:34:51 +000055 ** will be calling are designed to work with multiple tables and expect
drhc8392582001-12-31 02:48:51 +000056 ** an IdList* parameter instead of just a Table* parameter.
drhcce7d172000-05-31 15:34:51 +000057 */
58 pTabList = sqliteIdListAppend(0, pTableName);
drhdaffd0e2001-04-11 14:28:42 +000059 if( pTabList==0 ) goto update_cleanup;
drhcce7d172000-05-31 15:34:51 +000060 for(i=0; i<pTabList->nId; i++){
drhecdc7532001-09-23 02:35:53 +000061 pTabList->a[i].pTab = sqliteFindTable(db, pTabList->a[i].zName);
drhcce7d172000-05-31 15:34:51 +000062 if( pTabList->a[i].pTab==0 ){
63 sqliteSetString(&pParse->zErrMsg, "no such table: ",
64 pTabList->a[i].zName, 0);
65 pParse->nErr++;
66 goto update_cleanup;
67 }
68 if( pTabList->a[i].pTab->readOnly ){
69 sqliteSetString(&pParse->zErrMsg, "table ", pTabList->a[i].zName,
70 " may not be modified", 0);
71 pParse->nErr++;
72 goto update_cleanup;
73 }
74 }
75 pTab = pTabList->a[0].pTab;
76 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
77 if( aXRef==0 ) goto update_cleanup;
78 for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
79
drh967e8b72000-06-21 13:59:10 +000080 /* Resolve the column names in all the expressions in both the
81 ** WHERE clause and in the new values. Also find the column index
82 ** for each column to be updated in the pChanges array.
drhcce7d172000-05-31 15:34:51 +000083 */
84 if( pWhere ){
drh4794b982000-06-06 13:54:14 +000085 sqliteExprResolveInSelect(pParse, pWhere);
86 }
87 for(i=0; i<pChanges->nExpr; i++){
88 sqliteExprResolveInSelect(pParse, pChanges->a[i].pExpr);
89 }
90 if( pWhere ){
drha2e00042002-01-22 03:13:42 +000091 if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
drhcce7d172000-05-31 15:34:51 +000092 goto update_cleanup;
93 }
94 if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
95 goto update_cleanup;
96 }
97 }
drh4a324312001-12-21 14:30:42 +000098 chngRecno = 0;
drhcce7d172000-05-31 15:34:51 +000099 for(i=0; i<pChanges->nExpr; i++){
drha2e00042002-01-22 03:13:42 +0000100 if( sqliteExprResolveIds(pParse, pTabList, 0, pChanges->a[i].pExpr) ){
drhcce7d172000-05-31 15:34:51 +0000101 goto update_cleanup;
102 }
103 if( sqliteExprCheck(pParse, pChanges->a[i].pExpr, 0, 0) ){
104 goto update_cleanup;
105 }
106 for(j=0; j<pTab->nCol; j++){
drh6206d502000-06-19 19:09:08 +0000107 if( sqliteStrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
drh9647ff82002-01-14 02:56:24 +0000108 if( j==pTab->iPKey ){
drh4a324312001-12-21 14:30:42 +0000109 chngRecno = 1;
110 pRecnoExpr = pChanges->a[i].pExpr;
111 }
drhcce7d172000-05-31 15:34:51 +0000112 aXRef[j] = i;
113 break;
114 }
115 }
116 if( j>=pTab->nCol ){
drh967e8b72000-06-21 13:59:10 +0000117 sqliteSetString(&pParse->zErrMsg, "no such column: ",
drhcce7d172000-05-31 15:34:51 +0000118 pChanges->a[i].zName, 0);
119 pParse->nErr++;
120 goto update_cleanup;
121 }
122 }
123
drh5a2c2c22001-11-21 02:21:11 +0000124 /* Allocate memory for the array apIdx[] and fill it with pointers to every
drhcce7d172000-05-31 15:34:51 +0000125 ** index that needs to be updated. Indices only need updating if their
drhc8392582001-12-31 02:48:51 +0000126 ** key includes one of the columns named in pChanges or if the record
127 ** number of the original table entry is changing.
drhcce7d172000-05-31 15:34:51 +0000128 */
drh0ca3e242002-01-29 23:07:02 +0000129 for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){
drh4a324312001-12-21 14:30:42 +0000130 if( chngRecno ){
131 i = 0;
132 }else {
133 for(i=0; i<pIdx->nColumn; i++){
134 if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
135 }
drhcce7d172000-05-31 15:34:51 +0000136 }
drh967e8b72000-06-21 13:59:10 +0000137 if( i<pIdx->nColumn ) nIdx++;
drhcce7d172000-05-31 15:34:51 +0000138 }
drh0ca3e242002-01-29 23:07:02 +0000139 if( nIdxTotal>0 ){
140 apIdx = sqliteMalloc( sizeof(Index*) * nIdx + nIdxTotal );
drhb0729502001-03-14 12:35:57 +0000141 if( apIdx==0 ) goto update_cleanup;
drh0ca3e242002-01-29 23:07:02 +0000142 aIdxUsed = (char*)&apIdx[nIdx];
drhb0729502001-03-14 12:35:57 +0000143 }
drh0ca3e242002-01-29 23:07:02 +0000144 for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
drh4a324312001-12-21 14:30:42 +0000145 if( chngRecno ){
146 i = 0;
147 }else{
148 for(i=0; i<pIdx->nColumn; i++){
149 if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
150 }
drhcce7d172000-05-31 15:34:51 +0000151 }
drh0ca3e242002-01-29 23:07:02 +0000152 if( i<pIdx->nColumn ){
153 apIdx[nIdx++] = pIdx;
154 aIdxUsed[j] = 1;
155 }else{
156 aIdxUsed[j] = 0;
157 }
drhcce7d172000-05-31 15:34:51 +0000158 }
159
160 /* Begin generating code.
161 */
drhd8bc7082000-06-07 23:51:50 +0000162 v = sqliteGetVdbe(pParse);
drhcce7d172000-05-31 15:34:51 +0000163 if( v==0 ) goto update_cleanup;
drhecdc7532001-09-23 02:35:53 +0000164 if( (db->flags & SQLITE_InTrans)==0 ){
drh99fcd712001-10-13 01:06:47 +0000165 sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
166 sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
drhecdc7532001-09-23 02:35:53 +0000167 pParse->schemaVerified = 1;
drh5e00f6c2001-09-13 13:46:56 +0000168 }
drhcce7d172000-05-31 15:34:51 +0000169
170 /* Begin the database scan
171 */
drhcce7d172000-05-31 15:34:51 +0000172 pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1);
173 if( pWInfo==0 ) goto update_cleanup;
174
175 /* Remember the index of every item to be updated.
176 */
drh99fcd712001-10-13 01:06:47 +0000177 sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
drhcce7d172000-05-31 15:34:51 +0000178
179 /* End the database scan loop.
180 */
181 sqliteWhereEnd(pWInfo);
182
drh1bee3d72001-10-15 00:44:35 +0000183 /* Initialize the count of updated rows
184 */
185 if( db->flags & SQLITE_CountRows ){
186 sqliteVdbeAddOp(v, OP_Integer, 0, 0);
187 }
188
drhcce7d172000-05-31 15:34:51 +0000189 /* Rewind the list of records that need to be updated and
drh0ca3e242002-01-29 23:07:02 +0000190 ** open every index that needs updating. Note that if any
191 ** index could potentially invoke a REPLACE conflict resolution
192 ** action, then we need to open all indices because we might need
193 ** to be deleting some records.
drhcce7d172000-05-31 15:34:51 +0000194 */
drh99fcd712001-10-13 01:06:47 +0000195 sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
drh4794b982000-06-06 13:54:14 +0000196 base = pParse->nTab;
drhf57b3392001-10-08 13:22:32 +0000197 openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite;
drh99fcd712001-10-13 01:06:47 +0000198 sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
drh0ca3e242002-01-29 23:07:02 +0000199 if( onError==OE_Replace ){
200 openAll = 1;
201 }else{
202 openAll = 0;
203 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
204 if( pIdx->onError==OE_Replace ){
205 openAll = 1;
206 break;
207 }
208 }
209 }
210 for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
211 if( openAll || aIdxUsed[i] ){
212 sqliteVdbeAddOp(v, openOp, base+i+1, pIdx->tnum);
213 }
drhcce7d172000-05-31 15:34:51 +0000214 }
215
216 /* Loop over every record that needs updating. We have to load
drh967e8b72000-06-21 13:59:10 +0000217 ** the old data for each record to be updated because some columns
drh1ccde152000-06-17 13:12:39 +0000218 ** might not change and we will need to copy the old value.
drhcce7d172000-05-31 15:34:51 +0000219 ** Also, the old data is needed to delete the old index entires.
drh4a324312001-12-21 14:30:42 +0000220 ** So make the cursor point at the old record.
drhcce7d172000-05-31 15:34:51 +0000221 */
drh0ca3e242002-01-29 23:07:02 +0000222 addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
drh99fcd712001-10-13 01:06:47 +0000223 sqliteVdbeAddOp(v, OP_Dup, 0, 0);
224 sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
drhcce7d172000-05-31 15:34:51 +0000225
drh0ca3e242002-01-29 23:07:02 +0000226 /* If the record number will change, push the record number as it
227 ** will be after the update. (The old record number is currently
228 ** on top of the stack.)
drh4a324312001-12-21 14:30:42 +0000229 */
230 if( chngRecno ){
drh0ca3e242002-01-29 23:07:02 +0000231 if( pTab->iPKey<0 || (j = aXRef[pTab->iPKey])<0 ){
232 sqliteVdbeAddOp(v, OP_Dup, 0, 0);
233 }else{
234 sqliteExprCode(pParse, pChanges->a[j].pExpr);
235 sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
236 }
drh4a324312001-12-21 14:30:42 +0000237 }
238
drh5a2c2c22001-11-21 02:21:11 +0000239 /* Compute new data for this record.
drhcce7d172000-05-31 15:34:51 +0000240 */
241 for(i=0; i<pTab->nCol; i++){
drh4a324312001-12-21 14:30:42 +0000242 if( i==pTab->iPKey ){
drh0ca3e242002-01-29 23:07:02 +0000243 sqliteVdbeAddOp(v, OP_String, 0, 0);
drh4a324312001-12-21 14:30:42 +0000244 continue;
245 }
drhcce7d172000-05-31 15:34:51 +0000246 j = aXRef[i];
247 if( j<0 ){
drh99fcd712001-10-13 01:06:47 +0000248 sqliteVdbeAddOp(v, OP_Column, base, i);
drhcce7d172000-05-31 15:34:51 +0000249 }else{
250 sqliteExprCode(pParse, pChanges->a[j].pExpr);
251 }
252 }
253
drh0ca3e242002-01-29 23:07:02 +0000254 /* Do constraint checks
255 */
256 sqliteGenerateConstraintChecks(pParse, pTab, base, aIdxUsed, chngRecno,
257 onError, addr,1);
258
259 /* Delete the old indices for the current record.
260 */
261 sqliteGenerateRowIndexDelete(v, pTab, base, aIdxUsed);
262
drhc8392582001-12-31 02:48:51 +0000263 /* If changing the record number, delete the old record.
drh4a324312001-12-21 14:30:42 +0000264 */
265 if( chngRecno ){
266 sqliteVdbeAddOp(v, OP_Delete, 0, 0);
267 }
268
drh0ca3e242002-01-29 23:07:02 +0000269 /* Create the new index entries and the new record.
drhcce7d172000-05-31 15:34:51 +0000270 */
drh0ca3e242002-01-29 23:07:02 +0000271 sqliteCompleteInsertion(pParse, pTab, base, aIdxUsed, chngRecno);
drhcce7d172000-05-31 15:34:51 +0000272
drh0ca3e242002-01-29 23:07:02 +0000273 /* Increment the row counter
drh1bee3d72001-10-15 00:44:35 +0000274 */
275 if( db->flags & SQLITE_CountRows ){
276 sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
277 }
278
drhcce7d172000-05-31 15:34:51 +0000279 /* Repeat the above with the next record to be updated, until
280 ** all record selected by the WHERE clause have been updated.
281 */
drh99fcd712001-10-13 01:06:47 +0000282 sqliteVdbeAddOp(v, OP_Goto, 0, addr);
drh0ca3e242002-01-29 23:07:02 +0000283 sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
drha8b38d22001-11-01 14:41:34 +0000284 sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
drhecdc7532001-09-23 02:35:53 +0000285 if( (db->flags & SQLITE_InTrans)==0 ){
drh99fcd712001-10-13 01:06:47 +0000286 sqliteVdbeAddOp(v, OP_Commit, 0, 0);
drh5e00f6c2001-09-13 13:46:56 +0000287 }
drhcce7d172000-05-31 15:34:51 +0000288
drh1bee3d72001-10-15 00:44:35 +0000289 /*
290 ** Return the number of rows that were changed.
291 */
292 if( db->flags & SQLITE_CountRows ){
293 sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
294 sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
295 sqliteVdbeChangeP3(v, -1, "rows updated", P3_STATIC);
296 sqliteVdbeAddOp(v, OP_Callback, 1, 0);
297 }
298
drhcce7d172000-05-31 15:34:51 +0000299update_cleanup:
300 sqliteFree(apIdx);
301 sqliteFree(aXRef);
302 sqliteIdListDelete(pTabList);
303 sqliteExprListDelete(pChanges);
304 sqliteExprDelete(pWhere);
305 return;
306}