blob: 57b91cda1ae65127bbe7bcaeb6cd3b45f45f664a [file] [log] [blame]
drh63da0892010-03-10 21:42:07 +00001# 2010 March 10
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# Tests for the sqlite3_db_status() function
13#
14
15set testdir [file dirname $argv0]
16source $testdir/tester.tcl
dan272989b2016-07-06 10:12:02 +000017set testprefix dbstatus
drh63da0892010-03-10 21:42:07 +000018
dan2f56da32012-02-13 10:00:35 +000019ifcapable !compound {
20 finish_test
21 return
22}
23
drh887f8d32010-09-09 17:43:06 +000024# Memory statistics must be enabled for this test.
25db close
26sqlite3_shutdown
27sqlite3_config_memstatus 1
dan272989b2016-07-06 10:12:02 +000028sqlite3_config_uri 1
drh887f8d32010-09-09 17:43:06 +000029sqlite3_initialize
30sqlite3 db test.db
31
drh63da0892010-03-10 21:42:07 +000032
33# Make sure sqlite3_db_config() and sqlite3_db_status are working.
34#
35unset -nocomplain PAGESZ
36unset -nocomplain BASESZ
37do_test dbstatus-1.1 {
38 db close
39 sqlite3 db :memory:
40 db eval {
41 CREATE TABLE t1(x);
42 }
43 set sz1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1]
44 db eval {
45 CREATE TABLE t2(y);
46 }
47 set sz2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1]
48 set ::PAGESZ [expr {$sz2-$sz1}]
49 set ::BASESZ [expr {$sz1-$::PAGESZ}]
drh60a31172010-07-28 18:51:26 +000050 expr {$::PAGESZ>1024 && $::PAGESZ<1300}
drh63da0892010-03-10 21:42:07 +000051} {1}
52do_test dbstatus-1.2 {
53 db eval {
54 INSERT INTO t1 VALUES(zeroblob(9000));
55 }
56 lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1
57} [expr {$BASESZ + 10*$PAGESZ}]
58
dand46def72010-07-24 11:28:28 +000059
60proc lookaside {db} {
61 expr { $::lookaside_buffer_size *
62 [lindex [sqlite3_db_status $db SQLITE_DBSTATUS_LOOKASIDE_USED 0] 1]
63 }
64}
65
dan8ad169a2013-08-12 20:14:04 +000066ifcapable stat4||stat3 {
drh4e50c5e2011-08-13 19:35:19 +000067 set STAT3 1
68} else {
69 set STAT3 0
70}
71
dand46def72010-07-24 11:28:28 +000072#---------------------------------------------------------------------------
drh643f35e2010-07-26 11:59:40 +000073# Run the dbstatus-2 and dbstatus-3 tests with several of different
dand46def72010-07-24 11:28:28 +000074# lookaside buffer sizes.
75#
76foreach ::lookaside_buffer_size {0 64 120} {
drhe39cd912016-07-09 17:47:01 +000077 ifcapable malloc_usable_size break
dand46def72010-07-24 11:28:28 +000078
dan4f7b8d62010-08-06 14:37:13 +000079 # Do not run any of these tests if there is SQL configured to run
80 # as part of the [sqlite3] command. This prevents the script from
81 # configuring the size of the lookaside buffer after [sqlite3] has
82 # returned.
83 if {[presql] != ""} break
84
dand46def72010-07-24 11:28:28 +000085 #-------------------------------------------------------------------------
86 # Tests for SQLITE_DBSTATUS_SCHEMA_USED.
87 #
88 # Each test in the following block works as follows. Each test uses a
89 # different database schema.
90 #
91 # 1. Open a connection to an empty database. Disable statement caching.
92 #
93 # 2. Execute the SQL to create the database schema. Measure the total
94 # heap and lookaside memory allocated by SQLite, and the memory
95 # allocated for the database schema according to sqlite3_db_status().
96 #
97 # 3. Drop all tables in the database schema. Measure the total memory
98 # and the schema memory again.
99 #
100 # 4. Repeat step 2.
101 #
102 # 5. Repeat step 3.
103 #
104 # Then test that:
105 #
106 # a) The difference in schema memory quantities in steps 2 and 3 is the
107 # same as the difference in total memory in steps 2 and 3.
108 #
109 # b) Step 4 reports the same amount of schema and total memory used as
110 # in step 2.
111 #
112 # c) Step 5 reports the same amount of schema and total memory used as
113 # in step 3.
114 #
115 foreach {tn schema} {
116 1 { CREATE TABLE t1(a, b) }
117 2 { CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1, c UNIQUE) }
118 3 {
119 CREATE TABLE t1(a, b);
120 CREATE INDEX i1 ON t1(a, b);
121 }
122 4 {
123 CREATE TABLE t1(a, b);
124 CREATE TABLE t2(c, d);
125 CREATE TRIGGER AFTER INSERT ON t1 BEGIN
126 INSERT INTO t2 VALUES(new.a, new.b);
127 SELECT * FROM t1, t2 WHERE a=c AND b=d GROUP BY b HAVING a>5 ORDER BY a;
128 END;
129 }
130 5 {
131 CREATE TABLE t1(a, b);
132 CREATE TABLE t2(c, d);
133 CREATE VIEW v1 AS SELECT * FROM t1 UNION SELECT * FROM t2;
134 }
mistachkind55bccd2013-11-11 03:37:04 +0000135 6k {
dand46def72010-07-24 11:28:28 +0000136 CREATE TABLE t1(a, b);
137 CREATE INDEX i1 ON t1(a);
138 CREATE INDEX i2 ON t1(a,b);
139 CREATE INDEX i3 ON t1(b,b);
140 INSERT INTO t1 VALUES(randomblob(20), randomblob(25));
141 INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
142 INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
143 INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
144 ANALYZE;
145 }
146 7 {
147 CREATE TABLE t1(a, b);
148 CREATE TABLE t2(c, d);
149 CREATE VIEW v1 AS
150 SELECT * FROM t1
151 UNION
152 SELECT * FROM t2
153 UNION ALL
154 SELECT c||b, d||a FROM t2 LEFT OUTER JOIN t1 GROUP BY c, d
155 ORDER BY 1, 2
156 ;
157 CREATE TRIGGER tr1 INSTEAD OF INSERT ON v1 BEGIN
158 SELECT * FROM v1;
159 UPDATE t1 SET a=5, b=(SELECT c FROM t2);
160 END;
161 SELECT * FROM v1;
162 }
danccd4ad32010-07-26 14:47:14 +0000163 8x {
164 CREATE TABLE t1(a, b, UNIQUE(a, b));
165 CREATE VIRTUAL TABLE t2 USING echo(t1);
166 }
dand46def72010-07-24 11:28:28 +0000167 } {
168 set tn "$::lookaside_buffer_size-$tn"
169
170 # Step 1.
171 db close
mistachkinfda06be2011-08-02 00:57:34 +0000172 forcedelete test.db
dand46def72010-07-24 11:28:28 +0000173 sqlite3 db test.db
174 sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
175 db cache size 0
danccd4ad32010-07-26 14:47:14 +0000176
177 catch { register_echo_module db }
178 ifcapable !vtab { if {[string match *x $tn]} continue }
dand46def72010-07-24 11:28:28 +0000179
180 # Step 2.
181 execsql $schema
182 set nAlloc1 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
183 incr nAlloc1 [lookaside db]
184 set nSchema1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
185
186 # Step 3.
187 drop_all_tables
188 set nAlloc2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
189 incr nAlloc2 [lookaside db]
190 set nSchema2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
191
192 # Step 4.
193 execsql $schema
194 set nAlloc3 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
195 incr nAlloc3 [lookaside db]
196 set nSchema3 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
197
198 # Step 5.
199 drop_all_tables
200 set nAlloc4 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
201 incr nAlloc4 [lookaside db]
202 set nSchema4 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
dand46def72010-07-24 11:28:28 +0000203 set nFree [expr {$nAlloc1-$nAlloc2}]
danccd4ad32010-07-26 14:47:14 +0000204
mistachkind55bccd2013-11-11 03:37:04 +0000205 # Tests for which the test name ends in an "k" report slightly less
206 # memory than is actually freed when all schema items are finalized.
207 # This is because memory allocated by KeyInfo objects is no longer
208 # counted as "schema memory".
209 #
danccd4ad32010-07-26 14:47:14 +0000210 # Tests for which the test name ends in an "x" report slightly less
dand47f0d72010-08-11 11:35:50 +0000211 # memory than is actually freed when all schema items are finalized.
212 # This is because memory allocated by virtual table implementations
213 # for any reason is not counted as "schema memory".
danccd4ad32010-07-26 14:47:14 +0000214 #
dand47f0d72010-08-11 11:35:50 +0000215 # Additionally, in auto-vacuum mode, dropping tables and indexes causes
216 # the page-cache to shrink. So the amount of memory freed is always
217 # much greater than just that reported by DBSTATUS_SCHEMA_USED in this
218 # case.
219 #
danf52bb8d2013-08-03 20:24:58 +0000220 # Some of the memory used for sqlite_stat4 is unaccounted for by
drh4e50c5e2011-08-13 19:35:19 +0000221 # dbstatus.
222 #
dan4373bb82011-12-30 16:09:50 +0000223 # Finally, on osx the estimate of memory used by the schema may be
224 # slightly low.
225 #
mistachkind55bccd2013-11-11 03:37:04 +0000226 if {[string match *k $tn]
227 || [string match *x $tn] || $AUTOVACUUM
dan4373bb82011-12-30 16:09:50 +0000228 || ([string match *y $tn] && $STAT3)
229 || ($::tcl_platform(os) == "Darwin")
230 } {
danccd4ad32010-07-26 14:47:14 +0000231 do_test dbstatus-2.$tn.ax { expr {($nSchema1-$nSchema2)<=$nFree} } 1
232 } else {
233 do_test dbstatus-2.$tn.a { expr {$nSchema1-$nSchema2} } $nFree
234 }
235
dand46def72010-07-24 11:28:28 +0000236 do_test dbstatus-2.$tn.b { list $nAlloc1 $nSchema1 } "$nAlloc3 $nSchema3"
237 do_test dbstatus-2.$tn.c { list $nAlloc2 $nSchema2 } "$nAlloc4 $nSchema4"
238 }
239
240 #-------------------------------------------------------------------------
241 # Tests for SQLITE_DBSTATUS_STMT_USED.
242 #
243 # Each test in the following block works as follows. Each test uses a
244 # different database schema.
245 #
246 # 1. Open a connection to an empty database. Initialized the database
247 # schema.
248 #
249 # 2. Prepare a bunch of SQL statements. Measure the total heap and
250 # lookaside memory allocated by SQLite, and the memory allocated
251 # for the prepared statements according to sqlite3_db_status().
252 #
mistachkind55bccd2013-11-11 03:37:04 +0000253 # 3. Finalize all prepared statements. Measure the total memory
dand46def72010-07-24 11:28:28 +0000254 # and the prepared statement memory again.
255 #
256 # 4. Repeat step 2.
257 #
258 # 5. Repeat step 3.
259 #
260 # Then test that:
261 #
262 # a) The difference in schema memory quantities in steps 2 and 3 is the
263 # same as the difference in total memory in steps 2 and 3.
264 #
265 # b) Step 4 reports the same amount of schema and total memory used as
266 # in step 2.
267 #
268 # c) Step 5 reports the same amount of schema and total memory used as
269 # in step 3.
270 #
271 foreach {tn schema statements} {
272 1 { CREATE TABLE t1(a, b) } {
273 SELECT * FROM t1;
274 INSERT INTO t1 VALUES(1, 2);
275 INSERT INTO t1 SELECT * FROM t1;
276 UPDATE t1 SET a=5;
277 DELETE FROM t1;
278 }
279 2 {
280 PRAGMA recursive_triggers = 1;
281 CREATE TABLE t1(a, b);
282 CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
283 INSERT INTO t1 VALUES(new.a-1, new.b);
284 END;
285 } {
286 INSERT INTO t1 VALUES(5, 'x');
287 }
288 3 {
289 PRAGMA recursive_triggers = 1;
290 CREATE TABLE t1(a, b);
291 CREATE TABLE t2(a, b);
292 CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
293 INSERT INTO t2 VALUES(new.a-1, new.b);
294 END;
295 CREATE TRIGGER tr2 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
296 INSERT INTO t1 VALUES(new.a-1, new.b);
297 END;
298 } {
299 INSERT INTO t1 VALUES(10, 'x');
300 }
301 4 {
302 CREATE TABLE t1(a, b);
303 } {
304 SELECT count(*) FROM t1 WHERE upper(a)='ABC';
305 }
danccd4ad32010-07-26 14:47:14 +0000306 5x {
307 CREATE TABLE t1(a, b UNIQUE);
308 CREATE VIRTUAL TABLE t2 USING echo(t1);
309 } {
310 SELECT count(*) FROM t2;
311 SELECT * FROM t2 WHERE b>5;
312 SELECT * FROM t2 WHERE b='abcdefg';
313 }
dand46def72010-07-24 11:28:28 +0000314 } {
315 set tn "$::lookaside_buffer_size-$tn"
316
317 # Step 1.
318 db close
mistachkinfda06be2011-08-02 00:57:34 +0000319 forcedelete test.db
dand46def72010-07-24 11:28:28 +0000320 sqlite3 db test.db
321 sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
322 db cache size 1000
danccd4ad32010-07-26 14:47:14 +0000323
324 catch { register_echo_module db }
325 ifcapable !vtab { if {[string match *x $tn]} continue }
dand46def72010-07-24 11:28:28 +0000326
327 execsql $schema
328 db cache flush
329
330 # Step 2.
331 execsql $statements
332 set nAlloc1 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
333 incr nAlloc1 [lookaside db]
334 set nStmt1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
335 execsql $statements
336
337 # Step 3.
338 db cache flush
339 set nAlloc2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
dan111becf2010-07-26 15:57:01 +0000340 incr nAlloc2 [lookaside db]
dand46def72010-07-24 11:28:28 +0000341 set nStmt2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
342
343 # Step 3.
344 execsql $statements
345 set nAlloc3 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
346 incr nAlloc3 [lookaside db]
347 set nStmt3 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
348 execsql $statements
349
350 # Step 4.
351 db cache flush
352 set nAlloc4 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
353 incr nAlloc4 [lookaside db]
354 set nStmt4 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
355
356 set nFree [expr {$nAlloc1-$nAlloc2}]
danccd4ad32010-07-26 14:47:14 +0000357
358 do_test dbstatus-3.$tn.a { expr $nStmt2 } {0}
359
360 # Tests for which the test name ends in an "x" report slightly less
361 # memory than is actually freed when all statements are finalized.
362 # This is because a small amount of memory allocated by a virtual table
363 # implementation using sqlite3_mprintf() is technically considered
364 # external and so is not counted as "statement memory".
365 #
dand47f0d72010-08-11 11:35:50 +0000366#puts "$nStmt1 $nFree"
danccd4ad32010-07-26 14:47:14 +0000367 if {[string match *x $tn]} {
368 do_test dbstatus-3.$tn.bx { expr $nStmt1<=$nFree } {1}
369 } else {
370 do_test dbstatus-3.$tn.b { expr $nStmt1==$nFree } {1}
371 }
372
dand46def72010-07-24 11:28:28 +0000373 do_test dbstatus-3.$tn.c { list $nAlloc1 $nStmt1 } [list $nAlloc3 $nStmt3]
374 do_test dbstatus-3.$tn.d { list $nAlloc2 $nStmt2 } [list $nAlloc4 $nStmt4]
375 }
376}
377
dan272989b2016-07-06 10:12:02 +0000378#-------------------------------------------------------------------------
dan9c106082016-07-06 18:12:54 +0000379# The following tests focus on DBSTATUS_CACHE_USED_SHARED
dan272989b2016-07-06 10:12:02 +0000380#
381ifcapable shared_cache {
drh2aed9792016-07-25 12:10:25 +0000382 if {[permutation]=="memsys3"
383 || [permutation]=="memsys5"
drh01725682016-07-25 14:20:01 +0000384 || $::tcl_platform(os)=="Linux"} {
drh2aed9792016-07-25 12:10:25 +0000385 proc do_cacheused_test {tn db res} {
386 set cu [sqlite3_db_status $db SQLITE_DBSTATUS_CACHE_USED 0]
387 set pcu [sqlite3_db_status $db SQLITE_DBSTATUS_CACHE_USED_SHARED 0]
388 set cu [lindex $cu 1]
389 set pcu [lindex $pcu 1]
390 uplevel [list do_test $tn [list list $cu $pcu] "#/$res/"]
391 }
392 reset_db
393 sqlite3 db file:test.db?cache=shared
394
395 do_execsql_test 4.0 {
396 PRAGMA auto_vacuum=NONE;
397 CREATE TABLE t1(a, b, c);
398 INSERT INTO t1 VALUES(1, 2, 3);
399 }
400 do_cacheused_test 4.0.1 db { 4568 4568 }
401 do_execsql_test 4.1 {
402 CREATE TEMP TABLE tt(a, b, c);
403 INSERT INTO tt VALUES(1, 2, 3);
404 }
405 do_cacheused_test 4.1.1 db { 9000 9000 }
406
407 sqlite3 db2 file:test.db?cache=shared
408 do_cacheused_test 4.2.1 db2 { 4568 2284 }
409 do_cacheused_test 4.2.2 db { 9000 6716 }
410 db close
411 do_cacheused_test 4.2.3 db2 { 4568 4568 }
412 sqlite3 db file:test.db?cache=shared
413 do_cacheused_test 4.2.4 db2 { 4568 2284 }
414 db2 close
dan272989b2016-07-06 10:12:02 +0000415 }
dan272989b2016-07-06 10:12:02 +0000416}
417
dan68cf69e2018-03-14 08:27:39 +0000418#-------------------------------------------------------------------------
419# Test that passing an out-of-range value to sqlite3_stmt_status does
420# not cause a crash.
421reset_db
422do_execsql_test 5.0 {
423 CREATE TABLE t1(x, y);
424 INSERT INTO t1 VALUES(1, 2);
425 INSERT INTO t1 VALUES(3, 4);
426}
427
428do_test 5.1 {
429 set ::stmt [sqlite3_prepare db "SELECT * FROM t1" -1 dummy]
430 sqlite3_step $::stmt
431 sqlite3_step $::stmt
432 sqlite3_step $::stmt
433 sqlite3_reset $::stmt
434} {SQLITE_OK}
435
drh15ca9e32018-03-14 15:06:42 +0000436ifcapable api_armor {
437 do_test 5.2 { sqlite3_stmt_status $::stmt -1 0 } 0
438}
439do_test 5.3 { sqlite3_stmt_status $::stmt 0 0 } 0
dan68cf69e2018-03-14 08:27:39 +0000440do_test 5.4 {
441 expr [sqlite3_stmt_status $::stmt 99 0]>0
442} 1
443foreach {tn id res} {
444 1 SQLITE_STMTSTATUS_MEMUSED 1
445 2 SQLITE_STMTSTATUS_FULLSCAN_STEP 1
446 3 SQLITE_STMTSTATUS_SORT 0
447 4 SQLITE_STMTSTATUS_AUTOINDEX 0
448 5 SQLITE_STMTSTATUS_VM_STEP 1
449 6 SQLITE_STMTSTATUS_REPREPARE 0
450 7 SQLITE_STMTSTATUS_RUN 1
451} {
452if {$tn==2} breakpoint
453 do_test 5.5.$tn { expr [sqlite3_stmt_status $::stmt $id 0]>0 } $res
454}
455
456sqlite3_finalize $::stmt
drh63da0892010-03-10 21:42:07 +0000457finish_test