xref: /sqlite-3.40.0/ext/session/session1.test (revision 779e9906)
1# 2011 March 07
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
14if {![info exists testdir]} {
15  set testdir [file join [file dirname [info script]] .. .. test]
16}
17source [file join [file dirname [info script]] session_common.tcl]
18source $testdir/tester.tcl
19ifcapable !session {finish_test; return}
20
21set testprefix session1
22
23# Run all tests in this file twice. Once with "WITHOUT ROWID", and once
24# with regular rowid tables.
25#
26foreach {tn trailing} {
27  1 ""
28  2 " WITHOUT ROWID "
29} {
30eval [string map [list %WR% $trailing] {
31
32db close
33forcedelete test.db test.db2
34reset_db
35
36do_execsql_test $tn.1.0 {
37  CREATE TABLE t1(x PRIMARY KEY, y) %WR%;
38  INSERT INTO t1 VALUES('abc', 'def');
39}
40
41#-------------------------------------------------------------------------
42# Test creating, attaching tables to and deleting session objects.
43#
44do_test $tn.1.1 { sqlite3session S db main } {S}
45do_test $tn.1.2 { S delete } {}
46do_test $tn.1.3 { sqlite3session S db main } {S}
47do_test $tn.1.4 { S attach t1 } {}
48do_test $tn.1.5 { S delete } {}
49do_test $tn.1.6 { sqlite3session S db main } {S}
50do_test $tn.1.7 { S attach t1 ; S attach t2 ; S attach t3 } {}
51do_test $tn.1.8 { S attach t1 ; S attach t2 ; S attach t3 } {}
52do_test $tn.1.9 { S delete } {}
53do_test $tn.1.10 {
54  sqlite3session S db main
55  S attach t1
56  execsql { INSERT INTO t1 VALUES('ghi', 'jkl') }
57} {}
58do_test $tn.1.11 { S delete } {}
59if {$tn==1} {
60  do_test $tn.1.12 {
61    sqlite3session S db main
62    S attach t1
63    execsql { INSERT INTO t1 VALUES('mno', 'pqr') }
64    execsql { UPDATE t1 SET x = 111 WHERE rowid = 1 }
65    execsql { DELETE FROM t1 WHERE rowid = 2 }
66  } {}
67  do_test $tn.1.13 {
68    S changeset
69    S delete
70  } {}
71}
72
73#-------------------------------------------------------------------------
74# Simple changeset tests. Also test the sqlite3changeset_invert()
75# function.
76#
77do_test $tn.2.1.1 {
78  execsql { DELETE FROM t1 }
79  sqlite3session S db main
80  S attach t1
81  execsql { INSERT INTO t1 VALUES(1, 'Sukhothai') }
82  execsql { INSERT INTO t1 VALUES(2, 'Ayutthaya') }
83  execsql { INSERT INTO t1 VALUES(3, 'Thonburi') }
84} {}
85do_changeset_test $tn.2.1.2 S {
86  {INSERT t1 0 X. {} {i 1 t Sukhothai}}
87  {INSERT t1 0 X. {} {i 2 t Ayutthaya}}
88  {INSERT t1 0 X. {} {i 3 t Thonburi}}
89}
90do_changeset_invert_test $tn.2.1.3 S {
91  {DELETE t1 0 X. {i 1 t Sukhothai} {}}
92  {DELETE t1 0 X. {i 2 t Ayutthaya} {}}
93  {DELETE t1 0 X. {i 3 t Thonburi} {}}
94}
95do_test $tn.2.1.4 { S delete } {}
96
97do_test $tn.2.2.1 {
98  sqlite3session S db main
99  S attach t1
100  execsql { DELETE FROM t1 WHERE 1 }
101} {}
102do_changeset_test $tn.2.2.2 S {
103  {DELETE t1 0 X. {i 1 t Sukhothai} {}}
104  {DELETE t1 0 X. {i 2 t Ayutthaya} {}}
105  {DELETE t1 0 X. {i 3 t Thonburi} {}}
106}
107do_changeset_invert_test $tn.2.2.3 S {
108  {INSERT t1 0 X. {} {i 1 t Sukhothai}}
109  {INSERT t1 0 X. {} {i 2 t Ayutthaya}}
110  {INSERT t1 0 X. {} {i 3 t Thonburi}}
111}
112do_test $tn.2.2.4 { S delete } {}
113
114do_test $tn.2.3.1 {
115  execsql { DELETE FROM t1 }
116  sqlite3session S db main
117  execsql { INSERT INTO t1 VALUES(1, 'Sukhothai') }
118  execsql { INSERT INTO t1 VALUES(2, 'Ayutthaya') }
119  execsql { INSERT INTO t1 VALUES(3, 'Thonburi') }
120  S attach t1
121  execsql {
122    UPDATE t1 SET x = 10 WHERE x = 1;
123    UPDATE t1 SET y = 'Surin' WHERE x = 2;
124    UPDATE t1 SET x = 20, y = 'Thapae' WHERE x = 3;
125  }
126} {}
127
128do_changeset_test $tn.2.3.2 S {
129  {INSERT t1 0 X. {} {i 10 t Sukhothai}}
130  {DELETE t1 0 X. {i 1 t Sukhothai} {}}
131  {UPDATE t1 0 X. {i 2 t Ayutthaya} {{} {} t Surin}}
132  {DELETE t1 0 X. {i 3 t Thonburi} {}}
133  {INSERT t1 0 X. {} {i 20 t Thapae}}
134}
135
136do_changeset_invert_test $tn.2.3.3 S {
137  {DELETE t1 0 X. {i 10 t Sukhothai} {}}
138  {INSERT t1 0 X. {} {i 1 t Sukhothai}}
139  {UPDATE t1 0 X. {i 2 t Surin} {{} {} t Ayutthaya}}
140  {INSERT t1 0 X. {} {i 3 t Thonburi}}
141  {DELETE t1 0 X. {i 20 t Thapae} {}}
142}
143do_test $tn.2.3.4 { S delete } {}
144
145do_test $tn.2.4.1 {
146  sqlite3session S db main
147  S attach t1
148  execsql { INSERT INTO t1 VALUES(100, 'Bangkok') }
149  execsql { DELETE FROM t1 WHERE x = 100 }
150} {}
151do_changeset_test $tn.2.4.2 S {}
152do_changeset_invert_test $tn.2.4.3 S {}
153do_test $tn.2.4.4 { S delete } {}
154
155do_execsql_test $tn.2.5.0 {
156  SELECT * FROM t1 ORDER BY x
157} {
158  2  Surin
159  10 Sukhothai
160  20 Thapae
161}
162
163do_test $tn.2.5.1 {
164  sqlite3session S db main
165  S attach t1
166  execsql { DELETE FROM t1 }
167} {}
168do_changeset_test $tn.2.5.2 S {
169  {DELETE t1 0 X. {i 10 t Sukhothai} {}}
170  {DELETE t1 0 X. {i 2 t Surin} {}}
171  {DELETE t1 0 X. {i 20 t Thapae} {}}
172}
173do_test $tn.2.5.3 { S delete } {}
174
175#-------------------------------------------------------------------------
176# Test the application of simple changesets. These tests also test that
177# the conflict callback is invoked correctly. For these tests, the
178# conflict callback always returns OMIT.
179#
180db close
181forcedelete test.db test.db2
182sqlite3 db test.db
183sqlite3 db2 test.db2
184
185proc xConflict {args} {
186  lappend ::xConflict $args
187  return ""
188}
189
190proc bgerror {args} { set ::background_error $args }
191
192proc do_conflict_test {tn args} {
193  set O(-tables)    [list]
194  set O(-sql)       [list]
195  set O(-conflicts) [list]
196
197  array set V $args
198  foreach key [array names V] {
199    if {![info exists O($key)]} {error "no such option: $key"}
200  }
201  array set O $args
202
203  sqlite3session S db main
204  foreach t $O(-tables) { S attach $t }
205  execsql $O(-sql)
206  set ::xConflict [list]
207  sqlite3changeset_apply db2 [S changeset] xConflict
208
209  set conflicts [list]
210  foreach c $O(-conflicts) {
211    lappend conflicts $c
212  }
213
214  after 1 {set go 1}
215  vwait go
216
217  uplevel do_test $tn [list { set ::xConflict }] [list $conflicts]
218  S delete
219}
220
221proc do_db2_test {testname sql {result {}}} {
222  uplevel do_test $testname [list "execsql {$sql} db2"] [list [list {*}$result]]
223}
224
225# Test INSERT changesets.
226#
227do_test $tn.3.1.0 {
228  execsql { CREATE TABLE t1(a PRIMARY KEY, b NOT NULL) %WR% } db2
229  execsql {
230    CREATE TABLE t1(a PRIMARY KEY, b) %WR%;
231    INSERT INTO t1 VALUES(1, 'one');
232    INSERT INTO t1 VALUES(2, 'two');
233  } db
234} {}
235do_db2_test $tn.3.1.1 "INSERT INTO t1 VALUES(6, 'VI')"
236do_conflict_test $tn.3.1.2 -tables t1 -sql {
237  INSERT INTO t1 VALUES(3, 'three');
238  INSERT INTO t1 VALUES(4, 'four');
239  INSERT INTO t1 VALUES(5, 'five');
240  INSERT INTO t1 VALUES(6, 'six');
241  INSERT INTO t1 VALUES(7, 'seven');
242  INSERT INTO t1 VALUES(8, NULL);
243} -conflicts {
244  {INSERT t1 CONFLICT {i 6 t six} {i 6 t VI}}
245  {INSERT t1 CONSTRAINT {i 8 n {}}}
246}
247
248do_db2_test $tn.3.1.3 "SELECT * FROM t1 ORDER BY a" {
249  3 three 4 four 5 five 6 VI 7 seven
250}
251do_execsql_test $tn.3.1.4 "SELECT * FROM t1" {
252  1 one 2 two 3 three 4 four 5 five 6 six 7 seven 8 {}
253}
254
255# Test DELETE changesets.
256#
257do_execsql_test $tn.3.2.1 {
258  PRAGMA foreign_keys = on;
259  CREATE TABLE t2(a PRIMARY KEY, b)%WR%;
260  CREATE TABLE t3(c, d REFERENCES t2);
261  INSERT INTO t2 VALUES(1, 'one');
262  INSERT INTO t2 VALUES(2, 'two');
263  INSERT INTO t2 VALUES(3, 'three');
264  INSERT INTO t2 VALUES(4, 'four');
265}
266do_db2_test $tn.3.2.2 {
267  PRAGMA foreign_keys = on;
268  CREATE TABLE t2(a PRIMARY KEY, b)%WR%;
269  CREATE TABLE t3(c, d REFERENCES t2);
270  INSERT INTO t2 VALUES(1, 'one');
271  INSERT INTO t2 VALUES(2, 'two');
272  INSERT INTO t2 VALUES(4, 'five');
273  INSERT INTO t3 VALUES('i', 1);
274}
275do_conflict_test $tn.3.2.3 -tables t2 -sql {
276  DELETE FROM t2 WHERE a = 1;
277  DELETE FROM t2 WHERE a = 2;
278  DELETE FROM t2 WHERE a = 3;
279  DELETE FROM t2 WHERE a = 4;
280} -conflicts {
281  {DELETE t2 NOTFOUND {i 3 t three}}
282  {DELETE t2 DATA {i 4 t four} {i 4 t five}}
283  {FOREIGN_KEY 1}
284}
285do_execsql_test $tn.3.2.4 "SELECT * FROM t2" {}
286do_db2_test $tn.3.2.5 "SELECT * FROM t2" {4 five}
287
288# Test UPDATE changesets.
289#
290do_execsql_test $tn.3.3.1 {
291  CREATE TABLE t4(a, b, c, PRIMARY KEY(b, c))%WR%;
292  INSERT INTO t4 VALUES(1, 2, 3);
293  INSERT INTO t4 VALUES(4, 5, 6);
294  INSERT INTO t4 VALUES(7, 8, 9);
295  INSERT INTO t4 VALUES(10, 11, 12);
296}
297do_db2_test $tn.3.3.2 {
298  CREATE TABLE t4(a NOT NULL, b, c, PRIMARY KEY(b, c))%WR%;
299  INSERT INTO t4 VALUES(0, 2, 3);
300  INSERT INTO t4 VALUES(4, 5, 7);
301  INSERT INTO t4 VALUES(7, 8, 9);
302  INSERT INTO t4 VALUES(10, 11, 12);
303}
304do_conflict_test $tn.3.3.3 -tables t4 -sql {
305  UPDATE t4 SET a = -1 WHERE b = 2;
306  UPDATE t4 SET a = -1 WHERE b = 5;
307  UPDATE t4 SET a = NULL WHERE c = 9;
308  UPDATE t4 SET a = 'x' WHERE b = 11;
309} -conflicts {
310  {UPDATE t4 DATA {i 1 i 2 i 3} {i -1 {} {} {} {}} {i 0 i 2 i 3}}
311  {UPDATE t4 NOTFOUND {i 4 i 5 i 6} {i -1 {} {} {} {}}}
312  {UPDATE t4 CONSTRAINT {i 7 i 8 i 9} {n {} {} {} {} {}}}
313}
314do_db2_test $tn.3.3.4 { SELECT * FROM t4 } {0 2 3 4 5 7 7 8 9 x 11 12}
315do_execsql_test $tn.3.3.5 { SELECT * FROM t4 } {-1 2 3 -1 5 6 {} 8 9 x 11 12}
316
317#-------------------------------------------------------------------------
318# This next block of tests verifies that values returned by the conflict
319# handler are intepreted correctly.
320#
321
322proc test_reset {} {
323  db close
324  db2 close
325  forcedelete test.db test.db2
326  sqlite3 db test.db
327  sqlite3 db2 test.db2
328}
329
330proc xConflict {args} {
331  lappend ::xConflict $args
332  return $::conflict_return
333}
334
335foreach {tn2 conflict_return after} {
336  1 OMIT      {1 2 value1   4 5 7       10 x x}
337  2 REPLACE   {1 2 value1   4 5 value2  10 8 9}
338} {
339  test_reset
340
341  do_test $tn.4.$tn2.1 {
342    foreach db {db db2} {
343      execsql {
344        CREATE TABLE t1(a, b, c, PRIMARY KEY(a))%WR%;
345        INSERT INTO t1 VALUES(1, 2, 3);
346        INSERT INTO t1 VALUES(4, 5, 6);
347        INSERT INTO t1 VALUES(7, 8, 9);
348      } $db
349    }
350    execsql {
351      REPLACE INTO t1 VALUES(4, 5, 7);
352      REPLACE INTO t1 VALUES(10, 'x', 'x');
353    } db2
354  } {}
355
356  do_conflict_test $tn.4.$tn2.2 -tables t1 -sql {
357    UPDATE t1 SET c = 'value1' WHERE a = 1;       -- no conflict
358    UPDATE t1 SET c = 'value2' WHERE a = 4;       -- DATA conflict
359    UPDATE t1 SET a = 10 WHERE a = 7;             -- CONFLICT conflict
360  } -conflicts {
361    {INSERT t1 CONFLICT {i 10 i 8 i 9} {i 10 t x t x}}
362    {UPDATE t1 DATA {i 4 {} {} i 6} {{} {} {} {} t value2} {i 4 i 5 i 7}}
363  }
364
365  do_db2_test $tn.4.$tn2.3 "SELECT * FROM t1 ORDER BY a" $after
366}
367
368foreach {tn2 conflict_return} {
369  1 OMIT
370  2 REPLACE
371} {
372  test_reset
373
374  do_test $tn.5.$tn2.1 {
375    # Create an identical schema in both databases.
376    set schema {
377      CREATE TABLE "'foolish name'"(x, y, z, PRIMARY KEY(x, y))%WR%;
378    }
379    execsql $schema db
380    execsql $schema db2
381
382    # Add some rows to [db2]. These rows will cause conflicts later
383    # on when the changeset from [db] is applied to it.
384    execsql {
385      INSERT INTO "'foolish name'" VALUES('one', 'one', 'ii');
386      INSERT INTO "'foolish name'" VALUES('one', 'two', 'i');
387      INSERT INTO "'foolish name'" VALUES('two', 'two', 'ii');
388    } db2
389
390  } {}
391
392  do_conflict_test $tn.5.$tn2.2 -tables {{'foolish name'}} -sql {
393    INSERT INTO "'foolish name'" VALUES('one', 'two', 2);
394  } -conflicts {
395    {INSERT {'foolish name'} CONFLICT {t one t two i 2} {t one t two t i}}
396  }
397
398  set res(REPLACE) {one one ii one two 2 two two ii}
399  set res(OMIT)    {one one ii one two i two two ii}
400  do_db2_test $tn.5.$tn2.3 {
401    SELECT * FROM "'foolish name'" ORDER BY x, y
402  } $res($conflict_return)
403
404
405  do_test $tn.5.$tn2.1 {
406    set schema {
407      CREATE TABLE d1("z""z" PRIMARY KEY, y)%WR%;
408      INSERT INTO d1 VALUES(1, 'one');
409      INSERT INTO d1 VALUES(2, 'two');
410    }
411    execsql $schema db
412    execsql $schema db2
413
414    execsql {
415      UPDATE d1 SET y = 'TWO' WHERE "z""z" = 2;
416    } db2
417
418  } {}
419
420  do_conflict_test $tn.5.$tn2.2 -tables d1 -sql {
421    DELETE FROM d1 WHERE "z""z" = 2;
422  } -conflicts {
423    {DELETE d1 DATA {i 2 t two} {i 2 t TWO}}
424  }
425
426  set res(REPLACE) {1 one}
427  set res(OMIT)    {1 one 2 TWO}
428  do_db2_test $tn.5.$tn2.3 "SELECT * FROM d1" $res($conflict_return)
429}
430
431#-------------------------------------------------------------------------
432# Test that two tables can be monitored by a single session object.
433#
434test_reset
435set schema {
436  CREATE TABLE t1(a COLLATE nocase PRIMARY KEY, b)%WR%;
437  CREATE TABLE t2(a, b PRIMARY KEY)%WR%;
438}
439do_test $tn.6.0 {
440  execsql $schema db
441  execsql $schema db2
442  execsql {
443    INSERT INTO t1 VALUES('a', 'b');
444    INSERT INTO t2 VALUES('a', 'b');
445  } db2
446} {}
447
448set conflict_return ""
449do_conflict_test $tn.6.1 -tables {t1 t2} -sql {
450  INSERT INTO t1 VALUES('1', '2');
451  INSERT INTO t1 VALUES('A', 'B');
452  INSERT INTO t2 VALUES('A', 'B');
453} -conflicts {
454  {INSERT t1 CONFLICT {t A t B} {t a t b}}
455}
456
457do_db2_test $tn.6.2 "SELECT * FROM t1 ORDER BY a" {1 2 a b}
458do_db2_test $tn.6.3 "SELECT * FROM t2 ORDER BY a" {A B a b}
459
460#-------------------------------------------------------------------------
461# Test that session objects are not confused by changes to table in
462# other databases.
463#
464catch { db2 close }
465drop_all_tables
466forcedelete test.db2
467do_iterator_test $tn.7.1 * {
468  ATTACH 'test.db2' AS aux;
469  CREATE TABLE main.t1(x PRIMARY KEY, y)%WR%;
470  CREATE TABLE aux.t1(x PRIMARY KEY, y)%WR%;
471
472  INSERT INTO main.t1 VALUES('one', 1);
473  INSERT INTO main.t1 VALUES('two', 2);
474  INSERT INTO aux.t1 VALUES('three', 3);
475  INSERT INTO aux.t1 VALUES('four', 4);
476} {
477  {INSERT t1 0 X. {} {t two i 2}}
478  {INSERT t1 0 X. {} {t one i 1}}
479}
480
481#-------------------------------------------------------------------------
482# Test the sqlite3session_isempty() function.
483#
484do_test $tn.8.1 {
485  execsql {
486    CREATE TABLE t5(x PRIMARY KEY, y)%WR%;
487    CREATE TABLE t6(x PRIMARY KEY, y)%WR%;
488    INSERT INTO t5 VALUES('a', 'b');
489    INSERT INTO t6 VALUES('a', 'b');
490  }
491  sqlite3session S db main
492  S attach *
493
494  S isempty
495} {1}
496do_test $tn.8.2 {
497  execsql { DELETE FROM t5 }
498  S isempty
499} {0}
500do_test $tn.8.3 {
501  S delete
502  sqlite3session S db main
503  S attach t5
504  execsql { DELETE FROM t5 }
505  S isempty
506} {1}
507do_test $tn.8.4 { S delete } {}
508
509do_test $tn.8.5 {
510  sqlite3session S db main
511  S attach t5
512  S attach t6
513  execsql { INSERT INTO t5 VALUES(1, 2) }
514  S isempty
515} {0}
516
517do_test $tn.8.6 {
518  S delete
519  sqlite3session S db main
520  S attach t5
521  S attach t6
522  execsql { INSERT INTO t6 VALUES(1, 2) }
523  S isempty
524} {0}
525do_test $tn.8.7 { S delete } {}
526
527#-------------------------------------------------------------------------
528#
529do_execsql_test $tn.9.1 {
530  CREATE TABLE t7(a, b, c, d, e PRIMARY KEY, f, g)%WR%;
531  INSERT INTO t7 VALUES(1, 1, 1, 1, 1, 1, 1);
532}
533do_test $tn.9.2 {
534  sqlite3session S db main
535  S attach *
536  execsql { UPDATE t7 SET b=2, d=2 }
537} {}
538do_changeset_test $tn.9.2 S {{UPDATE t7 0 ....X.. {{} {} i 1 {} {} i 1 i 1 {} {} {} {}} {{} {} i 2 {} {} i 2 {} {} {} {} {} {}}}}
539S delete
540catch { db2 close }
541
542#-------------------------------------------------------------------------
543# Test a really long table name.
544#
545reset_db
546set tblname [string repeat tblname123 100]
547do_test $tn.10.1.1 {
548  execsql "
549    CREATE TABLE $tblname (a PRIMARY KEY, b)%WR%;
550    INSERT INTO $tblname VALUES('xyz', 'def');
551  "
552  sqlite3session S db main
553  S attach $tblname
554  execsql "
555    INSERT INTO $tblname VALUES('uvw', 'abc');
556    DELETE FROM $tblname WHERE a = 'xyz';
557  "
558} {}
559do_changeset_test $tn.10.1.2 S "
560  {INSERT $tblname 0 X. {} {t uvw t abc}}
561  {DELETE $tblname 0 X. {t xyz t def} {}}
562"
563do_test $tn.10.1.4 { S delete } {}
564
565#---------------------------------------------------------------
566reset_db
567do_execsql_test $tn.11.1 {
568  CREATE TABLE t1(a, b);
569}
570do_test $tn.11.2 {
571  sqlite3session S db main
572  S attach t1
573  execsql {
574    INSERT INTO t1 VALUES(1, 2);
575  }
576  S changeset
577} {}
578
579S delete
580
581
582#-------------------------------------------------------------------------
583# Test a really long table name.
584#
585reset_db
586set tblname [string repeat tblname123 100]
587do_test $tn.10.1.1 {
588  execsql "
589    CREATE TABLE $tblname (a PRIMARY KEY, b)%WR%;
590    INSERT INTO $tblname VALUES('xyz', 'def');
591  "
592  sqlite3session S db main
593  S attach $tblname
594  execsql "
595    INSERT INTO $tblname VALUES('uvw', 'abc');
596    DELETE FROM $tblname WHERE a = 'xyz';
597  "
598} {}
599do_changeset_test $tn.10.1.2 S "
600  {INSERT $tblname 0 X. {} {t uvw t abc}}
601  {DELETE $tblname 0 X. {t xyz t def} {}}
602"
603do_test $tn.10.1.4 { S delete } {}
604
605#-------------------------------------------------------------------------
606# Test the effect of updating a column from 0.0 to 0.0.
607#
608reset_db
609do_execsql_test $tn.11.1 {
610  CREATE TABLE t1(a INTEGER PRIMARY KEY, b REAL)%WR%;
611  INSERT INTO t1 VALUES(1, 0.0);
612}
613do_iterator_test $tn.11.2 * {
614  UPDATE t1 SET b = 0.0;
615} {
616}
617
618reset_db
619do_execsql_test $tn.12.1 {
620  CREATE TABLE t1(r INTEGER PRIMARY KEY, a, b)%WR%;
621  CREATE INDEX i1 ON t1(a);
622  INSERT INTO t1 VALUES(1, 1, 1);
623  INSERT INTO t1 VALUES(2, 1, 2);
624  INSERT INTO t1 VALUES(3, 1, 3);
625}
626
627do_iterator_test $tn.12.2 * {
628  UPDATE t1 SET b='one' WHERE a=1;
629} {
630  {UPDATE t1 0 X.. {i 1 {} {} i 1} {{} {} {} {} t one}}
631  {UPDATE t1 0 X.. {i 2 {} {} i 2} {{} {} {} {} t one}}
632  {UPDATE t1 0 X.. {i 3 {} {} i 3} {{} {} {} {} t one}}
633}
634
635#-------------------------------------------------------------------------
636# Test that no savepoint is used if -nosavepoint is specified.
637#
638do_execsql_test $tn.13.1 {
639  CREATE TABLE x1(a INTEGER PRIMARY KEY, b)%WR%;
640}
641do_test $tn.13.2 {
642  execsql BEGIN
643  set C [changeset_from_sql {
644    INSERT INTO x1 VALUES(1, 'one');
645    INSERT INTO x1 VALUES(2, 'two');
646    INSERT INTO x1 VALUES(3, 'three');
647  }]
648  execsql ROLLBACK
649  execsql {
650    INSERT INTO x1 VALUES(1, 'i');
651    INSERT INTO x1 VALUES(2, 'ii');
652    INSERT INTO x1 VALUES(3, 'iii');
653  }
654} {}
655
656proc xConflict {args} {
657  set ret [lindex $::CONFLICT_HANDLERS 0]
658  set ::CONFLICT_HANDLERS [lrange $::CONFLICT_HANDLERS 1 end]
659  set ret
660}
661do_test $tn.13.3 {
662  set CONFLICT_HANDLERS [list REPLACE REPLACE ABORT]
663  execsql BEGIN
664  catch { sqlite3changeset_apply_v2 db $C xConflict } msg
665  execsql {
666    SELECT * FROM x1
667  }
668} {1 i 2 ii 3 iii}
669do_test $tn.13.3 {
670  set CONFLICT_HANDLERS [list REPLACE REPLACE ABORT]
671  execsql ROLLBACK
672  execsql BEGIN
673  catch { sqlite3changeset_apply_v2 -nosavepoint db $C xConflict } msg
674  execsql { SELECT * FROM x1 }
675} {1 one 2 two 3 iii}
676execsql ROLLBACK
677
678do_test $tn.14.1 { sqlite3session_config strm_size -1 } 64
679do_test $tn.14.2 { sqlite3session_config strm_size 65536 } 65536
680do_test $tn.14.3 { sqlite3session_config strm_size 64 } 64
681do_test $tn.14.4 {
682  list [catch {sqlite3session_config invalid 123} msg] $msg
683} {1 SQLITE_MISUSE}
684
685}]
686}
687
688
689finish_test
690