extensions/sqlite/sqlite-source/vdbeblob.c
branchsourcemod-1.1.0
changeset 2283 03a67e41afbc
parent 1951 c7b4237fff50
child 2287 017a725c9d17
     1.1 --- a/extensions/sqlite/sqlite-source/vdbeblob.c	Fri Mar 28 06:21:34 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 */