Annotation of embedaddon/sqlite3/test/dbstatus.test, revision 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>