3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
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.
10 #***********************************************************************
12 # Tests for the sqlite3_db_status() function
15 set testdir [file dirname $argv0]
16 source $testdir/tester.tcl
23 # Memory statistics must be enabled for this test.
26 sqlite3_config_memstatus 1
31 # Make sure sqlite3_db_config() and sqlite3_db_status are working.
33 unset -nocomplain PAGESZ
34 unset -nocomplain BASESZ
35 do_test dbstatus-1.1 {
41 set sz1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1]
45 set sz2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1]
46 set ::PAGESZ [expr {$sz2-$sz1}]
47 set ::BASESZ [expr {$sz1-$::PAGESZ}]
48 expr {$::PAGESZ>1024 && $::PAGESZ<1300}
50 do_test dbstatus-1.2 {
52 INSERT INTO t1 VALUES(zeroblob(9000));
54 lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1
55 } [expr {$BASESZ + 10*$PAGESZ}]
59 expr { $::lookaside_buffer_size *
60 [lindex [sqlite3_db_status $db SQLITE_DBSTATUS_LOOKASIDE_USED 0] 1]
64 ifcapable stat4||stat3 {
70 ifcapable malloc_usable_size {
75 #---------------------------------------------------------------------------
76 # Run the dbstatus-2 and dbstatus-3 tests with several of different
77 # lookaside buffer sizes.
79 foreach ::lookaside_buffer_size {0 64 120} {
81 # Do not run any of these tests if there is SQL configured to run
82 # as part of the [sqlite3] command. This prevents the script from
83 # configuring the size of the lookaside buffer after [sqlite3] has
85 if {[presql] != ""} break
87 #-------------------------------------------------------------------------
88 # Tests for SQLITE_DBSTATUS_SCHEMA_USED.
90 # Each test in the following block works as follows. Each test uses a
91 # different database schema.
93 # 1. Open a connection to an empty database. Disable statement caching.
95 # 2. Execute the SQL to create the database schema. Measure the total
96 # heap and lookaside memory allocated by SQLite, and the memory
97 # allocated for the database schema according to sqlite3_db_status().
99 # 3. Drop all tables in the database schema. Measure the total memory
100 # and the schema memory again.
108 # a) The difference in schema memory quantities in steps 2 and 3 is the
109 # same as the difference in total memory in steps 2 and 3.
111 # b) Step 4 reports the same amount of schema and total memory used as
114 # c) Step 5 reports the same amount of schema and total memory used as
117 foreach {tn schema} {
118 1 { CREATE TABLE t1(a, b) }
119 2 { CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1, c UNIQUE) }
121 CREATE TABLE t1(a, b);
122 CREATE INDEX i1 ON t1(a, b);
125 CREATE TABLE t1(a, b);
126 CREATE TABLE t2(c, d);
127 CREATE TRIGGER AFTER INSERT ON t1 BEGIN
128 INSERT INTO t2 VALUES(new.a, new.b);
129 SELECT * FROM t1, t2 WHERE a=c AND b=d GROUP BY b HAVING a>5 ORDER BY a;
133 CREATE TABLE t1(a, b);
134 CREATE TABLE t2(c, d);
135 CREATE VIEW v1 AS SELECT * FROM t1 UNION SELECT * FROM t2;
138 CREATE TABLE t1(a, b);
139 CREATE INDEX i1 ON t1(a);
140 CREATE INDEX i2 ON t1(a,b);
141 CREATE INDEX i3 ON t1(b,b);
142 INSERT INTO t1 VALUES(randomblob(20), randomblob(25));
143 INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
144 INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
145 INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
149 CREATE TABLE t1(a, b);
150 CREATE TABLE t2(c, d);
156 SELECT c||b, d||a FROM t2 LEFT OUTER JOIN t1 GROUP BY c, d
159 CREATE TRIGGER tr1 INSTEAD OF INSERT ON v1 BEGIN
161 UPDATE t1 SET a=5, b=(SELECT c FROM t2);
166 CREATE TABLE t1(a, b, UNIQUE(a, b));
167 CREATE VIRTUAL TABLE t2 USING echo(t1);
170 set tn "$::lookaside_buffer_size-$tn"
176 sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
179 catch { register_echo_module db }
180 ifcapable !vtab { if {[string match *x $tn]} continue }
184 set nAlloc1 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
185 incr nAlloc1 [lookaside db]
186 set nSchema1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
190 set nAlloc2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
191 incr nAlloc2 [lookaside db]
192 set nSchema2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
196 set nAlloc3 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
197 incr nAlloc3 [lookaside db]
198 set nSchema3 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
202 set nAlloc4 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
203 incr nAlloc4 [lookaside db]
204 set nSchema4 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
205 set nFree [expr {$nAlloc1-$nAlloc2}]
207 # Tests for which the test name ends in an "k" report slightly less
208 # memory than is actually freed when all schema items are finalized.
209 # This is because memory allocated by KeyInfo objects is no longer
210 # counted as "schema memory".
212 # Tests for which the test name ends in an "x" report slightly less
213 # memory than is actually freed when all schema items are finalized.
214 # This is because memory allocated by virtual table implementations
215 # for any reason is not counted as "schema memory".
217 # Additionally, in auto-vacuum mode, dropping tables and indexes causes
218 # the page-cache to shrink. So the amount of memory freed is always
219 # much greater than just that reported by DBSTATUS_SCHEMA_USED in this
222 # Some of the memory used for sqlite_stat4 is unaccounted for by
225 # Finally, on osx the estimate of memory used by the schema may be
228 if {[string match *k $tn]
229 || [string match *x $tn] || $AUTOVACUUM
230 || ([string match *y $tn] && $STAT3)
231 || ($::tcl_platform(os) == "Darwin")
233 do_test dbstatus-2.$tn.ax { expr {($nSchema1-$nSchema2)<=$nFree} } 1
235 do_test dbstatus-2.$tn.a { expr {$nSchema1-$nSchema2} } $nFree
238 do_test dbstatus-2.$tn.b { list $nAlloc1 $nSchema1 } "$nAlloc3 $nSchema3"
239 do_test dbstatus-2.$tn.c { list $nAlloc2 $nSchema2 } "$nAlloc4 $nSchema4"
242 #-------------------------------------------------------------------------
243 # Tests for SQLITE_DBSTATUS_STMT_USED.
245 # Each test in the following block works as follows. Each test uses a
246 # different database schema.
248 # 1. Open a connection to an empty database. Initialized the database
251 # 2. Prepare a bunch of SQL statements. Measure the total heap and
252 # lookaside memory allocated by SQLite, and the memory allocated
253 # for the prepared statements according to sqlite3_db_status().
255 # 3. Finalize all prepared statements. Measure the total memory
256 # and the prepared statement memory again.
264 # a) The difference in schema memory quantities in steps 2 and 3 is the
265 # same as the difference in total memory in steps 2 and 3.
267 # b) Step 4 reports the same amount of schema and total memory used as
270 # c) Step 5 reports the same amount of schema and total memory used as
273 foreach {tn schema statements} {
274 1 { CREATE TABLE t1(a, b) } {
276 INSERT INTO t1 VALUES(1, 2);
277 INSERT INTO t1 SELECT * FROM t1;
282 PRAGMA recursive_triggers = 1;
283 CREATE TABLE t1(a, b);
284 CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
285 INSERT INTO t1 VALUES(new.a-1, new.b);
288 INSERT INTO t1 VALUES(5, 'x');
291 PRAGMA recursive_triggers = 1;
292 CREATE TABLE t1(a, b);
293 CREATE TABLE t2(a, b);
294 CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
295 INSERT INTO t2 VALUES(new.a-1, new.b);
297 CREATE TRIGGER tr2 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
298 INSERT INTO t1 VALUES(new.a-1, new.b);
301 INSERT INTO t1 VALUES(10, 'x');
304 CREATE TABLE t1(a, b);
306 SELECT count(*) FROM t1 WHERE upper(a)='ABC';
309 CREATE TABLE t1(a, b UNIQUE);
310 CREATE VIRTUAL TABLE t2 USING echo(t1);
312 SELECT count(*) FROM t2;
313 SELECT * FROM t2 WHERE b>5;
314 SELECT * FROM t2 WHERE b='abcdefg';
317 set tn "$::lookaside_buffer_size-$tn"
323 sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
326 catch { register_echo_module db }
327 ifcapable !vtab { if {[string match *x $tn]} continue }
334 set nAlloc1 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
335 incr nAlloc1 [lookaside db]
336 set nStmt1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
341 set nAlloc2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
342 incr nAlloc2 [lookaside db]
343 set nStmt2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
347 set nAlloc3 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
348 incr nAlloc3 [lookaside db]
349 set nStmt3 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
354 set nAlloc4 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
355 incr nAlloc4 [lookaside db]
356 set nStmt4 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
358 set nFree [expr {$nAlloc1-$nAlloc2}]
360 do_test dbstatus-3.$tn.a { expr $nStmt2 } {0}
362 # Tests for which the test name ends in an "x" report slightly less
363 # memory than is actually freed when all statements are finalized.
364 # This is because a small amount of memory allocated by a virtual table
365 # implementation using sqlite3_mprintf() is technically considered
366 # external and so is not counted as "statement memory".
368 #puts "$nStmt1 $nFree"
369 if {[string match *x $tn]} {
370 do_test dbstatus-3.$tn.bx { expr $nStmt1<=$nFree } {1}
372 do_test dbstatus-3.$tn.b { expr $nStmt1==$nFree } {1}
375 do_test dbstatus-3.$tn.c { list $nAlloc1 $nStmt1 } [list $nAlloc3 $nStmt3]
376 do_test dbstatus-3.$tn.d { list $nAlloc2 $nStmt2 } [list $nAlloc4 $nStmt4]