github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/incrblob2.test (about)

     1  # 2008 June 9
     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  # Test that it is possible to have two open blob handles on a single
    13  # blob object.
    14  #
    15  # $Id: incrblob2.test,v 1.11 2009/06/29 06:00:37 danielk1977 Exp $
    16  #
    17  
    18  set testdir [file dirname $argv0]
    19  source $testdir/tester.tcl
    20  
    21  ifcapable {!autovacuum || !pragma || !incrblob} {
    22    finish_test
    23    return
    24  }
    25  
    26  do_test incrblob2-1.0 {
    27    execsql {
    28      CREATE TABLE blobs(id INTEGER PRIMARY KEY, data BLOB);
    29      INSERT INTO blobs VALUES(NULL, zeroblob(5000));
    30      INSERT INTO blobs VALUES(NULL, zeroblob(5000));
    31      INSERT INTO blobs VALUES(NULL, zeroblob(5000));
    32      INSERT INTO blobs VALUES(NULL, zeroblob(5000));
    33    }
    34  } {}
    35  
    36  foreach iOffset [list 0 256 4094] {
    37    do_test incrblob2-1.$iOffset.1 {
    38      set fd [db incrblob blobs data 1]
    39      puts $fd "[string repeat x $iOffset]SQLite version 3.6.0"
    40      close $fd
    41    } {}
    42    
    43    do_test incrblob2-1.$iOffset.2 {
    44      set fd1 [db incrblob blobs data 1]
    45      set fd2 [db incrblob blobs data 1]
    46      fconfigure $fd1 -buffering none
    47      fconfigure $fd2 -buffering none
    48      if {$iOffset != 0} {
    49        seek $fd2 $iOffset start
    50        seek $fd1 $iOffset start
    51      }
    52      read $fd1 6
    53    } {SQLite}
    54    
    55    do_test incrblob2-1.$iOffset.3 {
    56      read $fd2 6
    57    } {SQLite}
    58    
    59    do_test incrblob2-1.$iOffset.4 {
    60      seek $fd2 $iOffset start
    61      seek $fd1 $iOffset start
    62      puts -nonewline $fd2 "etiLQS"
    63    } {}
    64  
    65    
    66    do_test incrblob2-1.$iOffset.5 {
    67      seek $fd1 $iOffset start
    68      read $fd1 6
    69    } {etiLQS}
    70    
    71    do_test incrblob2-1.$iOffset.6 {
    72      seek $fd2 $iOffset start
    73      read $fd2 6
    74    } {etiLQS}
    75    
    76    do_test incrblob2-1.$iOffset.7 {
    77      seek $fd1 $iOffset start
    78      read $fd1 6
    79    } {etiLQS}
    80    
    81    do_test incrblob2-1.$iOffset.8 {
    82      close $fd1
    83      close $fd2
    84    } {}
    85  }
    86  
    87  #--------------------------------------------------------------------------
    88  
    89  foreach iOffset [list 0 256 4094] {
    90  
    91    do_test incrblob2-2.$iOffset.1 {
    92      set fd1 [db incrblob blobs data 1]
    93      seek $fd1 [expr $iOffset - 5000] end
    94      fconfigure $fd1 -buffering none
    95  
    96      set fd2 [db incrblob blobs data 1]
    97      seek $fd2 [expr $iOffset - 5000] end
    98      fconfigure $fd2 -buffering none
    99  
   100      puts -nonewline $fd1 "123456"
   101    } {}
   102    
   103    do_test incrblob2-2.$iOffset.2 {
   104      read $fd2 6
   105    } {123456}
   106  
   107    do_test incrblob2-2.$iOffset.3 {
   108      close $fd1
   109      close $fd2
   110    } {}
   111  }
   112  
   113  do_test incrblob2-3.1 {
   114    set fd1 [db incrblob blobs data 1]
   115    fconfigure $fd1 -buffering none
   116  } {}
   117  do_test incrblob2-3.2 {
   118    execsql {
   119      INSERT INTO blobs VALUES(5, zeroblob(10240));
   120    }
   121  } {}
   122  do_test incrblob2-3.3 {
   123    set rc [catch { read $fd1 6 } msg]
   124    list $rc $msg
   125  } {0 123456}
   126  do_test incrblob2-3.4 {
   127    close $fd1
   128  } {}
   129  
   130  #--------------------------------------------------------------------------
   131  # The following tests - incrblob2-4.* - test that blob handles are 
   132  # invalidated at the correct times.
   133  #
   134  do_test incrblob2-4.1 {
   135    unset -nocomplain data
   136    db eval BEGIN
   137    db eval { CREATE TABLE t1(id INTEGER PRIMARY KEY, data BLOB); }
   138    for {set ii 1} {$ii < 100} {incr ii} {
   139      set data [string repeat "blob$ii" 500]
   140      db eval { INSERT INTO t1 VALUES($ii, $data) }
   141    }
   142    db eval COMMIT
   143  } {}
   144  
   145  proc aborted_handles {} {
   146    global handles
   147  
   148    set aborted {}
   149    for {set ii 1} {$ii < 100} {incr ii} {
   150      set str "blob$ii"
   151      set nByte [string length $str]
   152      set iOffset [expr $nByte * $ii * 2]
   153  
   154      set rc [catch {sqlite3_blob_read $handles($ii) $iOffset $nByte} msg]
   155      if {$rc && $msg eq "SQLITE_ABORT"} {
   156        lappend aborted $ii
   157      } else {
   158        if {$rc || $msg ne $str} {
   159          error "blob $ii: $msg"
   160        }
   161      }
   162    }
   163    set aborted
   164  }
   165  
   166  do_test incrblob2-4.2 {
   167    for {set ii 1} {$ii < 100} {incr ii} {
   168      set handles($ii) [db incrblob t1 data $ii]
   169    }
   170    aborted_handles
   171  } {}
   172  
   173  # Update row 3. This should abort handle 3 but leave all others untouched.
   174  #
   175  do_test incrblob2-4.3 {
   176    db eval {UPDATE t1 SET data = data || '' WHERE id = 3}
   177    aborted_handles
   178  } {3}
   179  
   180  # Test that a write to handle 3 also returns SQLITE_ABORT.
   181  #
   182  do_test incrblob2-4.3.1 {
   183    set rc [catch {sqlite3_blob_write $::handles(3) 10 HELLO} msg]
   184    list $rc $msg
   185  } {1 SQLITE_ABORT}
   186  
   187  # Delete row 14. This should abort handle 6 but leave all others untouched.
   188  #
   189  do_test incrblob2-4.4 {
   190    db eval {DELETE FROM t1 WHERE id = 14}
   191    aborted_handles
   192  } {3 14}
   193  
   194  # Change the rowid of row 15 to 102. Should abort handle 15.
   195  #
   196  do_test incrblob2-4.5 {
   197    db eval {UPDATE t1 SET id = 102 WHERE id = 15}
   198    aborted_handles
   199  } {3 14 15}
   200  
   201  # Clobber row 92 using INSERT OR REPLACE.
   202  #
   203  do_test incrblob2-4.6 {
   204    db eval {INSERT OR REPLACE INTO t1 VALUES(92, zeroblob(1000))}
   205    aborted_handles
   206  } {3 14 15 92}
   207  
   208  # Clobber row 65 using UPDATE OR REPLACE on row 35. This should abort 
   209  # handles 35 and 65.
   210  #
   211  do_test incrblob2-4.7 {
   212    db eval {UPDATE OR REPLACE t1 SET id = 65 WHERE id = 35}
   213    aborted_handles
   214  } {3 14 15 35 65 92}
   215  
   216  # Insert a couple of new rows. This should not invalidate any handles.
   217  #
   218  do_test incrblob2-4.9 {
   219    db eval {INSERT INTO t1 SELECT NULL, data FROM t1}
   220    aborted_handles
   221  } {3 14 15 35 65 92}
   222  
   223  # Delete all rows from 1 to 25. This should abort all handles up to 25.
   224  #
   225  do_test incrblob2-4.9 {
   226    db eval {DELETE FROM t1 WHERE id >=1 AND id <= 25}
   227    aborted_handles
   228  } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 35 65 92}
   229  
   230  # Delete the whole table (this will use sqlite3BtreeClearTable()). All handles
   231  # should now be aborted.
   232  #
   233  do_test incrblob2-4.10 {
   234    db eval {DELETE FROM t1}
   235    aborted_handles
   236  } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99}
   237  
   238  do_test incrblob2-4.1.X {
   239    for {set ii 1} {$ii < 100} {incr ii} {
   240      close $handles($ii) 
   241    }
   242  } {}
   243  
   244  #--------------------------------------------------------------------------
   245  # The following tests - incrblob2-5.* - test that in shared cache an open
   246  # blob handle counts as a read-lock on its table.
   247  #
   248  ifcapable shared_cache {
   249    db close
   250    set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
   251  
   252    do_test incrblob2-5.1 {
   253      sqlite3 db test.db
   254      sqlite3 db2 test.db
   255  
   256      execsql {
   257        INSERT INTO t1 VALUES(1, 'abcde');
   258      }
   259    } {}
   260  
   261    do_test incrblob2-5.2 {
   262      catchsql { INSERT INTO t1 VALUES(2, 'fghij') } db2
   263    } {0 {}}
   264  
   265    do_test incrblob2-5.3 {
   266      set blob [db incrblob t1 data 1]
   267      catchsql { INSERT INTO t1 VALUES(3, 'klmno') } db2
   268    } {1 {database table is locked}}
   269  
   270    do_test incrblob2-5.4 {
   271      close $blob
   272      execsql BEGIN db2
   273      catchsql { INSERT INTO t1 VALUES(4, 'pqrst') } db2
   274    } {0 {}}
   275  
   276    do_test incrblob2-5.5 {
   277      set rc [catch { db incrblob -readonly t1 data 1 } msg]
   278      list $rc $msg
   279    } {1 {database table is locked: t1}}
   280  
   281    do_test incrblob2-5.6 {
   282      execsql { PRAGMA read_uncommitted=1 }
   283      set blob [db incrblob -readonly t1 data 4]
   284      read $blob
   285    } {pqrst}
   286  
   287    do_test incrblob2-5.7 {
   288      catchsql { INSERT INTO t1 VALUES(3, 'klmno') } db2
   289    } {0 {}}
   290  
   291    do_test incrblob2-5.8 {
   292      close $blob
   293    } {}
   294  
   295    db2 close
   296    db close
   297    sqlite3_enable_shared_cache $::enable_shared_cache
   298  }
   299  
   300  #--------------------------------------------------------------------------
   301  # The following tests - incrblob2-6.* - test a specific scenario that might
   302  # be causing an error.
   303  #
   304  sqlite3 db test.db
   305  do_test incrblob2-6.1 {
   306    execsql {
   307      DELETE FROM t1;
   308      INSERT INTO t1 VALUES(1, zeroblob(100));
   309    }
   310    
   311    set rdHandle [db incrblob -readonly t1 data 1]
   312    set wrHandle [db incrblob t1 data 1]
   313  
   314    sqlite3_blob_read $rdHandle 0 100
   315  
   316    sqlite3_blob_write $wrHandle 0 ABCDEF
   317  
   318    close $wrHandle
   319    close $rdHandle
   320  } {}
   321  
   322  do_test incrblob2-6.2 {
   323    set rdHandle [db incrblob -readonly t1 data 1]
   324    sqlite3_blob_read $rdHandle 0 2
   325  } {AB}
   326  
   327  if {$::tcl_platform(pointerSize)>=8} {
   328    do_test incrblob2-6.2b {
   329      set rc [catch {
   330        # Prior to 2015-02-07, the following caused a segfault due to
   331        # integer overflow.
   332        sqlite3_blob_read $rdHandle 2147483647 2147483647
   333      } errmsg]
   334      if {[string match {out of memory in *test_blob.c} $errmsg]} {
   335        set errmsg SQLITE_ERROR
   336      }
   337      lappend rc $errmsg
   338    } {1 SQLITE_ERROR}
   339  }
   340  do_test incrblob2-6.2c {
   341    set rc [catch {
   342      # Prior to 2015-02-07, the following caused a segfault due to
   343      # integer overflow.
   344      sqlite3_blob_read $rdHandle 2147483647 100
   345    } errmsg]
   346    lappend rc $errmsg
   347  } {1 SQLITE_ERROR}
   348  
   349  do_test incrblob2-6.3 {
   350    set wrHandle [db incrblob t1 data 1]
   351    sqlite3_blob_write $wrHandle 0 ZZZZZZZZZZ
   352    sqlite3_blob_read $rdHandle 2 4
   353  } {ZZZZ}
   354  
   355  do_test incrblob2-6.3b {
   356    set rc [catch {
   357      # Prior to 2015-02-07, the following caused a segfault due to
   358      # integer overflow.
   359      sqlite3_blob_write $wrHandle 2147483647 YYYYYYYYYYYYYYYYYY
   360    } errmsg]
   361    lappend rc $errmsg
   362  } {1 SQLITE_ERROR}
   363  do_test incrblob2-6.3c {
   364    sqlite3_blob_read $rdHandle 2 4
   365  } {ZZZZ}
   366  
   367  
   368  do_test incrblob2-6.4 {
   369    close $wrHandle
   370    close $rdHandle
   371  } {}
   372  
   373  sqlite3_memory_highwater 1
   374  do_test incrblob2-7.1 {
   375    db eval {
   376      CREATE TABLE t2(B BLOB);
   377      INSERT INTO t2 VALUES(zeroblob(10 * 1024 * 1024)); 
   378    }
   379    expr {[sqlite3_memory_highwater]<(5 * 1024 * 1024)}
   380  } {1}
   381  
   382  do_test incrblob2-7.2 {
   383    set h [db incrblob t2 B 1]
   384    expr {[sqlite3_memory_highwater]<(5 * 1024 * 1024)}
   385  } {1}
   386  
   387  do_test incrblob2-7.3 {
   388    seek $h 0 end
   389    tell $h
   390  } [expr 10 * 1024 * 1024]
   391  
   392  do_test incrblob2-7.4 {
   393    expr {[sqlite3_memory_highwater]<(5 * 1024 * 1024)}
   394  } {1}
   395  
   396  do_test incrblob2-7.5 {
   397    close $h
   398  } {}
   399  
   400  #---------------------------------------------------------------------------
   401  # The following tests, incrblob2-8.*, test that nothing terrible happens
   402  # when a statement transaction is rolled back while there are open 
   403  # incremental-blob handles. At one point an assert() was failing when
   404  # this was attempted.
   405  #
   406  do_test incrblob2-8.1 {
   407    execsql BEGIN
   408    set h [db incrblob t2 B 1]
   409    set rc [catch {
   410      db eval {SELECT rowid FROM t2} { execsql "DROP TABLE t2" }
   411    } msg] 
   412    list $rc $msg
   413  } {1 {database table is locked}}
   414  do_test incrblob2-8.2 {
   415    close $h
   416    execsql COMMIT
   417  } {}
   418  do_test incrblob2-8.3 {
   419    execsql {
   420      CREATE TABLE t3(a INTEGER UNIQUE, b TEXT);
   421      INSERT INTO t3 VALUES(1, 'aaaaaaaaaaaaaaaaaaaa');
   422      INSERT INTO t3 VALUES(2, 'bbbbbbbbbbbbbbbbbbbb');
   423      INSERT INTO t3 VALUES(3, 'cccccccccccccccccccc');
   424      INSERT INTO t3 VALUES(4, 'dddddddddddddddddddd');
   425      INSERT INTO t3 VALUES(5, 'eeeeeeeeeeeeeeeeeeee');
   426    }
   427  } {}
   428  do_test incrblob2-8.4 {
   429    execsql BEGIN
   430    set h [db incrblob t3 b 3]
   431    sqlite3_blob_read $h 0 20
   432  } {cccccccccccccccccccc}
   433  do_test incrblob2-8.5 {
   434    catchsql {UPDATE t3 SET a = 6 WHERE a > 3}
   435  } {1 {UNIQUE constraint failed: t3.a}}
   436  do_test incrblob2-8.6 {
   437    catchsql {UPDATE t3 SET a = 6 WHERE a > 3}
   438  } {1 {UNIQUE constraint failed: t3.a}}
   439  do_test incrblob2-8.7 {
   440    sqlite3_blob_read $h 0 20
   441  } {cccccccccccccccccccc}
   442  do_test incrblob2-8.8 {
   443    catchsql {UPDATE t3 SET a = 6 WHERE a = 3 OR a = 5}
   444  } {1 {UNIQUE constraint failed: t3.a}}
   445  do_test incrblob2-8.9 {
   446    set rc [catch {sqlite3_blob_read $h 0 20} msg]
   447    list $rc $msg
   448  } {1 SQLITE_ABORT}
   449  do_test incrblob2-8.X {
   450    close $h
   451  } {}
   452  
   453  finish_test