- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / sqlite / src / test / savepoint6.test
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   file delete -force 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