extensions/sqlite/sqlite-source/vdbeblob.c
author Asher Baker <asherkin@gmail.com>
Thu Apr 26 16:58:18 2012 +0100 (2012-04-26)
changeset 3488 bee90c8ef6c3
parent 1952 b7aa2b626807
permissions -rw-r--r--
Fixed client serials not being unique on Windows (bug 5285, r=psychonic).
ds@1952
     1
/*
ds@1952
     2
** 2007 May 1
ds@1952
     3
**
ds@1952
     4
** The author disclaims copyright to this source code.  In place of
ds@1952
     5
** a legal notice, here is a blessing:
ds@1952
     6
**
ds@1952
     7
**    May you do good and not evil.
ds@1952
     8
**    May you find forgiveness for yourself and forgive others.
ds@1952
     9
**    May you share freely, never taking more than you give.
ds@1952
    10
**
ds@1952
    11
*************************************************************************
ds@1952
    12
**
ds@1952
    13
** This file contains code used to implement incremental BLOB I/O.
ds@1952
    14
**
ds@1952
    15
** $Id$
ds@1952
    16
*/
ds@1952
    17
ds@1952
    18
#include "sqliteInt.h"
ds@1952
    19
#include "vdbeInt.h"
ds@1952
    20
ds@1952
    21
#ifndef SQLITE_OMIT_INCRBLOB
ds@1952
    22
ds@1952
    23
/*
ds@1952
    24
** Valid sqlite3_blob* handles point to Incrblob structures.
ds@1952
    25
*/
ds@1952
    26
typedef struct Incrblob Incrblob;
ds@1952
    27
struct Incrblob {
ds@1952
    28
  int flags;              /* Copy of "flags" passed to sqlite3_blob_open() */
ds@1952
    29
  int nByte;              /* Size of open blob, in bytes */
ds@1952
    30
  int iOffset;            /* Byte offset of blob in cursor data */
ds@1952
    31
  BtCursor *pCsr;         /* Cursor pointing at blob row */
ds@1952
    32
  sqlite3_stmt *pStmt;    /* Statement holding cursor open */
ds@1952
    33
  sqlite3 *db;            /* The associated database */
ds@1952
    34
};
ds@1952
    35
ds@1952
    36
/*
ds@1952
    37
** Open a blob handle.
ds@1952
    38
*/
ds@1952
    39
int sqlite3_blob_open(
ds@1952
    40
  sqlite3* db,            /* The database connection */
ds@1952
    41
  const char *zDb,        /* The attached database containing the blob */
ds@1952
    42
  const char *zTable,     /* The table containing the blob */
ds@1952
    43
  const char *zColumn,    /* The column containing the blob */
ds@1952
    44
  sqlite_int64 iRow,      /* The row containing the glob */
ds@1952
    45
  int flags,              /* True -> read/write access, false -> read-only */
ds@1952
    46
  sqlite3_blob **ppBlob   /* Handle for accessing the blob returned here */
ds@1952
    47
){
ds@1952
    48
  int nAttempt = 0;
ds@1952
    49
  int iCol;               /* Index of zColumn in row-record */
ds@1952
    50
ds@1952
    51
  /* This VDBE program seeks a btree cursor to the identified 
ds@1952
    52
  ** db/table/row entry. The reason for using a vdbe program instead
ds@1952
    53
  ** of writing code to use the b-tree layer directly is that the
ds@1952
    54
  ** vdbe program will take advantage of the various transaction,
ds@1952
    55
  ** locking and error handling infrastructure built into the vdbe.
ds@1952
    56
  **
ds@1952
    57
  ** After seeking the cursor, the vdbe executes an OP_Callback.
ds@1952
    58
  ** Code external to the Vdbe then "borrows" the b-tree cursor and
ds@1952
    59
  ** uses it to implement the blob_read(), blob_write() and 
ds@1952
    60
  ** blob_bytes() functions.
ds@1952
    61
  **
ds@1952
    62
  ** The sqlite3_blob_close() function finalizes the vdbe program,
ds@1952
    63
  ** which closes the b-tree cursor and (possibly) commits the 
ds@1952
    64
  ** transaction.
ds@1952
    65
  */
ds@1952
    66
  static const VdbeOpList openBlob[] = {
ds@1952
    67
    {OP_Transaction, 0, 0, 0},     /* 0: Start a transaction */
ds@1952
    68
    {OP_VerifyCookie, 0, 0, 0},    /* 1: Check the schema cookie */
ds@1952
    69
    {OP_Integer, 0, 0, 0},         /* 2: Database number */
ds@1952
    70
ds@1952
    71
    /* One of the following two instructions is replaced by an
ds@1952
    72
    ** OP_Noop before exection.
ds@1952
    73
    */
ds@1952
    74
    {OP_OpenRead, 0, 0, 0},        /* 3: Open cursor 0 for reading */
ds@1952
    75
    {OP_OpenWrite, 0, 0, 0},       /* 4: Open cursor 0 for read/write */
ds@1952
    76
    {OP_SetNumColumns, 0, 0, 0},   /* 5: Num cols for cursor */
ds@1952
    77
ds@1952
    78
    {OP_Variable, 1, 0, 0},        /* 6: Push the rowid to the stack */
ds@1952
    79
    {OP_NotExists, 0, 10, 0},      /* 7: Seek the cursor */
ds@1952
    80
    {OP_Column, 0, 0, 0},          /* 8  */
ds@1952
    81
    {OP_Callback, 0, 0, 0},        /* 9  */
ds@1952
    82
    {OP_Close, 0, 0, 0},           /* 10 */
ds@1952
    83
    {OP_Halt, 0, 0, 0},            /* 11 */
ds@1952
    84
  };
ds@1952
    85
ds@1952
    86
  Vdbe *v = 0;
ds@1952
    87
  int rc = SQLITE_OK;
ds@1952
    88
  char zErr[128];
ds@1952
    89
ds@1952
    90
  zErr[0] = 0;
ds@1952
    91
  sqlite3_mutex_enter(db->mutex);
ds@1952
    92
  do {
ds@1952
    93
    Parse sParse;
ds@1952
    94
    Table *pTab;
ds@1952
    95
ds@1952
    96
    memset(&sParse, 0, sizeof(Parse));
ds@1952
    97
    sParse.db = db;
ds@1952
    98
ds@1952
    99
    rc = sqlite3SafetyOn(db);
ds@1952
   100
    if( rc!=SQLITE_OK ){
ds@1952
   101
      sqlite3_mutex_leave(db->mutex);
ds@1952
   102
      return rc;
ds@1952
   103
    }
ds@1952
   104
ds@1952
   105
    sqlite3BtreeEnterAll(db);
ds@1952
   106
    pTab = sqlite3LocateTable(&sParse, zTable, zDb);
ds@1952
   107
    if( !pTab ){
ds@1952
   108
      if( sParse.zErrMsg ){
ds@1952
   109
        sqlite3_snprintf(sizeof(zErr), zErr, "%s", sParse.zErrMsg);
ds@1952
   110
      }
ds@1952
   111
      sqlite3_free(sParse.zErrMsg);
ds@1952
   112
      rc = SQLITE_ERROR;
ds@1952
   113
      sqlite3SafetyOff(db);
ds@1952
   114
      sqlite3BtreeLeaveAll(db);
ds@1952
   115
      goto blob_open_out;
ds@1952
   116
    }
ds@1952
   117
ds@1952
   118
    /* Now search pTab for the exact column. */
ds@1952
   119
    for(iCol=0; iCol < pTab->nCol; iCol++) {
ds@1952
   120
      if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){
ds@1952
   121
        break;
ds@1952
   122
      }
ds@1952
   123
    }
ds@1952
   124
    if( iCol==pTab->nCol ){
ds@1952
   125
      sqlite3_snprintf(sizeof(zErr), zErr, "no such column: \"%s\"", zColumn);
ds@1952
   126
      rc = SQLITE_ERROR;
ds@1952
   127
      sqlite3SafetyOff(db);
ds@1952
   128
      sqlite3BtreeLeaveAll(db);
ds@1952
   129
      goto blob_open_out;
ds@1952
   130
    }
ds@1952
   131
ds@1952
   132
    /* If the value is being opened for writing, check that the
ds@1952
   133
    ** column is not indexed. It is against the rules to open an
ds@1952
   134
    ** indexed column for writing.
ds@1952
   135
    */
ds@1952
   136
    if( flags ){
ds@1952
   137
      Index *pIdx;
ds@1952
   138
      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
ds@1952
   139
        int j;
ds@1952
   140
        for(j=0; j<pIdx->nColumn; j++){
ds@1952
   141
          if( pIdx->aiColumn[j]==iCol ){
ds@1952
   142
            sqlite3_snprintf(sizeof(zErr), zErr,
ds@1952
   143
                             "cannot open indexed column for writing");
ds@1952
   144
            rc = SQLITE_ERROR;
ds@1952
   145
            sqlite3SafetyOff(db);
ds@1952
   146
            sqlite3BtreeLeaveAll(db);
ds@1952
   147
            goto blob_open_out;
ds@1952
   148
          }
ds@1952
   149
        }
ds@1952
   150
      }
ds@1952
   151
    }
ds@1952
   152
ds@1952
   153
    v = sqlite3VdbeCreate(db);
ds@1952
   154
    if( v ){
ds@1952
   155
      int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
ds@1952
   156
      sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob);
ds@1952
   157
ds@1952
   158
      /* Configure the OP_Transaction */
ds@1952
   159
      sqlite3VdbeChangeP1(v, 0, iDb);
ds@1952
   160
      sqlite3VdbeChangeP2(v, 0, (flags ? 1 : 0));
ds@1952
   161
ds@1952
   162
      /* Configure the OP_VerifyCookie */
ds@1952
   163
      sqlite3VdbeChangeP1(v, 1, iDb);
ds@1952
   164
      sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie);
ds@1952
   165
ds@1952
   166
      /* Make sure a mutex is held on the table to be accessed */
ds@1952
   167
      sqlite3VdbeUsesBtree(v, iDb); 
ds@1952
   168
ds@1952
   169
      /* Configure the db number pushed onto the stack */
ds@1952
   170
      sqlite3VdbeChangeP1(v, 2, iDb);
ds@1952
   171
ds@1952
   172
      /* Remove either the OP_OpenWrite or OpenRead. Set the P2 
ds@1952
   173
      ** parameter of the other to pTab->tnum. 
ds@1952
   174
      */
ds@1952
   175
      sqlite3VdbeChangeToNoop(v, (flags ? 3 : 4), 1);
ds@1952
   176
      sqlite3VdbeChangeP2(v, (flags ? 4 : 3), pTab->tnum);
ds@1952
   177
ds@1952
   178
      /* Configure the OP_SetNumColumns. Configure the cursor to
ds@1952
   179
      ** think that the table has one more column than it really
ds@1952
   180
      ** does. An OP_Column to retrieve this imaginary column will
ds@1952
   181
      ** always return an SQL NULL. This is useful because it means
ds@1952
   182
      ** we can invoke OP_Column to fill in the vdbe cursors type 
ds@1952
   183
      ** and offset cache without causing any IO.
ds@1952
   184
      */
ds@1952
   185
      sqlite3VdbeChangeP2(v, 5, pTab->nCol+1);
ds@1952
   186
      if( !db->mallocFailed ){
ds@1952
   187
        sqlite3VdbeMakeReady(v, 1, 0, 1, 0);
ds@1952
   188
      }
ds@1952
   189
    }
ds@1952
   190
   
ds@1952
   191
    sqlite3BtreeLeaveAll(db);
ds@1952
   192
    rc = sqlite3SafetyOff(db);
ds@1952
   193
    if( rc!=SQLITE_OK || db->mallocFailed ){
ds@1952
   194
      goto blob_open_out;
ds@1952
   195
    }
ds@1952
   196
ds@1952
   197
    sqlite3_bind_int64((sqlite3_stmt *)v, 1, iRow);
ds@1952
   198
    rc = sqlite3_step((sqlite3_stmt *)v);
ds@1952
   199
    if( rc!=SQLITE_ROW ){
ds@1952
   200
      nAttempt++;
ds@1952
   201
      rc = sqlite3_finalize((sqlite3_stmt *)v);
ds@1952
   202
      sqlite3_snprintf(sizeof(zErr), zErr, sqlite3_errmsg(db));
ds@1952
   203
      v = 0;
ds@1952
   204
    }
ds@1952
   205
  } while( nAttempt<5 && rc==SQLITE_SCHEMA );
ds@1952
   206
ds@1952
   207
  if( rc==SQLITE_ROW ){
ds@1952
   208
    /* The row-record has been opened successfully. Check that the
ds@1952
   209
    ** column in question contains text or a blob. If it contains
ds@1952
   210
    ** text, it is up to the caller to get the encoding right.
ds@1952
   211
    */
ds@1952
   212
    Incrblob *pBlob;
ds@1952
   213
    u32 type = v->apCsr[0]->aType[iCol];
ds@1952
   214
ds@1952
   215
    if( type<12 ){
ds@1952
   216
      sqlite3_snprintf(sizeof(zErr), zErr, "cannot open value of type %s",
ds@1952
   217
          type==0?"null": type==7?"real": "integer"
ds@1952
   218
      );
ds@1952
   219
      rc = SQLITE_ERROR;
ds@1952
   220
      goto blob_open_out;
ds@1952
   221
    }
ds@1952
   222
    pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
ds@1952
   223
    if( db->mallocFailed ){
ds@1952
   224
      sqlite3_free(pBlob);
ds@1952
   225
      goto blob_open_out;
ds@1952
   226
    }
ds@1952
   227
    pBlob->flags = flags;
ds@1952
   228
    pBlob->pCsr =  v->apCsr[0]->pCursor;
ds@1952
   229
    sqlite3BtreeEnterCursor(pBlob->pCsr);
ds@1952
   230
    sqlite3BtreeCacheOverflow(pBlob->pCsr);
ds@1952
   231
    sqlite3BtreeLeaveCursor(pBlob->pCsr);
ds@1952
   232
    pBlob->pStmt = (sqlite3_stmt *)v;
ds@1952
   233
    pBlob->iOffset = v->apCsr[0]->aOffset[iCol];
ds@1952
   234
    pBlob->nByte = sqlite3VdbeSerialTypeLen(type);
ds@1952
   235
    pBlob->db = db;
ds@1952
   236
    *ppBlob = (sqlite3_blob *)pBlob;
ds@1952
   237
    rc = SQLITE_OK;
ds@1952
   238
  }else if( rc==SQLITE_OK ){
ds@1952
   239
    sqlite3_snprintf(sizeof(zErr), zErr, "no such rowid: %lld", iRow);
ds@1952
   240
    rc = SQLITE_ERROR;
ds@1952
   241
  }
ds@1952
   242
ds@1952
   243
blob_open_out:
ds@1952
   244
  zErr[sizeof(zErr)-1] = '\0';
ds@1952
   245
  if( rc!=SQLITE_OK || db->mallocFailed ){
ds@1952
   246
    sqlite3_finalize((sqlite3_stmt *)v);
ds@1952
   247
  }
ds@1952
   248
  sqlite3Error(db, rc, (rc==SQLITE_OK?0:zErr));
ds@1952
   249
  rc = sqlite3ApiExit(db, rc);
ds@1952
   250
  sqlite3_mutex_leave(db->mutex);
ds@1952
   251
  return rc;
ds@1952
   252
}
ds@1952
   253
ds@1952
   254
/*
ds@1952
   255
** Close a blob handle that was previously created using
ds@1952
   256
** sqlite3_blob_open().
ds@1952
   257
*/
ds@1952
   258
int sqlite3_blob_close(sqlite3_blob *pBlob){
ds@1952
   259
  Incrblob *p = (Incrblob *)pBlob;
ds@1952
   260
  int rc;
ds@1952
   261
ds@1952
   262
  rc = sqlite3_finalize(p->pStmt);
ds@1952
   263
  sqlite3_free(p);
ds@1952
   264
  return rc;
ds@1952
   265
}
ds@1952
   266
ds@1952
   267
/*
ds@1952
   268
** Perform a read or write operation on a blob
ds@1952
   269
*/
ds@1952
   270
static int blobReadWrite(
ds@1952
   271
  sqlite3_blob *pBlob, 
ds@1952
   272
  void *z, 
ds@1952
   273
  int n, 
ds@1952
   274
  int iOffset, 
ds@1952
   275
  int (*xCall)(BtCursor*, u32, u32, void*)
ds@1952
   276
){
ds@1952
   277
  int rc;
ds@1952
   278
  Incrblob *p = (Incrblob *)pBlob;
ds@1952
   279
  Vdbe *v;
ds@1952
   280
  sqlite3 *db = p->db;  
ds@1952
   281
ds@1952
   282
  /* Request is out of range. Return a transient error. */
ds@1952
   283
  if( (iOffset+n)>p->nByte ){
ds@1952
   284
    return SQLITE_ERROR;
ds@1952
   285
  }
ds@1952
   286
  sqlite3_mutex_enter(db->mutex);
ds@1952
   287
ds@1952
   288
  /* If there is no statement handle, then the blob-handle has
ds@1952
   289
  ** already been invalidated. Return SQLITE_ABORT in this case.
ds@1952
   290
  */
ds@1952
   291
  v = (Vdbe*)p->pStmt;
ds@1952
   292
  if( v==0 ){
ds@1952
   293
    rc = SQLITE_ABORT;
ds@1952
   294
  }else{
ds@1952
   295
    /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is
ds@1952
   296
    ** returned, clean-up the statement handle.
ds@1952
   297
    */
ds@1952
   298
    assert( db == v->db );
ds@1952
   299
    sqlite3BtreeEnterCursor(p->pCsr);
ds@1952
   300
    rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
ds@1952
   301
    sqlite3BtreeLeaveCursor(p->pCsr);
ds@1952
   302
    if( rc==SQLITE_ABORT ){
ds@1952
   303
      sqlite3VdbeFinalize(v);
ds@1952
   304
      p->pStmt = 0;
ds@1952
   305
    }else{
ds@1952
   306
      db->errCode = rc;
ds@1952
   307
      v->rc = rc;
ds@1952
   308
    }
ds@1952
   309
  }
ds@1952
   310
  rc = sqlite3ApiExit(db, rc);
ds@1952
   311
  sqlite3_mutex_leave(db->mutex);
ds@1952
   312
  return rc;
ds@1952
   313
}
ds@1952
   314
ds@1952
   315
/*
ds@1952
   316
** Read data from a blob handle.
ds@1952
   317
*/
ds@1952
   318
int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){
ds@1952
   319
  return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData);
ds@1952
   320
}
ds@1952
   321
ds@1952
   322
/*
ds@1952
   323
** Write data to a blob handle.
ds@1952
   324
*/
ds@1952
   325
int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){
ds@1952
   326
  return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData);
ds@1952
   327
}
ds@1952
   328
ds@1952
   329
/*
ds@1952
   330
** Query a blob handle for the size of the data.
ds@1952
   331
**
ds@1952
   332
** The Incrblob.nByte field is fixed for the lifetime of the Incrblob
ds@1952
   333
** so no mutex is required for access.
ds@1952
   334
*/
ds@1952
   335
int sqlite3_blob_bytes(sqlite3_blob *pBlob){
ds@1952
   336
  Incrblob *p = (Incrblob *)pBlob;
ds@1952
   337
  return p->nByte;
ds@1952
   338
}
ds@1952
   339
ds@1952
   340
#endif /* #ifndef SQLITE_OMIT_INCRBLOB */