OLD | NEW |
(Empty) | |
| 1 # 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 |
| 15 set testdir [file dirname $argv0] |
| 16 source $testdir/tester.tcl |
| 17 set testprefix dbstatus |
| 18 |
| 19 ifcapable !compound { |
| 20 finish_test |
| 21 return |
| 22 } |
| 23 |
| 24 # Memory statistics must be enabled for this test. |
| 25 db close |
| 26 sqlite3_shutdown |
| 27 sqlite3_config_memstatus 1 |
| 28 sqlite3_config_uri 1 |
| 29 sqlite3_initialize |
| 30 sqlite3 db test.db |
| 31 |
| 32 |
| 33 # Make sure sqlite3_db_config() and sqlite3_db_status are working. |
| 34 # |
| 35 unset -nocomplain PAGESZ |
| 36 unset -nocomplain BASESZ |
| 37 do_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}] |
| 50 expr {$::PAGESZ>1024 && $::PAGESZ<1300} |
| 51 } {1} |
| 52 do_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 |
| 59 |
| 60 proc lookaside {db} { |
| 61 expr { $::lookaside_buffer_size * |
| 62 [lindex [sqlite3_db_status $db SQLITE_DBSTATUS_LOOKASIDE_USED 0] 1] |
| 63 } |
| 64 } |
| 65 |
| 66 ifcapable stat4||stat3 { |
| 67 set STAT3 1 |
| 68 } else { |
| 69 set STAT3 0 |
| 70 } |
| 71 |
| 72 #--------------------------------------------------------------------------- |
| 73 # Run the dbstatus-2 and dbstatus-3 tests with several of different |
| 74 # lookaside buffer sizes. |
| 75 # |
| 76 foreach ::lookaside_buffer_size {0 64 120} { |
| 77 ifcapable malloc_usable_size break |
| 78 |
| 79 # 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 |
| 85 #------------------------------------------------------------------------- |
| 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 } |
| 135 6k { |
| 136 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 } |
| 163 8x { |
| 164 CREATE TABLE t1(a, b, UNIQUE(a, b)); |
| 165 CREATE VIRTUAL TABLE t2 USING echo(t1); |
| 166 } |
| 167 } { |
| 168 set tn "$::lookaside_buffer_size-$tn" |
| 169 |
| 170 # Step 1. |
| 171 db close |
| 172 forcedelete test.db |
| 173 sqlite3 db test.db |
| 174 sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500 |
| 175 db cache size 0 |
| 176 |
| 177 catch { register_echo_module db } |
| 178 ifcapable !vtab { if {[string match *x $tn]} continue } |
| 179 |
| 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] |
| 203 set nFree [expr {$nAlloc1-$nAlloc2}] |
| 204 |
| 205 # 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 # |
| 210 # Tests for which the test name ends in an "x" report slightly less |
| 211 # 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". |
| 214 # |
| 215 # 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 # |
| 220 # Some of the memory used for sqlite_stat4 is unaccounted for by |
| 221 # dbstatus. |
| 222 # |
| 223 # Finally, on osx the estimate of memory used by the schema may be |
| 224 # slightly low. |
| 225 # |
| 226 if {[string match *k $tn] |
| 227 || [string match *x $tn] || $AUTOVACUUM |
| 228 || ([string match *y $tn] && $STAT3) |
| 229 || ($::tcl_platform(os) == "Darwin") |
| 230 } { |
| 231 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 |
| 236 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 # |
| 253 # 3. Finalize all prepared statements. Measure the total memory |
| 254 # 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 } |
| 306 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 } |
| 314 } { |
| 315 set tn "$::lookaside_buffer_size-$tn" |
| 316 |
| 317 # Step 1. |
| 318 db close |
| 319 forcedelete test.db |
| 320 sqlite3 db test.db |
| 321 sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500 |
| 322 db cache size 1000 |
| 323 |
| 324 catch { register_echo_module db } |
| 325 ifcapable !vtab { if {[string match *x $tn]} continue } |
| 326 |
| 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] |
| 340 incr nAlloc2 [lookaside db] |
| 341 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}] |
| 357 |
| 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 # |
| 366 #puts "$nStmt1 $nFree" |
| 367 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 |
| 373 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 |
| 378 #------------------------------------------------------------------------- |
| 379 # The following tests focus on DBSTATUS_CACHE_USED_SHARED |
| 380 # |
| 381 ifcapable shared_cache { |
| 382 if {[permutation]=="memsys3" |
| 383 || [permutation]=="memsys5" |
| 384 || $::tcl_platform(os)=="Linux"} { |
| 385 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 |
| 415 } |
| 416 } |
| 417 |
| 418 finish_test |
OLD | NEW |