xref: /sqlite-3.40.0/test/conflict.test (revision 92e21ef0)
1# 2002 January 29
2#
3# The author disclaims copyright to this source code.  In place of
4# a legal notice, here is a blessing:
5#
6#    May you do good and not evil.
7#    May you find forgiveness for yourself and forgive others.
8#    May you share freely, never taking more than you give.
9#
10#***********************************************************************
11# This file implements regression tests for SQLite library.
12#
13# This file implements tests for the conflict resolution extension
14# to SQLite.
15#
16
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
19
20ifcapable !conflict {
21  finish_test
22  return
23}
24
25# Create tables for the first group of tests.
26#
27do_test conflict-1.0 {
28  execsql {
29    CREATE TABLE t1(a, b, c, UNIQUE(a,b));
30    CREATE TABLE t2(x);
31    SELECT c FROM t1 ORDER BY c;
32  }
33} {}
34
35# Six columns of configuration data as follows:
36#
37#   i      The reference number of the test
38#   cmd    An INSERT or REPLACE command to execute against table t1
39#   t0     True if there is an error from $cmd
40#   t1     Content of "c" column of t1 assuming no error in $cmd
41#   t2     Content of "x" column of t2
42#   t3     Number of temporary files created by this test
43#
44foreach {i cmd t0 t1 t2 t3} {
45  1 INSERT                  1 {}  1  0
46  2 {INSERT OR IGNORE}      0 3   1  0
47  3 {INSERT OR REPLACE}     0 4   1  0
48  4 REPLACE                 0 4   1  0
49  5 {INSERT OR FAIL}        1 {}  1  0
50  6 {INSERT OR ABORT}       1 {}  1  0
51  7 {INSERT OR ROLLBACK}    1 {}  {} 0
52} {
53  do_test conflict-1.$i {
54    set ::sqlite_opentemp_count 0
55    set r0 [catch {execsql [subst {
56      DELETE FROM t1;
57      DELETE FROM t2;
58      INSERT INTO t1 VALUES(1,2,3);
59      BEGIN;
60      INSERT INTO t2 VALUES(1);
61      $cmd INTO t1 VALUES(1,2,4);
62    }]} r1]
63    catch {execsql {COMMIT}}
64    if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
65    set r2 [execsql {SELECT x FROM t2}]
66    set r3 $::sqlite_opentemp_count
67    list $r0 $r1 $r2 $r3
68  } [list $t0 $t1 $t2 $t3]
69}
70
71# Create tables for the first group of tests.
72#
73do_test conflict-2.0 {
74  execsql {
75    DROP TABLE t1;
76    DROP TABLE t2;
77    CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(a,b));
78    CREATE TABLE t2(x);
79    SELECT c FROM t1 ORDER BY c;
80  }
81} {}
82
83# Six columns of configuration data as follows:
84#
85#   i      The reference number of the test
86#   cmd    An INSERT or REPLACE command to execute against table t1
87#   t0     True if there is an error from $cmd
88#   t1     Content of "c" column of t1 assuming no error in $cmd
89#   t2     Content of "x" column of t2
90#
91foreach {i cmd t0 t1 t2} {
92  1 INSERT                  1 {}  1
93  2 {INSERT OR IGNORE}      0 3   1
94  3 {INSERT OR REPLACE}     0 4   1
95  4 REPLACE                 0 4   1
96  5 {INSERT OR FAIL}        1 {}  1
97  6 {INSERT OR ABORT}       1 {}  1
98  7 {INSERT OR ROLLBACK}    1 {}  {}
99} {
100  do_test conflict-2.$i {
101    set r0 [catch {execsql [subst {
102      DELETE FROM t1;
103      DELETE FROM t2;
104      INSERT INTO t1 VALUES(1,2,3);
105      BEGIN;
106      INSERT INTO t2 VALUES(1);
107      $cmd INTO t1 VALUES(1,2,4);
108    }]} r1]
109    catch {execsql {COMMIT}}
110    if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
111    set r2 [execsql {SELECT x FROM t2}]
112    list $r0 $r1 $r2
113  } [list $t0 $t1 $t2]
114}
115
116# Create tables for the first group of tests.
117#
118do_test conflict-3.0 {
119  execsql {
120    DROP TABLE t1;
121    DROP TABLE t2;
122    CREATE TABLE t1(a, b, c INTEGER, PRIMARY KEY(c), UNIQUE(a,b));
123    CREATE TABLE t2(x);
124    SELECT c FROM t1 ORDER BY c;
125  }
126} {}
127
128# Six columns of configuration data as follows:
129#
130#   i      The reference number of the test
131#   cmd    An INSERT or REPLACE command to execute against table t1
132#   t0     True if there is an error from $cmd
133#   t1     Content of "c" column of t1 assuming no error in $cmd
134#   t2     Content of "x" column of t2
135#
136foreach {i cmd t0 t1 t2} {
137  1 INSERT                  1 {}  1
138  2 {INSERT OR IGNORE}      0 3   1
139  3 {INSERT OR REPLACE}     0 4   1
140  4 REPLACE                 0 4   1
141  5 {INSERT OR FAIL}        1 {}  1
142  6 {INSERT OR ABORT}       1 {}  1
143  7 {INSERT OR ROLLBACK}    1 {}  {}
144} {
145  do_test conflict-3.$i {
146    set r0 [catch {execsql [subst {
147      DELETE FROM t1;
148      DELETE FROM t2;
149      INSERT INTO t1 VALUES(1,2,3);
150      BEGIN;
151      INSERT INTO t2 VALUES(1);
152      $cmd INTO t1 VALUES(1,2,4);
153    }]} r1]
154    catch {execsql {COMMIT}}
155    if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
156    set r2 [execsql {SELECT x FROM t2}]
157    list $r0 $r1 $r2
158  } [list $t0 $t1 $t2]
159}
160
161do_test conflict-4.0 {
162  execsql {
163    DROP TABLE t2;
164    CREATE TABLE t2(x);
165    SELECT x FROM t2;
166  }
167} {}
168
169# Six columns of configuration data as follows:
170#
171#   i      The reference number of the test
172#   conf1  The conflict resolution algorithm on the UNIQUE constraint
173#   cmd    An INSERT or REPLACE command to execute against table t1
174#   t0     True if there is an error from $cmd
175#   t1     Content of "c" column of t1 assuming no error in $cmd
176#   t2     Content of "x" column of t2
177#
178foreach {i conf1 cmd t0 t1 t2} {
179  1 {}       INSERT                  1 {}  1
180  2 REPLACE  INSERT                  0 4   1
181  3 IGNORE   INSERT                  0 3   1
182  4 FAIL     INSERT                  1 {}  1
183  5 ABORT    INSERT                  1 {}  1
184  6 ROLLBACK INSERT                  1 {}  {}
185  7 REPLACE  {INSERT OR IGNORE}      0 3   1
186  8 IGNORE   {INSERT OR REPLACE}     0 4   1
187  9 FAIL     {INSERT OR IGNORE}      0 3   1
188 10 ABORT    {INSERT OR REPLACE}     0 4   1
189 11 ROLLBACK {INSERT OR IGNORE }     0 3   1
190} {
191  do_test conflict-4.$i {
192    if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
193    set r0 [catch {execsql [subst {
194      DROP TABLE t1;
195      CREATE TABLE t1(a,b,c,UNIQUE(a,b) $conf1);
196      DELETE FROM t2;
197      INSERT INTO t1 VALUES(1,2,3);
198      BEGIN;
199      INSERT INTO t2 VALUES(1);
200      $cmd INTO t1 VALUES(1,2,4);
201    }]} r1]
202    catch {execsql {COMMIT}}
203    if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]}
204    set r2 [execsql {SELECT x FROM t2}]
205    list $r0 $r1 $r2
206  } [list $t0 $t1 $t2]
207}
208
209do_test conflict-5.0 {
210  execsql {
211    DROP TABLE t2;
212    CREATE TABLE t2(x);
213    SELECT x FROM t2;
214  }
215} {}
216
217# Six columns of configuration data as follows:
218#
219#   i      The reference number of the test
220#   conf1  The conflict resolution algorithm on the NOT NULL constraint
221#   cmd    An INSERT or REPLACE command to execute against table t1
222#   t0     True if there is an error from $cmd
223#   t1     Content of "c" column of t1 assuming no error in $cmd
224#   t2     Content of "x" column of t2
225#
226foreach {i conf1 cmd t0 t1 t2} {
227  1 {}       INSERT                  1 {}  1
228  2 REPLACE  INSERT                  0 5   1
229  3 IGNORE   INSERT                  0 {}  1
230  4 FAIL     INSERT                  1 {}  1
231  5 ABORT    INSERT                  1 {}  1
232  6 ROLLBACK INSERT                  1 {}  {}
233  7 REPLACE  {INSERT OR IGNORE}      0 {}  1
234  8 IGNORE   {INSERT OR REPLACE}     0 5   1
235  9 FAIL     {INSERT OR IGNORE}      0 {}  1
236 10 ABORT    {INSERT OR REPLACE}     0 5   1
237 11 ROLLBACK {INSERT OR IGNORE}      0 {}  1
238 12 {}       {INSERT OR IGNORE}      0 {}  1
239 13 {}       {INSERT OR REPLACE}     0 5   1
240 14 {}       {INSERT OR FAIL}        1 {}  1
241 15 {}       {INSERT OR ABORT}       1 {}  1
242 16 {}       {INSERT OR ROLLBACK}    1 {}  {}
243} {
244  if {$t0} {set t1 {NOT NULL constraint failed: t1.c}}
245  do_test conflict-5.$i {
246    if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
247    set r0 [catch {execsql [subst {
248      DROP TABLE t1;
249      CREATE TABLE t1(a,b,c NOT NULL $conf1 DEFAULT 5);
250      DELETE FROM t2;
251      BEGIN;
252      INSERT INTO t2 VALUES(1);
253      $cmd INTO t1 VALUES(1,2,NULL);
254    }]} r1]
255    catch {execsql {COMMIT}}
256    if {!$r0} {set r1 [execsql {SELECT c FROM t1}]}
257    set r2 [execsql {SELECT x FROM t2}]
258    list $r0 $r1 $r2
259  } [list $t0 $t1 $t2]
260}
261
262do_test conflict-6.0 {
263  execsql {
264    DROP TABLE t2;
265    CREATE TABLE t2(a,b,c);
266    INSERT INTO t2 VALUES(1,2,1);
267    INSERT INTO t2 VALUES(2,3,2);
268    INSERT INTO t2 VALUES(3,4,1);
269    INSERT INTO t2 VALUES(4,5,4);
270    SELECT c FROM t2 ORDER BY b;
271    CREATE TABLE t3(x);
272    INSERT INTO t3 VALUES(1);
273  }
274} {1 2 1 4}
275
276# Six columns of configuration data as follows:
277#
278#   i      The reference number of the test
279#   conf1  The conflict resolution algorithm on the UNIQUE constraint
280#   cmd    An UPDATE command to execute against table t1
281#   t0     True if there is an error from $cmd
282#   t1     Content of "b" column of t1 assuming no error in $cmd
283#   t2     Content of "x" column of t3
284#   t3     Number of temporary files for tables
285#   t4     Number of temporary files for statement journals
286#
287# Update (2007-08-21): Since temporary table files are now opened lazily,
288# and none of the following tests use large quantities of data, t3 is always 0.
289#
290# Update (2016-03-04): Subjournals now also open lazily, so t4 is also always 0.
291#
292foreach {i conf1 cmd t0 t1 t2 t3 t4} {
293  1 {}       UPDATE                  1 {6 7 8 9}  1 0 0
294  2 REPLACE  UPDATE                  0 {7 6 9}    1 0 0
295  3 IGNORE   UPDATE                  0 {6 7 3 9}  1 0 0
296  4 FAIL     UPDATE                  1 {6 7 3 4}  1 0 0
297  5 ABORT    UPDATE                  1 {1 2 3 4}  1 0 0
298  6 ROLLBACK UPDATE                  1 {1 2 3 4}  0 0 0
299  7 REPLACE  {UPDATE OR IGNORE}      0 {6 7 3 9}  1 0 0
300  8 IGNORE   {UPDATE OR REPLACE}     0 {7 6 9}    1 0 0
301  9 FAIL     {UPDATE OR IGNORE}      0 {6 7 3 9}  1 0 0
302 10 ABORT    {UPDATE OR REPLACE}     0 {7 6 9}    1 0 0
303 11 ROLLBACK {UPDATE OR IGNORE}      0 {6 7 3 9}  1 0 0
304 12 {}       {UPDATE OR IGNORE}      0 {6 7 3 9}  1 0 0
305 13 {}       {UPDATE OR REPLACE}     0 {7 6 9}    1 0 0
306 14 {}       {UPDATE OR FAIL}        1 {6 7 3 4}  1 0 0
307 15 {}       {UPDATE OR ABORT}       1 {1 2 3 4}  1 0 0
308 16 {}       {UPDATE OR ROLLBACK}    1 {1 2 3 4}  0 0 0
309} {
310  if {$t0} {set t1 {UNIQUE constraint failed: t1.a}}
311  if {[info exists TEMP_STORE] && $TEMP_STORE==3} {
312    set t3 0
313  } else {
314    set t3 [expr {$t3+$t4}]
315  }
316  do_test conflict-6.$i {
317    db close
318    sqlite3 db test.db
319    if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
320    execsql {pragma temp_store=file}
321    set ::sqlite_opentemp_count 0
322    set r0 [catch {execsql [subst {
323      DROP TABLE t1;
324      CREATE TABLE t1(a,b,c, UNIQUE(a) $conf1);
325      INSERT INTO t1 SELECT * FROM t2;
326      UPDATE t3 SET x=0;
327      BEGIN;
328      $cmd t3 SET x=1;
329      $cmd t1 SET b=b*2;
330      $cmd t1 SET a=c+5;
331    }]} r1]
332    catch {execsql {COMMIT}}
333    if {!$r0} {set r1 [execsql {SELECT a FROM t1 ORDER BY b}]}
334    set r2 [execsql {SELECT x FROM t3}]
335    list $r0 $r1 $r2 $::sqlite_opentemp_count
336  } [list $t0 $t1 $t2 $t3]
337}
338
339# Test to make sure a lot of IGNOREs don't cause a stack overflow
340#
341do_test conflict-7.1 {
342  execsql {
343    DROP TABLE t1;
344    DROP TABLE t2;
345    DROP TABLE t3;
346    CREATE TABLE t1(a unique, b);
347  }
348  for {set i 1} {$i<=50} {incr i} {
349    execsql "INSERT into t1 values($i,[expr {$i+1}]);"
350  }
351  execsql {
352    SELECT count(*), min(a), max(b) FROM t1;
353  }
354} {50 1 51}
355do_test conflict-7.2 {
356  execsql {
357    PRAGMA count_changes=on;
358    UPDATE OR IGNORE t1 SET a=1000;
359  }
360} {1}
361do_test conflict-7.2.1 {
362  db changes
363} {1}
364do_test conflict-7.3 {
365  execsql {
366    SELECT b FROM t1 WHERE a=1000;
367  }
368} {2}
369do_test conflict-7.4 {
370  execsql {
371    SELECT count(*) FROM t1;
372  }
373} {50}
374do_test conflict-7.5 {
375  execsql {
376    PRAGMA count_changes=on;
377    UPDATE OR REPLACE t1 SET a=1001;
378  }
379} {50}
380do_test conflict-7.5.1 {
381  db changes
382} {50}
383do_test conflict-7.6 {
384  execsql {
385    SELECT b FROM t1 WHERE a=1001;
386  }
387} {51}
388do_test conflict-7.7 {
389  execsql {
390    SELECT count(*) FROM t1;
391  }
392} {1}
393
394# Update for version 3: A SELECT statement no longer resets the change
395# counter (Test result changes from 0 to 50).
396do_test conflict-7.7.1 {
397  db changes
398} {50}
399
400# Make sure the row count is right for rows that are ignored on
401# an insert.
402#
403do_test conflict-8.1 {
404  execsql {
405    DELETE FROM t1;
406    INSERT INTO t1 VALUES(1,2);
407  }
408  execsql {
409    INSERT OR IGNORE INTO t1 VALUES(2,3);
410  }
411} {1}
412do_test conflict-8.1.1 {
413  db changes
414} {1}
415do_test conflict-8.2 {
416  execsql {
417    INSERT OR IGNORE INTO t1 VALUES(2,4);
418  }
419} {0}
420do_test conflict-8.2.1 {
421  db changes
422} {0}
423do_test conflict-8.3 {
424  execsql {
425    INSERT OR REPLACE INTO t1 VALUES(2,4);
426  }
427} {1}
428do_test conflict-8.3.1 {
429  db changes
430} {1}
431do_test conflict-8.4 {
432  execsql {
433    INSERT OR IGNORE INTO t1 SELECT * FROM t1;
434  }
435} {0}
436do_test conflict-8.4.1 {
437  db changes
438} {0}
439do_test conflict-8.5 {
440  execsql {
441    INSERT OR IGNORE INTO t1 SELECT a+2,b+2 FROM t1;
442  }
443} {2}
444do_test conflict-8.5.1 {
445  db changes
446} {2}
447do_test conflict-8.6 {
448  execsql {
449    INSERT OR IGNORE INTO t1 SELECT a+3,b+3 FROM t1;
450  }
451} {3}
452do_test conflict-8.6.1 {
453  db changes
454} {3}
455
456integrity_check conflict-8.99
457
458do_test conflict-9.1 {
459  execsql {
460    PRAGMA count_changes=0;
461    CREATE TABLE t2(
462      a INTEGER UNIQUE ON CONFLICT IGNORE,
463      b INTEGER UNIQUE ON CONFLICT FAIL,
464      c INTEGER UNIQUE ON CONFLICT REPLACE,
465      d INTEGER UNIQUE ON CONFLICT ABORT,
466      e INTEGER UNIQUE ON CONFLICT ROLLBACK
467    );
468    CREATE TABLE t3(x);
469    INSERT INTO t3 VALUES(1);
470    SELECT * FROM t3;
471  }
472} {1}
473do_test conflict-9.2 {
474  catchsql {
475    INSERT INTO t2 VALUES(1,1,1,1,1);
476    INSERT INTO t2 VALUES(2,2,2,2,2);
477    SELECT * FROM t2;
478  }
479} {0 {1 1 1 1 1 2 2 2 2 2}}
480do_test conflict-9.3 {
481  catchsql {
482    INSERT INTO t2 VALUES(1,3,3,3,3);
483    SELECT * FROM t2;
484  }
485} {0 {1 1 1 1 1 2 2 2 2 2}}
486do_test conflict-9.4 {
487  catchsql {
488    UPDATE t2 SET a=a+1 WHERE a=1;
489    SELECT * FROM t2;
490  }
491} {0 {1 1 1 1 1 2 2 2 2 2}}
492do_test conflict-9.5 {
493  catchsql {
494    INSERT INTO t2 VALUES(3,1,3,3,3);
495    SELECT * FROM t2;
496  }
497} {1 {UNIQUE constraint failed: t2.b}}
498do_test conflict-9.6 {
499  catchsql {
500    UPDATE t2 SET b=b+1 WHERE b=1;
501    SELECT * FROM t2;
502  }
503} {1 {UNIQUE constraint failed: t2.b}}
504do_test conflict-9.7 {
505  catchsql {
506    BEGIN;
507    UPDATE t3 SET x=x+1;
508    INSERT INTO t2 VALUES(3,1,3,3,3);
509    SELECT * FROM t2;
510  }
511} {1 {UNIQUE constraint failed: t2.b}}
512do_test conflict-9.8 {
513  execsql {COMMIT}
514  execsql {SELECT * FROM t3}
515} {2}
516do_test conflict-9.9 {
517  catchsql {
518    BEGIN;
519    UPDATE t3 SET x=x+1;
520    UPDATE t2 SET b=b+1 WHERE b=1;
521    SELECT * FROM t2;
522  }
523} {1 {UNIQUE constraint failed: t2.b}}
524do_test conflict-9.10 {
525  execsql {COMMIT}
526  execsql {SELECT * FROM t3}
527} {3}
528do_test conflict-9.11 {
529  catchsql {
530    INSERT INTO t2 VALUES(3,3,3,1,3);
531    SELECT * FROM t2;
532  }
533} {1 {UNIQUE constraint failed: t2.d}}
534do_test conflict-9.12 {
535  catchsql {
536    UPDATE t2 SET d=d+1 WHERE d=1;
537    SELECT * FROM t2;
538  }
539} {1 {UNIQUE constraint failed: t2.d}}
540do_test conflict-9.13 {
541  catchsql {
542    BEGIN;
543    UPDATE t3 SET x=x+1;
544    INSERT INTO t2 VALUES(3,3,3,1,3);
545    SELECT * FROM t2;
546  }
547} {1 {UNIQUE constraint failed: t2.d}}
548do_test conflict-9.14 {
549  execsql {COMMIT}
550  execsql {SELECT * FROM t3}
551} {4}
552do_test conflict-9.15 {
553  catchsql {
554    BEGIN;
555    UPDATE t3 SET x=x+1;
556    UPDATE t2 SET d=d+1 WHERE d=1;
557    SELECT * FROM t2;
558  }
559} {1 {UNIQUE constraint failed: t2.d}}
560do_test conflict-9.16 {
561  execsql {COMMIT}
562  execsql {SELECT * FROM t3}
563} {5}
564do_test conflict-9.17 {
565  catchsql {
566    INSERT INTO t2 VALUES(3,3,3,3,1);
567    SELECT * FROM t2;
568  }
569} {1 {UNIQUE constraint failed: t2.e}}
570do_test conflict-9.18 {
571  catchsql {
572    UPDATE t2 SET e=e+1 WHERE e=1;
573    SELECT * FROM t2;
574  }
575} {1 {UNIQUE constraint failed: t2.e}}
576do_test conflict-9.19 {
577  catchsql {
578    BEGIN;
579    UPDATE t3 SET x=x+1;
580    INSERT INTO t2 VALUES(3,3,3,3,1);
581    SELECT * FROM t2;
582  }
583} {1 {UNIQUE constraint failed: t2.e}}
584verify_ex_errcode conflict-9.21b SQLITE_CONSTRAINT_UNIQUE
585do_test conflict-9.20 {
586  catch {execsql {COMMIT}}
587  execsql {SELECT * FROM t3}
588} {5}
589do_test conflict-9.21 {
590  catchsql {
591    BEGIN;
592    UPDATE t3 SET x=x+1;
593    UPDATE t2 SET e=e+1 WHERE e=1;
594    SELECT * FROM t2;
595  }
596} {1 {UNIQUE constraint failed: t2.e}}
597verify_ex_errcode conflict-9.21b SQLITE_CONSTRAINT_UNIQUE
598do_test conflict-9.22 {
599  catch {execsql {COMMIT}}
600  execsql {SELECT * FROM t3}
601} {5}
602do_test conflict-9.23 {
603  catchsql {
604    INSERT INTO t2 VALUES(3,3,1,3,3);
605    SELECT * FROM t2;
606  }
607} {0 {2 2 2 2 2 3 3 1 3 3}}
608do_test conflict-9.24 {
609  catchsql {
610    UPDATE t2 SET c=c-1 WHERE c=2;
611    SELECT * FROM t2;
612  }
613} {0 {2 2 1 2 2}}
614do_test conflict-9.25 {
615  catchsql {
616    BEGIN;
617    UPDATE t3 SET x=x+1;
618    INSERT INTO t2 VALUES(3,3,1,3,3);
619    SELECT * FROM t2;
620  }
621} {0 {3 3 1 3 3}}
622do_test conflict-9.26 {
623  catch {execsql {COMMIT}}
624  execsql {SELECT * FROM t3}
625} {6}
626
627do_test conflict-10.1 {
628  catchsql {
629    DELETE FROM t1;
630    BEGIN;
631    INSERT OR ROLLBACK INTO t1 VALUES(1,2);
632    INSERT OR ROLLBACK INTO t1 VALUES(1,3);
633    COMMIT;
634  }
635  execsql {SELECT * FROM t1}
636} {}
637do_test conflict-10.2 {
638  catchsql {
639    CREATE TABLE t4(x);
640    CREATE UNIQUE INDEX t4x ON t4(x);
641    BEGIN;
642    INSERT OR ROLLBACK INTO t4 VALUES(1);
643    INSERT OR ROLLBACK INTO t4 VALUES(1);
644    COMMIT;
645  }
646  execsql {SELECT * FROM t4}
647} {}
648
649# Ticket #1171.  Make sure statement rollbacks do not
650# damage the database.
651#
652do_test conflict-11.1 {
653  execsql {
654    -- Create a database object (pages 2, 3 of the file)
655    BEGIN;
656      CREATE TABLE abc(a UNIQUE, b, c);
657      INSERT INTO abc VALUES(1, 2, 3);
658      INSERT INTO abc VALUES(4, 5, 6);
659      INSERT INTO abc VALUES(7, 8, 9);
660    COMMIT;
661  }
662
663
664  # Set a small cache size so that changes will spill into
665  # the database file.
666  execsql {
667    PRAGMA cache_size = 10;
668  }
669
670  # Make lots of changes.  Because of the small cache, some
671  # (most?) of these changes will spill into the disk file.
672  # In other words, some of the changes will not be held in
673  # cache.
674  #
675  execsql {
676    BEGIN;
677      -- Make sure the pager is in EXCLUSIVE state.
678      CREATE TABLE def(d, e, f);
679      INSERT INTO def VALUES
680          ('xxxxxxxxxxxxxxx', 'yyyyyyyyyyyyyyyy', 'zzzzzzzzzzzzzzzz');
681      INSERT INTO def SELECT * FROM def;
682      INSERT INTO def SELECT * FROM def;
683      INSERT INTO def SELECT * FROM def;
684      INSERT INTO def SELECT * FROM def;
685      INSERT INTO def SELECT * FROM def;
686      INSERT INTO def SELECT * FROM def;
687      INSERT INTO def SELECT * FROM def;
688      DELETE FROM abc WHERE a = 4;
689  }
690
691  # Execute a statement that does a statement rollback due to
692  # a constraint failure.
693  #
694  catchsql {
695    INSERT INTO abc SELECT 10, 20, 30 FROM def;
696  }
697
698  # Rollback the database.  Verify that the state of the ABC table
699  # is unchanged from the beginning of the transaction.  In other words,
700  # make sure the DELETE on table ABC that occurred within the transaction
701  # had no effect.
702  #
703  execsql {
704    ROLLBACK;
705    SELECT * FROM abc;
706  }
707} {1 2 3 4 5 6 7 8 9}
708integrity_check conflict-11.2
709
710# Repeat test conflict-11.1 but this time commit.
711#
712do_test conflict-11.3 {
713  execsql {
714    BEGIN;
715      -- Make sure the pager is in EXCLUSIVE state.
716      UPDATE abc SET a=a+1;
717      CREATE TABLE def(d, e, f);
718      INSERT INTO def VALUES
719          ('xxxxxxxxxxxxxxx', 'yyyyyyyyyyyyyyyy', 'zzzzzzzzzzzzzzzz');
720      INSERT INTO def SELECT * FROM def;
721      INSERT INTO def SELECT * FROM def;
722      INSERT INTO def SELECT * FROM def;
723      INSERT INTO def SELECT * FROM def;
724      INSERT INTO def SELECT * FROM def;
725      INSERT INTO def SELECT * FROM def;
726      INSERT INTO def SELECT * FROM def;
727      DELETE FROM abc WHERE a = 4;
728  }
729  catchsql {
730    INSERT INTO abc SELECT 10, 20, 30 FROM def;
731  }
732  execsql {
733    ROLLBACK;
734    SELECT * FROM abc;
735  }
736} {1 2 3 4 5 6 7 8 9}
737# Repeat test conflict-11.1 but this time commit.
738#
739do_test conflict-11.5 {
740  execsql {
741    BEGIN;
742      -- Make sure the pager is in EXCLUSIVE state.
743      CREATE TABLE def(d, e, f);
744      INSERT INTO def VALUES
745          ('xxxxxxxxxxxxxxx', 'yyyyyyyyyyyyyyyy', 'zzzzzzzzzzzzzzzz');
746      INSERT INTO def SELECT * FROM def;
747      INSERT INTO def SELECT * FROM def;
748      INSERT INTO def SELECT * FROM def;
749      INSERT INTO def SELECT * FROM def;
750      INSERT INTO def SELECT * FROM def;
751      INSERT INTO def SELECT * FROM def;
752      INSERT INTO def SELECT * FROM def;
753      DELETE FROM abc WHERE a = 4;
754  }
755  catchsql {
756    INSERT INTO abc SELECT 10, 20, 30 FROM def;
757  }
758  execsql {
759    COMMIT;
760    SELECT * FROM abc;
761  }
762} {1 2 3 7 8 9}
763integrity_check conflict-11.6
764
765# Make sure UPDATE OR REPLACE works on tables that have only
766# an INTEGER PRIMARY KEY.
767#
768do_test conflict-12.1 {
769  execsql {
770    CREATE TABLE t5(a INTEGER PRIMARY KEY, b text);
771    INSERT INTO t5 VALUES(1,'one');
772    INSERT INTO t5 VALUES(2,'two');
773    SELECT * FROM t5
774  }
775} {1 one 2 two}
776do_test conflict-12.2 {
777  execsql {
778    UPDATE OR IGNORE t5 SET a=a+1 WHERE a=1;
779    SELECT * FROM t5;
780  }
781} {1 one 2 two}
782do_test conflict-12.3 {
783  catchsql {
784    UPDATE t5 SET a=a+1 WHERE a=1;
785  }
786} {1 {UNIQUE constraint failed: t5.a}}
787verify_ex_errcode conflict-12.3b SQLITE_CONSTRAINT_PRIMARYKEY
788do_test conflict-12.4 {
789  execsql {
790    UPDATE OR REPLACE t5 SET a=a+1 WHERE a=1;
791    SELECT * FROM t5;
792  }
793} {2 one}
794do_test conflict-12.5 {
795  catchsql {
796    CREATE TABLE t5b(x);
797    INSERT INTO t5b(rowid, x) VALUES(1,10),(2,11);
798    UPDATE t5b SET rowid=rowid+1 WHERE x=10;
799  }
800} {1 {UNIQUE constraint failed: t5b.rowid}}
801verify_ex_errcode conflict-12.5b SQLITE_CONSTRAINT_ROWID
802
803
804# Ticket [c38baa3d969eab7946dc50ba9d9b4f0057a19437]
805# REPLACE works like ABORT on a CHECK constraint.
806#
807do_test conflict-13.1 {
808  execsql {
809    CREATE TABLE t13(a CHECK(a!=2));
810    BEGIN;
811    REPLACE INTO t13 VALUES(1);
812  }
813  catchsql {
814    REPLACE INTO t13 VALUES(2);
815  }
816} {1 {CHECK constraint failed: a!=2}}
817verify_ex_errcode conflict-13.1b SQLITE_CONSTRAINT_CHECK
818do_test conflict-13.2 {
819  execsql {
820    REPLACE INTO t13 VALUES(3);
821    COMMIT;
822    SELECT * FROM t13;
823  }
824} {1 3}
825
826
827# Ticket https://www.sqlite.org/src/tktview/e6f1f2e34dceeb1ed61531c7e9
828# Verify that it is not possible to sneak a NULL value into a NOT NULL
829# column using REPLACE.
830#
831do_catchsql_test conflict-14.1 {
832  DROP TABLE IF EXISTS t1;
833  CREATE TABLE t1(x NOT NULL DEFAULT NULL);
834  REPLACE INTO t1 DEFAULT VALUES;
835} {1 {NOT NULL constraint failed: t1.x}}
836
837# 2019-12-15 gramfuzz1 find
838# Three UNIQUE constraints, where the third would is a duplicate except
839# that it adds ON CONFLICT REPLACE.  Verify that the indexes end up
840# sorted in the correct order (REPLACE last) so that constraint processing
841# works correctly.
842#
843reset_db
844do_execsql_test conflict-15.10 {
845  CREATE TABLE t1(
846    x PRIMARY KEY,
847    UNIQUE(x,x),
848    UNIQUE(x,x) ON CONFLICT REPLACE
849  );
850  INSERT INTO t1(x) VALUES(1);
851  SELECT * FROM t1;
852} {1}
853do_catchsql_test conflict-15.20 {
854  INSERT INTO t1(x) VALUES(1);
855} {1 {UNIQUE constraint failed: t1.x}}
856do_execsql_test conflict-15.30 {
857  SELECT * FROM t1;
858} {1}
859
860finish_test
861