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