SQLite

Check-in [94cf91cc5d]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Tidy up malloc.test a bit. (CVS 2207)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 94cf91cc5dc0d656636211d23350a1ec29aced8a
User & Date: danielk1977 2005-01-13 13:35:58.000
Context
2005-01-13
23:54
Fix a bug in lemon that does not effect SQLite. Ticket #1068. (CVS 2208) (check-in: 7113b5ed8d user: drh tags: trunk)
13:35
Tidy up malloc.test a bit. (CVS 2207) (check-in: 94cf91cc5d user: danielk1977 tags: trunk)
11:10
Fix typo in shell .help. Ticket #1071. (CVS 2206) (check-in: 2c7a1a1698 user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to test/malloc.test.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#***********************************************************************
# This file attempts to check the library in an out-of-memory situation.
# When compiled with -DSQLITE_DEBUG=1, the SQLite library accepts a special
# command (sqlite_malloc_fail N) which causes the N-th malloc to fail.  This
# special feature is used to see what happens in the library if a malloc
# were to really fail due to an out-of-memory situation.
#
# $Id: malloc.test,v 1.19 2005/01/13 11:07:54 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Only run these tests if memory debugging is turned on.
#
if {[info command sqlite_malloc_stat]==""} {







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#***********************************************************************
# This file attempts to check the library in an out-of-memory situation.
# When compiled with -DSQLITE_DEBUG=1, the SQLite library accepts a special
# command (sqlite_malloc_fail N) which causes the N-th malloc to fail.  This
# special feature is used to see what happens in the library if a malloc
# were to really fail due to an out-of-memory situation.
#
# $Id: malloc.test,v 1.20 2005/01/13 13:35:58 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Only run these tests if memory debugging is turned on.
#
if {[info command sqlite_malloc_stat]==""} {
32
33
34
35
36
37
38

39
40
41
42
43
44
45
# The first argument, <test number>, is an integer used to name the
# tests executed by this proc. Options are as follows:
#
#     -tclprep          TCL script to run to prepare test.
#     -sqlprep          SQL script to run to prepare test.
#     -tclbody          TCL script to run with malloc failure simulation.
#     -sqlbody          TCL script to run with malloc failure simulation.

#
# This command runs a series of tests to verify SQLite's ability
# to handle an out-of-memory condition gracefully. It is assumed
# that if this condition occurs a malloc() call will return a
# NULL pointer. Linux, for example, doesn't do that by default. See
# the "BUGS" section of malloc(3).
#







>







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# The first argument, <test number>, is an integer used to name the
# tests executed by this proc. Options are as follows:
#
#     -tclprep          TCL script to run to prepare test.
#     -sqlprep          SQL script to run to prepare test.
#     -tclbody          TCL script to run with malloc failure simulation.
#     -sqlbody          TCL script to run with malloc failure simulation.
#     -cleanup          TCL script to run after the test.
#
# This command runs a series of tests to verify SQLite's ability
# to handle an out-of-memory condition gracefully. It is assumed
# that if this condition occurs a malloc() call will return a
# NULL pointer. Linux, for example, doesn't do that by default. See
# the "BUGS" section of malloc(3).
#
91
92
93
94
95
96
97
98




99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458

459
460
461
462
463
464
465
466
467
        set v {1 1}
      } else {
        set v2 [expr {$msg=="" || $msg=="out of memory"}]
        if {!$v2} {puts "\nError message returned: $msg"}
        lappend v $v2
      }
    } {1 1}
  }




  unset ::mallocopts
}

for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-1.$i {
     sqlite_malloc_fail 0
     catch {db close}
     catch {file delete -force test.db}
     catch {file delete -force test.db-journal}
     sqlite_malloc_fail $i [expr {$i%4}]
     set v [catch {sqlite3 db test.db} msg]
     if {$v} {
       set msg ""

     } else {
       set v [catch {execsql {
          CREATE TABLE t1(
             a int, b float, c double, d text, e varchar(20),
             primary key(a,b,c)
          );
          CREATE INDEX i1 ON t1(a,b);
          INSERT INTO t1 VALUES(1,2.3,4.5,'hi','there');
          INSERT INTO t1 VALUES(6,7.0,0.8,'hello','out yonder');
          SELECT * FROM t1;
          SELECT avg(b) FROM t1 GROUP BY a HAVING b>20.0;
          DELETE FROM t1 WHERE a IN (SELECT min(a) FROM t1);
          SELECT count(*) FROM t1;
       }} msg]
     }
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}

# Ensure that no file descriptors were leaked.
do_test malloc-1.X {
  catch {db close}
  set sqlite_open_file_count
} {0}

set fd [open ./data.tmp w]
for {set i 1} {$i<=20} {incr i} {
  puts $fd "$i\t[expr {$i*$i}]\t[expr {100-$i}]  abcdefghijklmnopqrstuvwxyz"
}
close $fd

for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-2.$i {
     sqlite_malloc_fail 0
     catch {db close}
     catch {file delete -force test.db}
     catch {file delete -force test.db-journal}
     sqlite_malloc_fail $i
     set v [catch {sqlite3 db test.db} msg]
     if {$v} {
       set msg ""
     } else {
       set v [catch {execsql {
         CREATE TABLE t1(a int, b int, c int);
         CREATE INDEX i1 ON t1(a,b);
         INSERT INTO t1 VALUES(1,1,'99 abcdefghijklmnopqrstuvwxyz');
         INSERT INTO t1 VALUES(2,4,'98 abcdefghijklmnopqrstuvwxyz');
         INSERT INTO t1 VALUES(3,9,'97 abcdefghijklmnopqrstuvwxyz');
         INSERT INTO t1 VALUES(4,16,'96 abcdefghijklmnopqrstuvwxyz');
         INSERT INTO t1 VALUES(5,25,'95 abcdefghijklmnopqrstuvwxyz');
         INSERT INTO t1 VALUES(6,36,'94 abcdefghijklmnopqrstuvwxyz');
         SELECT 'stuff', count(*) as 'other stuff', max(a+10) FROM t1;
         UPDATE t1 SET b=b||b||b||b;
         UPDATE t1 SET b=a WHERE a in (10,12,22);
         INSERT INTO t1(c,b,a) VALUES(20,10,5);
         INSERT INTO t1 SELECT * FROM t1
             WHERE a IN (SELECT a FROM t1 WHERE a<10);
         DELETE FROM t1 WHERE a>=10;
         DROP INDEX i1;
         DELETE FROM t1;
       }} msg]
     }
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}

# Ensure that no file descriptors were leaked.
do_test malloc-2.X {
  catch {db close}
  set sqlite_open_file_count
} {0}

for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-3.$i {
     sqlite_malloc_fail 0
     catch {db close}
     catch {file delete -force test.db}
     catch {file delete -force test.db-journal}
     sqlite_malloc_fail $i
     set v [catch {sqlite3 db test.db} msg]
     if {$v} {
       set msg ""
     } else {
       set v [catch {execsql {
         BEGIN TRANSACTION;
         CREATE TABLE t1(a int, b int, c int);
         CREATE INDEX i1 ON t1(a,b);
         INSERT INTO t1 VALUES(1,1,99);
         INSERT INTO t1 VALUES(2,4,98);
         INSERT INTO t1 VALUES(3,9,97);
         INSERT INTO t1 VALUES(4,16,96);
         INSERT INTO t1 VALUES(5,25,95);
         INSERT INTO t1 VALUES(6,36,94);
         INSERT INTO t1(c,b,a) VALUES(20,10,5);
         DELETE FROM t1 WHERE a>=10;
         DROP INDEX i1;
         DELETE FROM t1;
         ROLLBACK;
       }} msg]
     }
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}

# Ensure that no file descriptors were leaked.
do_test malloc-3.X {
  catch {db close}
  set sqlite_open_file_count
} {0}

for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-4.$i {
     sqlite_malloc_fail 0
     catch {db close}
     catch {file delete -force test.db}
     catch {file delete -force test.db-journal}
     sqlite_malloc_fail $i
     set v [catch {sqlite3 db test.db} msg]
     if {$v} {
       set msg ""
     } else {
       set v [catch {execsql {
         BEGIN TRANSACTION;
         CREATE TABLE t1(a int, b int, c int);
         CREATE INDEX i1 ON t1(a,b);
         INSERT INTO t1 VALUES(1,1,99);
         INSERT INTO t1 VALUES(2,4,98);
         INSERT INTO t1 VALUES(3,9,97);
         INSERT INTO t1 VALUES(4,16,96);
         INSERT INTO t1 VALUES(5,25,95);
         INSERT INTO t1 VALUES(6,36,94);
         UPDATE t1 SET b=a WHERE a in (10,12,22);
         INSERT INTO t1 SELECT * FROM t1
             WHERE a IN (SELECT a FROM t1 WHERE a<10);
         DROP INDEX i1;
         DELETE FROM t1;
         COMMIT;
       }} msg]
     }
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}

# Ensure that no file descriptors were leaked.
do_test malloc-4.X {
  catch {db close}
  set sqlite_open_file_count
} {0}

for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-5.$i {
     sqlite_malloc_fail 0
     catch {db close}
     catch {file delete -force test.db}
     catch {file delete -force test.db-journal}
     sqlite_malloc_fail $i
     set v [catch {sqlite3 db test.db} msg]
     if {$v} {
       set msg ""
     } else {
       set v [catch {execsql {
         BEGIN TRANSACTION;
         CREATE TABLE t1(a,b);
         CREATE TABLE t2(x,y);
         CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
           INSERT INTO t2(x,y) VALUES(new.rowid,1);
         END;
         INSERT INTO t1(a,b) VALUES(2,3);
         COMMIT;
       }} msg]
     }
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}

# Ensure that no file descriptors were leaked.
do_test malloc-5.X {
  catch {db close}
  set sqlite_open_file_count
} {0}

for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-6.$i {
     sqlite_malloc_fail 0
     catch {db close}
     catch {file delete -force test.db}
     catch {file delete -force test.db-journal}
     sqlite3 db test.db
     execsql {
         BEGIN TRANSACTION;
         CREATE TABLE t1(a);
         INSERT INTO t1 VALUES(1);
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         INSERT INTO t1 SELECT a*2 FROM t1;
         DELETE FROM t1 where rowid%5 = 0;
         COMMIT;
     }
     sqlite_malloc_fail $i
     set v [catch {execsql {
       VACUUM;
     }} msg]
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}

for {set go 1; set i 1} {$go} {incr i} {
  do_test malloc-7.$i {
     sqlite_malloc_fail 0
     catch {db close}
     catch {file delete -force test.db}
     catch {file delete -force test.db-journal}
     sqlite3 db test.db
     execsql {
       CREATE TABLE t1(a, b);
       INSERT INTO t1 VALUES(1, 2);
       INSERT INTO t1 VALUES(3, 4);
       INSERT INTO t1 VALUES(5, 6);
       INSERT INTO t1 VALUES(7, randstr(1200,1200));
     }
     sqlite_malloc_fail $i
     set v [catch {execsql {
       SELECT min(a) FROM t1 WHERE a<6 GROUP BY b;
       SELECT a FROM t1 WHERE a<6 ORDER BY a;
       SELECT b FROM t1 WHERE a>6;
     }} msg]
     set leftover [lindex [sqlite_malloc_stat] 2]
     if {$leftover>0} {
       if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
       set ::go 0
       set v {1 1}
     } else {
       set v2 [expr {$msg=="" || $msg=="out of memory"}]
       if {!$v2} {puts "\nError message returned: $msg"}
       lappend v $v2
     }
  } {1 1}
}

# This block is designed to test that some malloc failures that may
# occur in vdbeapi.c. Specifically, if a malloc failure that occurs
# when converting UTF-16 text to integers and real numbers is handled
# correctly. 
#
# This is done by retrieving a string from the database engine and
# manipulating it using the sqlite3_column_*** APIs. This doesn't 
# actually return an error to the user when a malloc() fails.. That 
# could be viewed as a bug.
#
# These tests only run if UTF-16 support is compiled in.
#
for {set go 1; set i 1} {$go && $::sqlite_options(utf16)} {incr i} {
  do_test malloc-8.$i {
     sqlite_malloc_fail 0
     catch {db close}
     catch {file delete -force test.db}
     catch {file delete -force test.db-journal}

     set ::DB [sqlite3 db test.db]
     set sql "SELECT '[string repeat abc 20]', '[string repeat def 20]', ?"
     set ::STMT [sqlite3_prepare $::DB $sql -1 X]
     sqlite3_step $::STMT

     if { $::tcl_platform(byteOrder)=="littleEndian" } {
       set ::bomstr "\xFF\xFE"
     } else {
       set ::bomstr "\xFE\xFF"
     }
     append ::bomstr [encoding convertto unicode "123456789_123456789_12345678"]

     sqlite_malloc_fail $i
     catch {
       sqlite3_column_text16 $::STMT 0
       sqlite3_column_int $::STMT 0
       sqlite3_column_text16 $::STMT 1
       sqlite3_column_double $::STMT 1
       sqlite3_reset $::STMT
       sqlite3_bind_text16 $::STMT 1 $::bomstr 60
       
     } msg
     sqlite3_finalize $::STMT
     if {[lindex [sqlite_malloc_stat] 2]>0} {
       set ::go 0
     }
     expr 0
  } {0}

}


# This block tests that malloc() failures that occur whilst commiting
# a multi-file transaction are handled correctly.
#
do_malloc_test 9 -sqlprep {
  ATTACH 'test2.db' as test2;
  CREATE TABLE abc1(a, b, c);







|
>
>
>
>



<
<
|
|
<
<
|
|
|
<
>
|
<
|
|
|
|
|
|
|
|
|
|
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<







<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<







<
<
|
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
<
<
<
<
<
<
<
<
<
|
<
<







<
<
|
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<







<
<
|
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<







<
<
|
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
<
|
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
|
<
<
<
<
<
|
|
|
|
|
<
|
<
|
|
|
<
<
<
<
<
<
<
<
<
<
|
<
<













|
<
|
<
<
<
<
<
|
|
|
<
|
|
|
|
|
|
|
<
<
|
|
|
|
|
|
<
<
|
|
|
|
<
|
>
|
|







92
93
94
95
96
97
98
99
100
101
102
103
104
105
106


107
108


109
110
111

112
113

114
115
116
117
118
119
120
121
122
123
124

125












126
127
128
129
130
131
132








133









134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

151












152
153
154
155
156
157
158


159









160
161
162
163
164
165
166
167
168
169
170
171
172
173

174









175


176
177
178
179
180
181
182


183









184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

199












200
201
202
203
204
205
206


207









208
209
210
211
212
213
214
215

216












217
218
219
220
221
222
223


224





225
226
227
228
229
230
231
232
233
234
235
236
237
238
239

240

241










242

243



244





245
246
247
248
249

250

251
252
253










254


255
256
257
258
259
260
261
262
263
264
265
266
267
268

269





270
271
272

273
274
275
276
277
278
279


280
281
282
283
284
285


286
287
288
289

290
291
292
293
294
295
296
297
298
299
300
        set v {1 1}
      } else {
        set v2 [expr {$msg=="" || $msg=="out of memory"}]
        if {!$v2} {puts "\nError message returned: $msg"}
        lappend v $v2
      }
    } {1 1}

    if {[info exists ::mallocopts(-cleanup)]} {
      catch $::mallocopts(-cleanup)
    }
  }
  unset ::mallocopts
}



do_malloc_test 1 -tclprep {
  db close


} -tclbody {
  if {[catch {sqlite3 db test.db}]} {
    error "out of memory"

  }
} -sqlbody {

  CREATE TABLE t1(
     a int, b float, c double, d text, e varchar(20),
     primary key(a,b,c)
  );
  CREATE INDEX i1 ON t1(a,b);
  INSERT INTO t1 VALUES(1,2.3,4.5,'hi','there');
  INSERT INTO t1 VALUES(6,7.0,0.8,'hello','out yonder');
  SELECT * FROM t1;
  SELECT avg(b) FROM t1 GROUP BY a HAVING b>20.0;
  DELETE FROM t1 WHERE a IN (SELECT min(a) FROM t1);
  SELECT count(*) FROM t1;

} 













# Ensure that no file descriptors were leaked.
do_test malloc-1.X {
  catch {db close}
  set sqlite_open_file_count
} {0}









do_malloc_test 2 -sqlbody {









  CREATE TABLE t1(a int, b int, c int);
  CREATE INDEX i1 ON t1(a,b);
  INSERT INTO t1 VALUES(1,1,'99 abcdefghijklmnopqrstuvwxyz');
  INSERT INTO t1 VALUES(2,4,'98 abcdefghijklmnopqrstuvwxyz');
  INSERT INTO t1 VALUES(3,9,'97 abcdefghijklmnopqrstuvwxyz');
  INSERT INTO t1 VALUES(4,16,'96 abcdefghijklmnopqrstuvwxyz');
  INSERT INTO t1 VALUES(5,25,'95 abcdefghijklmnopqrstuvwxyz');
  INSERT INTO t1 VALUES(6,36,'94 abcdefghijklmnopqrstuvwxyz');
  SELECT 'stuff', count(*) as 'other stuff', max(a+10) FROM t1;
  UPDATE t1 SET b=b||b||b||b;
  UPDATE t1 SET b=a WHERE a in (10,12,22);
  INSERT INTO t1(c,b,a) VALUES(20,10,5);
  INSERT INTO t1 SELECT * FROM t1
      WHERE a IN (SELECT a FROM t1 WHERE a<10);
  DELETE FROM t1 WHERE a>=10;
  DROP INDEX i1;
  DELETE FROM t1;

} 













# Ensure that no file descriptors were leaked.
do_test malloc-2.X {
  catch {db close}
  set sqlite_open_file_count
} {0}



do_malloc_test 3 -sqlbody {









  BEGIN TRANSACTION;
  CREATE TABLE t1(a int, b int, c int);
  CREATE INDEX i1 ON t1(a,b);
  INSERT INTO t1 VALUES(1,1,99);
  INSERT INTO t1 VALUES(2,4,98);
  INSERT INTO t1 VALUES(3,9,97);
  INSERT INTO t1 VALUES(4,16,96);
  INSERT INTO t1 VALUES(5,25,95);
  INSERT INTO t1 VALUES(6,36,94);
  INSERT INTO t1(c,b,a) VALUES(20,10,5);
  DELETE FROM t1 WHERE a>=10;
  DROP INDEX i1;
  DELETE FROM t1;
  ROLLBACK;

} 













# Ensure that no file descriptors were leaked.
do_test malloc-3.X {
  catch {db close}
  set sqlite_open_file_count
} {0}



do_malloc_test 4 -sqlbody {









  BEGIN TRANSACTION;
  CREATE TABLE t1(a int, b int, c int);
  CREATE INDEX i1 ON t1(a,b);
  INSERT INTO t1 VALUES(1,1,99);
  INSERT INTO t1 VALUES(2,4,98);
  INSERT INTO t1 VALUES(3,9,97);
  INSERT INTO t1 VALUES(4,16,96);
  INSERT INTO t1 VALUES(5,25,95);
  INSERT INTO t1 VALUES(6,36,94);
  UPDATE t1 SET b=a WHERE a in (10,12,22);
  INSERT INTO t1 SELECT * FROM t1
     WHERE a IN (SELECT a FROM t1 WHERE a<10);
  DROP INDEX i1;
  DELETE FROM t1;
  COMMIT;

} 













# Ensure that no file descriptors were leaked.
do_test malloc-4.X {
  catch {db close}
  set sqlite_open_file_count
} {0}



do_malloc_test 5 -sqlbody {









  BEGIN TRANSACTION;
  CREATE TABLE t1(a,b);
  CREATE TABLE t2(x,y);
  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
  INSERT INTO t2(x,y) VALUES(new.rowid,1);
  END;
  INSERT INTO t1(a,b) VALUES(2,3);
  COMMIT;

} 













# Ensure that no file descriptors were leaked.
do_test malloc-5.X {
  catch {db close}
  set sqlite_open_file_count
} {0}



do_malloc_test 6 -sqlprep {





  BEGIN TRANSACTION;
  CREATE TABLE t1(a);
  INSERT INTO t1 VALUES(1);
  INSERT INTO t1 SELECT a*2 FROM t1;
  INSERT INTO t1 SELECT a*2 FROM t1;
  INSERT INTO t1 SELECT a*2 FROM t1;
  INSERT INTO t1 SELECT a*2 FROM t1;
  INSERT INTO t1 SELECT a*2 FROM t1;
  INSERT INTO t1 SELECT a*2 FROM t1;
  INSERT INTO t1 SELECT a*2 FROM t1;
  INSERT INTO t1 SELECT a*2 FROM t1;
  INSERT INTO t1 SELECT a*2 FROM t1;
  INSERT INTO t1 SELECT a*2 FROM t1;
  DELETE FROM t1 where rowid%5 = 0;
  COMMIT;

} -sqlbody {

  VACUUM;










} 





do_malloc_test 7 -sqlprep {





  CREATE TABLE t1(a, b);
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(3, 4);
  INSERT INTO t1 VALUES(5, 6);
  INSERT INTO t1 VALUES(7, randstr(1200,1200));

} -sqlbody {

  SELECT min(a) FROM t1 WHERE a<6 GROUP BY b;
  SELECT a FROM t1 WHERE a<6 ORDER BY a;
  SELECT b FROM t1 WHERE a>6;










} 



# This block is designed to test that some malloc failures that may
# occur in vdbeapi.c. Specifically, if a malloc failure that occurs
# when converting UTF-16 text to integers and real numbers is handled
# correctly. 
#
# This is done by retrieving a string from the database engine and
# manipulating it using the sqlite3_column_*** APIs. This doesn't 
# actually return an error to the user when a malloc() fails.. That 
# could be viewed as a bug.
#
# These tests only run if UTF-16 support is compiled in.
#
if {$::sqlite_options(utf16)} {

  do_malloc_test 8 -tclprep {





    set sql "SELECT '[string repeat abc 20]', '[string repeat def 20]', ?"
    set ::STMT [sqlite3_prepare $::DB $sql -1 X]
    sqlite3_step $::STMT

    if { $::tcl_platform(byteOrder)=="littleEndian" } {
      set ::bomstr "\xFF\xFE"
    } else {
      set ::bomstr "\xFE\xFF"
    }
    append ::bomstr [encoding convertto unicode "123456789_123456789_12345678"]
  } -tclbody {


    sqlite3_column_text16 $::STMT 0
    sqlite3_column_int $::STMT 0
    sqlite3_column_text16 $::STMT 1
    sqlite3_column_double $::STMT 1
    sqlite3_reset $::STMT
    sqlite3_bind_text16 $::STMT 1 $::bomstr 60


    catch {sqlite3_finalize $::STMT}
    if {[lindex [sqlite_malloc_stat] 2]<=0} {
      error "out of memory"
    }

  } -cleanup {
    sqlite3_finalize $::STMT
  }
}

# This block tests that malloc() failures that occur whilst commiting
# a multi-file transaction are handled correctly.
#
do_malloc_test 9 -sqlprep {
  ATTACH 'test2.db' as test2;
  CREATE TABLE abc1(a, b, c);