OLD | NEW |
1 /* | 1 /* |
2 ** 2001 September 15 | 2 ** 2001 September 15 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
(...skipping 18 matching lines...) Expand all Loading... |
29 ** | 29 ** |
30 */ | 30 */ |
31 Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ | 31 Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ |
32 struct SrcList_item *pItem = pSrc->a; | 32 struct SrcList_item *pItem = pSrc->a; |
33 Table *pTab; | 33 Table *pTab; |
34 assert( pItem && pSrc->nSrc==1 ); | 34 assert( pItem && pSrc->nSrc==1 ); |
35 pTab = sqlite3LocateTableItem(pParse, 0, pItem); | 35 pTab = sqlite3LocateTableItem(pParse, 0, pItem); |
36 sqlite3DeleteTable(pParse->db, pItem->pTab); | 36 sqlite3DeleteTable(pParse->db, pItem->pTab); |
37 pItem->pTab = pTab; | 37 pItem->pTab = pTab; |
38 if( pTab ){ | 38 if( pTab ){ |
39 pTab->nRef++; | 39 pTab->nTabRef++; |
40 } | 40 } |
41 if( sqlite3IndexedByLookup(pParse, pItem) ){ | 41 if( sqlite3IndexedByLookup(pParse, pItem) ){ |
42 pTab = 0; | 42 pTab = 0; |
43 } | 43 } |
44 return pTab; | 44 return pTab; |
45 } | 45 } |
46 | 46 |
47 /* | 47 /* |
48 ** Check to make sure the given table is writable. If it is not | 48 ** Check to make sure the given table is writable. If it is not |
49 ** writable, generate an error message and return 1. If it is | 49 ** writable, generate an error message and return 1. If it is |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 SelectDest dest; | 95 SelectDest dest; |
96 Select *pSel; | 96 Select *pSel; |
97 SrcList *pFrom; | 97 SrcList *pFrom; |
98 sqlite3 *db = pParse->db; | 98 sqlite3 *db = pParse->db; |
99 int iDb = sqlite3SchemaToIndex(db, pView->pSchema); | 99 int iDb = sqlite3SchemaToIndex(db, pView->pSchema); |
100 pWhere = sqlite3ExprDup(db, pWhere, 0); | 100 pWhere = sqlite3ExprDup(db, pWhere, 0); |
101 pFrom = sqlite3SrcListAppend(db, 0, 0, 0); | 101 pFrom = sqlite3SrcListAppend(db, 0, 0, 0); |
102 if( pFrom ){ | 102 if( pFrom ){ |
103 assert( pFrom->nSrc==1 ); | 103 assert( pFrom->nSrc==1 ); |
104 pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName); | 104 pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName); |
105 pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); | 105 pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName); |
106 assert( pFrom->a[0].pOn==0 ); | 106 assert( pFrom->a[0].pOn==0 ); |
107 assert( pFrom->a[0].pUsing==0 ); | 107 assert( pFrom->a[0].pUsing==0 ); |
108 } | 108 } |
109 pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, | 109 pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, |
110 SF_IncludeHidden, 0, 0); | 110 SF_IncludeHidden, 0, 0); |
111 sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); | 111 sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); |
112 sqlite3Select(pParse, pSel, &dest); | 112 sqlite3Select(pParse, pSel, &dest); |
113 sqlite3SelectDelete(db, pSel); | 113 sqlite3SelectDelete(db, pSel); |
114 } | 114 } |
115 #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */ | 115 #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */ |
(...skipping 20 matching lines...) Expand all Loading... |
136 Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */ | 136 Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */ |
137 Expr *pSelectRowid = NULL; /* SELECT rowid ... */ | 137 Expr *pSelectRowid = NULL; /* SELECT rowid ... */ |
138 ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */ | 138 ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */ |
139 SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */ | 139 SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */ |
140 Select *pSelect = NULL; /* Complete SELECT tree */ | 140 Select *pSelect = NULL; /* Complete SELECT tree */ |
141 | 141 |
142 /* Check that there isn't an ORDER BY without a LIMIT clause. | 142 /* Check that there isn't an ORDER BY without a LIMIT clause. |
143 */ | 143 */ |
144 if( pOrderBy && (pLimit == 0) ) { | 144 if( pOrderBy && (pLimit == 0) ) { |
145 sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType); | 145 sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType); |
146 goto limit_where_cleanup_2; | 146 goto limit_where_cleanup; |
147 } | 147 } |
148 | 148 |
149 /* We only need to generate a select expression if there | 149 /* We only need to generate a select expression if there |
150 ** is a limit/offset term to enforce. | 150 ** is a limit/offset term to enforce. |
151 */ | 151 */ |
152 if( pLimit == 0 ) { | 152 if( pLimit == 0 ) { |
153 /* if pLimit is null, pOffset will always be null as well. */ | 153 /* if pLimit is null, pOffset will always be null as well. */ |
154 assert( pOffset == 0 ); | 154 assert( pOffset == 0 ); |
155 return pWhere; | 155 return pWhere; |
156 } | 156 } |
157 | 157 |
158 /* Generate a select expression tree to enforce the limit/offset | 158 /* Generate a select expression tree to enforce the limit/offset |
159 ** term for the DELETE or UPDATE statement. For example: | 159 ** term for the DELETE or UPDATE statement. For example: |
160 ** DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 | 160 ** DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 |
161 ** becomes: | 161 ** becomes: |
162 ** DELETE FROM table_a WHERE rowid IN ( | 162 ** DELETE FROM table_a WHERE rowid IN ( |
163 ** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 | 163 ** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1 |
164 ** ); | 164 ** ); |
165 */ | 165 */ |
166 | 166 |
167 pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0); | 167 pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0); |
168 if( pSelectRowid == 0 ) goto limit_where_cleanup_2; | 168 if( pSelectRowid == 0 ) goto limit_where_cleanup; |
169 pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid); | 169 pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid); |
170 if( pEList == 0 ) goto limit_where_cleanup_2; | 170 if( pEList == 0 ) goto limit_where_cleanup; |
171 | 171 |
172 /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree | 172 /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree |
173 ** and the SELECT subtree. */ | 173 ** and the SELECT subtree. */ |
174 pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0); | 174 pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0); |
175 if( pSelectSrc == 0 ) { | 175 if( pSelectSrc == 0 ) { |
176 sqlite3ExprListDelete(pParse->db, pEList); | 176 sqlite3ExprListDelete(pParse->db, pEList); |
177 goto limit_where_cleanup_2; | 177 goto limit_where_cleanup; |
178 } | 178 } |
179 | 179 |
180 /* generate the SELECT expression tree. */ | 180 /* generate the SELECT expression tree. */ |
181 pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0, | 181 pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0, |
182 pOrderBy,0,pLimit,pOffset); | 182 pOrderBy,0,pLimit,pOffset); |
183 if( pSelect == 0 ) return 0; | 183 if( pSelect == 0 ) return 0; |
184 | 184 |
185 /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ | 185 /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */ |
186 pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0); | 186 pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0); |
187 if( pWhereRowid == 0 ) goto limit_where_cleanup_1; | 187 pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0) : 0; |
188 pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0); | 188 sqlite3PExprAddSelect(pParse, pInClause, pSelect); |
189 if( pInClause == 0 ) goto limit_where_cleanup_1; | |
190 | |
191 pInClause->x.pSelect = pSelect; | |
192 pInClause->flags |= EP_xIsSelect; | |
193 sqlite3ExprSetHeightAndFlags(pParse, pInClause); | |
194 return pInClause; | 189 return pInClause; |
195 | 190 |
196 /* something went wrong. clean up anything allocated. */ | 191 limit_where_cleanup: |
197 limit_where_cleanup_1: | |
198 sqlite3SelectDelete(pParse->db, pSelect); | |
199 return 0; | |
200 | |
201 limit_where_cleanup_2: | |
202 sqlite3ExprDelete(pParse->db, pWhere); | 192 sqlite3ExprDelete(pParse->db, pWhere); |
203 sqlite3ExprListDelete(pParse->db, pOrderBy); | 193 sqlite3ExprListDelete(pParse->db, pOrderBy); |
204 sqlite3ExprDelete(pParse->db, pLimit); | 194 sqlite3ExprDelete(pParse->db, pLimit); |
205 sqlite3ExprDelete(pParse->db, pOffset); | 195 sqlite3ExprDelete(pParse->db, pOffset); |
206 return 0; | 196 return 0; |
207 } | 197 } |
208 #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */ | 198 #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */ |
209 /* && !defined(SQLITE_OMIT_SUBQUERY) */ | 199 /* && !defined(SQLITE_OMIT_SUBQUERY) */ |
210 | 200 |
211 /* | 201 /* |
212 ** Generate code for a DELETE FROM statement. | 202 ** Generate code for a DELETE FROM statement. |
213 ** | 203 ** |
214 ** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL; | 204 ** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL; |
215 ** \________/ \________________/ | 205 ** \________/ \________________/ |
216 ** pTabList pWhere | 206 ** pTabList pWhere |
217 */ | 207 */ |
218 void sqlite3DeleteFrom( | 208 void sqlite3DeleteFrom( |
219 Parse *pParse, /* The parser context */ | 209 Parse *pParse, /* The parser context */ |
220 SrcList *pTabList, /* The table from which we should delete things */ | 210 SrcList *pTabList, /* The table from which we should delete things */ |
221 Expr *pWhere /* The WHERE clause. May be null */ | 211 Expr *pWhere /* The WHERE clause. May be null */ |
222 ){ | 212 ){ |
223 Vdbe *v; /* The virtual database engine */ | 213 Vdbe *v; /* The virtual database engine */ |
224 Table *pTab; /* The table from which records will be deleted */ | 214 Table *pTab; /* The table from which records will be deleted */ |
225 const char *zDb; /* Name of database holding pTab */ | |
226 int i; /* Loop counter */ | 215 int i; /* Loop counter */ |
227 WhereInfo *pWInfo; /* Information about the WHERE clause */ | 216 WhereInfo *pWInfo; /* Information about the WHERE clause */ |
228 Index *pIdx; /* For looping over indices of the table */ | 217 Index *pIdx; /* For looping over indices of the table */ |
229 int iTabCur; /* Cursor number for the table */ | 218 int iTabCur; /* Cursor number for the table */ |
230 int iDataCur = 0; /* VDBE cursor for the canonical data source */ | 219 int iDataCur = 0; /* VDBE cursor for the canonical data source */ |
231 int iIdxCur = 0; /* Cursor number of the first index */ | 220 int iIdxCur = 0; /* Cursor number of the first index */ |
232 int nIdx; /* Number of indices */ | 221 int nIdx; /* Number of indices */ |
233 sqlite3 *db; /* Main database structure */ | 222 sqlite3 *db; /* Main database structure */ |
234 AuthContext sContext; /* Authorization context */ | 223 AuthContext sContext; /* Authorization context */ |
235 NameContext sNC; /* Name context to resolve expressions in */ | 224 NameContext sNC; /* Name context to resolve expressions in */ |
236 int iDb; /* Database number */ | 225 int iDb; /* Database number */ |
237 int memCnt = -1; /* Memory cell used for change counting */ | 226 int memCnt = -1; /* Memory cell used for change counting */ |
238 int rcauth; /* Value returned by authorization callback */ | 227 int rcauth; /* Value returned by authorization callback */ |
239 int eOnePass; /* ONEPASS_OFF or _SINGLE or _MULTI */ | 228 int eOnePass; /* ONEPASS_OFF or _SINGLE or _MULTI */ |
240 int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ | 229 int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */ |
241 u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */ | 230 u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */ |
242 Index *pPk; /* The PRIMARY KEY index on the table */ | 231 Index *pPk; /* The PRIMARY KEY index on the table */ |
243 int iPk = 0; /* First of nPk registers holding PRIMARY KEY value */ | 232 int iPk = 0; /* First of nPk registers holding PRIMARY KEY value */ |
244 i16 nPk = 1; /* Number of columns in the PRIMARY KEY */ | 233 i16 nPk = 1; /* Number of columns in the PRIMARY KEY */ |
245 int iKey; /* Memory cell holding key of row to be deleted */ | 234 int iKey; /* Memory cell holding key of row to be deleted */ |
246 i16 nKey; /* Number of memory cells in the row key */ | 235 i16 nKey; /* Number of memory cells in the row key */ |
247 int iEphCur = 0; /* Ephemeral table holding all primary key values */ | 236 int iEphCur = 0; /* Ephemeral table holding all primary key values */ |
248 int iRowSet = 0; /* Register for rowset of rows to delete */ | 237 int iRowSet = 0; /* Register for rowset of rows to delete */ |
249 int addrBypass = 0; /* Address of jump over the delete logic */ | 238 int addrBypass = 0; /* Address of jump over the delete logic */ |
250 int addrLoop = 0; /* Top of the delete loop */ | 239 int addrLoop = 0; /* Top of the delete loop */ |
251 int addrEphOpen = 0; /* Instruction to open the Ephemeral table */ | 240 int addrEphOpen = 0; /* Instruction to open the Ephemeral table */ |
| 241 int bComplex; /* True if there are triggers or FKs or |
| 242 ** subqueries in the WHERE clause */ |
252 | 243 |
253 #ifndef SQLITE_OMIT_TRIGGER | 244 #ifndef SQLITE_OMIT_TRIGGER |
254 int isView; /* True if attempting to delete from a view */ | 245 int isView; /* True if attempting to delete from a view */ |
255 Trigger *pTrigger; /* List of table triggers, if required */ | 246 Trigger *pTrigger; /* List of table triggers, if required */ |
256 int bComplex; /* True if there are either triggers or FKs */ | |
257 #endif | 247 #endif |
258 | 248 |
259 memset(&sContext, 0, sizeof(sContext)); | 249 memset(&sContext, 0, sizeof(sContext)); |
260 db = pParse->db; | 250 db = pParse->db; |
261 if( pParse->nErr || db->mallocFailed ){ | 251 if( pParse->nErr || db->mallocFailed ){ |
262 goto delete_from_cleanup; | 252 goto delete_from_cleanup; |
263 } | 253 } |
264 assert( pTabList->nSrc==1 ); | 254 assert( pTabList->nSrc==1 ); |
265 | 255 |
266 /* Locate the table which we want to delete. This table has to be | 256 /* Locate the table which we want to delete. This table has to be |
267 ** put in an SrcList structure because some of the subroutines we | 257 ** put in an SrcList structure because some of the subroutines we |
268 ** will be calling are designed to work with multiple tables and expect | 258 ** will be calling are designed to work with multiple tables and expect |
269 ** an SrcList* parameter instead of just a Table* parameter. | 259 ** an SrcList* parameter instead of just a Table* parameter. |
270 */ | 260 */ |
271 pTab = sqlite3SrcListLookup(pParse, pTabList); | 261 pTab = sqlite3SrcListLookup(pParse, pTabList); |
272 if( pTab==0 ) goto delete_from_cleanup; | 262 if( pTab==0 ) goto delete_from_cleanup; |
273 | 263 |
274 /* Figure out if we have any triggers and if the table being | 264 /* Figure out if we have any triggers and if the table being |
275 ** deleted from is a view | 265 ** deleted from is a view |
276 */ | 266 */ |
277 #ifndef SQLITE_OMIT_TRIGGER | 267 #ifndef SQLITE_OMIT_TRIGGER |
278 pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); | 268 pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); |
279 isView = pTab->pSelect!=0; | 269 isView = pTab->pSelect!=0; |
280 bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0); | 270 bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0); |
281 #else | 271 #else |
282 # define pTrigger 0 | 272 # define pTrigger 0 |
283 # define isView 0 | 273 # define isView 0 |
284 # define bComplex 0 | |
285 #endif | 274 #endif |
286 #ifdef SQLITE_OMIT_VIEW | 275 #ifdef SQLITE_OMIT_VIEW |
287 # undef isView | 276 # undef isView |
288 # define isView 0 | 277 # define isView 0 |
289 #endif | 278 #endif |
290 | 279 |
291 /* If pTab is really a view, make sure it has been initialized. | 280 /* If pTab is really a view, make sure it has been initialized. |
292 */ | 281 */ |
293 if( sqlite3ViewGetColumnNames(pParse, pTab) ){ | 282 if( sqlite3ViewGetColumnNames(pParse, pTab) ){ |
294 goto delete_from_cleanup; | 283 goto delete_from_cleanup; |
295 } | 284 } |
296 | 285 |
297 if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ | 286 if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ |
298 goto delete_from_cleanup; | 287 goto delete_from_cleanup; |
299 } | 288 } |
300 iDb = sqlite3SchemaToIndex(db, pTab->pSchema); | 289 iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
301 assert( iDb<db->nDb ); | 290 assert( iDb<db->nDb ); |
302 zDb = db->aDb[iDb].zName; | 291 rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, |
303 rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb); | 292 db->aDb[iDb].zDbSName); |
304 assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); | 293 assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); |
305 if( rcauth==SQLITE_DENY ){ | 294 if( rcauth==SQLITE_DENY ){ |
306 goto delete_from_cleanup; | 295 goto delete_from_cleanup; |
307 } | 296 } |
308 assert(!isView || pTrigger); | 297 assert(!isView || pTrigger); |
309 | 298 |
310 /* Assign cursor numbers to the table and all its indices. | 299 /* Assign cursor numbers to the table and all its indices. |
311 */ | 300 */ |
312 assert( pTabList->nSrc==1 ); | 301 assert( pTabList->nSrc==1 ); |
313 iTabCur = pTabList->a[0].iCursor = pParse->nTab++; | 302 iTabCur = pTabList->a[0].iCursor = pParse->nTab++; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 | 348 |
360 #ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION | 349 #ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION |
361 /* Special case: A DELETE without a WHERE clause deletes everything. | 350 /* Special case: A DELETE without a WHERE clause deletes everything. |
362 ** It is easier just to erase the whole table. Prior to version 3.6.5, | 351 ** It is easier just to erase the whole table. Prior to version 3.6.5, |
363 ** this optimization caused the row change count (the value returned by | 352 ** this optimization caused the row change count (the value returned by |
364 ** API function sqlite3_count_changes) to be set incorrectly. */ | 353 ** API function sqlite3_count_changes) to be set incorrectly. */ |
365 if( rcauth==SQLITE_OK | 354 if( rcauth==SQLITE_OK |
366 && pWhere==0 | 355 && pWhere==0 |
367 && !bComplex | 356 && !bComplex |
368 && !IsVirtual(pTab) | 357 && !IsVirtual(pTab) |
| 358 #ifdef SQLITE_ENABLE_PREUPDATE_HOOK |
| 359 && db->xPreUpdateCallback==0 |
| 360 #endif |
369 ){ | 361 ){ |
370 assert( !isView ); | 362 assert( !isView ); |
371 sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); | 363 sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); |
372 if( HasRowid(pTab) ){ | 364 if( HasRowid(pTab) ){ |
373 sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt, | 365 sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt, |
374 pTab->zName, P4_STATIC); | 366 pTab->zName, P4_STATIC); |
375 } | 367 } |
376 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ | 368 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
377 assert( pIdx->pSchema==pTab->pSchema ); | 369 assert( pIdx->pSchema==pTab->pSchema ); |
378 sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); | 370 sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); |
379 } | 371 } |
380 }else | 372 }else |
381 #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ | 373 #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ |
382 { | 374 { |
383 u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK; | 375 u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK|WHERE_SEEK_TABLE; |
| 376 if( sNC.ncFlags & NC_VarSelect ) bComplex = 1; |
384 wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW); | 377 wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW); |
385 if( HasRowid(pTab) ){ | 378 if( HasRowid(pTab) ){ |
386 /* For a rowid table, initialize the RowSet to an empty set */ | 379 /* For a rowid table, initialize the RowSet to an empty set */ |
387 pPk = 0; | 380 pPk = 0; |
388 nPk = 1; | 381 nPk = 1; |
389 iRowSet = ++pParse->nMem; | 382 iRowSet = ++pParse->nMem; |
390 sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); | 383 sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); |
391 }else{ | 384 }else{ |
392 /* For a WITHOUT ROWID table, create an ephemeral table used to | 385 /* For a WITHOUT ROWID table, create an ephemeral table used to |
393 ** hold all primary keys for rows to be deleted. */ | 386 ** hold all primary keys for rows to be deleted. */ |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 iKey = pParse->nMem + 1; | 425 iKey = pParse->nMem + 1; |
433 iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0); | 426 iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0); |
434 if( iKey>pParse->nMem ) pParse->nMem = iKey; | 427 if( iKey>pParse->nMem ) pParse->nMem = iKey; |
435 } | 428 } |
436 | 429 |
437 if( eOnePass!=ONEPASS_OFF ){ | 430 if( eOnePass!=ONEPASS_OFF ){ |
438 /* For ONEPASS, no need to store the rowid/primary-key. There is only | 431 /* For ONEPASS, no need to store the rowid/primary-key. There is only |
439 ** one, so just keep it in its register(s) and fall through to the | 432 ** one, so just keep it in its register(s) and fall through to the |
440 ** delete code. */ | 433 ** delete code. */ |
441 nKey = nPk; /* OP_Found will use an unpacked key */ | 434 nKey = nPk; /* OP_Found will use an unpacked key */ |
442 aToOpen = sqlite3DbMallocRaw(db, nIdx+2); | 435 aToOpen = sqlite3DbMallocRawNN(db, nIdx+2); |
443 if( aToOpen==0 ){ | 436 if( aToOpen==0 ){ |
444 sqlite3WhereEnd(pWInfo); | 437 sqlite3WhereEnd(pWInfo); |
445 goto delete_from_cleanup; | 438 goto delete_from_cleanup; |
446 } | 439 } |
447 memset(aToOpen, 1, nIdx+1); | 440 memset(aToOpen, 1, nIdx+1); |
448 aToOpen[nIdx+1] = 0; | 441 aToOpen[nIdx+1] = 0; |
449 if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0; | 442 if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0; |
450 if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0; | 443 if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0; |
451 if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen); | 444 if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen); |
452 }else{ | 445 }else{ |
453 if( pPk ){ | 446 if( pPk ){ |
454 /* Add the PK key for this row to the temporary table */ | 447 /* Add the PK key for this row to the temporary table */ |
455 iKey = ++pParse->nMem; | 448 iKey = ++pParse->nMem; |
456 nKey = 0; /* Zero tells OP_Found to use a composite key */ | 449 nKey = 0; /* Zero tells OP_Found to use a composite key */ |
457 sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey, | 450 sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey, |
458 sqlite3IndexAffinityStr(pParse->db, pPk), nPk); | 451 sqlite3IndexAffinityStr(pParse->db, pPk), nPk); |
459 sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey); | 452 sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEphCur, iKey, iPk, nPk); |
460 }else{ | 453 }else{ |
461 /* Add the rowid of the row to be deleted to the RowSet */ | 454 /* Add the rowid of the row to be deleted to the RowSet */ |
462 nKey = 1; /* OP_Seek always uses a single rowid */ | 455 nKey = 1; /* OP_Seek always uses a single rowid */ |
463 sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey); | 456 sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey); |
464 } | 457 } |
465 } | 458 } |
466 | 459 |
467 /* If this DELETE cannot use the ONEPASS strategy, this is the | 460 /* If this DELETE cannot use the ONEPASS strategy, this is the |
468 ** end of the WHERE loop */ | 461 ** end of the WHERE loop */ |
469 if( eOnePass!=ONEPASS_OFF ){ | 462 if( eOnePass!=ONEPASS_OFF ){ |
470 addrBypass = sqlite3VdbeMakeLabel(v); | 463 addrBypass = sqlite3VdbeMakeLabel(v); |
471 }else{ | 464 }else{ |
472 sqlite3WhereEnd(pWInfo); | 465 sqlite3WhereEnd(pWInfo); |
473 } | 466 } |
474 | 467 |
475 /* Unless this is a view, open cursors for the table we are | 468 /* Unless this is a view, open cursors for the table we are |
476 ** deleting from and all its indices. If this is a view, then the | 469 ** deleting from and all its indices. If this is a view, then the |
477 ** only effect this statement has is to fire the INSTEAD OF | 470 ** only effect this statement has is to fire the INSTEAD OF |
478 ** triggers. | 471 ** triggers. |
479 */ | 472 */ |
480 if( !isView ){ | 473 if( !isView ){ |
481 int iAddrOnce = 0; | 474 int iAddrOnce = 0; |
482 u8 p5 = (eOnePass==ONEPASS_OFF ? 0 : OPFLAG_FORDELETE); | |
483 if( eOnePass==ONEPASS_MULTI ){ | 475 if( eOnePass==ONEPASS_MULTI ){ |
484 iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v); | 476 iAddrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); |
485 } | 477 } |
486 testcase( IsVirtual(pTab) ); | 478 testcase( IsVirtual(pTab) ); |
487 sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, p5, iTabCur, | 479 sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE, |
488 aToOpen, &iDataCur, &iIdxCur); | 480 iTabCur, aToOpen, &iDataCur, &iIdxCur); |
489 assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur ); | 481 assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur ); |
490 assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 ); | 482 assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 ); |
491 if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce); | 483 if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce); |
492 } | 484 } |
493 | 485 |
494 /* Set up a loop over the rowids/primary-keys that were found in the | 486 /* Set up a loop over the rowids/primary-keys that were found in the |
495 ** where-clause loop above. | 487 ** where-clause loop above. |
496 */ | 488 */ |
497 if( eOnePass!=ONEPASS_OFF ){ | 489 if( eOnePass!=ONEPASS_OFF ){ |
498 assert( nKey==nPk ); /* OP_Found will use an unpacked key */ | 490 assert( nKey==nPk ); /* OP_Found will use an unpacked key */ |
499 if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){ | 491 if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){ |
500 assert( pPk!=0 || pTab->pSelect!=0 ); | 492 assert( pPk!=0 || pTab->pSelect!=0 ); |
501 sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); | 493 sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey); |
502 VdbeCoverage(v); | 494 VdbeCoverage(v); |
503 } | 495 } |
504 }else if( pPk ){ | 496 }else if( pPk ){ |
505 addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v); | 497 addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v); |
506 sqlite3VdbeAddOp2(v, OP_RowKey, iEphCur, iKey); | 498 sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey); |
507 assert( nKey==0 ); /* OP_Found will use a composite key */ | 499 assert( nKey==0 ); /* OP_Found will use a composite key */ |
508 }else{ | 500 }else{ |
509 addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey); | 501 addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey); |
510 VdbeCoverage(v); | 502 VdbeCoverage(v); |
511 assert( nKey==1 ); | 503 assert( nKey==1 ); |
512 } | 504 } |
513 | 505 |
514 /* Delete the row */ | 506 /* Delete the row */ |
515 #ifndef SQLITE_OMIT_VIRTUALTABLE | 507 #ifndef SQLITE_OMIT_VIRTUALTABLE |
516 if( IsVirtual(pTab) ){ | 508 if( IsVirtual(pTab) ){ |
517 const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); | 509 const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); |
518 sqlite3VtabMakeWritable(pParse, pTab); | 510 sqlite3VtabMakeWritable(pParse, pTab); |
519 sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); | 511 sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); |
520 sqlite3VdbeChangeP5(v, OE_Abort); | 512 sqlite3VdbeChangeP5(v, OE_Abort); |
521 assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); | 513 assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); |
522 sqlite3MayAbort(pParse); | 514 sqlite3MayAbort(pParse); |
523 if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){ | 515 if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){ |
524 pParse->isMultiWrite = 0; | 516 pParse->isMultiWrite = 0; |
525 } | 517 } |
526 }else | 518 }else |
527 #endif | 519 #endif |
528 { | 520 { |
529 int count = (pParse->nested==0); /* True to count changes */ | 521 int count = (pParse->nested==0); /* True to count changes */ |
530 int iIdxNoSeek = -1; | |
531 if( bComplex==0 && aiCurOnePass[1]!=iDataCur ){ | |
532 iIdxNoSeek = aiCurOnePass[1]; | |
533 } | |
534 sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, | 522 sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur, |
535 iKey, nKey, count, OE_Default, eOnePass, iIdxNoSeek); | 523 iKey, nKey, count, OE_Default, eOnePass, aiCurOnePass[1]); |
536 } | 524 } |
537 | 525 |
538 /* End of the loop over all rowids/primary-keys. */ | 526 /* End of the loop over all rowids/primary-keys. */ |
539 if( eOnePass!=ONEPASS_OFF ){ | 527 if( eOnePass!=ONEPASS_OFF ){ |
540 sqlite3VdbeResolveLabel(v, addrBypass); | 528 sqlite3VdbeResolveLabel(v, addrBypass); |
541 sqlite3WhereEnd(pWInfo); | 529 sqlite3WhereEnd(pWInfo); |
542 }else if( pPk ){ | 530 }else if( pPk ){ |
543 sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v); | 531 sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v); |
544 sqlite3VdbeJumpHere(v, addrLoop); | 532 sqlite3VdbeJumpHere(v, addrLoop); |
545 }else{ | 533 }else{ |
546 sqlite3VdbeGoto(v, addrLoop); | 534 sqlite3VdbeGoto(v, addrLoop); |
547 sqlite3VdbeJumpHere(v, addrLoop); | 535 sqlite3VdbeJumpHere(v, addrLoop); |
548 } | 536 } |
549 | |
550 /* Close the cursors open on the table and its indexes. */ | |
551 if( !isView && !IsVirtual(pTab) ){ | |
552 if( !pPk ) sqlite3VdbeAddOp1(v, OP_Close, iDataCur); | |
553 for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ | |
554 sqlite3VdbeAddOp1(v, OP_Close, iIdxCur + i); | |
555 } | |
556 } | |
557 } /* End non-truncate path */ | 537 } /* End non-truncate path */ |
558 | 538 |
559 /* Update the sqlite_sequence table by storing the content of the | 539 /* Update the sqlite_sequence table by storing the content of the |
560 ** maximum rowid counter values recorded while inserting into | 540 ** maximum rowid counter values recorded while inserting into |
561 ** autoincrement tables. | 541 ** autoincrement tables. |
562 */ | 542 */ |
563 if( pParse->nested==0 && pParse->pTriggerTab==0 ){ | 543 if( pParse->nested==0 && pParse->pTriggerTab==0 ){ |
564 sqlite3AutoincrementEnd(pParse); | 544 sqlite3AutoincrementEnd(pParse); |
565 } | 545 } |
566 | 546 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 ** | 593 ** |
614 ** eMode: | 594 ** eMode: |
615 ** Parameter eMode may be passed either ONEPASS_OFF (0), ONEPASS_SINGLE, or | 595 ** Parameter eMode may be passed either ONEPASS_OFF (0), ONEPASS_SINGLE, or |
616 ** ONEPASS_MULTI. If eMode is not ONEPASS_OFF, then the cursor | 596 ** ONEPASS_MULTI. If eMode is not ONEPASS_OFF, then the cursor |
617 ** iDataCur already points to the row to delete. If eMode is ONEPASS_OFF | 597 ** iDataCur already points to the row to delete. If eMode is ONEPASS_OFF |
618 ** then this function must seek iDataCur to the entry identified by iPk | 598 ** then this function must seek iDataCur to the entry identified by iPk |
619 ** and nPk before reading from it. | 599 ** and nPk before reading from it. |
620 ** | 600 ** |
621 ** If eMode is ONEPASS_MULTI, then this call is being made as part | 601 ** If eMode is ONEPASS_MULTI, then this call is being made as part |
622 ** of a ONEPASS delete that affects multiple rows. In this case, if | 602 ** of a ONEPASS delete that affects multiple rows. In this case, if |
623 ** iIdxNoSeek is a valid cursor number (>=0), then its position should | 603 ** iIdxNoSeek is a valid cursor number (>=0) and is not the same as |
624 ** be preserved following the delete operation. Or, if iIdxNoSeek is not | 604 ** iDataCur, then its position should be preserved following the delete |
625 ** a valid cursor number, the position of iDataCur should be preserved | 605 ** operation. Or, if iIdxNoSeek is not a valid cursor number, the |
626 ** instead. | 606 ** position of iDataCur should be preserved instead. |
627 ** | 607 ** |
628 ** iIdxNoSeek: | 608 ** iIdxNoSeek: |
629 ** If iIdxNoSeek is a valid cursor number (>=0), then it identifies an | 609 ** If iIdxNoSeek is a valid cursor number (>=0) not equal to iDataCur, |
630 ** index cursor (from within array of cursors starting at iIdxCur) that | 610 ** then it identifies an index cursor (from within array of cursors |
631 ** already points to the index entry to be deleted. | 611 ** starting at iIdxCur) that already points to the index entry to be deleted. |
| 612 ** Except, this optimization is disabled if there are BEFORE triggers since |
| 613 ** the trigger body might have moved the cursor. |
632 */ | 614 */ |
633 void sqlite3GenerateRowDelete( | 615 void sqlite3GenerateRowDelete( |
634 Parse *pParse, /* Parsing context */ | 616 Parse *pParse, /* Parsing context */ |
635 Table *pTab, /* Table containing the row to be deleted */ | 617 Table *pTab, /* Table containing the row to be deleted */ |
636 Trigger *pTrigger, /* List of triggers to (potentially) fire */ | 618 Trigger *pTrigger, /* List of triggers to (potentially) fire */ |
637 int iDataCur, /* Cursor from which column data is extracted */ | 619 int iDataCur, /* Cursor from which column data is extracted */ |
638 int iIdxCur, /* First index cursor */ | 620 int iIdxCur, /* First index cursor */ |
639 int iPk, /* First memory cell containing the PRIMARY KEY */ | 621 int iPk, /* First memory cell containing the PRIMARY KEY */ |
640 i16 nPk, /* Number of PRIMARY KEY memory cells */ | 622 i16 nPk, /* Number of PRIMARY KEY memory cells */ |
641 u8 count, /* If non-zero, increment the row change counter */ | 623 u8 count, /* If non-zero, increment the row change counter */ |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 } | 674 } |
693 | 675 |
694 /* Invoke BEFORE DELETE trigger programs. */ | 676 /* Invoke BEFORE DELETE trigger programs. */ |
695 addrStart = sqlite3VdbeCurrentAddr(v); | 677 addrStart = sqlite3VdbeCurrentAddr(v); |
696 sqlite3CodeRowTrigger(pParse, pTrigger, | 678 sqlite3CodeRowTrigger(pParse, pTrigger, |
697 TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel | 679 TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel |
698 ); | 680 ); |
699 | 681 |
700 /* If any BEFORE triggers were coded, then seek the cursor to the | 682 /* If any BEFORE triggers were coded, then seek the cursor to the |
701 ** row to be deleted again. It may be that the BEFORE triggers moved | 683 ** row to be deleted again. It may be that the BEFORE triggers moved |
702 ** the cursor or of already deleted the row that the cursor was | 684 ** the cursor or already deleted the row that the cursor was |
703 ** pointing to. | 685 ** pointing to. |
| 686 ** |
| 687 ** Also disable the iIdxNoSeek optimization since the BEFORE trigger |
| 688 ** may have moved that cursor. |
704 */ | 689 */ |
705 if( addrStart<sqlite3VdbeCurrentAddr(v) ){ | 690 if( addrStart<sqlite3VdbeCurrentAddr(v) ){ |
706 sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); | 691 sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk); |
707 VdbeCoverageIf(v, opSeek==OP_NotExists); | 692 VdbeCoverageIf(v, opSeek==OP_NotExists); |
708 VdbeCoverageIf(v, opSeek==OP_NotFound); | 693 VdbeCoverageIf(v, opSeek==OP_NotFound); |
| 694 testcase( iIdxNoSeek>=0 ); |
| 695 iIdxNoSeek = -1; |
709 } | 696 } |
710 | 697 |
711 /* Do FK processing. This call checks that any FK constraints that | 698 /* Do FK processing. This call checks that any FK constraints that |
712 ** refer to this table (i.e. constraints attached to other tables) | 699 ** refer to this table (i.e. constraints attached to other tables) |
713 ** are not violated by deleting this row. */ | 700 ** are not violated by deleting this row. */ |
714 sqlite3FkCheck(pParse, pTab, iOld, 0, 0, 0); | 701 sqlite3FkCheck(pParse, pTab, iOld, 0, 0, 0); |
715 } | 702 } |
716 | 703 |
717 /* Delete the index and table entries. Skip this step if pTab is really | 704 /* Delete the index and table entries. Skip this step if pTab is really |
718 ** a view (in which case the only effect of the DELETE statement is to | 705 ** a view (in which case the only effect of the DELETE statement is to |
719 ** fire the INSTEAD OF triggers). */ | 706 ** fire the INSTEAD OF triggers). |
| 707 ** |
| 708 ** If variable 'count' is non-zero, then this OP_Delete instruction should |
| 709 ** invoke the update-hook. The pre-update-hook, on the other hand should |
| 710 ** be invoked unless table pTab is a system table. The difference is that |
| 711 ** the update-hook is not invoked for rows removed by REPLACE, but the |
| 712 ** pre-update-hook is. |
| 713 */ |
720 if( pTab->pSelect==0 ){ | 714 if( pTab->pSelect==0 ){ |
| 715 u8 p5 = 0; |
721 sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); | 716 sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek); |
722 sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); | 717 sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0)); |
723 if( count ){ | 718 if( pParse->nested==0 ){ |
724 sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT); | 719 sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE); |
725 } | 720 } |
726 if( iIdxNoSeek>=0 ){ | 721 if( eMode!=ONEPASS_OFF ){ |
| 722 sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE); |
| 723 } |
| 724 if( iIdxNoSeek>=0 && iIdxNoSeek!=iDataCur ){ |
727 sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); | 725 sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek); |
728 } | 726 } |
729 sqlite3VdbeChangeP5(v, eMode==ONEPASS_MULTI); | 727 if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION; |
| 728 sqlite3VdbeChangeP5(v, p5); |
730 } | 729 } |
731 | 730 |
732 /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to | 731 /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to |
733 ** handle rows (possibly in other tables) that refer via a foreign key | 732 ** handle rows (possibly in other tables) that refer via a foreign key |
734 ** to the row just deleted. */ | 733 ** to the row just deleted. */ |
735 sqlite3FkActions(pParse, pTab, 0, iOld, 0, 0); | 734 sqlite3FkActions(pParse, pTab, 0, iOld, 0, 0); |
736 | 735 |
737 /* Invoke AFTER DELETE trigger programs. */ | 736 /* Invoke AFTER DELETE trigger programs. */ |
738 sqlite3CodeRowTrigger(pParse, pTrigger, | 737 sqlite3CodeRowTrigger(pParse, pTrigger, |
739 TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel | 738 TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
869 /* If the column affinity is REAL but the number is an integer, then it | 868 /* If the column affinity is REAL but the number is an integer, then it |
870 ** might be stored in the table as an integer (using a compact | 869 ** might be stored in the table as an integer (using a compact |
871 ** representation) then converted to REAL by an OP_RealAffinity opcode. | 870 ** representation) then converted to REAL by an OP_RealAffinity opcode. |
872 ** But we are getting ready to store this value back into an index, where | 871 ** But we are getting ready to store this value back into an index, where |
873 ** it should be converted by to INTEGER again. So omit the OP_RealAffinity | 872 ** it should be converted by to INTEGER again. So omit the OP_RealAffinity |
874 ** opcode if it is present */ | 873 ** opcode if it is present */ |
875 sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity); | 874 sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity); |
876 } | 875 } |
877 if( regOut ){ | 876 if( regOut ){ |
878 sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut); | 877 sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut); |
| 878 if( pIdx->pTable->pSelect ){ |
| 879 const char *zAff = sqlite3IndexAffinityStr(pParse->db, pIdx); |
| 880 sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT); |
| 881 } |
879 } | 882 } |
880 sqlite3ReleaseTempRange(pParse, regBase, nCol); | 883 sqlite3ReleaseTempRange(pParse, regBase, nCol); |
881 return regBase; | 884 return regBase; |
882 } | 885 } |
883 | 886 |
884 /* | 887 /* |
885 ** If a prior call to sqlite3GenerateIndexKey() generated a jump-over label | 888 ** If a prior call to sqlite3GenerateIndexKey() generated a jump-over label |
886 ** because it was a partial index, then this routine should be called to | 889 ** because it was a partial index, then this routine should be called to |
887 ** resolve that label. | 890 ** resolve that label. |
888 */ | 891 */ |
889 void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){ | 892 void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){ |
890 if( iLabel ){ | 893 if( iLabel ){ |
891 sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel); | 894 sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel); |
892 sqlite3ExprCachePop(pParse); | 895 sqlite3ExprCachePop(pParse); |
893 } | 896 } |
894 } | 897 } |
OLD | NEW |