1: /*
2: ** 2007 May 1
3: **
4: ** The author disclaims copyright to this source code. In place of
5: ** a legal notice, here is a blessing:
6: **
7: ** May you do good and not evil.
8: ** May you find forgiveness for yourself and forgive others.
9: ** May you share freely, never taking more than you give.
10: **
11: *************************************************************************
12: **
13: ** This file contains code used to implement incremental BLOB I/O.
14: */
15:
16: #include "sqliteInt.h"
17: #include "vdbeInt.h"
18:
19: #ifndef SQLITE_OMIT_INCRBLOB
20:
21: /*
22: ** Valid sqlite3_blob* handles point to Incrblob structures.
23: */
24: typedef struct Incrblob Incrblob;
25: struct Incrblob {
26: int flags; /* Copy of "flags" passed to sqlite3_blob_open() */
27: int nByte; /* Size of open blob, in bytes */
28: int iOffset; /* Byte offset of blob in cursor data */
29: int iCol; /* Table column this handle is open on */
30: BtCursor *pCsr; /* Cursor pointing at blob row */
31: sqlite3_stmt *pStmt; /* Statement holding cursor open */
32: sqlite3 *db; /* The associated database */
33: };
34:
35:
36: /*
37: ** This function is used by both blob_open() and blob_reopen(). It seeks
38: ** the b-tree cursor associated with blob handle p to point to row iRow.
39: ** If successful, SQLITE_OK is returned and subsequent calls to
40: ** sqlite3_blob_read() or sqlite3_blob_write() access the specified row.
41: **
42: ** If an error occurs, or if the specified row does not exist or does not
43: ** contain a value of type TEXT or BLOB in the column nominated when the
44: ** blob handle was opened, then an error code is returned and *pzErr may
45: ** be set to point to a buffer containing an error message. It is the
46: ** responsibility of the caller to free the error message buffer using
47: ** sqlite3DbFree().
48: **
49: ** If an error does occur, then the b-tree cursor is closed. All subsequent
50: ** calls to sqlite3_blob_read(), blob_write() or blob_reopen() will
51: ** immediately return SQLITE_ABORT.
52: */
53: static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
54: int rc; /* Error code */
55: char *zErr = 0; /* Error message */
56: Vdbe *v = (Vdbe *)p->pStmt;
57:
58: /* Set the value of the SQL statements only variable to integer iRow.
59: ** This is done directly instead of using sqlite3_bind_int64() to avoid
60: ** triggering asserts related to mutexes.
61: */
62: assert( v->aVar[0].flags&MEM_Int );
63: v->aVar[0].u.i = iRow;
64:
65: rc = sqlite3_step(p->pStmt);
66: if( rc==SQLITE_ROW ){
67: u32 type = v->apCsr[0]->aType[p->iCol];
68: if( type<12 ){
69: zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
70: type==0?"null": type==7?"real": "integer"
71: );
72: rc = SQLITE_ERROR;
73: sqlite3_finalize(p->pStmt);
74: p->pStmt = 0;
75: }else{
76: p->iOffset = v->apCsr[0]->aOffset[p->iCol];
77: p->nByte = sqlite3VdbeSerialTypeLen(type);
78: p->pCsr = v->apCsr[0]->pCursor;
79: sqlite3BtreeEnterCursor(p->pCsr);
80: sqlite3BtreeCacheOverflow(p->pCsr);
81: sqlite3BtreeLeaveCursor(p->pCsr);
82: }
83: }
84:
85: if( rc==SQLITE_ROW ){
86: rc = SQLITE_OK;
87: }else if( p->pStmt ){
88: rc = sqlite3_finalize(p->pStmt);
89: p->pStmt = 0;
90: if( rc==SQLITE_OK ){
91: zErr = sqlite3MPrintf(p->db, "no such rowid: %lld", iRow);
92: rc = SQLITE_ERROR;
93: }else{
94: zErr = sqlite3MPrintf(p->db, "%s", sqlite3_errmsg(p->db));
95: }
96: }
97:
98: assert( rc!=SQLITE_OK || zErr==0 );
99: assert( rc!=SQLITE_ROW && rc!=SQLITE_DONE );
100:
101: *pzErr = zErr;
102: return rc;
103: }
104:
105: /*
106: ** Open a blob handle.
107: */
108: int sqlite3_blob_open(
109: sqlite3* db, /* The database connection */
110: const char *zDb, /* The attached database containing the blob */
111: const char *zTable, /* The table containing the blob */
112: const char *zColumn, /* The column containing the blob */
113: sqlite_int64 iRow, /* The row containing the glob */
114: int flags, /* True -> read/write access, false -> read-only */
115: sqlite3_blob **ppBlob /* Handle for accessing the blob returned here */
116: ){
117: int nAttempt = 0;
118: int iCol; /* Index of zColumn in row-record */
119:
120: /* This VDBE program seeks a btree cursor to the identified
121: ** db/table/row entry. The reason for using a vdbe program instead
122: ** of writing code to use the b-tree layer directly is that the
123: ** vdbe program will take advantage of the various transaction,
124: ** locking and error handling infrastructure built into the vdbe.
125: **
126: ** After seeking the cursor, the vdbe executes an OP_ResultRow.
127: ** Code external to the Vdbe then "borrows" the b-tree cursor and
128: ** uses it to implement the blob_read(), blob_write() and
129: ** blob_bytes() functions.
130: **
131: ** The sqlite3_blob_close() function finalizes the vdbe program,
132: ** which closes the b-tree cursor and (possibly) commits the
133: ** transaction.
134: */
135: static const VdbeOpList openBlob[] = {
136: {OP_Transaction, 0, 0, 0}, /* 0: Start a transaction */
137: {OP_VerifyCookie, 0, 0, 0}, /* 1: Check the schema cookie */
138: {OP_TableLock, 0, 0, 0}, /* 2: Acquire a read or write lock */
139:
140: /* One of the following two instructions is replaced by an OP_Noop. */
141: {OP_OpenRead, 0, 0, 0}, /* 3: Open cursor 0 for reading */
142: {OP_OpenWrite, 0, 0, 0}, /* 4: Open cursor 0 for read/write */
143:
144: {OP_Variable, 1, 1, 1}, /* 5: Push the rowid to the stack */
145: {OP_NotExists, 0, 10, 1}, /* 6: Seek the cursor */
146: {OP_Column, 0, 0, 1}, /* 7 */
147: {OP_ResultRow, 1, 0, 0}, /* 8 */
148: {OP_Goto, 0, 5, 0}, /* 9 */
149: {OP_Close, 0, 0, 0}, /* 10 */
150: {OP_Halt, 0, 0, 0}, /* 11 */
151: };
152:
153: int rc = SQLITE_OK;
154: char *zErr = 0;
155: Table *pTab;
156: Parse *pParse = 0;
157: Incrblob *pBlob = 0;
158:
159: flags = !!flags; /* flags = (flags ? 1 : 0); */
160: *ppBlob = 0;
161:
162: sqlite3_mutex_enter(db->mutex);
163:
164: pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
165: if( !pBlob ) goto blob_open_out;
166: pParse = sqlite3StackAllocRaw(db, sizeof(*pParse));
167: if( !pParse ) goto blob_open_out;
168:
169: do {
170: memset(pParse, 0, sizeof(Parse));
171: pParse->db = db;
172: sqlite3DbFree(db, zErr);
173: zErr = 0;
174:
175: sqlite3BtreeEnterAll(db);
176: pTab = sqlite3LocateTable(pParse, 0, zTable, zDb);
177: if( pTab && IsVirtual(pTab) ){
178: pTab = 0;
179: sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable);
180: }
181: #ifndef SQLITE_OMIT_VIEW
182: if( pTab && pTab->pSelect ){
183: pTab = 0;
184: sqlite3ErrorMsg(pParse, "cannot open view: %s", zTable);
185: }
186: #endif
187: if( !pTab ){
188: if( pParse->zErrMsg ){
189: sqlite3DbFree(db, zErr);
190: zErr = pParse->zErrMsg;
191: pParse->zErrMsg = 0;
192: }
193: rc = SQLITE_ERROR;
194: sqlite3BtreeLeaveAll(db);
195: goto blob_open_out;
196: }
197:
198: /* Now search pTab for the exact column. */
199: for(iCol=0; iCol<pTab->nCol; iCol++) {
200: if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){
201: break;
202: }
203: }
204: if( iCol==pTab->nCol ){
205: sqlite3DbFree(db, zErr);
206: zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn);
207: rc = SQLITE_ERROR;
208: sqlite3BtreeLeaveAll(db);
209: goto blob_open_out;
210: }
211:
212: /* If the value is being opened for writing, check that the
213: ** column is not indexed, and that it is not part of a foreign key.
214: ** It is against the rules to open a column to which either of these
215: ** descriptions applies for writing. */
216: if( flags ){
217: const char *zFault = 0;
218: Index *pIdx;
219: #ifndef SQLITE_OMIT_FOREIGN_KEY
220: if( db->flags&SQLITE_ForeignKeys ){
221: /* Check that the column is not part of an FK child key definition. It
222: ** is not necessary to check if it is part of a parent key, as parent
223: ** key columns must be indexed. The check below will pick up this
224: ** case. */
225: FKey *pFKey;
226: for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
227: int j;
228: for(j=0; j<pFKey->nCol; j++){
229: if( pFKey->aCol[j].iFrom==iCol ){
230: zFault = "foreign key";
231: }
232: }
233: }
234: }
235: #endif
236: for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
237: int j;
238: for(j=0; j<pIdx->nColumn; j++){
239: if( pIdx->aiColumn[j]==iCol ){
240: zFault = "indexed";
241: }
242: }
243: }
244: if( zFault ){
245: sqlite3DbFree(db, zErr);
246: zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault);
247: rc = SQLITE_ERROR;
248: sqlite3BtreeLeaveAll(db);
249: goto blob_open_out;
250: }
251: }
252:
253: pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(db);
254: assert( pBlob->pStmt || db->mallocFailed );
255: if( pBlob->pStmt ){
256: Vdbe *v = (Vdbe *)pBlob->pStmt;
257: int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
258:
259: sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob);
260:
261:
262: /* Configure the OP_Transaction */
263: sqlite3VdbeChangeP1(v, 0, iDb);
264: sqlite3VdbeChangeP2(v, 0, flags);
265:
266: /* Configure the OP_VerifyCookie */
267: sqlite3VdbeChangeP1(v, 1, iDb);
268: sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie);
269: sqlite3VdbeChangeP3(v, 1, pTab->pSchema->iGeneration);
270:
271: /* Make sure a mutex is held on the table to be accessed */
272: sqlite3VdbeUsesBtree(v, iDb);
273:
274: /* Configure the OP_TableLock instruction */
275: #ifdef SQLITE_OMIT_SHARED_CACHE
276: sqlite3VdbeChangeToNoop(v, 2);
277: #else
278: sqlite3VdbeChangeP1(v, 2, iDb);
279: sqlite3VdbeChangeP2(v, 2, pTab->tnum);
280: sqlite3VdbeChangeP3(v, 2, flags);
281: sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
282: #endif
283:
284: /* Remove either the OP_OpenWrite or OpenRead. Set the P2
285: ** parameter of the other to pTab->tnum. */
286: sqlite3VdbeChangeToNoop(v, 4 - flags);
287: sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
288: sqlite3VdbeChangeP3(v, 3 + flags, iDb);
289:
290: /* Configure the number of columns. Configure the cursor to
291: ** think that the table has one more column than it really
292: ** does. An OP_Column to retrieve this imaginary column will
293: ** always return an SQL NULL. This is useful because it means
294: ** we can invoke OP_Column to fill in the vdbe cursors type
295: ** and offset cache without causing any IO.
296: */
297: sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
298: sqlite3VdbeChangeP2(v, 7, pTab->nCol);
299: if( !db->mallocFailed ){
300: pParse->nVar = 1;
301: pParse->nMem = 1;
302: pParse->nTab = 1;
303: sqlite3VdbeMakeReady(v, pParse);
304: }
305: }
306:
307: pBlob->flags = flags;
308: pBlob->iCol = iCol;
309: pBlob->db = db;
310: sqlite3BtreeLeaveAll(db);
311: if( db->mallocFailed ){
312: goto blob_open_out;
313: }
314: sqlite3_bind_int64(pBlob->pStmt, 1, iRow);
315: rc = blobSeekToRow(pBlob, iRow, &zErr);
316: } while( (++nAttempt)<5 && rc==SQLITE_SCHEMA );
317:
318: blob_open_out:
319: if( rc==SQLITE_OK && db->mallocFailed==0 ){
320: *ppBlob = (sqlite3_blob *)pBlob;
321: }else{
322: if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt);
323: sqlite3DbFree(db, pBlob);
324: }
325: sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr);
326: sqlite3DbFree(db, zErr);
327: sqlite3StackFree(db, pParse);
328: rc = sqlite3ApiExit(db, rc);
329: sqlite3_mutex_leave(db->mutex);
330: return rc;
331: }
332:
333: /*
334: ** Close a blob handle that was previously created using
335: ** sqlite3_blob_open().
336: */
337: int sqlite3_blob_close(sqlite3_blob *pBlob){
338: Incrblob *p = (Incrblob *)pBlob;
339: int rc;
340: sqlite3 *db;
341:
342: if( p ){
343: db = p->db;
344: sqlite3_mutex_enter(db->mutex);
345: rc = sqlite3_finalize(p->pStmt);
346: sqlite3DbFree(db, p);
347: sqlite3_mutex_leave(db->mutex);
348: }else{
349: rc = SQLITE_OK;
350: }
351: return rc;
352: }
353:
354: /*
355: ** Perform a read or write operation on a blob
356: */
357: static int blobReadWrite(
358: sqlite3_blob *pBlob,
359: void *z,
360: int n,
361: int iOffset,
362: int (*xCall)(BtCursor*, u32, u32, void*)
363: ){
364: int rc;
365: Incrblob *p = (Incrblob *)pBlob;
366: Vdbe *v;
367: sqlite3 *db;
368:
369: if( p==0 ) return SQLITE_MISUSE_BKPT;
370: db = p->db;
371: sqlite3_mutex_enter(db->mutex);
372: v = (Vdbe*)p->pStmt;
373:
374: if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){
375: /* Request is out of range. Return a transient error. */
376: rc = SQLITE_ERROR;
377: sqlite3Error(db, SQLITE_ERROR, 0);
378: }else if( v==0 ){
379: /* If there is no statement handle, then the blob-handle has
380: ** already been invalidated. Return SQLITE_ABORT in this case.
381: */
382: rc = SQLITE_ABORT;
383: }else{
384: /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is
385: ** returned, clean-up the statement handle.
386: */
387: assert( db == v->db );
388: sqlite3BtreeEnterCursor(p->pCsr);
389: rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
390: sqlite3BtreeLeaveCursor(p->pCsr);
391: if( rc==SQLITE_ABORT ){
392: sqlite3VdbeFinalize(v);
393: p->pStmt = 0;
394: }else{
395: db->errCode = rc;
396: v->rc = rc;
397: }
398: }
399: rc = sqlite3ApiExit(db, rc);
400: sqlite3_mutex_leave(db->mutex);
401: return rc;
402: }
403:
404: /*
405: ** Read data from a blob handle.
406: */
407: int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){
408: return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData);
409: }
410:
411: /*
412: ** Write data to a blob handle.
413: */
414: int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){
415: return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData);
416: }
417:
418: /*
419: ** Query a blob handle for the size of the data.
420: **
421: ** The Incrblob.nByte field is fixed for the lifetime of the Incrblob
422: ** so no mutex is required for access.
423: */
424: int sqlite3_blob_bytes(sqlite3_blob *pBlob){
425: Incrblob *p = (Incrblob *)pBlob;
426: return (p && p->pStmt) ? p->nByte : 0;
427: }
428:
429: /*
430: ** Move an existing blob handle to point to a different row of the same
431: ** database table.
432: **
433: ** If an error occurs, or if the specified row does not exist or does not
434: ** contain a blob or text value, then an error code is returned and the
435: ** database handle error code and message set. If this happens, then all
436: ** subsequent calls to sqlite3_blob_xxx() functions (except blob_close())
437: ** immediately return SQLITE_ABORT.
438: */
439: int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
440: int rc;
441: Incrblob *p = (Incrblob *)pBlob;
442: sqlite3 *db;
443:
444: if( p==0 ) return SQLITE_MISUSE_BKPT;
445: db = p->db;
446: sqlite3_mutex_enter(db->mutex);
447:
448: if( p->pStmt==0 ){
449: /* If there is no statement handle, then the blob-handle has
450: ** already been invalidated. Return SQLITE_ABORT in this case.
451: */
452: rc = SQLITE_ABORT;
453: }else{
454: char *zErr;
455: rc = blobSeekToRow(p, iRow, &zErr);
456: if( rc!=SQLITE_OK ){
457: sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr);
458: sqlite3DbFree(db, zErr);
459: }
460: assert( rc!=SQLITE_SCHEMA );
461: }
462:
463: rc = sqlite3ApiExit(db, rc);
464: assert( rc==SQLITE_OK || p->pStmt==0 );
465: sqlite3_mutex_leave(db->mutex);
466: return rc;
467: }
468:
469: #endif /* #ifndef SQLITE_OMIT_INCRBLOB */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>