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