1.1 --- a/extensions/sqlite/sqlite-source/vdbeblob.c Fri Jul 11 06:51:21 2008 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,340 +0,0 @@
1.4 -/*
1.5 -** 2007 May 1
1.6 -**
1.7 -** The author disclaims copyright to this source code. In place of
1.8 -** a legal notice, here is a blessing:
1.9 -**
1.10 -** May you do good and not evil.
1.11 -** May you find forgiveness for yourself and forgive others.
1.12 -** May you share freely, never taking more than you give.
1.13 -**
1.14 -*************************************************************************
1.15 -**
1.16 -** This file contains code used to implement incremental BLOB I/O.
1.17 -**
1.18 -** $Id$
1.19 -*/
1.20 -
1.21 -#include "sqliteInt.h"
1.22 -#include "vdbeInt.h"
1.23 -
1.24 -#ifndef SQLITE_OMIT_INCRBLOB
1.25 -
1.26 -/*
1.27 -** Valid sqlite3_blob* handles point to Incrblob structures.
1.28 -*/
1.29 -typedef struct Incrblob Incrblob;
1.30 -struct Incrblob {
1.31 - int flags; /* Copy of "flags" passed to sqlite3_blob_open() */
1.32 - int nByte; /* Size of open blob, in bytes */
1.33 - int iOffset; /* Byte offset of blob in cursor data */
1.34 - BtCursor *pCsr; /* Cursor pointing at blob row */
1.35 - sqlite3_stmt *pStmt; /* Statement holding cursor open */
1.36 - sqlite3 *db; /* The associated database */
1.37 -};
1.38 -
1.39 -/*
1.40 -** Open a blob handle.
1.41 -*/
1.42 -int sqlite3_blob_open(
1.43 - sqlite3* db, /* The database connection */
1.44 - const char *zDb, /* The attached database containing the blob */
1.45 - const char *zTable, /* The table containing the blob */
1.46 - const char *zColumn, /* The column containing the blob */
1.47 - sqlite_int64 iRow, /* The row containing the glob */
1.48 - int flags, /* True -> read/write access, false -> read-only */
1.49 - sqlite3_blob **ppBlob /* Handle for accessing the blob returned here */
1.50 -){
1.51 - int nAttempt = 0;
1.52 - int iCol; /* Index of zColumn in row-record */
1.53 -
1.54 - /* This VDBE program seeks a btree cursor to the identified
1.55 - ** db/table/row entry. The reason for using a vdbe program instead
1.56 - ** of writing code to use the b-tree layer directly is that the
1.57 - ** vdbe program will take advantage of the various transaction,
1.58 - ** locking and error handling infrastructure built into the vdbe.
1.59 - **
1.60 - ** After seeking the cursor, the vdbe executes an OP_Callback.
1.61 - ** Code external to the Vdbe then "borrows" the b-tree cursor and
1.62 - ** uses it to implement the blob_read(), blob_write() and
1.63 - ** blob_bytes() functions.
1.64 - **
1.65 - ** The sqlite3_blob_close() function finalizes the vdbe program,
1.66 - ** which closes the b-tree cursor and (possibly) commits the
1.67 - ** transaction.
1.68 - */
1.69 - static const VdbeOpList openBlob[] = {
1.70 - {OP_Transaction, 0, 0, 0}, /* 0: Start a transaction */
1.71 - {OP_VerifyCookie, 0, 0, 0}, /* 1: Check the schema cookie */
1.72 - {OP_Integer, 0, 0, 0}, /* 2: Database number */
1.73 -
1.74 - /* One of the following two instructions is replaced by an
1.75 - ** OP_Noop before exection.
1.76 - */
1.77 - {OP_OpenRead, 0, 0, 0}, /* 3: Open cursor 0 for reading */
1.78 - {OP_OpenWrite, 0, 0, 0}, /* 4: Open cursor 0 for read/write */
1.79 - {OP_SetNumColumns, 0, 0, 0}, /* 5: Num cols for cursor */
1.80 -
1.81 - {OP_Variable, 1, 0, 0}, /* 6: Push the rowid to the stack */
1.82 - {OP_NotExists, 0, 10, 0}, /* 7: Seek the cursor */
1.83 - {OP_Column, 0, 0, 0}, /* 8 */
1.84 - {OP_Callback, 0, 0, 0}, /* 9 */
1.85 - {OP_Close, 0, 0, 0}, /* 10 */
1.86 - {OP_Halt, 0, 0, 0}, /* 11 */
1.87 - };
1.88 -
1.89 - Vdbe *v = 0;
1.90 - int rc = SQLITE_OK;
1.91 - char zErr[128];
1.92 -
1.93 - zErr[0] = 0;
1.94 - sqlite3_mutex_enter(db->mutex);
1.95 - do {
1.96 - Parse sParse;
1.97 - Table *pTab;
1.98 -
1.99 - memset(&sParse, 0, sizeof(Parse));
1.100 - sParse.db = db;
1.101 -
1.102 - rc = sqlite3SafetyOn(db);
1.103 - if( rc!=SQLITE_OK ){
1.104 - sqlite3_mutex_leave(db->mutex);
1.105 - return rc;
1.106 - }
1.107 -
1.108 - sqlite3BtreeEnterAll(db);
1.109 - pTab = sqlite3LocateTable(&sParse, zTable, zDb);
1.110 - if( !pTab ){
1.111 - if( sParse.zErrMsg ){
1.112 - sqlite3_snprintf(sizeof(zErr), zErr, "%s", sParse.zErrMsg);
1.113 - }
1.114 - sqlite3_free(sParse.zErrMsg);
1.115 - rc = SQLITE_ERROR;
1.116 - sqlite3SafetyOff(db);
1.117 - sqlite3BtreeLeaveAll(db);
1.118 - goto blob_open_out;
1.119 - }
1.120 -
1.121 - /* Now search pTab for the exact column. */
1.122 - for(iCol=0; iCol < pTab->nCol; iCol++) {
1.123 - if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){
1.124 - break;
1.125 - }
1.126 - }
1.127 - if( iCol==pTab->nCol ){
1.128 - sqlite3_snprintf(sizeof(zErr), zErr, "no such column: \"%s\"", zColumn);
1.129 - rc = SQLITE_ERROR;
1.130 - sqlite3SafetyOff(db);
1.131 - sqlite3BtreeLeaveAll(db);
1.132 - goto blob_open_out;
1.133 - }
1.134 -
1.135 - /* If the value is being opened for writing, check that the
1.136 - ** column is not indexed. It is against the rules to open an
1.137 - ** indexed column for writing.
1.138 - */
1.139 - if( flags ){
1.140 - Index *pIdx;
1.141 - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
1.142 - int j;
1.143 - for(j=0; j<pIdx->nColumn; j++){
1.144 - if( pIdx->aiColumn[j]==iCol ){
1.145 - sqlite3_snprintf(sizeof(zErr), zErr,
1.146 - "cannot open indexed column for writing");
1.147 - rc = SQLITE_ERROR;
1.148 - sqlite3SafetyOff(db);
1.149 - sqlite3BtreeLeaveAll(db);
1.150 - goto blob_open_out;
1.151 - }
1.152 - }
1.153 - }
1.154 - }
1.155 -
1.156 - v = sqlite3VdbeCreate(db);
1.157 - if( v ){
1.158 - int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
1.159 - sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob);
1.160 -
1.161 - /* Configure the OP_Transaction */
1.162 - sqlite3VdbeChangeP1(v, 0, iDb);
1.163 - sqlite3VdbeChangeP2(v, 0, (flags ? 1 : 0));
1.164 -
1.165 - /* Configure the OP_VerifyCookie */
1.166 - sqlite3VdbeChangeP1(v, 1, iDb);
1.167 - sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie);
1.168 -
1.169 - /* Make sure a mutex is held on the table to be accessed */
1.170 - sqlite3VdbeUsesBtree(v, iDb);
1.171 -
1.172 - /* Configure the db number pushed onto the stack */
1.173 - sqlite3VdbeChangeP1(v, 2, iDb);
1.174 -
1.175 - /* Remove either the OP_OpenWrite or OpenRead. Set the P2
1.176 - ** parameter of the other to pTab->tnum.
1.177 - */
1.178 - sqlite3VdbeChangeToNoop(v, (flags ? 3 : 4), 1);
1.179 - sqlite3VdbeChangeP2(v, (flags ? 4 : 3), pTab->tnum);
1.180 -
1.181 - /* Configure the OP_SetNumColumns. Configure the cursor to
1.182 - ** think that the table has one more column than it really
1.183 - ** does. An OP_Column to retrieve this imaginary column will
1.184 - ** always return an SQL NULL. This is useful because it means
1.185 - ** we can invoke OP_Column to fill in the vdbe cursors type
1.186 - ** and offset cache without causing any IO.
1.187 - */
1.188 - sqlite3VdbeChangeP2(v, 5, pTab->nCol+1);
1.189 - if( !db->mallocFailed ){
1.190 - sqlite3VdbeMakeReady(v, 1, 0, 1, 0);
1.191 - }
1.192 - }
1.193 -
1.194 - sqlite3BtreeLeaveAll(db);
1.195 - rc = sqlite3SafetyOff(db);
1.196 - if( rc!=SQLITE_OK || db->mallocFailed ){
1.197 - goto blob_open_out;
1.198 - }
1.199 -
1.200 - sqlite3_bind_int64((sqlite3_stmt *)v, 1, iRow);
1.201 - rc = sqlite3_step((sqlite3_stmt *)v);
1.202 - if( rc!=SQLITE_ROW ){
1.203 - nAttempt++;
1.204 - rc = sqlite3_finalize((sqlite3_stmt *)v);
1.205 - sqlite3_snprintf(sizeof(zErr), zErr, sqlite3_errmsg(db));
1.206 - v = 0;
1.207 - }
1.208 - } while( nAttempt<5 && rc==SQLITE_SCHEMA );
1.209 -
1.210 - if( rc==SQLITE_ROW ){
1.211 - /* The row-record has been opened successfully. Check that the
1.212 - ** column in question contains text or a blob. If it contains
1.213 - ** text, it is up to the caller to get the encoding right.
1.214 - */
1.215 - Incrblob *pBlob;
1.216 - u32 type = v->apCsr[0]->aType[iCol];
1.217 -
1.218 - if( type<12 ){
1.219 - sqlite3_snprintf(sizeof(zErr), zErr, "cannot open value of type %s",
1.220 - type==0?"null": type==7?"real": "integer"
1.221 - );
1.222 - rc = SQLITE_ERROR;
1.223 - goto blob_open_out;
1.224 - }
1.225 - pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
1.226 - if( db->mallocFailed ){
1.227 - sqlite3_free(pBlob);
1.228 - goto blob_open_out;
1.229 - }
1.230 - pBlob->flags = flags;
1.231 - pBlob->pCsr = v->apCsr[0]->pCursor;
1.232 - sqlite3BtreeEnterCursor(pBlob->pCsr);
1.233 - sqlite3BtreeCacheOverflow(pBlob->pCsr);
1.234 - sqlite3BtreeLeaveCursor(pBlob->pCsr);
1.235 - pBlob->pStmt = (sqlite3_stmt *)v;
1.236 - pBlob->iOffset = v->apCsr[0]->aOffset[iCol];
1.237 - pBlob->nByte = sqlite3VdbeSerialTypeLen(type);
1.238 - pBlob->db = db;
1.239 - *ppBlob = (sqlite3_blob *)pBlob;
1.240 - rc = SQLITE_OK;
1.241 - }else if( rc==SQLITE_OK ){
1.242 - sqlite3_snprintf(sizeof(zErr), zErr, "no such rowid: %lld", iRow);
1.243 - rc = SQLITE_ERROR;
1.244 - }
1.245 -
1.246 -blob_open_out:
1.247 - zErr[sizeof(zErr)-1] = '\0';
1.248 - if( rc!=SQLITE_OK || db->mallocFailed ){
1.249 - sqlite3_finalize((sqlite3_stmt *)v);
1.250 - }
1.251 - sqlite3Error(db, rc, (rc==SQLITE_OK?0:zErr));
1.252 - rc = sqlite3ApiExit(db, rc);
1.253 - sqlite3_mutex_leave(db->mutex);
1.254 - return rc;
1.255 -}
1.256 -
1.257 -/*
1.258 -** Close a blob handle that was previously created using
1.259 -** sqlite3_blob_open().
1.260 -*/
1.261 -int sqlite3_blob_close(sqlite3_blob *pBlob){
1.262 - Incrblob *p = (Incrblob *)pBlob;
1.263 - int rc;
1.264 -
1.265 - rc = sqlite3_finalize(p->pStmt);
1.266 - sqlite3_free(p);
1.267 - return rc;
1.268 -}
1.269 -
1.270 -/*
1.271 -** Perform a read or write operation on a blob
1.272 -*/
1.273 -static int blobReadWrite(
1.274 - sqlite3_blob *pBlob,
1.275 - void *z,
1.276 - int n,
1.277 - int iOffset,
1.278 - int (*xCall)(BtCursor*, u32, u32, void*)
1.279 -){
1.280 - int rc;
1.281 - Incrblob *p = (Incrblob *)pBlob;
1.282 - Vdbe *v;
1.283 - sqlite3 *db = p->db;
1.284 -
1.285 - /* Request is out of range. Return a transient error. */
1.286 - if( (iOffset+n)>p->nByte ){
1.287 - return SQLITE_ERROR;
1.288 - }
1.289 - sqlite3_mutex_enter(db->mutex);
1.290 -
1.291 - /* If there is no statement handle, then the blob-handle has
1.292 - ** already been invalidated. Return SQLITE_ABORT in this case.
1.293 - */
1.294 - v = (Vdbe*)p->pStmt;
1.295 - if( v==0 ){
1.296 - rc = SQLITE_ABORT;
1.297 - }else{
1.298 - /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is
1.299 - ** returned, clean-up the statement handle.
1.300 - */
1.301 - assert( db == v->db );
1.302 - sqlite3BtreeEnterCursor(p->pCsr);
1.303 - rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
1.304 - sqlite3BtreeLeaveCursor(p->pCsr);
1.305 - if( rc==SQLITE_ABORT ){
1.306 - sqlite3VdbeFinalize(v);
1.307 - p->pStmt = 0;
1.308 - }else{
1.309 - db->errCode = rc;
1.310 - v->rc = rc;
1.311 - }
1.312 - }
1.313 - rc = sqlite3ApiExit(db, rc);
1.314 - sqlite3_mutex_leave(db->mutex);
1.315 - return rc;
1.316 -}
1.317 -
1.318 -/*
1.319 -** Read data from a blob handle.
1.320 -*/
1.321 -int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){
1.322 - return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData);
1.323 -}
1.324 -
1.325 -/*
1.326 -** Write data to a blob handle.
1.327 -*/
1.328 -int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){
1.329 - return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData);
1.330 -}
1.331 -
1.332 -/*
1.333 -** Query a blob handle for the size of the data.
1.334 -**
1.335 -** The Incrblob.nByte field is fixed for the lifetime of the Incrblob
1.336 -** so no mutex is required for access.
1.337 -*/
1.338 -int sqlite3_blob_bytes(sqlite3_blob *pBlob){
1.339 - Incrblob *p = (Incrblob *)pBlob;
1.340 - return p->nByte;
1.341 -}
1.342 -
1.343 -#endif /* #ifndef SQLITE_OMIT_INCRBLOB */