Annotation of embedaddon/sqlite3/test/dbstatus.test, revision 1.1.1.1

1.1       misho       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: 
                     18: # Memory statistics must be enabled for this test.
                     19: db close
                     20: sqlite3_shutdown
                     21: sqlite3_config_memstatus 1
                     22: sqlite3_initialize
                     23: sqlite3 db test.db
                     24: 
                     25: 
                     26: # Make sure sqlite3_db_config() and sqlite3_db_status are working.
                     27: #
                     28: unset -nocomplain PAGESZ
                     29: unset -nocomplain BASESZ
                     30: do_test dbstatus-1.1 {
                     31:   db close
                     32:   sqlite3 db :memory:
                     33:   db eval {
                     34:     CREATE TABLE t1(x);
                     35:   }
                     36:   set sz1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1]
                     37:   db eval {
                     38:     CREATE TABLE t2(y);
                     39:   }
                     40:   set sz2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1]
                     41:   set ::PAGESZ [expr {$sz2-$sz1}]
                     42:   set ::BASESZ [expr {$sz1-$::PAGESZ}]
                     43:   expr {$::PAGESZ>1024 && $::PAGESZ<1300}
                     44: } {1}
                     45: do_test dbstatus-1.2 {
                     46:   db eval {
                     47:     INSERT INTO t1 VALUES(zeroblob(9000));
                     48:   }
                     49:   lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1
                     50: } [expr {$BASESZ + 10*$PAGESZ}]
                     51: 
                     52: 
                     53: proc lookaside {db} {
                     54:   expr { $::lookaside_buffer_size *
                     55:     [lindex [sqlite3_db_status $db SQLITE_DBSTATUS_LOOKASIDE_USED 0] 1]
                     56:   }
                     57: }
                     58: 
                     59: ifcapable stat3 {
                     60:   set STAT3 1
                     61: } else {
                     62:   set STAT3 0
                     63: }
                     64: 
                     65: ifcapable malloc_usable_size {
                     66:   finish_test
                     67:   return
                     68: }
                     69: 
                     70: #---------------------------------------------------------------------------
                     71: # Run the dbstatus-2 and dbstatus-3 tests with several of different
                     72: # lookaside buffer sizes.
                     73: #
                     74: foreach ::lookaside_buffer_size {0 64 120} {
                     75: 
                     76:   # Do not run any of these tests if there is SQL configured to run
                     77:   # as part of the [sqlite3] command. This prevents the script from
                     78:   # configuring the size of the lookaside buffer after [sqlite3] has
                     79:   # returned.
                     80:   if {[presql] != ""} break
                     81: 
                     82:   #-------------------------------------------------------------------------
                     83:   # Tests for SQLITE_DBSTATUS_SCHEMA_USED.
                     84:   #
                     85:   # Each test in the following block works as follows. Each test uses a
                     86:   # different database schema.
                     87:   #
                     88:   #   1. Open a connection to an empty database. Disable statement caching.
                     89:   #
                     90:   #   2. Execute the SQL to create the database schema. Measure the total 
                     91:   #      heap and lookaside memory allocated by SQLite, and the memory 
                     92:   #      allocated for the database schema according to sqlite3_db_status().
                     93:   #
                     94:   #   3. Drop all tables in the database schema. Measure the total memory 
                     95:   #      and the schema memory again.
                     96:   #
                     97:   #   4. Repeat step 2.
                     98:   #
                     99:   #   5. Repeat step 3.
                    100:   #
                    101:   # Then test that:
                    102:   #
                    103:   #   a) The difference in schema memory quantities in steps 2 and 3 is the
                    104:   #      same as the difference in total memory in steps 2 and 3.
                    105:   #
                    106:   #   b) Step 4 reports the same amount of schema and total memory used as
                    107:   #      in step 2.
                    108:   #
                    109:   #   c) Step 5 reports the same amount of schema and total memory used as
                    110:   #      in step 3.
                    111:   #
                    112:   foreach {tn schema} { 
                    113:     1 { CREATE TABLE t1(a, b) }
                    114:     2 { CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1, c UNIQUE) }
                    115:     3 {
                    116:       CREATE TABLE t1(a, b);
                    117:       CREATE INDEX i1 ON t1(a, b);
                    118:     }
                    119:     4 {
                    120:       CREATE TABLE t1(a, b);
                    121:       CREATE TABLE t2(c, d);
                    122:       CREATE TRIGGER AFTER INSERT ON t1 BEGIN
                    123:         INSERT INTO t2 VALUES(new.a, new.b);
                    124:         SELECT * FROM t1, t2 WHERE a=c AND b=d GROUP BY b HAVING a>5 ORDER BY a;
                    125:       END;
                    126:     }
                    127:     5 {
                    128:       CREATE TABLE t1(a, b);
                    129:       CREATE TABLE t2(c, d);
                    130:       CREATE VIEW v1 AS SELECT * FROM t1 UNION SELECT * FROM t2;
                    131:     }
                    132:     6y {
                    133:       CREATE TABLE t1(a, b);
                    134:       CREATE INDEX i1 ON t1(a);
                    135:       CREATE INDEX i2 ON t1(a,b);
                    136:       CREATE INDEX i3 ON t1(b,b);
                    137:       INSERT INTO t1 VALUES(randomblob(20), randomblob(25));
                    138:       INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
                    139:       INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
                    140:       INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
                    141:       ANALYZE;
                    142:     }
                    143:     7 {
                    144:       CREATE TABLE t1(a, b);
                    145:       CREATE TABLE t2(c, d);
                    146:       CREATE VIEW v1 AS 
                    147:         SELECT * FROM t1 
                    148:         UNION 
                    149:         SELECT * FROM t2
                    150:         UNION ALL
                    151:         SELECT c||b, d||a FROM t2 LEFT OUTER JOIN t1 GROUP BY c, d
                    152:         ORDER BY 1, 2
                    153:       ;
                    154:       CREATE TRIGGER tr1 INSTEAD OF INSERT ON v1 BEGIN
                    155:         SELECT * FROM v1;
                    156:         UPDATE t1 SET a=5, b=(SELECT c FROM t2);
                    157:       END;
                    158:       SELECT * FROM v1;
                    159:     }
                    160:     8x {
                    161:       CREATE TABLE t1(a, b, UNIQUE(a, b));
                    162:       CREATE VIRTUAL TABLE t2 USING echo(t1);
                    163:     }
                    164:   } {
                    165:     set tn "$::lookaside_buffer_size-$tn"
                    166:   
                    167:     # Step 1.
                    168:     db close
                    169:     forcedelete test.db
                    170:     sqlite3 db test.db
                    171:     sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
                    172:     db cache size 0
                    173: 
                    174:     catch { register_echo_module db }
                    175:     ifcapable !vtab { if {[string match *x $tn]} continue }
                    176:   
                    177:     # Step 2.
                    178:     execsql $schema
                    179:     set nAlloc1  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
                    180:     incr nAlloc1 [lookaside db]
                    181:     set nSchema1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
                    182:   
                    183:     # Step 3.
                    184:     drop_all_tables
                    185:     set nAlloc2  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
                    186:     incr nAlloc2 [lookaside db]
                    187:     set nSchema2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
                    188:   
                    189:     # Step 4.
                    190:     execsql $schema
                    191:     set nAlloc3  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
                    192:     incr nAlloc3 [lookaside db]
                    193:     set nSchema3 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
                    194:     
                    195:     # Step 5.
                    196:     drop_all_tables
                    197:     set nAlloc4  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
                    198:     incr nAlloc4 [lookaside db]
                    199:     set nSchema4 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
                    200:     set nFree [expr {$nAlloc1-$nAlloc2}]
                    201:     
                    202:     # Tests for which the test name ends in an "x" report slightly less
                    203:     # memory than is actually freed when all schema items are finalized.
                    204:     # This is because memory allocated by virtual table implementations
                    205:     # for any reason is not counted as "schema memory".
                    206:     #
                    207:     # Additionally, in auto-vacuum mode, dropping tables and indexes causes
                    208:     # the page-cache to shrink. So the amount of memory freed is always
                    209:     # much greater than just that reported by DBSTATUS_SCHEMA_USED in this
                    210:     # case.
                    211:     #
                    212:     # Some of the memory used for sqlite_stat3 is unaccounted for by
                    213:     # dbstatus.
                    214:     #
                    215:     # Finally, on osx the estimate of memory used by the schema may be
                    216:     # slightly low. 
                    217:     #
                    218:     if {[string match *x $tn] || $AUTOVACUUM
                    219:          || ([string match *y $tn] && $STAT3)
                    220:          || ($::tcl_platform(os) == "Darwin")
                    221:     } {
                    222:       do_test dbstatus-2.$tn.ax { expr {($nSchema1-$nSchema2)<=$nFree} } 1
                    223:     } else {
                    224:       do_test dbstatus-2.$tn.a { expr {$nSchema1-$nSchema2} } $nFree
                    225:     }
                    226:   
                    227:     do_test dbstatus-2.$tn.b { list $nAlloc1 $nSchema1 } "$nAlloc3 $nSchema3"
                    228:     do_test dbstatus-2.$tn.c { list $nAlloc2 $nSchema2 } "$nAlloc4 $nSchema4"
                    229:   }
                    230:   
                    231:   #-------------------------------------------------------------------------
                    232:   # Tests for SQLITE_DBSTATUS_STMT_USED.
                    233:   #
                    234:   # Each test in the following block works as follows. Each test uses a
                    235:   # different database schema.
                    236:   #
                    237:   #   1. Open a connection to an empty database. Initialized the database
                    238:   #      schema.
                    239:   #
                    240:   #   2. Prepare a bunch of SQL statements. Measure the total heap and 
                    241:   #      lookaside memory allocated by SQLite, and the memory allocated 
                    242:   #      for the prepared statements according to sqlite3_db_status().
                    243:   #
                    244:   #   3. Finalize all prepared statements Measure the total memory 
                    245:   #      and the prepared statement memory again.
                    246:   #
                    247:   #   4. Repeat step 2.
                    248:   #
                    249:   #   5. Repeat step 3.
                    250:   #
                    251:   # Then test that:
                    252:   #
                    253:   #   a) The difference in schema memory quantities in steps 2 and 3 is the
                    254:   #      same as the difference in total memory in steps 2 and 3.
                    255:   #
                    256:   #   b) Step 4 reports the same amount of schema and total memory used as
                    257:   #      in step 2.
                    258:   #
                    259:   #   c) Step 5 reports the same amount of schema and total memory used as
                    260:   #      in step 3.
                    261:   #
                    262:   foreach {tn schema statements} { 
                    263:     1 { CREATE TABLE t1(a, b) } {
                    264:       SELECT * FROM t1;
                    265:       INSERT INTO t1 VALUES(1, 2);
                    266:       INSERT INTO t1 SELECT * FROM t1;
                    267:       UPDATE t1 SET a=5;
                    268:       DELETE FROM t1;
                    269:     }
                    270:     2 {
                    271:       PRAGMA recursive_triggers = 1;
                    272:       CREATE TABLE t1(a, b);
                    273:       CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
                    274:         INSERT INTO t1 VALUES(new.a-1, new.b);
                    275:       END;
                    276:     } {
                    277:       INSERT INTO t1 VALUES(5, 'x');
                    278:     } 
                    279:     3 {
                    280:       PRAGMA recursive_triggers = 1;
                    281:       CREATE TABLE t1(a, b);
                    282:       CREATE TABLE t2(a, b);
                    283:       CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
                    284:         INSERT INTO t2 VALUES(new.a-1, new.b);
                    285:       END;
                    286:       CREATE TRIGGER tr2 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
                    287:         INSERT INTO t1 VALUES(new.a-1, new.b);
                    288:       END;
                    289:     } {
                    290:       INSERT INTO t1 VALUES(10, 'x');
                    291:     } 
                    292:     4 {
                    293:       CREATE TABLE t1(a, b);
                    294:     } {
                    295:       SELECT count(*) FROM t1 WHERE upper(a)='ABC';
                    296:     }
                    297:     5x {
                    298:       CREATE TABLE t1(a, b UNIQUE);
                    299:       CREATE VIRTUAL TABLE t2 USING echo(t1);
                    300:     } {
                    301:       SELECT count(*) FROM t2;
                    302:       SELECT * FROM t2 WHERE b>5;
                    303:       SELECT * FROM t2 WHERE b='abcdefg';
                    304:     }
                    305:   } {
                    306:     set tn "$::lookaside_buffer_size-$tn"
                    307: 
                    308:     # Step 1.
                    309:     db close
                    310:     forcedelete test.db
                    311:     sqlite3 db test.db
                    312:     sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
                    313:     db cache size 1000
                    314: 
                    315:     catch { register_echo_module db }
                    316:     ifcapable !vtab { if {[string match *x $tn]} continue }
                    317:   
                    318:     execsql $schema
                    319:     db cache flush
                    320:   
                    321:     # Step 2.
                    322:     execsql $statements
                    323:     set nAlloc1  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
                    324:     incr nAlloc1 [lookaside db]
                    325:     set nStmt1   [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
                    326:     execsql $statements
                    327:   
                    328:     # Step 3.
                    329:     db cache flush
                    330:     set nAlloc2  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
                    331:     incr nAlloc2 [lookaside db]
                    332:     set nStmt2   [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
                    333:     
                    334:     # Step 3.
                    335:     execsql $statements
                    336:     set nAlloc3  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
                    337:     incr nAlloc3 [lookaside db]
                    338:     set nStmt3   [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
                    339:     execsql $statements
                    340:   
                    341:     # Step 4.
                    342:     db cache flush
                    343:     set nAlloc4  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
                    344:     incr nAlloc4 [lookaside db]
                    345:     set nStmt4 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
                    346:   
                    347:     set nFree [expr {$nAlloc1-$nAlloc2}]
                    348: 
                    349:     do_test dbstatus-3.$tn.a { expr $nStmt2 } {0}
                    350: 
                    351:     # Tests for which the test name ends in an "x" report slightly less
                    352:     # memory than is actually freed when all statements are finalized.
                    353:     # This is because a small amount of memory allocated by a virtual table
                    354:     # implementation using sqlite3_mprintf() is technically considered
                    355:     # external and so is not counted as "statement memory".
                    356:     #
                    357: #puts "$nStmt1 $nFree"
                    358:     if {[string match *x $tn]} {
                    359:       do_test dbstatus-3.$tn.bx { expr $nStmt1<=$nFree }  {1}
                    360:     } else {
                    361:       do_test dbstatus-3.$tn.b { expr $nStmt1==$nFree } {1}
                    362:     }
                    363: 
                    364:     do_test dbstatus-3.$tn.c { list $nAlloc1 $nStmt1 } [list $nAlloc3 $nStmt3]
                    365:     do_test dbstatus-3.$tn.d { list $nAlloc2 $nStmt2 } [list $nAlloc4 $nStmt4]
                    366:   }
                    367: }
                    368: 
                    369: finish_test

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>