Annotation of embedaddon/sqlite3/src/vdbeblob.c, revision 1.1.1.1

1.1       misho       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>