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