Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(646)

Side by Side Diff: third_party/sqlite/src/src/delete.c

Issue 2751253002: [sql] Import SQLite 3.17.0. (Closed)
Patch Set: also clang on Linux i386 Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/sqlite/src/src/dbstat.c ('k') | third_party/sqlite/src/src/expr.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « third_party/sqlite/src/src/dbstat.c ('k') | third_party/sqlite/src/src/expr.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698