1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-12 13:01:09 +03:00

Disable the multi-row one-pass DELETE optimization when the WHERE clause

contains a subquery.  Fix for ticket [dc6ebeda9396087].

FossilOrigin-Name: 3f221f592a9a19009076e568566c59801cd3fc32
This commit is contained in:
drh
2016-05-02 12:18:56 +00:00
parent 44aebff246
commit 57a07ba9a9
4 changed files with 34 additions and 10 deletions

View File

@@ -1,5 +1,5 @@
C Improvements\sto\sthe\sway\sthe\sLIKE\soptimization\sis\simplemented,\sresulting\sin\nslightly\ssmaller\sand\sfaster\scode\sthat\sis\seasier\sto\stest. C Disable\sthe\smulti-row\sone-pass\sDELETE\soptimization\swhen\sthe\sWHERE\sclause\ncontains\sa\ssubquery.\s\sFix\sfor\sticket\s[dc6ebeda9396087].
D 2016-05-02T10:25:42.392 D 2016-05-02T12:18:56.634
F Makefile.in 9e816d0323e418fbc0f8b2c05fc14e0b3763d9e8 F Makefile.in 9e816d0323e418fbc0f8b2c05fc14e0b3763d9e8
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 71b8b16cf9393f68e2e2035486ca104872558836 F Makefile.msc 71b8b16cf9393f68e2e2035486ca104872558836
@@ -330,7 +330,7 @@ F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198 F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198
F src/date.c 1cc9fb516ec9932c6fd4d2a0d2f8bc4480145c39 F src/date.c 1cc9fb516ec9932c6fd4d2a0d2f8bc4480145c39
F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b F src/dbstat.c c845548d4346e606e2f2b7d2e714ace2b8a7dd1b
F src/delete.c 78eb999114ec04fcf1b7d123ccedb4b5b734930e F src/delete.c 362f89f8e6783e672c4ab06b90fca0177f9a576d
F src/expr.c 8796c0739b2ad091e6779253f62aad6e767e2be1 F src/expr.c 8796c0739b2ad091e6779253f62aad6e767e2be1
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 4c0bd09e602b8ae8d36d81e31e4872d0b53c87bb F src/fkey.c 4c0bd09e602b8ae8d36d81e31e4872d0b53c87bb
@@ -617,7 +617,7 @@ F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
F test/delete.test e1bcdf8926234e27aac24b346ad83d3329ec8b6f F test/delete.test e1bcdf8926234e27aac24b346ad83d3329ec8b6f
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
F test/delete4.test 738044ee892ee0c84e0848e36ba92c55f907d52b F test/delete4.test 21d2113217eeaacac2d99defe14fe6611615ae86
F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240 F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240
F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2 F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
@@ -1486,7 +1486,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 820c57bb24ad3d8663ca512e4022268b940bb2ee P 54c63b329288729031f45b7778752552cd90e226
R c58e65d0f2e2d03ddd82d7f66bccab45 R 31fbd50c446b686ccdad6a76f26cbea2
U drh U drh
Z 38f3015d7db64980369a2f7c9273004f Z 89acbaae560b0638ea30c0a72d46ae74

View File

@@ -1 +1 @@
54c63b329288729031f45b7778752552cd90e226 3f221f592a9a19009076e568566c59801cd3fc32

View File

@@ -239,11 +239,12 @@ void sqlite3DeleteFrom(
int addrBypass = 0; /* Address of jump over the delete logic */ int addrBypass = 0; /* Address of jump over the delete logic */
int addrLoop = 0; /* Top of the delete loop */ int addrLoop = 0; /* Top of the delete loop */
int addrEphOpen = 0; /* Instruction to open the Ephemeral table */ 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 #ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to delete from a view */ int isView; /* True if attempting to delete from a view */
Trigger *pTrigger; /* List of table triggers, if required */ Trigger *pTrigger; /* List of table triggers, if required */
int bComplex; /* True if there are either triggers or FKs */
#endif #endif
memset(&sContext, 0, sizeof(sContext)); memset(&sContext, 0, sizeof(sContext));
@@ -271,7 +272,6 @@ void sqlite3DeleteFrom(
#else #else
# define pTrigger 0 # define pTrigger 0
# define isView 0 # define isView 0
# define bComplex 0
#endif #endif
#ifdef SQLITE_OMIT_VIEW #ifdef SQLITE_OMIT_VIEW
# undef isView # undef isView
@@ -374,6 +374,7 @@ void sqlite3DeleteFrom(
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
{ {
u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK; u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK;
if( pWhere && ExprHasProperty(pWhere, EP_Subquery) ) bComplex = 1;
wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW); wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW);
if( HasRowid(pTab) ){ if( HasRowid(pTab) ){
/* For a rowid table, initialize the RowSet to an empty set */ /* For a rowid table, initialize the RowSet to an empty set */

View File

@@ -161,4 +161,27 @@ do_execsql_test 5.0 {
SELECT a 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 finish_test