blob: ed760ff993ff931af070a9c88a63c29af76eca8c [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**
drh9647ff82002-01-14 02:56:24 +000015** $Id: update.c,v 1.26 2002/01/14 02:56:25 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 */
26 Expr *pWhere /* The WHERE clause. May be null */
27){
28 int i, j; /* Loop counters */
29 Table *pTab; /* The table to be updated */
30 IdList *pTabList = 0; /* List containing only pTab */
31 int end, addr; /* A couple of addresses in the generated code */
32 WhereInfo *pWInfo; /* Information about the WHERE clause */
33 Vdbe *v; /* The virtual database engine */
34 Index *pIdx; /* For looping over indices */
35 int nIdx; /* Number of indices that need updating */
drh4794b982000-06-06 13:54:14 +000036 int base; /* Index of first available table cursor */
drhecdc7532001-09-23 02:35:53 +000037 sqlite *db; /* The database structure */
drhcce7d172000-05-31 15:34:51 +000038 Index **apIdx = 0; /* An array of indices that need updating too */
39 int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
drh967e8b72000-06-21 13:59:10 +000040 ** an expression for the i-th column of the table.
41 ** aXRef[i]==-1 if the i-th column is not changed. */
drhf57b3392001-10-08 13:22:32 +000042 int openOp; /* Opcode used to open tables */
drh4a324312001-12-21 14:30:42 +000043 int chngRecno; /* True if the record number is being changed */
44 Expr *pRecnoExpr; /* Expression defining the new record number */
drhcce7d172000-05-31 15:34:51 +000045
drhdaffd0e2001-04-11 14:28:42 +000046 if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;
drhecdc7532001-09-23 02:35:53 +000047 db = pParse->db;
drhdaffd0e2001-04-11 14:28:42 +000048
drhcce7d172000-05-31 15:34:51 +000049 /* Locate the table which we want to update. This table has to be
drh1ccde152000-06-17 13:12:39 +000050 ** put in an IdList structure because some of the subroutines we
drhcce7d172000-05-31 15:34:51 +000051 ** will be calling are designed to work with multiple tables and expect
drhc8392582001-12-31 02:48:51 +000052 ** an IdList* parameter instead of just a Table* parameter.
drhcce7d172000-05-31 15:34:51 +000053 */
54 pTabList = sqliteIdListAppend(0, pTableName);
drhdaffd0e2001-04-11 14:28:42 +000055 if( pTabList==0 ) goto update_cleanup;
drhcce7d172000-05-31 15:34:51 +000056 for(i=0; i<pTabList->nId; i++){
drhecdc7532001-09-23 02:35:53 +000057 pTabList->a[i].pTab = sqliteFindTable(db, pTabList->a[i].zName);
drhcce7d172000-05-31 15:34:51 +000058 if( pTabList->a[i].pTab==0 ){
59 sqliteSetString(&pParse->zErrMsg, "no such table: ",
60 pTabList->a[i].zName, 0);
61 pParse->nErr++;
62 goto update_cleanup;
63 }
64 if( pTabList->a[i].pTab->readOnly ){
65 sqliteSetString(&pParse->zErrMsg, "table ", pTabList->a[i].zName,
66 " may not be modified", 0);
67 pParse->nErr++;
68 goto update_cleanup;
69 }
70 }
71 pTab = pTabList->a[0].pTab;
72 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
73 if( aXRef==0 ) goto update_cleanup;
74 for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
75
drh967e8b72000-06-21 13:59:10 +000076 /* Resolve the column names in all the expressions in both the
77 ** WHERE clause and in the new values. Also find the column index
78 ** for each column to be updated in the pChanges array.
drhcce7d172000-05-31 15:34:51 +000079 */
80 if( pWhere ){
drh4794b982000-06-06 13:54:14 +000081 sqliteExprResolveInSelect(pParse, pWhere);
82 }
83 for(i=0; i<pChanges->nExpr; i++){
84 sqliteExprResolveInSelect(pParse, pChanges->a[i].pExpr);
85 }
86 if( pWhere ){
drhcce7d172000-05-31 15:34:51 +000087 if( sqliteExprResolveIds(pParse, pTabList, pWhere) ){
88 goto update_cleanup;
89 }
90 if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
91 goto update_cleanup;
92 }
93 }
drh4a324312001-12-21 14:30:42 +000094 chngRecno = 0;
drhcce7d172000-05-31 15:34:51 +000095 for(i=0; i<pChanges->nExpr; i++){
96 if( sqliteExprResolveIds(pParse, pTabList, pChanges->a[i].pExpr) ){
97 goto update_cleanup;
98 }
99 if( sqliteExprCheck(pParse, pChanges->a[i].pExpr, 0, 0) ){
100 goto update_cleanup;
101 }
102 for(j=0; j<pTab->nCol; j++){
drh6206d502000-06-19 19:09:08 +0000103 if( sqliteStrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
drh9647ff82002-01-14 02:56:24 +0000104 if( j==pTab->iPKey ){
drh4a324312001-12-21 14:30:42 +0000105 chngRecno = 1;
106 pRecnoExpr = pChanges->a[i].pExpr;
107 }
drhcce7d172000-05-31 15:34:51 +0000108 aXRef[j] = i;
109 break;
110 }
111 }
112 if( j>=pTab->nCol ){
drh967e8b72000-06-21 13:59:10 +0000113 sqliteSetString(&pParse->zErrMsg, "no such column: ",
drhcce7d172000-05-31 15:34:51 +0000114 pChanges->a[i].zName, 0);
115 pParse->nErr++;
116 goto update_cleanup;
117 }
118 }
119
drh5a2c2c22001-11-21 02:21:11 +0000120 /* Allocate memory for the array apIdx[] and fill it with pointers to every
drhcce7d172000-05-31 15:34:51 +0000121 ** index that needs to be updated. Indices only need updating if their
drhc8392582001-12-31 02:48:51 +0000122 ** key includes one of the columns named in pChanges or if the record
123 ** number of the original table entry is changing.
drhcce7d172000-05-31 15:34:51 +0000124 */
125 for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
drh4a324312001-12-21 14:30:42 +0000126 if( chngRecno ){
127 i = 0;
128 }else {
129 for(i=0; i<pIdx->nColumn; i++){
130 if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
131 }
drhcce7d172000-05-31 15:34:51 +0000132 }
drh967e8b72000-06-21 13:59:10 +0000133 if( i<pIdx->nColumn ) nIdx++;
drhcce7d172000-05-31 15:34:51 +0000134 }
drhb0729502001-03-14 12:35:57 +0000135 if( nIdx>0 ){
136 apIdx = sqliteMalloc( sizeof(Index*) * nIdx );
137 if( apIdx==0 ) goto update_cleanup;
138 }
drhcce7d172000-05-31 15:34:51 +0000139 for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
drh4a324312001-12-21 14:30:42 +0000140 if( chngRecno ){
141 i = 0;
142 }else{
143 for(i=0; i<pIdx->nColumn; i++){
144 if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
145 }
drhcce7d172000-05-31 15:34:51 +0000146 }
drh967e8b72000-06-21 13:59:10 +0000147 if( i<pIdx->nColumn ) apIdx[nIdx++] = pIdx;
drhcce7d172000-05-31 15:34:51 +0000148 }
149
150 /* Begin generating code.
151 */
drhd8bc7082000-06-07 23:51:50 +0000152 v = sqliteGetVdbe(pParse);
drhcce7d172000-05-31 15:34:51 +0000153 if( v==0 ) goto update_cleanup;
drhecdc7532001-09-23 02:35:53 +0000154 if( (db->flags & SQLITE_InTrans)==0 ){
drh99fcd712001-10-13 01:06:47 +0000155 sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
156 sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
drhecdc7532001-09-23 02:35:53 +0000157 pParse->schemaVerified = 1;
drh5e00f6c2001-09-13 13:46:56 +0000158 }
drhcce7d172000-05-31 15:34:51 +0000159
160 /* Begin the database scan
161 */
drhcce7d172000-05-31 15:34:51 +0000162 pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1);
163 if( pWInfo==0 ) goto update_cleanup;
164
165 /* Remember the index of every item to be updated.
166 */
drh99fcd712001-10-13 01:06:47 +0000167 sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
drhcce7d172000-05-31 15:34:51 +0000168
169 /* End the database scan loop.
170 */
171 sqliteWhereEnd(pWInfo);
172
drh1bee3d72001-10-15 00:44:35 +0000173 /* Initialize the count of updated rows
174 */
175 if( db->flags & SQLITE_CountRows ){
176 sqliteVdbeAddOp(v, OP_Integer, 0, 0);
177 }
178
drhcce7d172000-05-31 15:34:51 +0000179 /* Rewind the list of records that need to be updated and
180 ** open every index that needs updating.
181 */
drh99fcd712001-10-13 01:06:47 +0000182 sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
drh4794b982000-06-06 13:54:14 +0000183 base = pParse->nTab;
drhf57b3392001-10-08 13:22:32 +0000184 openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite;
drh99fcd712001-10-13 01:06:47 +0000185 sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
drhcce7d172000-05-31 15:34:51 +0000186 for(i=0; i<nIdx; i++){
drh99fcd712001-10-13 01:06:47 +0000187 sqliteVdbeAddOp(v, openOp, base+i+1, apIdx[i]->tnum);
drhcce7d172000-05-31 15:34:51 +0000188 }
189
190 /* Loop over every record that needs updating. We have to load
drh967e8b72000-06-21 13:59:10 +0000191 ** the old data for each record to be updated because some columns
drh1ccde152000-06-17 13:12:39 +0000192 ** might not change and we will need to copy the old value.
drhcce7d172000-05-31 15:34:51 +0000193 ** Also, the old data is needed to delete the old index entires.
drh4a324312001-12-21 14:30:42 +0000194 ** So make the cursor point at the old record.
drhcce7d172000-05-31 15:34:51 +0000195 */
196 end = sqliteVdbeMakeLabel(v);
drh99fcd712001-10-13 01:06:47 +0000197 addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
198 sqliteVdbeAddOp(v, OP_Dup, 0, 0);
199 sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
drhcce7d172000-05-31 15:34:51 +0000200
201 /* Delete the old indices for the current record.
202 */
203 for(i=0; i<nIdx; i++){
drh99fcd712001-10-13 01:06:47 +0000204 sqliteVdbeAddOp(v, OP_Dup, 0, 0);
drhcce7d172000-05-31 15:34:51 +0000205 pIdx = apIdx[i];
drh967e8b72000-06-21 13:59:10 +0000206 for(j=0; j<pIdx->nColumn; j++){
drhc8392582001-12-31 02:48:51 +0000207 int x = pIdx->aiColumn[j];
208 if( x==pTab->iPKey ){
209 sqliteVdbeAddOp(v, OP_Dup, j, 0);
210 }else{
211 sqliteVdbeAddOp(v, OP_Column, base, x);
212 }
drhcce7d172000-05-31 15:34:51 +0000213 }
drh99fcd712001-10-13 01:06:47 +0000214 sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
drh8721ce42001-11-07 14:22:00 +0000215 sqliteVdbeAddOp(v, OP_IdxDelete, base+i+1, 0);
drhcce7d172000-05-31 15:34:51 +0000216 }
217
drh4a324312001-12-21 14:30:42 +0000218 /* If changing the record number, remove the old record number
219 ** from the top of the stack and replace it with the new one.
220 */
221 if( chngRecno ){
222 sqliteVdbeAddOp(v, OP_Pop, 1, 0);
223 sqliteExprCode(pParse, pRecnoExpr);
drh8aff1012001-12-22 14:49:24 +0000224 sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
drh4a324312001-12-21 14:30:42 +0000225 }
226
drh5a2c2c22001-11-21 02:21:11 +0000227 /* Compute new data for this record.
drhcce7d172000-05-31 15:34:51 +0000228 */
229 for(i=0; i<pTab->nCol; i++){
drh4a324312001-12-21 14:30:42 +0000230 if( i==pTab->iPKey ){
231 sqliteVdbeAddOp(v, OP_Dup, i, 0);
232 continue;
233 }
drhcce7d172000-05-31 15:34:51 +0000234 j = aXRef[i];
235 if( j<0 ){
drh99fcd712001-10-13 01:06:47 +0000236 sqliteVdbeAddOp(v, OP_Column, base, i);
drhcce7d172000-05-31 15:34:51 +0000237 }else{
238 sqliteExprCode(pParse, pChanges->a[j].pExpr);
239 }
240 }
241
drhc8392582001-12-31 02:48:51 +0000242 /* If changing the record number, delete the old record.
drh4a324312001-12-21 14:30:42 +0000243 */
244 if( chngRecno ){
245 sqliteVdbeAddOp(v, OP_Delete, 0, 0);
246 }
247
drhcce7d172000-05-31 15:34:51 +0000248 /* Insert new index entries that correspond to the new data
249 */
250 for(i=0; i<nIdx; i++){
drh99fcd712001-10-13 01:06:47 +0000251 sqliteVdbeAddOp(v, OP_Dup, pTab->nCol, 0); /* The KEY */
drhcce7d172000-05-31 15:34:51 +0000252 pIdx = apIdx[i];
drh967e8b72000-06-21 13:59:10 +0000253 for(j=0; j<pIdx->nColumn; j++){
drh4a324312001-12-21 14:30:42 +0000254 int idx = pIdx->aiColumn[j];
255 if( idx==pTab->iPKey ){
256 sqliteVdbeAddOp(v, OP_Dup, j, 0);
257 }else{
258 sqliteVdbeAddOp(v, OP_Dup, j+pTab->nCol-idx, 0);
259 }
drhcce7d172000-05-31 15:34:51 +0000260 }
drh99fcd712001-10-13 01:06:47 +0000261 sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
drh8721ce42001-11-07 14:22:00 +0000262 sqliteVdbeAddOp(v, OP_IdxPut, base+i+1, pIdx->isUnique);
drhcce7d172000-05-31 15:34:51 +0000263 }
264
265 /* Write the new data back into the database.
266 */
drh99fcd712001-10-13 01:06:47 +0000267 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
268 sqliteVdbeAddOp(v, OP_Put, base, 0);
drhcce7d172000-05-31 15:34:51 +0000269
drh1bee3d72001-10-15 00:44:35 +0000270 /* Increment the count of rows affected by the update
271 */
272 if( db->flags & SQLITE_CountRows ){
273 sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
274 }
275
drhcce7d172000-05-31 15:34:51 +0000276 /* Repeat the above with the next record to be updated, until
277 ** all record selected by the WHERE clause have been updated.
278 */
drh99fcd712001-10-13 01:06:47 +0000279 sqliteVdbeAddOp(v, OP_Goto, 0, addr);
280 sqliteVdbeResolveLabel(v, end);
drha8b38d22001-11-01 14:41:34 +0000281 sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
drhecdc7532001-09-23 02:35:53 +0000282 if( (db->flags & SQLITE_InTrans)==0 ){
drh99fcd712001-10-13 01:06:47 +0000283 sqliteVdbeAddOp(v, OP_Commit, 0, 0);
drh5e00f6c2001-09-13 13:46:56 +0000284 }
drhcce7d172000-05-31 15:34:51 +0000285
drh1bee3d72001-10-15 00:44:35 +0000286 /*
287 ** Return the number of rows that were changed.
288 */
289 if( db->flags & SQLITE_CountRows ){
290 sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
291 sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
292 sqliteVdbeChangeP3(v, -1, "rows updated", P3_STATIC);
293 sqliteVdbeAddOp(v, OP_Callback, 1, 0);
294 }
295
drhcce7d172000-05-31 15:34:51 +0000296update_cleanup:
297 sqliteFree(apIdx);
298 sqliteFree(aXRef);
299 sqliteIdListDelete(pTabList);
300 sqliteExprListDelete(pChanges);
301 sqliteExprDelete(pWhere);
302 return;
303}