xref: /sqlite-3.40.0/ext/session/session2.test (revision 12ca0b56)
1# 2011 Mar 16
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#
12# The focus of this file is testing the session module.
13#
14
15if {![info exists testdir]} {
16  set testdir [file join [file dirname [info script]] .. .. test]
17}
18source [file join [file dirname [info script]] session_common.tcl]
19source $testdir/tester.tcl
20
21set testprefix session2
22
23proc test_reset {} {
24  catch { db close }
25  catch { db2 close }
26  forcedelete test.db test.db2
27  sqlite3 db test.db
28  sqlite3 db2 test.db2
29}
30
31##########################################################################
32# End of proc definitions. Start of tests.
33##########################################################################
34
35test_reset
36do_execsql_test 1.0 {
37  CREATE TABLE t1(a PRIMARY KEY, b);
38  INSERT INTO t1 VALUES('i', 'one');
39}
40do_iterator_test 1.1 t1 {
41  DELETE FROM t1 WHERE a = 'i';
42  INSERT INTO t1 VALUES('ii', 'two');
43} {
44  {DELETE t1 {t i t one} {}}
45  {INSERT t1 {} {t ii t two}}
46}
47do_iterator_test 1.2 t1 {
48  INSERT INTO t1 VALUES(1.5, 99.9)
49} {
50  {INSERT t1 {} {f 1.5 f 99.9}}
51}
52
53
54# Execute each of the following blocks of SQL on database [db1]. Collect
55# changes using a session object. Apply the resulting changeset to
56# database [db2]. Then check that the contents of the two databases are
57# identical.
58#
59
60set set_of_tests {
61  1 { INSERT INTO %T1% VALUES(1, 2) }
62
63  2 {
64    INSERT INTO %T2% VALUES(1, NULL);
65    INSERT INTO %T2% VALUES(2, NULL);
66    INSERT INTO %T2% VALUES(3, NULL);
67    DELETE FROM %T2% WHERE a = 2;
68    INSERT INTO %T2% VALUES(4, NULL);
69    UPDATE %T2% SET b=0 WHERE b=1;
70  }
71
72  3 { INSERT INTO %T3% SELECT *, NULL FROM %T2% }
73
74  4 {
75    INSERT INTO %T3% SELECT a||a, b||b, NULL FROM %T3%;
76    DELETE FROM %T3% WHERE rowid%2;
77  }
78
79  5 { UPDATE %T3% SET c = a||b }
80
81  6 { UPDATE %T1% SET a = 32 }
82
83  7 {
84    INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
85    INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
86    INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
87    INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
88    INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
89    INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
90    INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
91    INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
92    INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
93    INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
94    INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
95    DELETE FROM %T1% WHERE (rowid%3)==0;
96  }
97
98  8 {
99    BEGIN;
100      INSERT INTO %T1% SELECT randomblob(32), randomblob(32) FROM %T1%;
101    ROLLBACK;
102  }
103  9 {
104    BEGIN;
105      UPDATE %T1% SET b = 'xxx';
106    ROLLBACK;
107  }
108  10 {
109    BEGIN;
110      DELETE FROM %T1% WHERE 1;
111    ROLLBACK;
112  }
113  11 {
114    INSERT INTO %T1% VALUES(randomblob(21000), randomblob(0));
115    INSERT INTO %T1% VALUES(1.5, 1.5);
116    INSERT INTO %T1% VALUES(4.56, -99.999999999999999999999);
117  }
118  12 {
119    INSERT INTO %T2% VALUES(NULL, NULL);
120  }
121
122  13 {
123    DELETE FROM %T1% WHERE 1;
124
125    -- Insert many rows with real primary keys. Enough to force the session
126    -- objects hash table to resize.
127    INSERT INTO %T1% VALUES(0.1, 0.1);
128    INSERT INTO %T1% SELECT a+0.1, b+0.1 FROM %T1%;
129    INSERT INTO %T1% SELECT a+0.2, b+0.2 FROM %T1%;
130    INSERT INTO %T1% SELECT a+0.4, b+0.4 FROM %T1%;
131    INSERT INTO %T1% SELECT a+0.8, b+0.8 FROM %T1%;
132    INSERT INTO %T1% SELECT a+1.6, b+1.6 FROM %T1%;
133    INSERT INTO %T1% SELECT a+3.2, b+3.2 FROM %T1%;
134    INSERT INTO %T1% SELECT a+6.4, b+6.4 FROM %T1%;
135    INSERT INTO %T1% SELECT a+12.8, b+12.8 FROM %T1%;
136    INSERT INTO %T1% SELECT a+25.6, b+25.6 FROM %T1%;
137    INSERT INTO %T1% SELECT a+51.2, b+51.2 FROM %T1%;
138    INSERT INTO %T1% SELECT a+102.4, b+102.4 FROM %T1%;
139    INSERT INTO %T1% SELECT a+204.8, b+204.8 FROM %T1%;
140  }
141
142  14 {
143    DELETE FROM %T1% WHERE 1;
144  }
145
146  15 {
147    INSERT INTO %T1% VALUES(1, 1);
148    INSERT INTO %T1% SELECT a+2, b+2 FROM %T1%;
149    INSERT INTO %T1% SELECT a+4, b+4 FROM %T1%;
150    INSERT INTO %T1% SELECT a+8, b+8 FROM %T1%;
151    INSERT INTO %T1% SELECT a+256, b+256 FROM %T1%;
152  }
153}
154
155test_reset
156do_common_sql {
157  CREATE TABLE t1(a PRIMARY KEY, b);
158  CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
159  CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
160}
161
162foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3} $set_of_tests] {
163  do_then_apply_sql $sql
164  do_test 2.$tn { compare_db db db2 } {}
165}
166
167# The following block of tests is similar to the last, except that the
168# session object is recording changes made to an attached database. The
169# main database contains a table of the same name as the table being
170# modified within the attached db.
171#
172test_reset
173forcedelete test.db3
174sqlite3 db3 test.db3
175do_test 3.0 {
176  execsql {
177    ATTACH 'test.db3' AS 'aux';
178    CREATE TABLE t1(a, b PRIMARY KEY);
179    CREATE TABLE t2(x, y, z);
180    CREATE TABLE t3(a);
181
182    CREATE TABLE aux.t1(a PRIMARY KEY, b);
183    CREATE TABLE aux.t2(a, b INTEGER PRIMARY KEY);
184    CREATE TABLE aux.t3(a, b, c, PRIMARY KEY(a, b));
185  }
186  execsql {
187    CREATE TABLE t1(a PRIMARY KEY, b);
188    CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
189    CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
190  } db2
191} {}
192
193proc xTrace {args} { puts $args }
194
195foreach {tn sql} [
196  string map {%T1% aux.t1 %T2% aux.t2 %T3% aux.t3} $set_of_tests
197] {
198  do_then_apply_sql $sql aux
199  do_test 3.$tn { compare_db db3 db2 } {}
200}
201catch {db3 close}
202
203
204#-------------------------------------------------------------------------
205# The following tests verify that NULL values in primary key columns are
206# handled correctly by the session module.
207#
208test_reset
209do_execsql_test 4.0 {
210  CREATE TABLE t1(a PRIMARY KEY);
211  CREATE TABLE t2(a, b, c, PRIMARY KEY(c, b));
212  CREATE TABLE t3(a, b INTEGER PRIMARY KEY);
213}
214
215foreach {tn sql changeset} {
216  1 {
217    INSERT INTO t1 VALUES(123);
218    INSERT INTO t1 VALUES(NULL);
219    INSERT INTO t1 VALUES(456);
220  } {
221    {INSERT t1 {} {i 456}}
222    {INSERT t1 {} {i 123}}
223  }
224
225  2 {
226    UPDATE t1 SET a = NULL;
227  } {
228    {DELETE t1 {i 456} {}}
229    {DELETE t1 {i 123} {}}
230  }
231
232  3 { DELETE FROM t1 } { }
233
234  4 {
235    INSERT INTO t3 VALUES(NULL, NULL)
236  } {
237    {INSERT t3 {} {n {} i 1}}
238  }
239
240  5 { INSERT INTO t2 VALUES(1, 2, NULL) }    { }
241  6 { INSERT INTO t2 VALUES(1, NULL, 3) }    { }
242  7 { INSERT INTO t2 VALUES(1, NULL, NULL) } { }
243  8 { INSERT INTO t2 VALUES(1, 2, 3) }       { {INSERT t2 {} {i 1 i 2 i 3}} }
244  9 { DELETE FROM t2 WHERE 1 }               { {DELETE t2 {i 1 i 2 i 3} {}} }
245
246} {
247  do_iterator_test 4.$tn {t1 t2 t3} $sql $changeset
248}
249
250
251finish_test
252
253