xref: /sqlite-3.40.0/ext/rbu/rbu5.test (revision 6ab91a7a)
1# 2014 August 30
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# Test some properties of the pager_rbu_mode and rbu_mode pragmas.
13#
14
15source [file join [file dirname [info script]] rbu_common.tcl]
16set ::testprefix rbu5
17
18
19# Return a list of the primary key columns for table $tbl in the database
20# opened by database handle $db.
21#
22proc pkcols {db tbl} {
23  set ret [list]
24  $db eval "PRAGMA table_info = '$tbl'" {
25    if {$pk} { lappend ret $name }
26  }
27  return $ret
28}
29
30# Return a list of all columns for table $tbl in the database opened by
31# database handle $db.
32#
33proc allcols {db tbl} {
34  set ret [list]
35  $db eval "PRAGMA table_info = '$tbl'" {
36    lappend ret $name
37  }
38  return $ret
39}
40
41# Return a checksum on all tables and data in the main database attached
42# to database handle $db. It is possible to add indexes without changing
43# the checksum.
44#
45proc datacksum {db} {
46
47  $db eval { SELECT name FROM sqlite_master WHERE type='table' } {
48    append txt $name
49    set cols [list]
50    set order [list]
51    set cnt 0
52    $db eval "PRAGMA table_info = $name" x {
53      lappend cols "quote($x(name))"
54      lappend order [incr cnt]
55    }
56    set cols [join $cols ,]
57    set order [join $order ,]
58    append txt [$db eval "SELECT $cols FROM $name ORDER BY $order"]
59  }
60  return "[string length $txt]-[md5 $txt]"
61}
62
63proc ucontrol {args} {
64  set ret ""
65  foreach a $args {
66    if {$a} {
67      append ret .
68    } else {
69      append ret x
70    }
71  }
72  return $ret
73}
74
75# Argument $target is the name of an SQLite database file. $sql is an SQL
76# script containing INSERT, UPDATE and DELETE statements to execute against
77# it. This command creates an RBU update database in file $rbu that has
78# the same effect as the script. The target database is not modified by
79# this command.
80#
81proc generate_rbu_db {target rbu sql} {
82
83  forcedelete $rbu
84  forcecopy $target copy.db
85
86  # Evaluate the SQL script to modify the contents of copy.db.
87  #
88  sqlite3 dbRbu copy.db
89  dbRbu eval $sql
90
91  dbRbu function ucontrol ucontrol
92
93  # Evaluate the SQL script to modify the contents of copy.db.
94  set ret [datacksum dbRbu]
95
96  dbRbu eval { ATTACH $rbu AS rbu }
97  dbRbu eval { ATTACH $target AS orig }
98
99  dbRbu eval { SELECT name AS tbl FROM sqlite_master WHERE type = 'table' } {
100    set pk [pkcols dbRbu $tbl]
101    set cols [allcols dbRbu $tbl]
102
103    # A WHERE clause to test that the PK columns match.
104    #
105    set where [list]
106    foreach c $pk { lappend where "main.$tbl.$c IS orig.$tbl.$c" }
107    set where [join $where " AND "]
108
109    # A WHERE clause to test that all columns match.
110    #
111    set where2 [list]
112    foreach c $cols { lappend where2 "main.$tbl.$c IS orig.$tbl.$c" }
113    set ucontrol "ucontrol([join $where2 ,])"
114    set where2 [join $where2 " AND "]
115
116    # Create a data_xxx table in the RBU update database.
117    dbRbu eval "
118      CREATE TABLE rbu.data_$tbl AS SELECT *, '' AS rbu_control
119      FROM main.$tbl LIMIT 0
120    "
121
122    # Find all new rows INSERTed by the script.
123    dbRbu eval "
124      INSERT INTO rbu.data_$tbl
125          SELECT *, 0 AS rbu_control FROM main.$tbl
126          WHERE NOT EXISTS (
127            SELECT 1 FROM orig.$tbl WHERE $where
128          )
129    "
130
131    # Find all old rows DELETEd by the script.
132    dbRbu eval "
133      INSERT INTO rbu.data_$tbl
134          SELECT *, 1 AS rbu_control FROM orig.$tbl
135          WHERE NOT EXISTS (
136            SELECT 1 FROM main.$tbl WHERE $where
137          )
138    "
139
140    # Find all rows UPDATEd by the script.
141    set origcols [list]
142    foreach c $cols { lappend origcols "main.$tbl.$c" }
143    set origcols [join $origcols ,]
144    dbRbu eval "
145      INSERT INTO rbu.data_$tbl
146          SELECT $origcols, $ucontrol AS rbu_control
147          FROM orig.$tbl, main.$tbl
148          WHERE $where AND NOT ($where2)
149    "
150
151  }
152
153  dbRbu close
154  forcedelete copy.db
155
156  return $ret
157}
158
159#-------------------------------------------------------------------------
160#
161do_execsql_test 1.0 {
162  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
163  CREATE TABLE t2(x, y, z, PRIMARY KEY(y, z)) WITHOUT ROWID;
164
165  INSERT INTO t1 VALUES(1, 2, 3);
166  INSERT INTO t1 VALUES(2, 4, 6);
167  INSERT INTO t1 VALUES(3, 6, 9);
168
169  INSERT INTO t2 VALUES(1, 2, 3);
170  INSERT INTO t2 VALUES(2, 4, 6);
171  INSERT INTO t2 VALUES(3, 6, 9);
172}
173db close
174
175set cksum [generate_rbu_db test.db rbu.db {
176  INSERT INTO t1 VALUES(4, 8, 12);
177  DELETE FROM t1 WHERE a = 2;
178  UPDATE t1 SET c = 15 WHERE a=3;
179
180  INSERT INTO t2 VALUES(4, 8, 12);
181  DELETE FROM t2 WHERE x = 2;
182  UPDATE t2 SET x = 15 WHERE z=9;
183}]
184
185foreach {tn idx} {
186  1 {
187  }
188  2 {
189    CREATE INDEX i1 ON t1(a, b, c);
190    CREATE INDEX i2 ON t2(x, y, z);
191  }
192} {
193  foreach cmd {run step} {
194    forcecopy test.db test.db2
195    forcecopy rbu.db rbu.db2
196
197    sqlite3 db test.db2
198    db eval $idx
199
200    do_test 1.$tn.$cmd.1 {
201      ${cmd}_rbu test.db2 rbu.db2
202      datacksum db
203    } $cksum
204
205    do_test 1.$tn.$cmd.2 {
206      db eval { PRAGMA integrity_check }
207    } {ok}
208
209    db close
210  }
211}
212
213#-------------------------------------------------------------------------
214#
215reset_db
216do_execsql_test 2.0 {
217  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d, e);
218  INSERT INTO t1 VALUES(-750250,'fyetckfaagjkzqjx',-185831,X'FEAD',444258.29);
219  INSERT INTO t1 VALUES(649081,NULL,X'7DF25BF78778',-342324.63,'akvspktocwozo');
220  INSERT INTO t1 VALUES(-133045,-44822.31,X'',287935,NULL);
221  INSERT INTO t1 VALUES(202132,NULL,X'5399','cujsjtspryqeyovcdpz','m');
222  INSERT INTO t1 VALUES(302910,NULL,'dvdhivtfkaedzhdcnn',-717113.41,688487);
223  INSERT INTO t1 VALUES(-582327,X'7A267A',X'7E6B3CFE5CB9','zacuzilrok',-196478);
224  INSERT INTO t1 VALUES(-190462,X'D1A087E7D68D9578','lsmleti',NULL,-928094);
225  INSERT INTO t1 VALUES(-467665,176344.57,-536684.23,828876.22,X'903E');
226  INSERT INTO t1 VALUES(-629138,632630.29,X'28D6',-774501,X'819BBBFC65');
227  INSERT INTO t1 VALUES(-828110,-54379.24,-881121.44,X'',X'8D5A894F0D');
228
229  CREATE TABLE t2(a PRIMARY KEY, b, c, d, e) WITHOUT ROWID;
230  INSERT INTO t2 VALUES(-65174,X'AC1DBFFE27310F',-194471.08,347988,X'84041BA6F9BDDE86A8');
231  INSERT INTO t2 VALUES('bzbpi',-952693.69,811628.25,NULL,-817434);
232  INSERT INTO t2 VALUES(-643830,NULL,'n',NULL,'dio');
233  INSERT INTO t2 VALUES('rovoenxxj',NULL,'owupbtdcoxxnvg',-119676,X'55431DFA');
234  INSERT INTO t2 VALUES(899770,'jlygdl',X'DBCA4D1A',NULL,-631773);
235  INSERT INTO t2 VALUES(334698.80,NULL,-697585.58,-89277,-817352);
236  INSERT INTO t2 VALUES(X'1A9EB7547A4AAF38','aiprdhkpzdz','anw','szvjbwdvzucybpwwqjt',X'53');
237  INSERT INTO t2 VALUES(713220,NULL,'hfcqhqzjuqplvkum',X'20B076075649DE','fthgpvqdyy');
238  INSERT INTO t2 VALUES(763908,NULL,'xgslzcpvwfknbr',X'75',X'668146');
239  INSERT INTO t2 VALUES(X'E1BA2B6BA27278','wjbpd',NULL,139341,-290086.15);
240}
241db close
242
243set cksum [generate_rbu_db test.db rbu.db {
244INSERT INTO t2 VALUES(222916.23,'idh',X'472C517405',X'E3',X'7C4F31824669');
245INSERT INTO t2 VALUES('xcndjwafcoxwxizoktd',-319567.21,NULL,-720906.43,-577170);
246INSERT INTO t2 VALUES(376369.99,-536058,'yoaiurfqupdscwc',X'29EC8A2542EC3953E9',-740485.22);
247INSERT INTO t2 VALUES(X'0EFB4DC50693',-175590.83,X'1779E253CAB5B1789E',X'BC6903',NULL);
248INSERT INTO t2 VALUES(-288299,'hfrp',NULL,528477,730676.77);
249DELETE FROM t2 WHERE a < -60000;
250
251UPDATE t2 SET b = 'pgnnaaoflnw' WHERE a = 'bzbpi';
252UPDATE t2 SET c = -675583 WHERE a = 'rovoenxxj';
253UPDATE t2 SET d = X'09CDF2B2C241' WHERE a = 713220;
254
255INSERT INTO t1 VALUES(224938,'bmruycvfznhhnfmgqys','fr',854381,789143);
256INSERT INTO t1 VALUES(-863931,-1386.26,X'2A058540C2FB5C',NULL,X'F9D5990A');
257INSERT INTO t1 VALUES(673696,X'97301F0AC5735F44B5',X'440C',227999.92,-709599.79);
258INSERT INTO t1 VALUES(-243640,NULL,-71718.11,X'1EEFEB38',X'8CC7C55D95E142FBA5');
259INSERT INTO t1 VALUES(275893,X'',375606.30,X'0AF9EC334711FB',-468194);
260DELETE FROM t1 WHERE a > 200000;
261
262UPDATE t1 SET b = 'pgnnaaoflnw' WHERE a = -190462;
263UPDATE t1 SET c = -675583 WHERE a = -467665;
264UPDATE t1 SET d = X'09CDF2B2C241' WHERE a = -133045;
265
266}]
267
268foreach {tn idx} {
269  1 {
270  }
271  2 {
272    CREATE UNIQUE INDEX i1 ON t1(b, c, d);
273    CREATE UNIQUE INDEX i2 ON t1(d, e, a);
274    CREATE UNIQUE INDEX i3 ON t1(e, d, c, b);
275
276    CREATE UNIQUE INDEX i4 ON t2(b, c, d);
277    CREATE UNIQUE INDEX i5 ON t2(d, e, a);
278    CREATE UNIQUE INDEX i6 ON t2(e, d, c, b);
279  }
280} {
281  foreach cmd {run step} {
282    forcecopy test.db test.db2
283    forcecopy rbu.db rbu.db2
284
285    sqlite3 db test.db2
286    db eval $idx
287
288    do_test 2.$tn.$cmd.1 {
289      ${cmd}_rbu test.db2 rbu.db2
290      datacksum db
291    } $cksum
292
293    do_test 2.$tn.$cmd.2 {
294      db eval { PRAGMA integrity_check }
295    } {ok}
296
297    db close
298  }
299}
300
301
302finish_test
303