Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Disable the multi-row one-pass DELETE optimization when the WHERE clause contains a subquery. Fix for ticket [dc6ebeda9396087]. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
3f221f592a9a19009076e568566c5980 |
User & Date: | drh 2016-05-02 12:18:56.634 |
References
2016-05-04
| ||
14:45 | Only disable the one-pass DELETE optimization if the WHERE clause contains a correlated subquery. Uncorrelated subqueries are allowed. This is a refinement of check-in [3f221f592a9a1] that is the fix for ticket [dc6ebeda9396087]. (check-in: aae389692a user: drh tags: trunk) | |
Context
2016-05-02
| ||
13:57 | Fix harmless LLVM compiler warnings in the srcck1.c utility program used during the build process. (check-in: e4af967533 user: drh tags: trunk) | |
12:18 | Disable the multi-row one-pass DELETE optimization when the WHERE clause contains a subquery. Fix for ticket [dc6ebeda9396087]. (check-in: 3f221f592a user: drh tags: trunk) | |
10:25 | Improvements to the way the LIKE optimization is implemented, resulting in slightly smaller and faster code that is easier to test. (check-in: 54c63b3292 user: drh tags: trunk) | |
Changes
Changes to src/delete.c.
︙ | ︙ | |||
235 236 237 238 239 240 241 242 243 244 245 | int iKey; /* Memory cell holding key of row to be deleted */ i16 nKey; /* Number of memory cells in the row key */ int iEphCur = 0; /* Ephemeral table holding all primary key values */ int iRowSet = 0; /* Register for rowset of rows to delete */ int addrBypass = 0; /* Address of jump over the delete logic */ int addrLoop = 0; /* Top of the delete loop */ int addrEphOpen = 0; /* Instruction to open the Ephemeral table */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ Trigger *pTrigger; /* List of table triggers, if required */ | > > < | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | int iKey; /* Memory cell holding key of row to be deleted */ i16 nKey; /* Number of memory cells in the row key */ int iEphCur = 0; /* Ephemeral table holding all primary key values */ int iRowSet = 0; /* Register for rowset of rows to delete */ int addrBypass = 0; /* Address of jump over the delete logic */ int addrLoop = 0; /* Top of the delete loop */ int addrEphOpen = 0; /* Instruction to open the Ephemeral table */ int bComplex; /* True if there are triggers or FKs or or ** subqueries in the WHERE clause */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ Trigger *pTrigger; /* List of table triggers, if required */ #endif memset(&sContext, 0, sizeof(sContext)); db = pParse->db; if( pParse->nErr || db->mallocFailed ){ goto delete_from_cleanup; } |
︙ | ︙ | |||
267 268 269 270 271 272 273 | #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); isView = pTab->pSelect!=0; bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0); #else # define pTrigger 0 # define isView 0 | < | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | #ifndef SQLITE_OMIT_TRIGGER pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); isView = pTab->pSelect!=0; bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0); #else # define pTrigger 0 # define isView 0 #endif #ifdef SQLITE_OMIT_VIEW # undef isView # define isView 0 #endif /* If pTab is really a view, make sure it has been initialized. |
︙ | ︙ | |||
370 371 372 373 374 375 376 377 378 379 380 381 382 383 | assert( pIdx->pSchema==pTab->pSchema ); sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); } }else #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ { u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK; wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW); if( HasRowid(pTab) ){ /* For a rowid table, initialize the RowSet to an empty set */ pPk = 0; nPk = 1; iRowSet = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); | > | 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | assert( pIdx->pSchema==pTab->pSchema ); sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); } }else #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ { u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK; if( pWhere && ExprHasProperty(pWhere, EP_Subquery) ) bComplex = 1; wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW); if( HasRowid(pTab) ){ /* For a rowid table, initialize the RowSet to an empty set */ pPk = 0; nPk = 1; iRowSet = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); |
︙ | ︙ |
Changes to test/delete4.test.
︙ | ︙ | |||
156 157 158 159 160 161 162 163 164 | INSERT INTO t1(a,b,c) SELECT a+2, 1, c FROM t1; INSERT INTO t1(a,b,c) SELECT a+10, 2, c FROM t1 WHERE b=1; INSERT INTO t1(a,b,c) SELECT a+20, 3, c FROM t1 WHERE b=1; PRAGMA reverse_unordered_selects = ON; DELETE FROM t1 WHERE b=2; SELECT a FROM t1 WHERE b=2; } {} finish_test | > > > > > > > > > > > > > > > > > > > > > > > | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | INSERT INTO t1(a,b,c) SELECT a+2, 1, c FROM t1; INSERT INTO t1(a,b,c) SELECT a+10, 2, c FROM t1 WHERE b=1; INSERT INTO t1(a,b,c) SELECT a+20, 3, c FROM t1 WHERE b=1; PRAGMA reverse_unordered_selects = ON; DELETE FROM t1 WHERE b=2; SELECT a FROM t1 WHERE b=2; } {} # 2016-05-02 # Ticket https://www.sqlite.org/src/tktview/dc6ebeda93960877 # A subquery in the WHERE clause of a one-pass DELETE can cause an # incorrect answer. # db close forcedelete test.db sqlite3 db test.db do_execsql_test 6.0 { CREATE TABLE t2(x INT); INSERT INTO t2(x) VALUES(1),(2),(3),(4),(5); DELETE FROM t2 WHERE EXISTS(SELECT 1 FROM t2 AS v WHERE v.x=t2.x-1); SELECT x FROM t2; } {1} do_execsql_test 6.1 { DROP TABLE IF EXISTS t2; CREATE TABLE t2(x INT); INSERT INTO t2(x) VALUES(1),(2),(3),(4),(5); DELETE FROM t2 WHERE EXISTS(SELECT 1 FROM t2 AS v WHERE v.x=t2.x+1); SELECT x FROM t2; } {5} finish_test |