CoolFace
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
dbstatus.test458 linesDownload Raw Back to test
1# 2010 March 102#3# The author disclaims copyright to this source code.  In place of4# 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() function13#14 15set testdir [file dirname $argv0]16source $testdir/tester.tcl17set testprefix dbstatus18 19ifcapable !compound {20  finish_test21  return22}23 24# Memory statistics must be enabled for this test.25db close26sqlite3_shutdown27sqlite3_config_memstatus 128sqlite3_config_uri 129sqlite3_initialize30sqlite3 db test.db31 32 33# Make sure sqlite3_db_config() and sqlite3_db_status are working.34#35unset -nocomplain PAGESZ36unset -nocomplain BASESZ37do_test dbstatus-1.1 {38  db close39  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}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] 157} [expr {$BASESZ + 10*$PAGESZ}]58 59 60proc lookaside {db} {61  expr { $::lookaside_buffer_size *62    [lindex [sqlite3_db_status $db SQLITE_DBSTATUS_LOOKASIDE_USED 0] 1]63  }64}65 66ifcapable stat4 {67  set STAT3 168} else {69  set STAT3 070}71 72#---------------------------------------------------------------------------73# Run the dbstatus-2 and dbstatus-3 tests with several of different74# lookaside buffer sizes.75#76foreach ::lookaside_buffer_size {0 64 120} {77  ifcapable malloc_usable_size break78 79  # Do not run any of these tests if there is SQL configured to run80  # as part of the [sqlite3] command. This prevents the script from81  # configuring the size of the lookaside buffer after [sqlite3] has82  # returned.83  if {[presql] != ""} break84 85  #-------------------------------------------------------------------------86  # Tests for SQLITE_DBSTATUS_SCHEMA_USED.87  #88  # Each test in the following block works as follows. Each test uses a89  # 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 the107  #      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 as110  #      in step 2.111  #112  #   c) Step 5 reports the same amount of schema and total memory used as113  #      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 BEGIN126        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 t2153        UNION ALL154        SELECT c||b, d||a FROM t2 LEFT OUTER JOIN t1 GROUP BY c, d155        ORDER BY 1, 2156      ;157      CREATE TRIGGER tr1 INSTEAD OF INSERT ON v1 BEGIN158        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 close172    forcedelete test.db173    sqlite3 db test.db174    sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500175    db cache size 0176 177    catch { register_echo_module db }178    ifcapable !vtab { if {[string match *x $tn]} continue }179  180    # Step 2.181    execsql $schema182    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_tables188    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 $schema194    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_tables200    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 less206    # memory than is actually freed when all schema items are finalized.207    # This is because memory allocated by KeyInfo objects is no longer208    # counted as "schema memory".209    #210    # Tests for which the test name ends in an "x" report slightly less211    # memory than is actually freed when all schema items are finalized.212    # This is because memory allocated by virtual table implementations213    # for any reason is not counted as "schema memory".214    #215    # Additionally, in auto-vacuum mode, dropping tables and indexes causes216    # the page-cache to shrink. So the amount of memory freed is always217    # much greater than just that reported by DBSTATUS_SCHEMA_USED in this218    # case.219    #220    # Some of the memory used for sqlite_stat4 is unaccounted for by221    # dbstatus.222    #223    # Finally, on osx the estimate of memory used by the schema may be224    # slightly low. 225    #226    if {[string match *k $tn]227         || [string match *x $tn] || $AUTOVACUUM228         || ([string match *y $tn] && $STAT3)229         || ($::tcl_platform(os) == "Darwin")230    } {231      do_test dbstatus-2.$tn.ax { expr {($nSchema1-$nSchema2)<=$nFree} } 1232    } else {233      do_test dbstatus-2.$tn.a { expr {$nSchema1-$nSchema2} } $nFree234    }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 a244  # different database schema.245  #246  #   1. Open a connection to an empty database. Initialized the database247  #      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 the263  #      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 as266  #      in step 2.267  #268  #   c) Step 5 reports the same amount of schema and total memory used as269  #      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) BEGIN283        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) BEGIN293        INSERT INTO t2 VALUES(new.a-1, new.b);294      END;295      CREATE TRIGGER tr2 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN296        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 close319    forcedelete test.db320    sqlite3 db test.db321    sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500322    db cache size 1000323 324    catch { register_echo_module db }325    ifcapable !vtab { if {[string match *x $tn]} continue }326  327    execsql $schema328    db cache flush329  330    # Step 2.331    execsql $statements332    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 $statements336  337    # Step 3.338    db cache flush339    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 $statements345    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 $statements349  350    # Step 4.351    db cache flush352    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 less361    # memory than is actually freed when all statements are finalized.362    # This is because a small amount of memory allocated by a virtual table363    # implementation using sqlite3_mprintf() is technically considered364    # 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_SHARED380#381ifcapable shared_cache {382  if {([permutation]=="memsys3"383      || [permutation]=="memsys5"384      || $::tcl_platform(os)=="Linux") && ![sqlite3 -has-codec]} {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_db393    sqlite3 db file:test.db?cache=shared394  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=shared408    do_cacheused_test 4.2.1 db2 { 4568 2284 }409    do_cacheused_test 4.2.2 db { 9000 6716 }410    db close411    do_cacheused_test 4.2.3 db2 { 4568 4568 }412    sqlite3 db file:test.db?cache=shared413    do_cacheused_test 4.2.4 db2 { 4568 2284 }414    db2 close415  }416}417 418#-------------------------------------------------------------------------419# Test that passing an out-of-range value to sqlite3_stmt_status does420# not cause a crash.421reset_db422do_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 $::stmt431  sqlite3_step $::stmt432  sqlite3_step $::stmt433  sqlite3_reset $::stmt434} {SQLITE_OK}435 436ifcapable api_armor {437  do_test 5.2 { sqlite3_stmt_status $::stmt -1 0 } 0438}439do_test 5.3 { sqlite3_stmt_status $::stmt  0 0 } 0440do_test 5.4 { 441  expr [sqlite3_stmt_status $::stmt 99 0]>0 442} 1443foreach {tn id res} {444  1 SQLITE_STMTSTATUS_MEMUSED 1445  2 SQLITE_STMTSTATUS_FULLSCAN_STEP 1446  3 SQLITE_STMTSTATUS_SORT 0447  4 SQLITE_STMTSTATUS_AUTOINDEX 0448  5 SQLITE_STMTSTATUS_VM_STEP 1449  6 SQLITE_STMTSTATUS_REPREPARE 0450  7 SQLITE_STMTSTATUS_RUN 1451} {452if {$tn==2} breakpoint453  do_test 5.5.$tn { expr [sqlite3_stmt_status $::stmt $id 0]>0 } $res454}455 456sqlite3_finalize $::stmt457finish_test458