000001  # 2014 October 30
000002  #
000003  # The author disclaims copyright to this source code.  In place of
000004  # a legal notice, here is a blessing:
000005  #
000006  #    May you do good and not evil.
000007  #    May you find forgiveness for yourself and forgive others.
000008  #    May you share freely, never taking more than you give.
000009  #
000010  #***********************************************************************
000011  #
000012  
000013  set testdir [file dirname $argv0]
000014  source $testdir/tester.tcl
000015  set testprefix e_blobclose
000016  
000017  set dots [string repeat . 40]
000018  do_execsql_test 1.0 {
000019    CREATE TABLE x1(a INTEGER PRIMARY KEY, b DOTS);
000020    INSERT INTO x1 VALUES(-1, $dots);
000021    INSERT INTO x1 VALUES(-10, $dots);
000022    INSERT INTO x1 VALUES(-100, $dots);
000023    INSERT INTO x1 VALUES(-1000, $dots);
000024    INSERT INTO x1 VALUES(-10000, $dots);
000025  }
000026  
000027  # EVIDENCE-OF: R-03145-46390 This function closes an open BLOB handle.
000028  #
000029  #   It's not clear how to test that a blob handle really is closed.
000030  #   Attempting to use a closed blob handle will likely crash the process.
000031  #   Assume here that if the SHARED lock on the db file is released,
000032  #   the blob handle has been closed.
000033  #
000034  do_execsql_test 1.1 { PRAGMA lock_status } {main unlocked temp closed}
000035  sqlite3_blob_open db main x1 b -1 0 B
000036  do_execsql_test 1.2 { PRAGMA lock_status } {main shared temp closed}
000037  sqlite3_blob_close $B
000038  do_execsql_test 1.3 { PRAGMA lock_status } {main unlocked temp closed}
000039  
000040  
000041  # EVIDENCE-OF: R-34027-00617 If the blob handle being closed was opened
000042  # for read-write access, and if the database is in auto-commit mode and
000043  # there are no other open read-write blob handles or active write
000044  # statements, the current transaction is committed.
000045  #
000046  #   2.1.*: Transaction is not committed if there are other open 
000047  #          read-write blob handles.
000048  #
000049  #   2.2.*: Transaction is not committed if not in auto-commit mode.
000050  #
000051  #   2.3.*: Active write statements.
000052  #
000053  do_test 2.1.1 {
000054    sqlite3_blob_open db main x1 b -100 1 B1
000055    sqlite3_blob_open db main x1 b -1000 1 B2
000056    sqlite3_blob_open db main x1 b -10000 1 B3
000057    sqlite3_blob_open db main x1 b -10000 0 B4      ;# B4 is read-only!
000058    execsql { PRAGMA lock_status }
000059  } {main reserved temp closed}
000060  do_test 2.1.2 {
000061    sqlite3_blob_close $B1 
000062    execsql { PRAGMA lock_status }
000063  } {main reserved temp closed}
000064  do_test 2.1.3 {
000065    sqlite3_blob_close $B2 
000066    execsql { PRAGMA lock_status }
000067  } {main reserved temp closed}
000068  do_test 2.1.4 {
000069    sqlite3_blob_close $B3 
000070    execsql { PRAGMA lock_status }
000071  } {main shared temp closed}
000072  do_test 2.1.5 {
000073    sqlite3_blob_close $B4 
000074    execsql { PRAGMA lock_status }
000075  } {main unlocked temp closed}
000076  
000077  do_test 2.2.1 {
000078    sqlite3_blob_open db main x1 b -100 1 B1
000079    execsql { PRAGMA lock_status }
000080  } {main reserved temp closed}
000081  do_test 2.2.2 {
000082    execsql { BEGIN }
000083    sqlite3_blob_close $B1 
000084    execsql { PRAGMA lock_status }
000085  } {main reserved temp closed}
000086  do_test 2.2.3 {
000087    execsql { COMMIT }
000088    execsql { PRAGMA lock_status }
000089  } {main unlocked temp closed}
000090  
000091  proc val {} { 
000092    sqlite3_blob_close $::B 
000093    db eval { PRAGMA lock_status }
000094  }
000095  db func val val
000096  do_test 2.3.1 {
000097    sqlite3_blob_open db main x1 b -100 1 B
000098    execsql { PRAGMA lock_status }
000099  } {main reserved temp closed}
000100  do_test 2.3.2 {
000101    execsql { INSERT INTO x1 VALUES(15, val()) }
000102    execsql { PRAGMA lock_status }
000103  } {main unlocked temp closed}
000104  do_test 2.3.3 {
000105    execsql { SELECT * FROM x1 WHERE a = 15 }
000106  } {15 {main reserved temp closed}}
000107  
000108  # A reader does not inhibit commit.
000109  do_test 2.3.4 {
000110    sqlite3_blob_open db main x1 b -100 1 B
000111    execsql { PRAGMA lock_status }
000112  } {main reserved temp closed}
000113  do_test 2.3.5 {
000114    execsql { SELECT a, val() FROM x1 LIMIT 1 }
000115  } {-10000 {main shared temp closed}}
000116  
000117  
000118  do_test 3.1 {
000119    sqlite3_blob_open db main x1 b -10 1 B
000120    execsql {
000121      INSERT INTO x1 VALUES(1, 'abc');
000122      SELECT * FROM x1 WHERE a=1;
000123    }
000124  } {1 abc}
000125  do_test 3.2 {
000126    sqlite3_blob_write $B 0 "abcdefghij" 10
000127    execsql { SELECT * FROM x1 WHERE a=-10 }
000128  } {-10 abcdefghij..............................}
000129  
000130  do_test 3.3 {
000131    sqlite3 db2 test.db
000132    execsql { BEGIN ; SELECT * FROM x1 } db2
000133    sqlite3_blob_close $B 
000134  } {SQLITE_BUSY}
000135  
000136  # EVIDENCE-OF: R-41959-38737 Otherwise, if this function is passed a
000137  # valid open blob handle, the values returned by the sqlite3_errcode()
000138  # and sqlite3_errmsg() functions are set before returning.
000139  #
000140  do_test 3.4 {
000141    list [sqlite3_errcode db] [sqlite3_errmsg db]
000142  } {SQLITE_BUSY {database is locked}}
000143  
000144  # EVIDENCE-OF: R-37801-37633 The BLOB handle is closed unconditionally.
000145  # Even if this routine returns an error code, the handle is still
000146  # closed.
000147  #
000148  #   Test that the lock has been released. Assume this means the handle
000149  #   is closed, even though blob_close() returned SQLITE_BUSY.
000150  #
000151  do_execsql_test 3.4 { PRAGMA lock_status } {main unlocked temp closed}
000152  
000153  # EVIDENCE-OF: R-35111-05628 If an error occurs while committing the
000154  # transaction, an error code is returned and the transaction rolled
000155  # back.
000156  #
000157  #   Row 1 is removed (it was inserted this transaction) and row -10
000158  #   is restored to its original state. Transaction has been rolled back.
000159  #
000160  do_execsql_test 3.5 {
000161    SELECT * FROM x1 WHERE a IN (1, -10);
000162  } {-10 ........................................}
000163  
000164  # EVIDENCE-OF: R-25894-51060 Calling this routine with a null pointer
000165  # (such as would be returned by a failed call to sqlite3_blob_open()) is
000166  # a harmless no-op.
000167  #
000168  do_test 4.0 { sqlite3_blob_close 0 } {}
000169  
000170  finish_test