1: # 2010 October 20
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: #
13:
14: set testdir [file dirname $argv0]
15: source $testdir/tester.tcl
16:
17: sqlite3 db test.db
18: sqlite3_db_config_lookaside db 0 0 0
19:
20: do_execsql_test incrblob3-1.1 {
21: CREATE TABLE blobs(k INTEGER PRIMARY KEY, v BLOB);
22: INSERT INTO blobs VALUES(1, zeroblob(100));
23: INSERT INTO blobs VALUES(2, zeroblob(100));
24: } {}
25:
26: # Test the sqlite3_blob_reopen()/read()/write() functions.
27: #
28: do_test incrblob3-1.2 {
29: set ::blob [db incrblob blobs v 1]
30: puts $::blob "hello world"
31: } {}
32:
33: do_test incrblob3-1.3 {
34: sqlite3_blob_reopen $::blob 2
35: puts $::blob "world hello"
36: } {}
37:
38: do_test incrblob3-1.4 {
39: sqlite3_blob_reopen $::blob 1
40: gets $::blob
41: } {hello world}
42:
43: do_test incrblob3-1.5 {
44: sqlite3_blob_reopen $::blob 2
45: gets $::blob
46: } {world hello}
47:
48: do_test incrblob3-1.6 { close $::blob } {}
49:
50: # Test some error conditions.
51: #
52: # incrblob3-2.1: Attempting to reopen a row that does not exist.
53: # incrblob3-2.2: Attempting to reopen a row that does not contain a blob
54: # or text value.
55: #
56: do_test incrblob3-2.1.1 {
57: set ::blob [db incrblob blobs v 1]
58: list [catch {sqlite3_blob_reopen $::blob 3} msg] $msg
59: } {1 SQLITE_ERROR}
60: do_test incrblob3-2.1.2 {
61: list [sqlite3_errcode db] [sqlite3_errmsg db]
62: } {SQLITE_ERROR {no such rowid: 3}}
63: do_test incrblob3-2.1.3 {
64: list [catch {sqlite3_blob_reopen $::blob 1} msg] $msg
65: } {1 SQLITE_ABORT}
66: do_test incrblob3-2.1.4 { close $::blob } {}
67:
68: do_execsql_test incrblob3-2.2.1 {
69: INSERT INTO blobs VALUES(3, 42);
70: INSERT INTO blobs VALUES(4, 54.4);
71: INSERT INTO blobs VALUES(5, NULL);
72: }
73: foreach {tn rowid type} {
74: 1 3 integer
75: 2 4 real
76: 3 5 null
77: } {
78: do_test incrblob3-2.2.$tn.1 {
79: set ::blob [db incrblob blobs v 1]
80: list [catch {sqlite3_blob_reopen $::blob $rowid} msg] $msg
81: } {1 SQLITE_ERROR}
82: do_test incrblob3-2.2.$tn.2 {
83: list [sqlite3_errcode db] [sqlite3_errmsg db]
84: } "SQLITE_ERROR {cannot open value of type $type}"
85:
86: do_test incrblob3-2.2.$tn.3 {
87: list [catch {sqlite3_blob_reopen $::blob 1} msg] $msg
88: } {1 SQLITE_ABORT}
89: do_test incrblob3-2.2.$tn.4 {
90: list [catch {sqlite3_blob_read $::blob 0 10} msg] $msg
91: } {1 SQLITE_ABORT}
92: do_test incrblob3-2.2.$tn.5 {
93: list [catch {sqlite3_blob_write $::blob 0 "abcd"} msg] $msg
94: } {1 SQLITE_ABORT}
95: do_test incrblob3-2.2.$tn.6 {
96: sqlite3_blob_bytes $::blob
97: } {0}
98:
99: do_test incrblob3-2.2.$tn.7 { close $::blob } {}
100: }
101:
102: # Test that passing NULL to sqlite3_blob_XXX() APIs returns SQLITE_MISUSE.
103: #
104: # incrblob3-3.1: sqlite3_blob_reopen()
105: # incrblob3-3.2: sqlite3_blob_read()
106: # incrblob3-3.3: sqlite3_blob_write()
107: # incrblob3-3.4: sqlite3_blob_bytes()
108: #
109: do_test incrblob3-3.1 {
110: list [catch {sqlite3_blob_reopen {} 3} msg] $msg
111: } {1 SQLITE_MISUSE}
112:
113: do_test incrblob3-3.2 {
114: list [catch {sqlite3_blob_read {} 0 10} msg] $msg
115: } {1 SQLITE_MISUSE}
116:
117: do_test incrblob3-3.3 {
118: list [catch {sqlite3_blob_write {} 0 "abcd"} msg] $msg
119: } {1 SQLITE_MISUSE}
120:
121: do_test incrblob3-3.4 { sqlite3_blob_bytes {} } {0}
122:
123: do_test incrblob3-3.5 { sqlite3_blob_close {} } {}
124:
125: # Test out-of-range reading and writing
126: #
127: do_test incrblob3-4.1 {
128: set ::blob [db incrblob blobs v 1]
129: sqlite3_blob_bytes $::blob
130: } {100}
131: do_test incrblob3-4.2 {
132: list [catch { sqlite3_blob_read $::blob -1 10 } msg] $msg
133: } {1 SQLITE_ERROR}
134: do_test incrblob3-4.3 {
135: list [catch { sqlite3_blob_read $::blob 0 -10 } msg] $msg
136: } {1 SQLITE_ERROR}
137: do_test incrblob3-4.4 {
138: list [catch { sqlite3_blob_read $::blob 95 10 } msg] $msg
139: } {1 SQLITE_ERROR}
140: do_test incrblob3-4.5 {
141: list [catch { sqlite3_blob_write $::blob -1 "abcdefghij" 10 } msg] $msg
142: } {1 SQLITE_ERROR}
143: do_test incrblob3-4.6 {
144: list [catch { sqlite3_blob_write $::blob 0 "abcdefghij" -10 } msg] $msg
145: } {1 SQLITE_ERROR}
146: do_test incrblob3-4.7 {
147: list [catch { sqlite3_blob_write $::blob 95 "abcdefghij" } msg] $msg
148: } {1 SQLITE_ERROR}
149:
150: do_test incrblob3-4.8 { close $::blob } {}
151:
152: # Test that modifying the row a blob handle points to aborts the blob.
153: #
154: do_test incrblob3-5.1 {
155: set ::blob [db incrblob blobs v 1]
156: sqlite3_blob_bytes $::blob
157: } {100}
158: do_test incrblob3-5.2 {
159: execsql { UPDATE blobs SET v = '123456789012345678901234567890' WHERE k = 1 }
160: list [catch { sqlite3_blob_read $::blob 0 10 } msg] $msg
161: } {1 SQLITE_ABORT}
162:
163: # Test various errors that can occur in sqlite3_blob_open():
164: #
165: # 1. Trying to open a virtual table column.
166: # 2. Trying to open a view column.
167: # 3. Trying to open a column that does not exist.
168: # 4. Trying to open a read/write handle on an indexed column.
169: # 5. Trying to open a read/write handle on the child key of an FK constraint.
170: #
171: ifcapable fts3 {
172: do_test incrblob3-6.1 {
173: execsql {
174: CREATE VIRTUAL TABLE ft USING fts3;
175: INSERT INTO ft VALUES('rules to open a column to which');
176: }
177:
178: list [catch { db incrblob ft content 1 } msg] $msg
179: } {1 {cannot open virtual table: ft}}
180: }
181: ifcapable view {
182: do_test incrblob3-6.2 {
183: execsql { CREATE VIEW v1 AS SELECT * FROM blobs }
184: list [catch { db incrblob v1 content 1 } msg] $msg
185: } {1 {cannot open view: v1}}
186: }
187:
188: do_test incrblob3-6.3 {
189: list [catch { db incrblob blobs content 1 } msg] $msg
190: } {1 {no such column: "content"}}
191:
192: do_test incrblob3-6.4.1 {
193: execsql {
194: CREATE TABLE t1(a, b);
195: CREATE INDEX i1 ON t1(b);
196: INSERT INTO t1 VALUES(zeroblob(100), zeroblob(100));
197: }
198: list [catch { db incrblob t1 b 1 } msg] $msg
199: } {1 {cannot open indexed column for writing}}
200: do_test incrblob3-6.4.2 {
201: set ::blob [db incrblob t1 a 1]
202: close $::blob
203: } {}
204: do_test incrblob3-6.4.3 {
205: set ::blob [db incrblob -readonly t1 b 1]
206: close $::blob
207: } {}
208:
209: do_test incrblob3-6.5.1 {
210: execsql {
211: CREATE TABLE p1(a PRIMARY KEY);
212: CREATE TABLE c1(a, b REFERENCES p1);
213: PRAGMA foreign_keys = 1;
214: INSERT INTO p1 VALUES(zeroblob(100));
215: INSERT INTO c1 VALUES(zeroblob(100), zeroblob(100));
216: }
217: list [catch { db incrblob c1 b 1 } msg] $msg
218: } {1 {cannot open foreign key column for writing}}
219:
220: do_test incrblob3-6.5.2 {
221: set ::blob [db incrblob c1 a 1]
222: close $::blob
223: } {}
224: do_test incrblob3-6.5.3 {
225: set ::blob [db incrblob -readonly c1 b 1]
226: close $::blob
227: } {}
228: do_test incrblob3-6.5.4 {
229: execsql { PRAGMA foreign_keys = 0 }
230: set ::blob [db incrblob c1 b 1]
231: close $::blob
232: } {}
233:
234:
235: # Test that sqlite3_blob_open() handles transient and persistent schema
236: # errors correctly.
237: #
238: do_test incrblob3-7.1 {
239: sqlite3 db2 test.db
240: sqlite3_db_config_lookaside db2 0 0 0
241: execsql { CREATE TABLE t2(x) } db2
242: set ::blob [db incrblob blobs v 1]
243: close $::blob
244: } {}
245: db2 close
246:
247: testvfs tvfs -default 1
248: tvfs filter xAccess
249: tvfs script access_method
250:
251: proc access_method {args} {
252: set schemacookie [hexio_get_int [hexio_read test.db 40 4]]
253: incr schemacookie
254: hexio_write test.db 40 [hexio_render_int32 $schemacookie]
255:
256: set dbversion [hexio_get_int [hexio_read test.db 24 4]]
257: incr dbversion
258: hexio_write test.db 24 [hexio_render_int32 $dbversion]
259:
260: return ""
261: }
262:
263: do_test incrblob3-7.2 {
264: sqlite3 db test.db
265: sqlite3_db_config_lookaside db 0 0 0
266: list [catch {db incrblob blobs v 1} msg] $msg
267: } {1 {database schema has changed}}
268: db close
269: tvfs delete
270:
271: finish_test
272:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>