File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sqlite3 / src / vdbeblob.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:04:17 2012 UTC (12 years, 8 months ago) by misho
Branches: sqlite3, MAIN
CVS tags: v3_7_10, HEAD
sqlite3

    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>