CoolFace
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
shared_err.test529 linesDownload Raw Back to test
1# 2005 December 302#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# The focus of the tests in this file are IO errors that occur in a shared13# cache context. What happens to connection B if one connection A encounters14# an IO-error whilst reading or writing the file-system?15#16# $Id: shared_err.test,v 1.24 2008/10/12 00:27:54 shane Exp $17 18proc skip {args} {}19 20 21set testdir [file dirname $argv0]22source $testdir/tester.tcl23source $testdir/malloc_common.tcl24db close25 26ifcapable !shared_cache||!subquery {27  finish_test28  return29}30 31set ::enable_shared_cache [sqlite3_enable_shared_cache 1]32 33do_ioerr_test shared_ioerr-1 -tclprep {34  sqlite3 db2 test.db35  execsql {36    PRAGMA read_uncommitted = 1;37    CREATE TABLE t1(a,b,c);38    BEGIN;39    SELECT * FROM sqlite_master;40  } db241} -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 rc74  } {1}75 76  # The "database disk image is malformed" is a special case that can77  # 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 database79  # corruption.80  db2 close81  do_test shared_ioerr-1.$n.cleanup.2 {82    execsql {pragma integrity_check} db83  } {ok}84}85 86do_ioerr_test shared_ioerr-2 -tclprep {87  sqlite3 db2 test.db88  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  } db2109} -tclbody {110  set ::residx 0111  execsql {DELETE FROM t1 WHERE 0 = (a % 2);}112  incr ::residx113 114  # When this transaction begins the table contains 512 entries. The115  # 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 ::residx123} -cleanup {124  catchsql ROLLBACK125  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 success141  } {1}142  db2 close143}144 145# This test is designed to provoke an IO error when a cursor position is146# "saved" (because another cursor is going to modify the underlying table). 147# 148do_ioerr_test shared_ioerr-3 -tclprep {149  sqlite3 db2 test.db150  execsql {151    PRAGMA read_uncommitted = 1;152    PRAGMA cache_size = 10;153    BEGIN;154    CREATE TABLE t1(a, b, UNIQUE(a, b));155  } db2156  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)} db2161  }162  execsql {COMMIT} db2163  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.000166  sqlite3_step $::STMT       ;# Cursor points at 001.001.001.001167 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 in183  #    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] returns187  #    SQLITE_ERROR and [sqlite3_finalize] returns IOERR.188  #189  # 3. If, after the initial IO error, SQLite tried to rollback the190  #    active transaction and a second IO error was encountered, then191  #    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...") and194  #    [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 close221}222 223# This is a repeat of the previous test except that this time we224# are doing a reverse-order scan of the table when the cursor is225# "saved".226# 227do_ioerr_test shared_ioerr-3rev -tclprep {228  sqlite3 db2 test.db229  execsql {230    PRAGMA read_uncommitted = 1;231    PRAGMA cache_size = 10;232    BEGIN;233    CREATE TABLE t1(a, b, UNIQUE(a, b));234  } db2235  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)} db2240  }241  execsql {COMMIT} db2242  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.199246  sqlite3_step $::STMT       ;# Cursor points at 198.198.198.198.198247 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 in263  #    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] returns267  #    SQLITE_ERROR and [sqlite3_finalize] returns IOERR.268  #269  # 3. If, after the initial IO error, SQLite tried to rollback the270  #    active transaction and a second IO error was encountered, then271  #    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...") and274  #    [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 close301}302 303# Provoke a malloc() failure when a cursor position is being saved. This304# only happens with index cursors (because they malloc() space to save the305# current key value). It does not happen with tables, because an integer306# key does not require a malloc() to store. 307#308# The library should return an SQLITE_NOMEM to the caller. The query that309# owns the cursor (the one for which the position is not saved) should310# continue unaffected.311# 312do_malloc_test shared_err-4 -tclprep {313  sqlite3 db2 test.db314  execsql {315    PRAGMA read_uncommitted = 1;316    BEGIN;317    CREATE TABLE t1(a, b, UNIQUE(a, b));318  } db2319  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)} db2323  }324  execsql {COMMIT} db2325  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 0000000000328  sqlite3_step $::STMT       ;# Cursor points at 1111111111329} -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 0341    } {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 close350}351 352do_malloc_test shared_err-5 -tclbody {353  db close354  sqlite3 dbX test.db355  sqlite3 dbY test.db356  dbX close357  dbY close358} -cleanup {359  catch {dbX close}360  catch {dbY close}361}362 363do_malloc_test shared_err-6 -tclbody {364  catch {db close}365  ifcapable deprecated {366    sqlite3_thread_cleanup367  }368  sqlite3_enable_shared_cache 0369} -cleanup {370  sqlite3_enable_shared_cache 1371}372 373# As of 3.5.0, sqlite3_enable_shared_cache can be called at374# any time and from any thread375#do_test shared_err-misuse-7.1 {376#  sqlite3 db test.db377#  catch {378#    sqlite3_enable_shared_cache 0379#  } msg380#  set msg381#} {bad parameter or other API misuse}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 that387# owns the cursor (the one for which the position is not saved) should388# be aborted.389# 390set ::aborted 0391do_malloc_test shared_err-8 -tclprep {392  sqlite3 db2 test.db393  execsql {394    PRAGMA read_uncommitted = 1;395    BEGIN;396    CREATE TABLE t1(a, b, UNIQUE(a, b));397  } db2398  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)} db2402  }403  execsql {COMMIT} db2404  execsql BEGIN405  execsql ROLLBACK406  set ::DB2 [sqlite3_connection_pointer db2]407  set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]408  sqlite3_step $::STMT       ;# Cursor points at 0000000000409  sqlite3_step $::STMT       ;# Cursor points at 1111111111410} -tclbody {411  execsql {412    BEGIN;413    INSERT INTO t1 VALUES(6, NULL);414    ROLLBACK}415} -cleanup {416  # UPDATE: As of [5668], if the rollback fails SQLITE_CORRUPT is returned. 417  # So these tests have been updated to expect SQLITE_CORRUPT and its418  # associated English language error message.419  #420  do_test shared_malloc-8.$::n.cleanup.1 {421    set res [catchsql {SELECT a FROM t1} db2]422    set ans [lindex $res 1]423    if {[lindex $res 0]} {424       set r [expr {425         $ans=="disk I/O error" ||426         $ans=="out of memory" ||427         $ans=="database disk image is malformed"428       }]429    } else {430       set r [expr {[lrange $ans 0 1]=="0000000000 1111111111"}]431    }432  } {1}433  do_test shared_malloc-8.$::n.cleanup.2 {434    set rc1 [sqlite3_step $::STMT]435    set rc2 [sqlite3_finalize $::STMT]436    if {$rc2=="SQLITE_ABORT"} {437      incr ::aborted438    }439    expr {440      ($rc1=="SQLITE_DONE" && $rc2=="SQLITE_OK") || 441      ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_ABORT") ||442      ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_NOMEM") ||443      ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_IOERR") ||444      ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_CORRUPT")445    }446  } {1}447  db2 close448}449 450# When this test case was written, OOM errors in write statements would 451# cause transaction rollback, which would trip cursors in other statements,452# aborting them. This no longer happens.453#454do_test shared_malloc-8.X {455  # Test that one or more queries were aborted due to the malloc() failure.456  # expr $::aborted>=1457  expr $::aborted==0458} {1}459 460# This test is designed to catch a specific bug that was present during461# development of 3.5.0. If a malloc() failed while setting the page-size,462# a buffer (Pager.pTmpSpace) was being freed. This could cause a seg-fault463# later if another connection tried to use the pager.464#465# This test will crash 3.4.2.466#467do_malloc_test shared_err-9 -tclprep {468  sqlite3 db2 test.db469} -sqlbody {470  PRAGMA page_size = 4096;471  PRAGMA page_size = 1024;472} -cleanup {473  db2 eval {474    CREATE TABLE abc(a, b, c);475    BEGIN;476    INSERT INTO abc VALUES(1, 2, 3);477    ROLLBACK;478  }     479  db2 close480}     481 482catch {db close}483catch {db2 close}484do_malloc_test shared_err-10 -tclprep {485  sqlite3 db test.db486  sqlite3 db2 test.db487  488  db eval { SELECT * FROM sqlite_master }489  db2 eval { 490    BEGIN;491    CREATE TABLE abc(a, b, c);492  }493} -tclbody {494  catch {db eval {SELECT * FROM sqlite_master}}495  error 1496} -cleanup {497  execsql { SELECT * FROM sqlite_master }498}499 500do_malloc_test shared_err-11 -tclprep {501  sqlite3 db test.db502  sqlite3 db2 test.db503  504  db eval { SELECT * FROM sqlite_master }505  db2 eval { 506    BEGIN;507    CREATE TABLE abc(a, b, c);508  }509} -tclbody {510  catch {db eval {SELECT * FROM sqlite_master}}511  catch {sqlite3_errmsg16 db}512  error 1513} -cleanup {514  execsql { SELECT * FROM sqlite_master }515}516 517catch {db close}518catch {db2 close}519 520do_malloc_test shared_err-12 -sqlbody {521  CREATE TABLE abc(a, b, c);522  INSERT INTO abc VALUES(1, 2, 3);523}524 525catch {db close}526catch {db2 close}527sqlite3_enable_shared_cache $::enable_shared_cache528finish_test529