1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 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
|
# 2010 March 10
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Tests for the sqlite3_db_status() function
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Memory statistics must be enabled for this test.
db close
sqlite3_shutdown
sqlite3_config_memstatus 1
sqlite3_initialize
sqlite3 db test.db
# Make sure sqlite3_db_config() and sqlite3_db_status are working.
#
unset -nocomplain PAGESZ
unset -nocomplain BASESZ
do_test dbstatus-1.1 {
db close
sqlite3 db :memory:
db eval {
CREATE TABLE t1(x);
}
set sz1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1]
db eval {
CREATE TABLE t2(y);
}
set sz2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1]
set ::PAGESZ [expr {$sz2-$sz1}]
set ::BASESZ [expr {$sz1-$::PAGESZ}]
expr {$::PAGESZ>1024 && $::PAGESZ<1300}
} {1}
do_test dbstatus-1.2 {
db eval {
INSERT INTO t1 VALUES(zeroblob(9000));
}
lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1
} [expr {$BASESZ + 10*$PAGESZ}]
proc lookaside {db} {
expr { $::lookaside_buffer_size *
[lindex [sqlite3_db_status $db SQLITE_DBSTATUS_LOOKASIDE_USED 0] 1]
}
}
#---------------------------------------------------------------------------
# Run the dbstatus-2 and dbstatus-3 tests with several of different
# lookaside buffer sizes.
#
foreach ::lookaside_buffer_size {0 64 120} {
# Do not run any of these tests if there is SQL configured to run
# as part of the [sqlite3] command. This prevents the script from
# configuring the size of the lookaside buffer after [sqlite3] has
# returned.
if {[presql] != ""} break
#-------------------------------------------------------------------------
# Tests for SQLITE_DBSTATUS_SCHEMA_USED.
#
# Each test in the following block works as follows. Each test uses a
# different database schema.
#
# 1. Open a connection to an empty database. Disable statement caching.
#
# 2. Execute the SQL to create the database schema. Measure the total
# heap and lookaside memory allocated by SQLite, and the memory
# allocated for the database schema according to sqlite3_db_status().
#
# 3. Drop all tables in the database schema. Measure the total memory
# and the schema memory again.
#
# 4. Repeat step 2.
#
# 5. Repeat step 3.
#
# Then test that:
#
# a) The difference in schema memory quantities in steps 2 and 3 is the
# same as the difference in total memory in steps 2 and 3.
#
# b) Step 4 reports the same amount of schema and total memory used as
# in step 2.
#
# c) Step 5 reports the same amount of schema and total memory used as
# in step 3.
#
foreach {tn schema} {
1 { CREATE TABLE t1(a, b) }
2 { CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1, c UNIQUE) }
3 {
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(a, b);
}
4 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(c, d);
CREATE TRIGGER AFTER INSERT ON t1 BEGIN
INSERT INTO t2 VALUES(new.a, new.b);
SELECT * FROM t1, t2 WHERE a=c AND b=d GROUP BY b HAVING a>5 ORDER BY a;
END;
}
5 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(c, d);
CREATE VIEW v1 AS SELECT * FROM t1 UNION SELECT * FROM t2;
}
6 {
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(a);
CREATE INDEX i2 ON t1(a,b);
CREATE INDEX i3 ON t1(b,b);
INSERT INTO t1 VALUES(randomblob(20), randomblob(25));
INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
ANALYZE;
}
7 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(c, d);
CREATE VIEW v1 AS
SELECT * FROM t1
UNION
SELECT * FROM t2
UNION ALL
SELECT c||b, d||a FROM t2 LEFT OUTER JOIN t1 GROUP BY c, d
ORDER BY 1, 2
;
CREATE TRIGGER tr1 INSTEAD OF INSERT ON v1 BEGIN
SELECT * FROM v1;
UPDATE t1 SET a=5, b=(SELECT c FROM t2);
END;
SELECT * FROM v1;
}
8x {
CREATE TABLE t1(a, b, UNIQUE(a, b));
CREATE VIRTUAL TABLE t2 USING echo(t1);
}
} {
set tn "$::lookaside_buffer_size-$tn"
# Step 1.
db close
file delete -force test.db
sqlite3 db test.db
sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
db cache size 0
catch { register_echo_module db }
ifcapable !vtab { if {[string match *x $tn]} continue }
# Step 2.
execsql $schema
set nAlloc1 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc1 [lookaside db]
set nSchema1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
# Step 3.
drop_all_tables
set nAlloc2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc2 [lookaside db]
set nSchema2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
# Step 4.
execsql $schema
set nAlloc3 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc3 [lookaside db]
set nSchema3 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
# Step 5.
drop_all_tables
set nAlloc4 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc4 [lookaside db]
set nSchema4 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
set nFree [expr {$nAlloc1-$nAlloc2}]
# Tests for which the test name ends in an "x" report slightly less
# memory than is actually freed when all schema items are finalized.
# This is because memory allocated by virtual table implementations
# for any reason is not counted as "schema memory".
#
# Additionally, in auto-vacuum mode, dropping tables and indexes causes
# the page-cache to shrink. So the amount of memory freed is always
# much greater than just that reported by DBSTATUS_SCHEMA_USED in this
# case.
#
if {[string match *x $tn] || $AUTOVACUUM} {
do_test dbstatus-2.$tn.ax { expr {($nSchema1-$nSchema2)<=$nFree} } 1
} else {
do_test dbstatus-2.$tn.a { expr {$nSchema1-$nSchema2} } $nFree
}
do_test dbstatus-2.$tn.b { list $nAlloc1 $nSchema1 } "$nAlloc3 $nSchema3"
do_test dbstatus-2.$tn.c { list $nAlloc2 $nSchema2 } "$nAlloc4 $nSchema4"
}
#-------------------------------------------------------------------------
# Tests for SQLITE_DBSTATUS_STMT_USED.
#
# Each test in the following block works as follows. Each test uses a
# different database schema.
#
# 1. Open a connection to an empty database. Initialized the database
# schema.
#
# 2. Prepare a bunch of SQL statements. Measure the total heap and
# lookaside memory allocated by SQLite, and the memory allocated
# for the prepared statements according to sqlite3_db_status().
#
# 3. Finalize all prepared statements Measure the total memory
# and the prepared statement memory again.
#
# 4. Repeat step 2.
#
# 5. Repeat step 3.
#
# Then test that:
#
# a) The difference in schema memory quantities in steps 2 and 3 is the
# same as the difference in total memory in steps 2 and 3.
#
# b) Step 4 reports the same amount of schema and total memory used as
# in step 2.
#
# c) Step 5 reports the same amount of schema and total memory used as
# in step 3.
#
foreach {tn schema statements} {
1 { CREATE TABLE t1(a, b) } {
SELECT * FROM t1;
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 SELECT * FROM t1;
UPDATE t1 SET a=5;
DELETE FROM t1;
}
2 {
PRAGMA recursive_triggers = 1;
CREATE TABLE t1(a, b);
CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
INSERT INTO t1 VALUES(new.a-1, new.b);
END;
} {
INSERT INTO t1 VALUES(5, 'x');
}
3 {
PRAGMA recursive_triggers = 1;
CREATE TABLE t1(a, b);
CREATE TABLE t2(a, b);
CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
INSERT INTO t2 VALUES(new.a-1, new.b);
END;
CREATE TRIGGER tr2 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
INSERT INTO t1 VALUES(new.a-1, new.b);
END;
} {
INSERT INTO t1 VALUES(10, 'x');
}
4 {
CREATE TABLE t1(a, b);
} {
SELECT count(*) FROM t1 WHERE upper(a)='ABC';
}
5x {
CREATE TABLE t1(a, b UNIQUE);
CREATE VIRTUAL TABLE t2 USING echo(t1);
} {
SELECT count(*) FROM t2;
SELECT * FROM t2 WHERE b>5;
SELECT * FROM t2 WHERE b='abcdefg';
}
} {
set tn "$::lookaside_buffer_size-$tn"
# Step 1.
db close
file delete -force test.db
sqlite3 db test.db
sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
db cache size 1000
catch { register_echo_module db }
ifcapable !vtab { if {[string match *x $tn]} continue }
execsql $schema
db cache flush
# Step 2.
execsql $statements
set nAlloc1 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc1 [lookaside db]
set nStmt1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
execsql $statements
# Step 3.
db cache flush
set nAlloc2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc2 [lookaside db]
set nStmt2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
# Step 3.
execsql $statements
set nAlloc3 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc3 [lookaside db]
set nStmt3 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
execsql $statements
# Step 4.
db cache flush
set nAlloc4 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc4 [lookaside db]
set nStmt4 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
set nFree [expr {$nAlloc1-$nAlloc2}]
do_test dbstatus-3.$tn.a { expr $nStmt2 } {0}
# Tests for which the test name ends in an "x" report slightly less
# memory than is actually freed when all statements are finalized.
# This is because a small amount of memory allocated by a virtual table
# implementation using sqlite3_mprintf() is technically considered
# external and so is not counted as "statement memory".
#
#puts "$nStmt1 $nFree"
if {[string match *x $tn]} {
do_test dbstatus-3.$tn.bx { expr $nStmt1<=$nFree } {1}
} else {
do_test dbstatus-3.$tn.b { expr $nStmt1==$nFree } {1}
}
do_test dbstatus-3.$tn.c { list $nAlloc1 $nStmt1 } [list $nAlloc3 $nStmt3]
do_test dbstatus-3.$tn.d { list $nAlloc2 $nStmt2 } [list $nAlloc4 $nStmt4]
}
}
finish_test
|