1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Do not use the one-pass optimization on an UPDATE if there is a subquery

in the WHERE clause, since if the subquery is hidden behind a short-circuit
operator, the subquery might not be evaluated until after one or more rows
have been updated.  Fix for the problem reported by
[forum:/forumpost/0007d1fdb1|forum post 0007d1fdb1].  This is the same
problem that was fixed by [73f0036f045bf371] only for UPDATE instead of
DELETE.

FossilOrigin-Name: 2c56b984a0bd3be5ec326a2109ea7b8f1d4ef63c8fc325caac9663cf2479eaff
This commit is contained in:
drh
2023-03-16 10:17:30 +00:00
parent 5531316dd0
commit 7d5a549121
6 changed files with 66 additions and 17 deletions

View File

@ -1269,11 +1269,14 @@ do_test 15.0 {
}]} {}
extra_schema_checks 0
do_execsql_test 15.1 {
do_catchsql_test 15.1 {
PRAGMA cell_size_check = 0;
UPDATE c1 SET c= NOT EXISTS(SELECT 1 FROM c1 ORDER BY (SELECT 1 FROM c1 ORDER BY a)) +10 WHERE d BETWEEN 4 AND 7;
} {}
} {1 {database disk image is malformed}}
extra_schema_checks 1
do_execsql_test 15.2 {
PRAGMA integrity_check;
} {/in database main/}
#-------------------------------------------------------------------------
reset_db

View File

@ -426,6 +426,9 @@ do_execsql_test delete-11.1 {
# run after one or more rows have been deleted, which can change
# the result of the subquery, and result in the wrong answer.
#
# Similar problem for UPDATE tested by update-21.4
# https://sqlite.org/forum/forumpost/0007d1fdb1
#
reset_db
do_execsql_test delete-12.0 {
CREATE TABLE t0(vkey INTEGER, pkey INTEGER,c1 INTEGER);

View File

@ -732,4 +732,37 @@ do_execsql_test update-20.30 {
PRAGMA integrity_check;
} {ok}
# 2023-03-16 https://sqlite.org/forum/forumpost/0007d1fdb1
# A subquery in the WHERE clause of an UPDATE and behind a
# short-circuit evaluation caused problems because multi-row
# single-pass was selected.
#
# Similar problem for DELETE tested by delete-12.0.
# https://sqlite.org/src/info/73f0036f045bf371
#
reset_db
do_execsql_test update-21.1 {
CREATE TABLE t1 (vkey INTEGER, c5 INTEGER);
INSERT INTO t1 VALUES(3,NULL),(6,-54);
}
db null NULL
do_execsql_test update-21.2 {
BEGIN;
UPDATE t1 SET vkey = 100 WHERE c5 is null;
SELECT * FROM t1 ORDER BY vkey, c5;
ROLLBACK;
} {6 -54 100 NULL}
do_execsql_test update-21.3 {
BEGIN;
UPDATE t1 SET vkey = 100 WHERE NOT (-10*(select min(vkey) from t1) >= c5);
SELECT * FROM t1 ORDER BY vkey, c5;
ROLLBACK;
} {3 NULL 6 -54}
do_execsql_test update-21.4 {
BEGIN;
UPDATE t1 SET vkey = 100 WHERE c5 is null OR NOT (-10*(select min(vkey) from t1) >= c5);
SELECT * FROM t1 ORDER BY vkey, c5;
ROLLBACK;
} {6 -54 100 NULL}
finish_test