File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sqlite3 / test / shared_err.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: # 2005 December 30
    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: # The focus of the tests in this file are IO errors that occur in a shared
   13: # cache context. What happens to connection B if one connection A encounters
   14: # an IO-error whilst reading or writing the file-system?
   15: #
   16: # $Id: shared_err.test,v 1.1.1.1 2012/02/21 17:04:16 misho Exp $
   17: 
   18: proc skip {args} {}
   19: 
   20: 
   21: set testdir [file dirname $argv0]
   22: source $testdir/tester.tcl
   23: source $testdir/malloc_common.tcl
   24: db close
   25: 
   26: ifcapable !shared_cache||!subquery {
   27:   finish_test
   28:   return
   29: }
   30: 
   31: set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
   32: 
   33: do_ioerr_test shared_ioerr-1 -tclprep {
   34:   sqlite3 db2 test.db
   35:   execsql {
   36:     PRAGMA read_uncommitted = 1;
   37:     CREATE TABLE t1(a,b,c);
   38:     BEGIN;
   39:     SELECT * FROM sqlite_master;
   40:   } db2
   41: } -sqlbody {
   42:   SELECT * FROM sqlite_master;
   43:   INSERT INTO t1 VALUES(1,2,3);
   44:   BEGIN TRANSACTION;
   45:   INSERT INTO t1 VALUES(1,2,3);
   46:   INSERT INTO t1 VALUES(4,5,6);
   47:   ROLLBACK;
   48:   SELECT * FROM t1;
   49:   BEGIN TRANSACTION;
   50:   INSERT INTO t1 VALUES(1,2,3);
   51:   INSERT INTO t1 VALUES(4,5,6);
   52:   COMMIT;
   53:   SELECT * FROM t1;
   54:   DELETE FROM t1 WHERE a<100;
   55: } -cleanup {
   56:   do_test shared_ioerr-1.$n.cleanup.1 {
   57:     set res [catchsql {
   58:       SELECT * FROM t1;
   59:     } db2]
   60:     set possible_results [list               \
   61:       "1 {disk I/O error}"                   \
   62:       "0 {1 2 3}"                            \
   63:       "0 {1 2 3 1 2 3 4 5 6}"                \
   64:       "0 {1 2 3 1 2 3 4 5 6 1 2 3 4 5 6}"    \
   65:       "0 {}"                                 \
   66:       "1 {database disk image is malformed}" \
   67:     ]
   68:     set rc [expr [lsearch -exact $possible_results $res] >= 0]
   69:     if {$rc != 1} {
   70:       puts ""
   71:       puts "Result: $res"
   72:     }
   73:     set rc
   74:   } {1}
   75: 
   76:   # The "database disk image is malformed" is a special case that can
   77:   # occur if an IO error occurs during a rollback in the {SELECT * FROM t1}
   78:   # statement above. This test is to make sure there is no real database
   79:   # corruption.
   80:   db2 close
   81:   do_test shared_ioerr-1.$n.cleanup.2 {
   82:     execsql {pragma integrity_check} db
   83:   } {ok}
   84: }
   85: 
   86: do_ioerr_test shared_ioerr-2 -tclprep {
   87:   sqlite3 db2 test.db
   88:   execsql {
   89:     PRAGMA read_uncommitted = 1;
   90:     BEGIN;
   91:     CREATE TABLE t1(a, b);
   92:     INSERT INTO t1(oid) VALUES(NULL);
   93:     INSERT INTO t1(oid) SELECT NULL FROM t1;
   94:     INSERT INTO t1(oid) SELECT NULL FROM t1;
   95:     INSERT INTO t1(oid) SELECT NULL FROM t1;
   96:     INSERT INTO t1(oid) SELECT NULL FROM t1;
   97:     INSERT INTO t1(oid) SELECT NULL FROM t1;
   98:     INSERT INTO t1(oid) SELECT NULL FROM t1;
   99:     INSERT INTO t1(oid) SELECT NULL FROM t1;
  100:     INSERT INTO t1(oid) SELECT NULL FROM t1;
  101:     INSERT INTO t1(oid) SELECT NULL FROM t1;
  102:     INSERT INTO t1(oid) SELECT NULL FROM t1;
  103:     UPDATE t1 set a = oid, b = 'abcdefghijklmnopqrstuvwxyz0123456789';
  104:     CREATE INDEX i1 ON t1(a);
  105:     COMMIT;
  106:     BEGIN;
  107:     SELECT * FROM sqlite_master;
  108:   } db2
  109: } -tclbody {
  110:   set ::residx 0
  111:   execsql {DELETE FROM t1 WHERE 0 = (a % 2);}
  112:   incr ::residx
  113: 
  114:   # When this transaction begins the table contains 512 entries. The
  115:   # two statements together add 512+146 more if it succeeds. 
  116:   # (1024/7==146)
  117:   execsql {BEGIN;}
  118:   execsql {INSERT INTO t1 SELECT a+1, b FROM t1;}
  119:   execsql {INSERT INTO t1 SELECT 'string' || a, b FROM t1 WHERE 0 = (a%7);}
  120:   execsql {COMMIT;}
  121: 
  122:   incr ::residx
  123: } -cleanup {
  124:   catchsql ROLLBACK
  125:   do_test shared_ioerr-2.$n.cleanup.1 {
  126:     set res [catchsql {
  127:       SELECT max(a), min(a), count(*) FROM (SELECT a FROM t1 order by a);
  128:     } db2]
  129:     set possible_results [list \
  130:       {0 {1024 1 1024}}        \
  131:       {0 {1023 1 512}}         \
  132:       {0 {string994 1 1170}}   \
  133:     ]
  134:     set idx [lsearch -exact $possible_results $res]
  135:     set success [expr {$idx==$::residx || $res=="1 {disk I/O error}"}]
  136:     if {!$success} {
  137:       puts ""
  138:       puts "Result: \"$res\" ($::residx)"
  139:     }
  140:     set success
  141:   } {1}
  142:   db2 close
  143: }
  144: 
  145: # This test is designed to provoke an IO error when a cursor position is
  146: # "saved" (because another cursor is going to modify the underlying table). 
  147: # 
  148: do_ioerr_test shared_ioerr-3 -tclprep {
  149:   sqlite3 db2 test.db
  150:   execsql {
  151:     PRAGMA read_uncommitted = 1;
  152:     PRAGMA cache_size = 10;
  153:     BEGIN;
  154:     CREATE TABLE t1(a, b, UNIQUE(a, b));
  155:   } db2
  156:   for {set i 0} {$i < 200} {incr i} {
  157:     set a [string range [string repeat "[format %03d $i]." 5] 0 end-1]
  158: 
  159:     set b [string repeat $i 2000]
  160:     execsql {INSERT INTO t1 VALUES($a, $b)} db2
  161:   }
  162:   execsql {COMMIT} db2
  163:   set ::DB2 [sqlite3_connection_pointer db2]
  164:   set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
  165:   sqlite3_step $::STMT       ;# Cursor points at 000.000.000.000
  166:   sqlite3_step $::STMT       ;# Cursor points at 001.001.001.001
  167: 
  168: } -tclbody {
  169:   execsql {
  170:     BEGIN;
  171:     INSERT INTO t1 VALUES('201.201.201.201.201', NULL);
  172:     UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%';
  173:     COMMIT;
  174:   }
  175: } -cleanup {
  176:   set ::steprc  [sqlite3_step $::STMT]
  177:   set ::column  [sqlite3_column_text $::STMT 0]
  178:   set ::finalrc [sqlite3_finalize $::STMT]
  179: 
  180:   # There are three possible outcomes here (assuming persistent IO errors):
  181:   #
  182:   # 1. If the [sqlite3_step] did not require any IO (required pages in
  183:   #    the cache), then the next row ("002...") may be retrieved 
  184:   #    successfully.
  185:   #
  186:   # 2. If the [sqlite3_step] does require IO, then [sqlite3_step] returns
  187:   #    SQLITE_ERROR and [sqlite3_finalize] returns IOERR.
  188:   #
  189:   # 3. If, after the initial IO error, SQLite tried to rollback the
  190:   #    active transaction and a second IO error was encountered, then
  191:   #    statement $::STMT will have been aborted. This means [sqlite3_stmt]
  192:   #    returns SQLITE_ABORT, and the statement cursor does not move. i.e.
  193:   #    [sqlite3_column] still returns the current row ("001...") and
  194:   #    [sqlite3_finalize] returns SQLITE_OK.
  195:   #
  196: 
  197:   do_test shared_ioerr-3.$n.cleanup.1 {
  198:     expr {
  199:       $::steprc eq "SQLITE_ROW" || 
  200:       $::steprc eq "SQLITE_ERROR" ||
  201:       $::steprc eq "SQLITE_ABORT" 
  202:     }
  203:   } {1}
  204:   do_test shared_ioerr-3.$n.cleanup.2 {
  205:     expr {
  206:       ($::steprc eq "SQLITE_ROW" && $::column eq "002.002.002.002.002") ||
  207:       ($::steprc eq "SQLITE_ERROR" && $::column eq "") ||
  208:       ($::steprc eq "SQLITE_ABORT" && $::column eq "001.001.001.001.001") 
  209:     }
  210:   } {1}
  211:   do_test shared_ioerr-3.$n.cleanup.3 {
  212:     expr {
  213:       ($::steprc eq "SQLITE_ROW" && $::finalrc eq "SQLITE_OK") ||
  214:       ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_IOERR") ||
  215:       ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_ABORT")
  216:     }
  217:   } {1}
  218: 
  219: # db2 eval {select * from sqlite_master}
  220:   db2 close
  221: }
  222: 
  223: # This is a repeat of the previous test except that this time we
  224: # are doing a reverse-order scan of the table when the cursor is
  225: # "saved".
  226: # 
  227: do_ioerr_test shared_ioerr-3rev -tclprep {
  228:   sqlite3 db2 test.db
  229:   execsql {
  230:     PRAGMA read_uncommitted = 1;
  231:     PRAGMA cache_size = 10;
  232:     BEGIN;
  233:     CREATE TABLE t1(a, b, UNIQUE(a, b));
  234:   } db2
  235:   for {set i 0} {$i < 200} {incr i} {
  236:     set a [string range [string repeat "[format %03d $i]." 5] 0 end-1]
  237: 
  238:     set b [string repeat $i 2000]
  239:     execsql {INSERT INTO t1 VALUES($a, $b)} db2
  240:   }
  241:   execsql {COMMIT} db2
  242:   set ::DB2 [sqlite3_connection_pointer db2]
  243:   set ::STMT [sqlite3_prepare $::DB2 \
  244:            "SELECT a FROM t1 ORDER BY a DESC" -1 DUMMY]
  245:   sqlite3_step $::STMT       ;# Cursor points at 199.199.199.199.199
  246:   sqlite3_step $::STMT       ;# Cursor points at 198.198.198.198.198
  247: 
  248: } -tclbody {
  249:   execsql {
  250:     BEGIN;
  251:     INSERT INTO t1 VALUES('201.201.201.201.201', NULL);
  252:     UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%';
  253:     COMMIT;
  254:   }
  255: } -cleanup {
  256:   set ::steprc  [sqlite3_step $::STMT]
  257:   set ::column  [sqlite3_column_text $::STMT 0]
  258:   set ::finalrc [sqlite3_finalize $::STMT]
  259: 
  260:   # There are three possible outcomes here (assuming persistent IO errors):
  261:   #
  262:   # 1. If the [sqlite3_step] did not require any IO (required pages in
  263:   #    the cache), then the next row ("002...") may be retrieved 
  264:   #    successfully.
  265:   #
  266:   # 2. If the [sqlite3_step] does require IO, then [sqlite3_step] returns
  267:   #    SQLITE_ERROR and [sqlite3_finalize] returns IOERR.
  268:   #
  269:   # 3. If, after the initial IO error, SQLite tried to rollback the
  270:   #    active transaction and a second IO error was encountered, then
  271:   #    statement $::STMT will have been aborted. This means [sqlite3_stmt]
  272:   #    returns SQLITE_ABORT, and the statement cursor does not move. i.e.
  273:   #    [sqlite3_column] still returns the current row ("001...") and
  274:   #    [sqlite3_finalize] returns SQLITE_OK.
  275:   #
  276: 
  277:   do_test shared_ioerr-3rev.$n.cleanup.1 {
  278:     expr {
  279:       $::steprc eq "SQLITE_ROW" || 
  280:       $::steprc eq "SQLITE_ERROR" ||
  281:       $::steprc eq "SQLITE_ABORT" 
  282:     }
  283:   } {1}
  284:   do_test shared_ioerr-3rev.$n.cleanup.2 {
  285:     expr {
  286:       ($::steprc eq "SQLITE_ROW" && $::column eq "197.197.197.197.197") ||
  287:       ($::steprc eq "SQLITE_ERROR" && $::column eq "") ||
  288:       ($::steprc eq "SQLITE_ABORT" && $::column eq "198.198.198.198.198") 
  289:     }
  290:   } {1}
  291:   do_test shared_ioerr-3rev.$n.cleanup.3 {
  292:     expr {
  293:       ($::steprc eq "SQLITE_ROW" && $::finalrc eq "SQLITE_OK") ||
  294:       ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_IOERR") ||
  295:       ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_ABORT")
  296:     }
  297:   } {1}
  298: 
  299: # db2 eval {select * from sqlite_master}
  300:   db2 close
  301: }
  302: 
  303: # Provoke a malloc() failure when a cursor position is being saved. This
  304: # only happens with index cursors (because they malloc() space to save the
  305: # current key value). It does not happen with tables, because an integer
  306: # key does not require a malloc() to store. 
  307: #
  308: # The library should return an SQLITE_NOMEM to the caller. The query that
  309: # owns the cursor (the one for which the position is not saved) should
  310: # continue unaffected.
  311: # 
  312: do_malloc_test shared_err-4 -tclprep {
  313:   sqlite3 db2 test.db
  314:   execsql {
  315:     PRAGMA read_uncommitted = 1;
  316:     BEGIN;
  317:     CREATE TABLE t1(a, b, UNIQUE(a, b));
  318:   } db2
  319:   for {set i 0} {$i < 5} {incr i} {
  320:     set a [string repeat $i 10]
  321:     set b [string repeat $i 2000]
  322:     execsql {INSERT INTO t1 VALUES($a, $b)} db2
  323:   }
  324:   execsql {COMMIT} db2
  325:   set ::DB2 [sqlite3_connection_pointer db2]
  326:   set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
  327:   sqlite3_step $::STMT       ;# Cursor points at 0000000000
  328:   sqlite3_step $::STMT       ;# Cursor points at 1111111111
  329: } -tclbody {
  330:   execsql {
  331:     INSERT INTO t1 VALUES(6, NULL);
  332:   }
  333: } -cleanup {
  334:   do_test shared_malloc-4.$::n.cleanup.1 {
  335:     set ::rc [sqlite3_step $::STMT]
  336:     expr {$::rc=="SQLITE_ROW" || $::rc=="SQLITE_ERROR"}
  337:   } {1}
  338:   if {$::rc=="SQLITE_ROW"} {
  339:     do_test shared_malloc-4.$::n.cleanup.2 {
  340:       sqlite3_column_text $::STMT 0
  341:     } {2222222222}
  342:   }
  343:   do_test shared_malloc-4.$::n.cleanup.3 {
  344:    set rc [sqlite3_finalize $::STMT]
  345:    expr {$rc=="SQLITE_OK" || $rc=="SQLITE_ABORT" ||
  346:          $rc=="SQLITE_NOMEM" || $rc=="SQLITE_IOERR"}
  347:   } {1}
  348: # db2 eval {select * from sqlite_master}
  349:   db2 close
  350: }
  351: 
  352: do_malloc_test shared_err-5 -tclbody {
  353:   db close
  354:   sqlite3 dbX test.db
  355:   sqlite3 dbY test.db
  356:   dbX close
  357:   dbY close
  358: } -cleanup {
  359:   catch {dbX close}
  360:   catch {dbY close}
  361: }
  362: 
  363: do_malloc_test shared_err-6 -tclbody {
  364:   catch {db close}
  365:   ifcapable deprecated {
  366:     sqlite3_thread_cleanup
  367:   }
  368:   sqlite3_enable_shared_cache 0
  369: } -cleanup {
  370:   sqlite3_enable_shared_cache 1
  371: }
  372: 
  373: # As of 3.5.0, sqlite3_enable_shared_cache can be called at
  374: # any time and from any thread
  375: #do_test shared_err-misuse-7.1 {
  376: #  sqlite3 db test.db
  377: #  catch {
  378: #    sqlite3_enable_shared_cache 0
  379: #  } msg
  380: #  set msg
  381: #} {library routine called out of sequence}
  382: 
  383: # Again provoke a malloc() failure when a cursor position is being saved, 
  384: # this time during a ROLLBACK operation by some other handle. 
  385: #
  386: # The library should return an SQLITE_NOMEM to the caller. The query that
  387: # owns the cursor (the one for which the position is not saved) should
  388: # be aborted.
  389: # 
  390: set ::aborted 0
  391: do_malloc_test shared_err-8 -tclprep {
  392:   sqlite3 db2 test.db
  393:   execsql {
  394:     PRAGMA read_uncommitted = 1;
  395:     BEGIN;
  396:     CREATE TABLE t1(a, b, UNIQUE(a, b));
  397:   } db2
  398:   for {set i 0} {$i < 2} {incr i} {
  399:     set a [string repeat $i 10]
  400:     set b [string repeat $i 2000]
  401:     execsql {INSERT INTO t1 VALUES($a, $b)} db2
  402:   }
  403:   execsql {COMMIT} db2
  404:   set ::DB2 [sqlite3_connection_pointer db2]
  405:   set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
  406:   sqlite3_step $::STMT       ;# Cursor points at 0000000000
  407:   sqlite3_step $::STMT       ;# Cursor points at 1111111111
  408: } -tclbody {
  409:   execsql {
  410:     BEGIN;
  411:     INSERT INTO t1 VALUES(6, NULL);
  412:     ROLLBACK;
  413:   }
  414: } -cleanup {
  415:   # UPDATE: As of [5668], if the rollback fails SQLITE_CORRUPT is returned. 
  416:   # So these tests have been updated to expect SQLITE_CORRUPT and its
  417:   # associated English language error message.
  418:   #
  419:   do_test shared_malloc-8.$::n.cleanup.1 {
  420:     set res [catchsql {SELECT a FROM t1} db2]
  421:     set ans [lindex $res 1]
  422:     if {[lindex $res 0]} {
  423:        set r [expr {
  424:          $ans=="disk I/O error" ||
  425:          $ans=="out of memory" ||
  426:          $ans=="database disk image is malformed"
  427:        }]
  428:     } else {
  429:        set r [expr {[lrange $ans 0 1]=="0000000000 1111111111"}]
  430:     }
  431:   } {1}
  432:   do_test shared_malloc-8.$::n.cleanup.2 {
  433:     set rc1 [sqlite3_step $::STMT]
  434:     set rc2 [sqlite3_finalize $::STMT]
  435:     if {$rc2=="SQLITE_ABORT"} {
  436:       incr ::aborted
  437:     }
  438:     expr {
  439:       ($rc1=="SQLITE_DONE" && $rc2=="SQLITE_OK") || 
  440:       ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_ABORT") ||
  441:       ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_NOMEM") ||
  442:       ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_IOERR") ||
  443:       ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_CORRUPT")
  444:     }
  445:   } {1}
  446:   db2 close
  447: }
  448: do_test shared_malloc-8.X {
  449:   # Test that one or more queries were aborted due to the malloc() failure.
  450:   expr $::aborted>=1
  451: } {1}
  452: 
  453: # This test is designed to catch a specific bug that was present during
  454: # development of 3.5.0. If a malloc() failed while setting the page-size,
  455: # a buffer (Pager.pTmpSpace) was being freed. This could cause a seg-fault
  456: # later if another connection tried to use the pager.
  457: #
  458: # This test will crash 3.4.2.
  459: #
  460: do_malloc_test shared_err-9 -tclprep {
  461:   sqlite3 db2 test.db
  462: } -sqlbody {
  463:   PRAGMA page_size = 4096;
  464:   PRAGMA page_size = 1024;
  465: } -cleanup {
  466:   db2 eval {
  467:     CREATE TABLE abc(a, b, c);
  468:     BEGIN;
  469:     INSERT INTO abc VALUES(1, 2, 3);
  470:     ROLLBACK;
  471:   }     
  472:   db2 close
  473: }     
  474: 
  475: catch {db close}
  476: catch {db2 close}
  477: do_malloc_test shared_err-10 -tclprep {
  478:   sqlite3 db test.db
  479:   sqlite3 db2 test.db
  480:   
  481:   db eval { SELECT * FROM sqlite_master }
  482:   db2 eval { 
  483:     BEGIN;
  484:     CREATE TABLE abc(a, b, c);
  485:   }
  486: } -tclbody {
  487:   catch {db eval {SELECT * FROM sqlite_master}}
  488:   error 1
  489: } -cleanup {
  490:   execsql { SELECT * FROM sqlite_master }
  491: }
  492: 
  493: do_malloc_test shared_err-11 -tclprep {
  494:   sqlite3 db test.db
  495:   sqlite3 db2 test.db
  496:   
  497:   db eval { SELECT * FROM sqlite_master }
  498:   db2 eval { 
  499:     BEGIN;
  500:     CREATE TABLE abc(a, b, c);
  501:   }
  502: } -tclbody {
  503:   catch {db eval {SELECT * FROM sqlite_master}}
  504:   catch {sqlite3_errmsg16 db}
  505:   error 1
  506: } -cleanup {
  507:   execsql { SELECT * FROM sqlite_master }
  508: }
  509: 
  510: catch {db close}
  511: catch {db2 close}
  512: 
  513: do_malloc_test shared_err-12 -sqlbody {
  514:   CREATE TABLE abc(a, b, c);
  515:   INSERT INTO abc VALUES(1, 2, 3);
  516: }
  517: 
  518: catch {db close}
  519: catch {db2 close}
  520: sqlite3_enable_shared_cache $::enable_shared_cache
  521: finish_test

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