Annotation of embedaddon/sqlite3/test/savepoint6.test, revision 1.1.1.1
1.1 misho 1: # 2009 January 3
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: # $Id: savepoint6.test,v 1.4 2009/06/05 17:09:12 drh Exp $
13:
14: set testdir [file dirname $argv0]
15: source $testdir/tester.tcl
16:
17: proc sql {zSql} {
18: uplevel db eval [list $zSql]
19: #puts stderr "$zSql ;"
20: }
21:
22: set DATABASE_SCHEMA {
23: PRAGMA auto_vacuum = incremental;
24: CREATE TABLE t1(x, y);
25: CREATE UNIQUE INDEX i1 ON t1(x);
26: CREATE INDEX i2 ON t1(y);
27: }
28:
29: if {0==[info exists ::G(savepoint6_iterations)]} {
30: set ::G(savepoint6_iterations) 1000
31: }
32:
33: #--------------------------------------------------------------------------
34: # In memory database state.
35: #
36: # ::lSavepoint is a list containing one entry for each active savepoint. The
37: # first entry in the list corresponds to the most recently opened savepoint.
38: # Each entry consists of two elements:
39: #
40: # 1. The savepoint name.
41: #
42: # 2. A serialized Tcl array representing the contents of table t1 at the
43: # start of the savepoint. The keys of the array are the x values. The
44: # values are the y values.
45: #
46: # Array ::aEntry contains the contents of database table t1. Array keys are
47: # x values, the array data values are y values.
48: #
49: set lSavepoint [list]
50: array set aEntry [list]
51:
52: proc x_to_y {x} {
53: set nChar [expr int(rand()*250) + 250]
54: set str " $nChar [string repeat $x. $nChar]"
55: string range $str 1 $nChar
56: }
57: #--------------------------------------------------------------------------
58:
59: #-------------------------------------------------------------------------
60: # Procs to operate on database:
61: #
62: # savepoint NAME
63: # rollback NAME
64: # release NAME
65: #
66: # insert_rows XVALUES
67: # delete_rows XVALUES
68: #
69: proc savepoint {zName} {
70: catch { sql "SAVEPOINT $zName" }
71: lappend ::lSavepoint [list $zName [array get ::aEntry]]
72: }
73:
74: proc rollback {zName} {
75: catch { sql "ROLLBACK TO $zName" }
76: for {set i [expr {[llength $::lSavepoint]-1}]} {$i>=0} {incr i -1} {
77: set zSavepoint [lindex $::lSavepoint $i 0]
78: if {$zSavepoint eq $zName} {
79: unset -nocomplain ::aEntry
80: array set ::aEntry [lindex $::lSavepoint $i 1]
81:
82:
83: if {$i+1 < [llength $::lSavepoint]} {
84: set ::lSavepoint [lreplace $::lSavepoint [expr $i+1] end]
85: }
86: break
87: }
88: }
89: }
90:
91: proc release {zName} {
92: catch { sql "RELEASE $zName" }
93: for {set i [expr {[llength $::lSavepoint]-1}]} {$i>=0} {incr i -1} {
94: set zSavepoint [lindex $::lSavepoint $i 0]
95: if {$zSavepoint eq $zName} {
96: set ::lSavepoint [lreplace $::lSavepoint $i end]
97: break
98: }
99: }
100:
101: if {[llength $::lSavepoint] == 0} {
102: #puts stderr "-- End of transaction!!!!!!!!!!!!!"
103: }
104: }
105:
106: proc insert_rows {lX} {
107: foreach x $lX {
108: set y [x_to_y $x]
109:
110: # Update database [db]
111: sql "INSERT OR REPLACE INTO t1 VALUES($x, '$y')"
112:
113: # Update the Tcl database.
114: set ::aEntry($x) $y
115: }
116: }
117:
118: proc delete_rows {lX} {
119: foreach x $lX {
120: # Update database [db]
121: sql "DELETE FROM t1 WHERE x = $x"
122:
123: # Update the Tcl database.
124: unset -nocomplain ::aEntry($x)
125: }
126: }
127: #-------------------------------------------------------------------------
128:
129: #-------------------------------------------------------------------------
130: # Proc to compare database content with the in-memory representation.
131: #
132: # checkdb
133: #
134: proc checkdb {} {
135: set nEntry [db one {SELECT count(*) FROM t1}]
136: set nEntry2 [array size ::aEntry]
137: if {$nEntry != $nEntry2} {
138: error "$nEntry entries in database, $nEntry2 entries in array"
139: }
140: db eval {SELECT x, y FROM t1} {
141: if {![info exists ::aEntry($x)]} {
142: error "Entry $x exists in database, but not in array"
143: }
144: if {$::aEntry($x) ne $y} {
145: error "Entry $x is set to {$y} in database, {$::aEntry($x)} in array"
146: }
147: }
148:
149: db eval { PRAGMA integrity_check }
150: }
151: #-------------------------------------------------------------------------
152:
153: #-------------------------------------------------------------------------
154: # Proc to return random set of x values.
155: #
156: # random_integers
157: #
158: proc random_integers {nRes nRange} {
159: set ret [list]
160: for {set i 0} {$i<$nRes} {incr i} {
161: lappend ret [expr int(rand()*$nRange)]
162: }
163: return $ret
164: }
165: #-------------------------------------------------------------------------
166:
167: proc database_op {} {
168: set i [expr int(rand()*2)]
169: if {$i==0} {
170: insert_rows [random_integers 100 1000]
171: }
172: if {$i==1} {
173: delete_rows [random_integers 100 1000]
174: set i [expr int(rand()*3)]
175: if {$i==0} {
176: sql {PRAGMA incremental_vacuum}
177: }
178: }
179: }
180:
181: proc savepoint_op {} {
182: set names {one two three four five}
183: set cmds {savepoint savepoint savepoint savepoint release rollback}
184:
185: set C [lindex $cmds [expr int(rand()*6)]]
186: set N [lindex $names [expr int(rand()*5)]]
187:
188: #puts stderr " $C $N ; "
189: #flush stderr
190:
191: $C $N
192: return ok
193: }
194:
195: expr srand(0)
196:
197: ############################################################################
198: ############################################################################
199: # Start of test cases.
200:
201: do_test savepoint6-1.1 {
202: sql $DATABASE_SCHEMA
203: } {}
204: do_test savepoint6-1.2 {
205: insert_rows {
206: 497 166 230 355 779 588 394 317 290 475 362 193 805 851 564
207: 763 44 930 389 819 765 760 966 280 538 414 500 18 25 287 320
208: 30 382 751 87 283 981 429 630 974 421 270 810 405
209: }
210:
211: savepoint one
212: insert_rows 858
213: delete_rows 930
214: savepoint two
215: execsql {PRAGMA incremental_vacuum}
216: savepoint three
217: insert_rows 144
218: rollback three
219: rollback two
220: release one
221:
222: execsql {SELECT count(*) FROM t1}
223: } {44}
224:
225: foreach zSetup [list {
226: set testname normal
227: sqlite3 db test.db
228: } {
229: if {[wal_is_wal_mode]} continue
230: set testname tempdb
231: sqlite3 db ""
232: } {
233: if {[permutation] eq "journaltest"} {
234: continue
235: }
236: set testname nosync
237: sqlite3 db test.db
238: sql { PRAGMA synchronous = off }
239: } {
240: set testname smallcache
241: sqlite3 db test.db
242: sql { PRAGMA cache_size = 10 }
243: }] {
244:
245: unset -nocomplain ::lSavepoint
246: unset -nocomplain ::aEntry
247:
248: catch { db close }
249: forcedelete test.db test.db-wal test.db-journal
250: eval $zSetup
251: sql $DATABASE_SCHEMA
252:
253: wal_set_journal_mode
254:
255: do_test savepoint6-$testname.setup {
256: savepoint one
257: insert_rows [random_integers 100 1000]
258: release one
259: checkdb
260: } {ok}
261:
262: for {set i 0} {$i < $::G(savepoint6_iterations)} {incr i} {
263: do_test savepoint6-$testname.$i.1 {
264: savepoint_op
265: checkdb
266: } {ok}
267:
268: do_test savepoint6-$testname.$i.2 {
269: database_op
270: database_op
271: checkdb
272: } {ok}
273: }
274:
275: wal_check_journal_mode savepoint6-$testname.walok
276: }
277:
278: unset -nocomplain ::lSavepoint
279: unset -nocomplain ::aEntry
280:
281: finish_test
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>