xref: /sqlite-3.40.0/ext/session/session2.test (revision db04571c)
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  16 {
155    INSERT INTO %T4% VALUES('abc', 'def');
156    INSERT INTO %T4% VALUES('def', 'abc');
157  }
158  17 { UPDATE %T4% SET b = 1 }
159  18 { DELETE FROM %T4% WHERE 1 }
160}
161
162test_reset
163do_common_sql {
164  CREATE TABLE t1(a PRIMARY KEY, b);
165  CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
166  CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
167  CREATE TABLE t4(a, b, PRIMARY KEY(b, a));
168}
169
170foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3 %T4% t4} $set_of_tests] {
171  do_then_apply_sql $sql
172  do_test 2.$tn { compare_db db db2 } {}
173}
174
175# The following block of tests is similar to the last, except that the
176# session object is recording changes made to an attached database. The
177# main database contains a table of the same name as the table being
178# modified within the attached db.
179#
180test_reset
181forcedelete test.db3
182sqlite3 db3 test.db3
183do_test 3.0 {
184  execsql {
185    ATTACH 'test.db3' AS 'aux';
186    CREATE TABLE t1(a, b PRIMARY KEY);
187    CREATE TABLE t2(x, y, z);
188    CREATE TABLE t3(a);
189
190    CREATE TABLE aux.t1(a PRIMARY KEY, b);
191    CREATE TABLE aux.t2(a, b INTEGER PRIMARY KEY);
192    CREATE TABLE aux.t3(a, b, c, PRIMARY KEY(a, b));
193    CREATE TABLE aux.t4(a, b, PRIMARY KEY(b, a));
194  }
195  execsql {
196    CREATE TABLE t1(a PRIMARY KEY, b);
197    CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
198    CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
199    CREATE TABLE t4(a, b, PRIMARY KEY(b, a));
200  } db2
201} {}
202
203proc xTrace {args} { puts $args }
204
205foreach {tn sql} [
206  string map {%T1% aux.t1 %T2% aux.t2 %T3% aux.t3 %T4% aux.t4} $set_of_tests
207] {
208  do_then_apply_sql $sql aux
209  do_test 3.$tn { compare_db db2 db3 } {}
210}
211catch {db3 close}
212
213
214#-------------------------------------------------------------------------
215# The following tests verify that NULL values in primary key columns are
216# handled correctly by the session module.
217#
218test_reset
219do_execsql_test 4.0 {
220  CREATE TABLE t1(a PRIMARY KEY);
221  CREATE TABLE t2(a, b, c, PRIMARY KEY(c, b));
222  CREATE TABLE t3(a, b INTEGER PRIMARY KEY);
223}
224
225foreach {tn sql changeset} {
226  1 {
227    INSERT INTO t1 VALUES(123);
228    INSERT INTO t1 VALUES(NULL);
229    INSERT INTO t1 VALUES(456);
230  } {
231    {INSERT t1 {} {i 456}}
232    {INSERT t1 {} {i 123}}
233  }
234
235  2 {
236    UPDATE t1 SET a = NULL;
237  } {
238    {DELETE t1 {i 456} {}}
239    {DELETE t1 {i 123} {}}
240  }
241
242  3 { DELETE FROM t1 } { }
243
244  4 {
245    INSERT INTO t3 VALUES(NULL, NULL)
246  } {
247    {INSERT t3 {} {n {} i 1}}
248  }
249
250  5 { INSERT INTO t2 VALUES(1, 2, NULL) }    { }
251  6 { INSERT INTO t2 VALUES(1, NULL, 3) }    { }
252  7 { INSERT INTO t2 VALUES(1, NULL, NULL) } { }
253  8 { INSERT INTO t2 VALUES(1, 2, 3) }       { {INSERT t2 {} {i 1 i 2 i 3}} }
254  9 { DELETE FROM t2 WHERE 1 }               { {DELETE t2 {i 1 i 2 i 3} {}} }
255
256} {
257  do_iterator_test 4.$tn {t1 t2 t3} $sql $changeset
258}
259
260
261finish_test
262
263