From: drh <> Date: Mon, 20 Jul 2026 14:37:21 +0000 (+0000) Subject: Move the new test cases for this branch into a new *.test file. X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=5179e97d9ec11a657d7f59b302e5e0c85ea9dff1;p=thirdparty%2Fsqlite.git Move the new test cases for this branch into a new *.test file. FossilOrigin-Name: 7bdce4ec3b9995a13536eaa2e6a5702333e792b35fa58e606b2e4fa38b85f524 --- diff --git a/manifest b/manifest index bbfe3a6169..6ff08765e0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Test\scase\sfixes\sdue\sto\sthe\sprevious. -D 2026-07-18T19:49:18.411 +C Move\sthe\snew\stest\scases\sfor\sthis\sbranch\sinto\sa\snew\s*.test\sfile. +D 2026-07-20T14:37:21.102 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -996,6 +996,7 @@ F test/columncount.test 6fe99c2f35738b0129357a1cf3fa483f76140f4cd8a89014c88c33c8 F test/conflict.test 3307ffdf988e04b01c4e942d8aa369a977f085bf629f43a627c9a77f39d65926 F test/conflict2.test 5557909ce683b1073982f5d1b61dfb1d41e369533bfdaf003180c5bc87282dd1 F test/conflict3.test 81865d9599609aca394fb3b9cd5f561d4729ea5b176bece3644f6ecb540f88ac +F test/conflict4.test ac0d4274d63dc3531707c78d112b1f2411a03a71b9801a237fb325d2ff76f0a1 F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4 F test/corrupt.test 54509b182b1927663e0a425b681b0935a08a01b11d8153a4a9545ed36760ebe2 F test/corrupt2.test 4ce5eadd51baa1aedb48e141dd885d155946f5c3677bb032547e350ce91b17f4 @@ -1947,7 +1948,7 @@ F test/upfrom2.test 66f3ebf721b3cebd922faee5c386bf244f816d416b57c000753ff51af623 F test/upfrom3.test 6130f24ebf97f5ea865e5d2a14a2d543fe5428a62e87cc60f62d875e45c1f5f0 F test/upfrom4.test 78f742a6577c91a7a55c64edb8811004e7c6aa99b8d57b2320f70a918c357807 F test/upfromfault.test 3a10075a0043f0c4fad6614b2c371f88a8ba5a4acab68b907438413865d6a8d6 -F test/upsert1.test 1ae9667f734f5ba1f4be4db351020e336e661e77192fb726b211cc5b74d6ce9b +F test/upsert1.test 55e85a95cc6e09ab436b411eb4d76b37952752e0501a57848e4296d6be585ef5 F test/upsert2.test 720e94d09f7362a282bc69b3c6b83d51daeaaf0440eb4920a08b86518b8c7496 F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5 @@ -2215,8 +2216,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P e2ab286bb713e1358ae9a1d50dc894362d0ea6f1a2e8467c587f42f0e483dd3a -R b1bddc0276aa195bc5ec2df639e3f657 +P 923665823276ee9404a9fdb19378b970eeea77a97bc2f4312446c6f6bc5e4405 +R c590c51c3034bc599664aab2db20c157 U drh -Z d0f0bea09313f1d71203c2b202fb85a6 +Z a7c0e72149e007f4528ceaeb8c532ec1 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index bb37efa99c..10ab057005 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -923665823276ee9404a9fdb19378b970eeea77a97bc2f4312446c6f6bc5e4405 +7bdce4ec3b9995a13536eaa2e6a5702333e792b35fa58e606b2e4fa38b85f524 diff --git a/test/conflict4.test b/test/conflict4.test new file mode 100644 index 0000000000..51d8ab84f6 --- /dev/null +++ b/test/conflict4.test @@ -0,0 +1,162 @@ +# 2026-07-20 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Test cases for UNIQUE ON CONFLICT REPLACE and UNIQUE ON CONFLICT FAIL +# behavior including when there are also triggers and/or an UPSERT. +# +# Forum thread 2026-07-17T09:30:42Z +# +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix conflict4 + +# Combination of ON CONFLICT FAIL on a UNIQUE index and +# an ON CONFLICT DO NOTHING in a different index leads to +# database corruption. +# +do_execsql_test 1.1 { + CREATE TABLE t0( + a INTEGER PRIMARY KEY ON CONFLICT REPLACE, + b INT UNIQUE ON CONFLICT FAIL, + c INT UNIQUE ON CONFLICT ABORT + ); + INSERT INTO t0 VALUES (1, 10, 100),(2, 20, 200); +} +do_catchsql_test 1.2 { + INSERT INTO t0 VALUES (1, 20, 300) ON CONFLICT(c) DO NOTHING; +} {1 {UNIQUE constraint failed: t0.b}} +do_execsql_test 1.3 { + PRAGMA integrity_check; +} {ok} +do_execsql_test 1.4 { + SELECT * FROM t0 ORDER BY a; +} {1 10 100 2 20 200} +do_execsql_test 1.5 { + DROP TABLE t0; + CREATE TABLE t0( + a INTEGER PRIMARY KEY ON CONFLICT REPLACE, + b INT UNIQUE ON CONFLICT IGNORE, + c INT UNIQUE ON CONFLICT ABORT + ); + INSERT INTO t0 VALUES (1, 10, 100),(2, 20, 200); +} +do_catchsql_test 1.6 { + INSERT INTO t0 VALUES (1, 20, 300) ON CONFLICT(c) DO NOTHING; +} {0 {}} +do_execsql_test 1.7 { + PRAGMA integrity_check; +} {ok} +do_execsql_test 1.8 { + SELECT * FROM t0 ORDER BY a; +} {1 10 100 2 20 200} +do_execsql_test 1.9 { + DROP TABLE t0; + CREATE TABLE t0( + a INTEGER PRIMARY KEY ON CONFLICT REPLACE, + b INT UNIQUE ON CONFLICT FAIL, + c INT UNIQUE ON CONFLICT ABORT + ); + INSERT INTO t0 VALUES (1, 10, 100),(2, 20, 200); +} +do_catchsql_test 1.10 { + INSERT INTO t0 VALUES (1, 20, 300) ON CONFLICT(c) DO NOTHING; +} {1 {UNIQUE constraint failed: t0.b}} +do_execsql_test 1.11 { + PRAGMA integrity_check; +} {ok} +do_execsql_test 1.12 { + SELECT * FROM t0 ORDER BY a; +} {1 10 100 2 20 200} +do_execsql_test 1.13 { + DROP TABLE t0; + CREATE TABLE t1( + a INTEGER PRIMARY KEY, + b UNIQUE ON CONFLICT FAIL, + c UNIQUE + ); + INSERT INTO t1 VALUES(1, 1, 1); +} +do_catchsql_test 1.14 { + -- Inserts 0 rows, because hitting the constraint on (b) does ABORT: + INSERT INTO t1 VALUES(3, 3, 3), (2, 1, 2) ON CONFLICT(c) DO NOTHING; +} {1 {UNIQUE constraint failed: t1.b}} +do_execsql_test 1.15 { + SELECT * FROM t1 ORDER BY a; +} {1 1 1 3 3 3} +do_catchsql_test 1.16 { + -- Inserts 1 row, because hitting the constraint on (b) does FAIL: + DELETE FROM t1 WHERE a=3; + INSERT INTO t1 VALUES(3, 3, 3), (2, 1, 2); +} {1 {UNIQUE constraint failed: t1.b}} +do_execsql_test 1.17 { + SELECT * FROM t1 ORDER BY a; +} {1 1 1 3 3 3} +do_execsql_test 1.18 { + PRAGMA integrity_check; +} ok + +# Counter-example to the fix at check-in 2026-07-17T16:26:56.257Z +# provided by Pavan Nambi at forum post 2026-07-18T03:35:48Z +do_execsql_test 2.1 { + DROP TABLE t1; + PRAGMA recursive_triggers=ON; + CREATE TABLE t2( + a INTEGER PRIMARY KEY ON CONFLICT REPLACE, + b INT UNIQUE ON CONFLICT FAIL, + c INT UNIQUE ON CONFLICT ABORT + ); + CREATE TRIGGER t_ad AFTER DELETE ON t2 BEGIN + INSERT INTO t2 VALUES(99,30,999); + END; + INSERT INTO t2 VALUES(1,10,100),(2,20,200); + SELECT * FROM t2 ORDER BY a; +} {1 10 100 2 20 200} +do_catchsql_test 2.2 { + INSERT INTO t2 VALUES(4,40,400),(1,30,300),(5,50,500) + ON CONFLICT(c) DO NOTHING; +} {1 {UNIQUE constraint failed: t2.b}} +do_execsql_test 2.3 { + PRAGMA integrity_check; +} ok +do_execsql_test 2.4 { + SELECT * FROM t2 ORDER BY a; +} {1 10 100 2 20 200} + +# This is a slightly simpler version of the test above. Before +# the bug was fixed, this would: +# +# 1) Checks there are no instances of 'HELLO' in the index on t1(b), +# 2) Deletes the row from t1 as a result of the REPLACE on the PK, +# 3) Fires the trigger, inserting ('HELLO', 200) into index t1(b). +# 4) Finishes the insert without rechecking t1(b), inserting +# ('HELLO', 100). Corruption. +# +reset_db +do_execsql_test 3.1 { + PRAGMA recursive_triggers = ON; + CREATE TABLE t1( + a PRIMARY KEY ON CONFLICT REPLACE, + b UNIQUE + ); + INSERT INTO t1 VALUES(100, 'abcde'); + CREATE TRIGGER tr1 AFTER DELETE ON t1 BEGIN + INSERT INTO t1 VALUES(200, 'HELLO'); + END; +} +do_catchsql_test 3.2 { + INSERT INTO t1 VALUES(100, 'HELLO'); +} {1 {UNIQUE constraint failed: t1.b}} +do_execsql_test 3.3 { + PRAGMA integrity_check; + SELECT * FROM t1 ORDER BY +a; +} {ok 100 abcde} + +finish_test diff --git a/test/upsert1.test b/test/upsert1.test index bb58166f99..e6f3138f9c 100644 --- a/test/upsert1.test +++ b/test/upsert1.test @@ -13,47 +13,47 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -set testprefix zipfile +set testprefix upsert1 -do_execsql_test upsert1-100 { +do_execsql_test 100 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c DEFAULT 0); CREATE UNIQUE INDEX t1x1 ON t1(b); INSERT INTO t1(a,b) VALUES(1,2) ON CONFLICT DO NOTHING; INSERT INTO t1(a,b) VALUES(1,99),(99,2) ON CONFLICT DO NOTHING; SELECT * FROM t1; } {1 2 0} -do_execsql_test upsert1-101 { +do_execsql_test 101 { DELETE FROM t1; INSERT INTO t1(a,b) VALUES(2,3) ON CONFLICT(a) DO NOTHING; INSERT INTO t1(a,b) VALUES(2,99) ON CONFLICT(a) DO NOTHING; SELECT * FROM t1; } {2 3 0} -do_execsql_test upsert1-102 { +do_execsql_test 102 { DELETE FROM t1; INSERT INTO t1(a,b) VALUES(3,4) ON CONFLICT(b) DO NOTHING; INSERT INTO t1(a,b) VALUES(99,4) ON CONFLICT(b) DO NOTHING; SELECT * FROM t1; } {3 4 0} -do_catchsql_test upsert1-110 { +do_catchsql_test 110 { INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(x) DO NOTHING; SELECT * FROM t1; } {1 {no such column: x}} -do_catchsql_test upsert1-120 { +do_catchsql_test 120 { INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(c) DO NOTHING; SELECT * FROM t1; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} breakpoint -do_catchsql_test upsert1-130 { +do_catchsql_test 130 { INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(b COLLATE nocase) DO NOTHING; SELECT * FROM t1; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} -do_execsql_test upsert1-140 { +do_execsql_test 140 { DELETE FROM t1; INSERT INTO t1(a,b) VALUES(5,6) ON CONFLICT(b COLLATE binary) DO NOTHING; SELECT * FROM t1; } {5 6 0} -do_catchsql_test upsert1-200 { +do_catchsql_test 200 { DROP TABLE t1; CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c DEFAULT 0); CREATE UNIQUE INDEX t1x1 ON t1(a+b); @@ -61,28 +61,28 @@ do_catchsql_test upsert1-200 { INSERT INTO t1(a,b) VALUES(8,7),(9,6) ON CONFLICT(a+b) DO NOTHING; SELECT * FROM t1; } {0 {7 8 0}} -do_catchsql_test upsert1-201 { +do_catchsql_test 201 { INSERT INTO t1(a,b) VALUES(8,7),(9,6) ON CONFLICT(a) DO NOTHING; } {1 {UNIQUE constraint failed: index 't1x1'}} -do_catchsql_test upsert1-210 { +do_catchsql_test 210 { DELETE FROM t1; INSERT INTO t1(a,b) VALUES(9,10) ON CONFLICT(a+(+b)) DO NOTHING; SELECT * FROM t1; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} -do_catchsql_test upsert1-300 { +do_catchsql_test 300 { DROP INDEX t1x1; DELETE FROM t1; CREATE UNIQUE INDEX t1x1 ON t1(b) WHERE b>10; INSERT INTO t1(a,b) VALUES(1,2),(3,2) ON CONFLICT(b) DO NOTHING; SELECT * FROM t1; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} -do_catchsql_test upsert1-310 { +do_catchsql_test 310 { DELETE FROM t1; INSERT INTO t1(a,b) VALUES(1,2),(3,2) ON CONFLICT(b) WHERE b!=10 DO NOTHING; SELECT * FROM t1; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} -do_execsql_test upsert1-320 { +do_execsql_test 320 { DELETE FROM t1; INSERT INTO t1(a,b) VALUES(1,2),(3,2),(4,20),(5,20) ON CONFLICT(b) WHERE b>10 DO NOTHING; @@ -90,7 +90,7 @@ do_execsql_test upsert1-320 { } {1 2 0 x 3 2 0 x 4 20 0 x} # Upsert works with count_changes=on; -do_execsql_test upsert1-400 { +do_execsql_test 400 { DROP TABLE IF EXISTS t2; CREATE TABLE t2(a TEXT UNIQUE, b INT DEFAULT 1); INSERT INTO t2(a) VALUES('one'),('two'),('three'); @@ -98,13 +98,13 @@ do_execsql_test upsert1-400 { INSERT INTO t2(a) VALUES('one'),('one'),('three'),('four') ON CONFLICT(a) DO UPDATE SET b=b+1; } {1} -do_execsql_test upsert1-410 { +do_execsql_test 410 { PRAGMA count_changes=OFF; SELECT a, b FROM t2 ORDER BY a; } {four 1 one 3 three 2 two 1} # Problem found by AFL prior to any release -do_execsql_test upsert1-500 { +do_execsql_test 500 { DROP TABLE t1; CREATE TABLE t1(x INTEGER PRIMARY KEY, y INT UNIQUE); INSERT INTO t1(x,y) SELECT 1,2 WHERE true @@ -116,13 +116,13 @@ do_execsql_test upsert1-500 { # Ticket https://sqlite.org/src/tktview/79cad5e4b2e219dd197242e9e5f4 # UPSERT leads to a corrupt index. # -do_execsql_test upsert1-600 { +do_execsql_test 600 { DROP TABLE t1; CREATE TABLE t1(b UNIQUE, a INT PRIMARY KEY) WITHOUT ROWID; INSERT OR IGNORE INTO t1(a) VALUES('1') ON CONFLICT(a) DO NOTHING; PRAGMA integrity_check; } {ok} -do_execsql_test upsert1-610 { +do_execsql_test 610 { DELETE FROM t1; INSERT OR IGNORE INTO t1(a) VALUES('1'),(1) ON CONFLICT(a) DO NOTHING; PRAGMA integrity_check; @@ -135,7 +135,7 @@ do_execsql_test upsert1-610 { # the other constraints pass or fail. In other words, the UPSERT constraint # should be tested first. # -do_execsql_test upsert1-700 { +do_execsql_test 700 { DROP TABLE t1; CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c INT, d INT, e INT); CREATE UNIQUE INDEX t1b ON t1(b); @@ -145,21 +145,21 @@ do_execsql_test upsert1-700 { ON CONFLICT(e) DO UPDATE SET c=excluded.c; SELECT * FROM t1; } {1 2 33 4 5} -do_execsql_test upsert1-710 { +do_execsql_test 710 { DELETE FROM t1; INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5); INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5) ON CONFLICT(a) DO UPDATE SET c=excluded.c; SELECT * FROM t1; } {1 2 33 4 5} -do_execsql_test upsert1-720 { +do_execsql_test 720 { DELETE FROM t1; INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5); INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5) ON CONFLICT(b) DO UPDATE SET c=excluded.c; SELECT * FROM t1; } {1 2 33 4 5} -do_execsql_test upsert1-730 { +do_execsql_test 730 { DROP TABLE t1; CREATE TABLE t1(a INT, b INT, c INT, d INT, e INT); CREATE UNIQUE INDEX t1a ON t1(a); @@ -170,21 +170,21 @@ do_execsql_test upsert1-730 { ON CONFLICT(e) DO UPDATE SET c=excluded.c; SELECT * FROM t1; } {1 2 33 4 5} -do_execsql_test upsert1-740 { +do_execsql_test 740 { DELETE FROM t1; INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5); INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5) ON CONFLICT(a) DO UPDATE SET c=excluded.c; SELECT * FROM t1; } {1 2 33 4 5} -do_execsql_test upsert1-750 { +do_execsql_test 750 { DELETE FROM t1; INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5); INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5) ON CONFLICT(b) DO UPDATE SET c=excluded.c; SELECT * FROM t1; } {1 2 33 4 5} -do_execsql_test upsert1-760 { +do_execsql_test 760 { DROP TABLE t1; CREATE TABLE t1(a INT PRIMARY KEY, b INT, c INT, d INT, e INT) WITHOUT ROWID; CREATE UNIQUE INDEX t1a ON t1(a); @@ -195,14 +195,14 @@ do_execsql_test upsert1-760 { ON CONFLICT(e) DO UPDATE SET c=excluded.c; SELECT * FROM t1; } {1 2 33 4 5} -do_execsql_test upsert1-770 { +do_execsql_test 770 { DELETE FROM t1; INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5); INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5) ON CONFLICT(a) DO UPDATE SET c=excluded.c; SELECT * FROM t1; } {1 2 33 4 5} -do_execsql_test upsert1-780 { +do_execsql_test 780 { DELETE FROM t1; INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5); INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5) @@ -211,7 +211,7 @@ do_execsql_test upsert1-780 { } {1 2 33 4 5} # 2019-08-30 ticket https://sqlite.org/src/info/5a3dba8104421320 -do_execsql_test upsert1-800 { +do_execsql_test 800 { DROP TABLE IF EXISTS t0; CREATE TABLE t0(c0 REAL UNIQUE, c1); CREATE UNIQUE INDEX test800i0 ON t0(0 || c1); @@ -223,19 +223,19 @@ do_execsql_test upsert1-800 { # 2019-12-06 gramfuzz find sqlite3 db :memory: -do_execsql_test upsert1-900 { +do_execsql_test 900 { CREATE VIEW t1(a) AS SELECT 1; CREATE TRIGGER t1r1 INSTEAD OF INSERT ON t1 BEGIN SELECT 2; END; } -do_catchsql_test upsert1-910 { +do_catchsql_test 910 { INSERT INTO t1 VALUES(3) ON CONFLICT(x) DO NOTHING; } {1 {cannot UPSERT a view}} # 2019-12-26 ticket 7c13db5c3bf74001 reset_db -do_catchsql_test upsert1-1000 { +do_catchsql_test 1000 { CREATE TABLE t0(c0 PRIMARY KEY, c1, c2 UNIQUE) WITHOUT ROWID; INSERT OR FAIL INTO t0(c2) VALUES (0), (NULL) ON CONFLICT(c2) DO UPDATE SET c1 = c0; @@ -248,7 +248,7 @@ do_catchsql_test upsert1-1000 { # in a NULL pointer dereference. # reset_db -do_execsql_test upsert1-1100 { +do_execsql_test 1100 { CREATE TABLE t1(a INTEGER PRIMARY KEY ON CONFLICT REPLACE, b UNIQUE); INSERT INTO t1(b) VALUES(22); INSERT INTO t1 VALUES(2,22) ON CONFLICT (b) DO NOTHING; @@ -259,12 +259,12 @@ do_execsql_test upsert1-1100 { # Bound parameters in the ON CONFLICT clause of an UPSERT. # reset_db -do_execsql_test upsert1-1200 { +do_execsql_test 1200 { CREATE TABLE t1(a INT, b INT); CREATE UNIQUE INDEX t1x ON t1(b+3); } sqlite3_db_config db ENABLE_QPSG 1 -do_catchsql_test upsert1-1210 { +do_catchsql_test 1210 { INSERT INTO t1(a,b) VALUES(1,2) ON CONFLICT(b+?1) DO NOTHING; } {1 {ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint}} @@ -273,7 +273,7 @@ do_catchsql_test upsert1-1210 { # an upsert. # reset_db -do_execsql_test upsert1-1300 { +do_execsql_test 1300 { CREATE TABLE t1(x INT, y TEXT); INSERT INTO t1 VALUES (11, printf('%.9000c','a')), @@ -292,146 +292,4 @@ do_execsql_test upsert1-1300 { ON CONFLICT (x) DO UPDATE SET y = excluded.y; } {} -# 2026-07-17 Forum Post 2026-07-17T09:30:42Z -# Combination of ON CONFLICT FAIL on a UNIQUE index and -# an ON CONFLICT DO NOTHING in a different index leads to -# database corruption. -# -reset_db -do_execsql_test upsert1-1400 { - CREATE TABLE t0( - a INTEGER PRIMARY KEY ON CONFLICT REPLACE, - b INT UNIQUE ON CONFLICT FAIL, - c INT UNIQUE ON CONFLICT ABORT - ); - INSERT INTO t0 VALUES (1, 10, 100),(2, 20, 200); -} -do_catchsql_test upsert1-1401 { - INSERT INTO t0 VALUES (1, 20, 300) ON CONFLICT(c) DO NOTHING; -} {1 {UNIQUE constraint failed: t0.b}} -do_execsql_test upsert1-1402 { - PRAGMA integrity_check; -} {ok} -do_execsql_test upsert1-1403 { - SELECT * FROM t0 ORDER BY a; -} {1 10 100 2 20 200} -do_execsql_test upsert1-1404 { - DROP TABLE t0; - CREATE TABLE t0( - a INTEGER PRIMARY KEY ON CONFLICT REPLACE, - b INT UNIQUE ON CONFLICT IGNORE, - c INT UNIQUE ON CONFLICT ABORT - ); - INSERT INTO t0 VALUES (1, 10, 100),(2, 20, 200); -} -do_catchsql_test upsert1-1405 { - INSERT INTO t0 VALUES (1, 20, 300) ON CONFLICT(c) DO NOTHING; -} {0 {}} -do_execsql_test upsert1-1406 { - PRAGMA integrity_check; -} {ok} -do_execsql_test upsert1-1407 { - SELECT * FROM t0 ORDER BY a; -} {1 10 100 2 20 200} -do_execsql_test upsert1-1408 { - DROP TABLE t0; - CREATE TABLE t0( - a INTEGER PRIMARY KEY ON CONFLICT REPLACE, - b INT UNIQUE ON CONFLICT FAIL, - c INT UNIQUE ON CONFLICT ABORT - ); - INSERT INTO t0 VALUES (1, 10, 100),(2, 20, 200); -} -do_catchsql_test upsert1-1409 { - INSERT INTO t0 VALUES (1, 20, 300) ON CONFLICT(c) DO NOTHING; -} {1 {UNIQUE constraint failed: t0.b}} -do_execsql_test upsert1-1490 { - PRAGMA integrity_check; -} {ok} -do_execsql_test upsert1-1410 { - SELECT * FROM t0 ORDER BY a; -} {1 10 100 2 20 200} -do_execsql_test upsert1-1411 { - DROP TABLE t0; - CREATE TABLE t1( - a INTEGER PRIMARY KEY, - b UNIQUE ON CONFLICT FAIL, - c UNIQUE - ); - INSERT INTO t1 VALUES(1, 1, 1); -} -do_catchsql_test upsert1-1412 { - -- Inserts 0 rows, because hitting the constraint on (b) does ABORT: - INSERT INTO t1 VALUES(3, 3, 3), (2, 1, 2) ON CONFLICT(c) DO NOTHING; -} {1 {UNIQUE constraint failed: t1.b}} -do_execsql_test upsert1-1413 { - SELECT * FROM t1 ORDER BY a; -} {1 1 1 3 3 3} -do_catchsql_test upsert1-1414 { - -- Inserts 1 row, because hitting the constraint on (b) does FAIL: - DELETE FROM t1 WHERE a=3; - INSERT INTO t1 VALUES(3, 3, 3), (2, 1, 2); -} {1 {UNIQUE constraint failed: t1.b}} -do_execsql_test upsert1-1415 { - SELECT * FROM t1 ORDER BY a; -} {1 1 1 3 3 3} -do_execsql_test upsert1-1416 { - PRAGMA integrity_check; -} ok -# Counter-example to the fix at check-in 2026-07-17T16:26:56.257Z -# provided by Pavan Nambi at forum post 2026-07-18T03:35:48Z -do_execsql_test upsert1-1417 { - DROP TABLE t1; - PRAGMA recursive_triggers=ON; - CREATE TABLE t2( - a INTEGER PRIMARY KEY ON CONFLICT REPLACE, - b INT UNIQUE ON CONFLICT FAIL, - c INT UNIQUE ON CONFLICT ABORT - ); - CREATE TRIGGER t_ad AFTER DELETE ON t2 BEGIN - INSERT INTO t2 VALUES(99,30,999); - END; - INSERT INTO t2 VALUES(1,10,100),(2,20,200); - SELECT * FROM t2 ORDER BY a; -} {1 10 100 2 20 200} -do_catchsql_test upsert1-1418 { - INSERT INTO t2 VALUES(4,40,400),(1,30,300),(5,50,500) - ON CONFLICT(c) DO NOTHING; -} {1 {UNIQUE constraint failed: t2.b}} -do_execsql_test upsert1-1419 { - PRAGMA integrity_check; -} ok -do_execsql_test upsert1-1420 { - SELECT * FROM t2 ORDER BY a; -} {1 10 100 2 20 200} - -# This is a slightly simpler version of the test above (1417-1420). Before -# the bug was fixed, this would: -# -# 1) Checks there are no instances of 'HELLO' in the index on t1(b), -# 2) Deletes the row from t1 as a result of the REPLACE on the PK, -# 3) Fires the trigger, inserting ('HELLO', 200) into index t1(b). -# 4) Finishes the insert without rechecking t1(b), inserting -# ('HELLO', 100). Corruption. -# -reset_db -do_execsql_test upsert-1421 { - PRAGMA recursive_triggers = ON; - CREATE TABLE t1( - a PRIMARY KEY ON CONFLICT REPLACE, - b UNIQUE - ); - INSERT INTO t1 VALUES(100, 'abcde'); - CREATE TRIGGER tr1 AFTER DELETE ON t1 BEGIN - INSERT INTO t1 VALUES(200, 'HELLO'); - END; -} -do_catchsql_test upsert-1422 { - INSERT INTO t1 VALUES(100, 'HELLO'); -} {1 {UNIQUE constraint failed: t1.b}} -do_execsql_test upsert-1423 { - PRAGMA integrity_check; - SELECT * FROM t1 ORDER BY +a; -} {ok 100 abcde} - finish_test