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