File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sqlite3 / test / tkt2409.test
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:04:16 2012 UTC (12 years, 10 months ago) by misho
Branches: sqlite3, MAIN
CVS tags: v3_7_10, HEAD
sqlite3

    1: # 2007 June 13
    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: # This file implements regression tests for SQLite library.
   12: #
   13: # This file implements tests to verify that ticket #2409 has been
   14: # fixed. More specifically, they verify that if SQLite cannot
   15: # obtain an EXCLUSIVE lock while trying to spill the cache during
   16: # any statement other than a COMMIT, an I/O error is returned instead
   17: # of SQLITE_BUSY.
   18: #
   19: # $Id: tkt2409.test,v 1.1.1.1 2012/02/21 17:04:16 misho Exp $
   20: 
   21: # Test Outline:
   22: #
   23: #   tkt-2409-1.*: Cause a cache-spill during an INSERT that is within
   24: #       a db transaction but does not start a statement transaction.
   25: #       Verify that the transaction is automatically rolled back
   26: #       and SQLITE_IOERR_BLOCKED is returned
   27: #
   28: #       UPDATE: As of the pcache modifications, failing to upgrade to
   29: #       an exclusive lock when attempting a cache-spill is no longer an
   30: #       error. The pcache module allocates more space and keeps working
   31: #       in memory if this occurs.
   32: #
   33: #   tkt-2409-2.*: Cause a cache-spill while updating the change-counter
   34: #       during a database COMMIT. Verify that the transaction is not
   35: #       rolled back and SQLITE_BUSY is returned.
   36: #
   37: #   tkt-2409-3.*: Similar to 2409-1.*, but using many INSERT statements
   38: #       within a transaction instead of just one.
   39: #
   40: #       UPDATE: Again, pcache now just keeps working in main memory.
   41: #
   42: #   tkt-2409-4.*: Similar to 2409-1.*, but rig it so that the
   43: #       INSERT statement starts a statement transaction. Verify that
   44: #       SQLITE_BUSY is returned and the transaction is not rolled back.
   45: #
   46: #       UPDATE: This time, SQLITE_BUSY is not returned. pcache just uses
   47: #       more malloc()'d memory.
   48: #
   49: 
   50: set testdir [file dirname $argv0]
   51: source $testdir/tester.tcl
   52: 
   53: ifcapable !pager_pragmas {
   54:   finish_test
   55:   return
   56: }
   57: 
   58: sqlite3_extended_result_codes $::DB 1
   59: 
   60: # Aquire a read-lock on the database using handle [db2].
   61: #
   62: proc read_lock_db {} {
   63:   if {$::STMT eq ""} {
   64:     set ::STMT [sqlite3_prepare db2 {SELECT rowid FROM sqlite_master} -1 TAIL]
   65:     set rc [sqlite3_step $::STMT]
   66:     if {$rc eq "SQLITE_ERROR"} {
   67:       unread_lock_db
   68:       read_lock_db
   69:     }
   70:   }
   71: }
   72: 
   73: # Release any read-lock obtained using [read_lock_db]
   74: #
   75: proc unread_lock_db {} {
   76:   if {$::STMT ne ""} {
   77:     sqlite3_finalize $::STMT
   78:     set ::STMT ""
   79:   }
   80: }
   81: 
   82: # Open the db handle used by [read_lock_db].
   83: #
   84: sqlite3 db2 test.db
   85: set ::STMT ""
   86: 
   87: do_test tkt2409-1.1 {
   88:   execsql {
   89:     PRAGMA cache_size=10;
   90:     CREATE TABLE t1(x TEXT UNIQUE NOT NULL, y BLOB);
   91:   }
   92:   read_lock_db
   93:   set ::zShort [string repeat 0123456789 1]
   94:   set ::zLong  [string repeat 0123456789 1500]
   95:   catchsql {
   96:     BEGIN;
   97:     INSERT INTO t1 VALUES($::zShort, $::zLong);
   98:   }
   99: } {0 {}}
  100: 
  101: do_test tkt2409-1.2 {
  102:   sqlite3_errcode $::DB
  103: } {SQLITE_OK}
  104: 
  105: # Check the integrity of the cache.
  106: #
  107: integrity_check tkt2409-1.3
  108: 
  109: # Check that the transaction was rolled back. Because the INSERT
  110: # statement in which the "I/O error" occured did not open a statement
  111: # transaction, SQLite had no choice but to roll back the transaction.
  112: #
  113: do_test tkt2409-1.4 {
  114:   unread_lock_db
  115:   catchsql { ROLLBACK }
  116: } {0 {}}
  117: 
  118: set ::zShort [string repeat 0123456789 1]
  119: set ::zLong  [string repeat 0123456789 1500]
  120: set ::rc 1
  121: for {set iCache 10} {$::rc} {incr iCache} {
  122:   execsql "PRAGMA cache_size = $iCache"
  123:   do_test tkt2409-2.1.$iCache {
  124:     read_lock_db
  125:     set ::rc [catch {
  126:       execsql {
  127:         BEGIN;
  128:         INSERT INTO t1 VALUES($::zShort, $::zLong);
  129:       }
  130:     } msg]
  131:     expr {($::rc == 1 && $msg eq "disk I/O error") || $::rc == 0}
  132:   } {1}
  133: }
  134: 
  135: do_test tkt2409-2.2 {
  136:   catchsql {
  137:     ROLLBACK;
  138:     BEGIN;
  139:     INSERT INTO t1 VALUES($::zShort, $::zLong);
  140:     COMMIT;
  141:   }
  142: } {1 {database is locked}}
  143: 
  144: do_test tkt2409-2.3 {
  145:   unread_lock_db
  146:   catchsql {
  147:     COMMIT;
  148:   }
  149: } {0 {}}
  150: 
  151: 
  152: do_test tkt2409-3.1 {
  153:   db close
  154:   set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db]
  155:   sqlite3_extended_result_codes $::DB 1
  156:   execsql {
  157:     PRAGMA cache_size=10;
  158:     DELETE FROM t1;
  159:   }
  160:   read_lock_db
  161:   set ::zShort [string repeat 0123456789 1]
  162:   set ::zLong  [string repeat 0123456789 1500]
  163:   catchsql {
  164:     BEGIN;
  165:     INSERT INTO t1 SELECT $::zShort, $::zLong;
  166:   }
  167: } {0 {}}
  168: 
  169: do_test tkt2409-3.2 {
  170:   sqlite3_errcode $::DB
  171: } {SQLITE_OK}
  172: 
  173: # Check the integrity of the cache.
  174: #
  175: integrity_check tkt2409-3.3
  176: 
  177: # Check that the transaction was rolled back. Because the INSERT
  178: # statement in which the "I/O error" occured did not open a statement
  179: # transaction, SQLite had no choice but to roll back the transaction.
  180: #
  181: do_test tkt2409-3.4 {
  182:   unread_lock_db
  183:   catchsql { ROLLBACK }
  184: } {0 {}}
  185: integrity_check tkt2409-3.5
  186: 
  187: expr {srand(1)}
  188: do_test tkt2409-4.1 {
  189:   execsql {
  190:     PRAGMA cache_size=20;
  191:     DROP TABLE t1;
  192:     CREATE TABLE t1 (x TEXT UNIQUE NOT NULL);
  193:   }
  194: 
  195:   unset -nocomplain t1
  196:   array unset t1
  197:   set t1(0) 1
  198:   set sql ""
  199:   for {set i 0} {$i<5000} {incr i} {
  200:     set r 0
  201:     while {[info exists t1($r)]} {
  202:       set r [expr {int(rand()*1000000000)}]
  203:     }
  204:     set t1($r) 1
  205:     append sql "INSERT INTO t1 VALUES('some-text-$r');"
  206:   }
  207: 
  208:   read_lock_db
  209:   execsql BEGIN
  210:   catchsql $sql
  211: } {0 {}}
  212: 
  213: do_test tkt2409-4.2 {
  214:   sqlite3_errcode $::DB
  215: } {SQLITE_OK}
  216: 
  217: # Check the integrity of the cache.
  218: #
  219: integrity_check tkt2409-4.3
  220: 
  221: do_test tkt2409-4.4 {
  222:   catchsql { ROLLBACK }
  223: } {0 {}}
  224: integrity_check tkt2409-4.5
  225: 
  226: unread_lock_db
  227: db2 close
  228: unset -nocomplain t1
  229: finish_test

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