/* ** Move data out of a btree key or data field and into a Mem structure. ** The data or key is taken from the entry that pCur is currently pointing ** to. offset and amt determine what portion of the data or key to retrieve. ** key is true to get the key or false to get data. The result is written ** into the pMem element. ** ** The pMem structure is assumed to be uninitialized. Any prior content ** is overwritten without being freed. ** ** If this routine fails for any reason (malloc returns NULL or unable ** to read from the disk) then the pMem is left in an inconsistent state. */ int sqlite3VdbeMemFromBtree( BtCursor *pCur, /* Cursor pointing at record to retrieve. */ int offset, /* Offset from the start of data to return bytes from. */ int amt, /* Number of bytes to return. */ int key, /* If true, retrieve from the btree key, not data. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ char *zData; /* Data from the btree layer */ int available = 0; /* Number of bytes available on the local btree page */ sqlite3 *db; /* Database connection */ int rc = SQLITE_OK; db = sqlite3BtreeCursorDb(pCur); assert( sqlite3_mutex_held(db->mutex) ); assert( (pMem->flags & MEM_RowSet)==0 ); if( key ){ zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); }else{ zData = (char *)sqlite3BtreeDataFetch(pCur, &available); } assert( zData!=0 ); if( offset+amt<=available && ((pMem->flags&MEM_Dyn)==0 || pMem->xDel) ){ sqlite3VdbeMemRelease(pMem); pMem->z = &zData[offset]; pMem->flags = MEM_Blob|MEM_Ephem; }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){ pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term; pMem->enc = 0; pMem->type = SQLITE_BLOB; if( key ){ rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z); }else{ rc = sqlite3BtreeData(pCur, offset, amt, pMem->z); } pMem->z[amt] = 0; pMem->z[amt+1] = 0; if( rc!=SQLITE_OK ){ sqlite3VdbeMemRelease(pMem); } } pMem->n = amt; return rc; }
/* ** Move data out of a btree key or data field and into a Mem structure. ** The data or key is taken from the entry that pCur is currently pointing ** to. offset and amt determine what portion of the data or key to retrieve. ** key is true to get the key or false to get data. The result is written ** into the pMem element. ** ** The pMem structure is assumed to be uninitialized. Any prior content ** is overwritten without being freed. ** ** If this routine fails for any reason (malloc returns NULL or unable ** to read from the disk) then the pMem is left in an inconsistent state. */ int sqlite3VdbeMemFromBtree( BtCursor *pCur, /* Cursor pointing at record to retrieve. */ int offset, /* Offset from the start of data to return bytes from. */ int amt, /* Number of bytes to return. */ int key, /* If true, retrieve from the btree key, not data. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ char *zData; /* Data from the btree layer */ int available = 0; /* Number of bytes available on the local btree page */ sqlite3 *db; /* Database connection */ db = sqlite3BtreeCursorDb(pCur); assert( sqlite3_mutex_held(db->mutex) ); if( key ){ zData = (char *)sqlite3BtreeKeyFetch(pCur, &available); }else{ zData = (char *)sqlite3BtreeDataFetch(pCur, &available); } assert( zData!=0 ); pMem->db = db; pMem->n = amt; if( offset+amt<=available ){ pMem->z = &zData[offset]; pMem->flags = MEM_Blob|MEM_Ephem; }else{ int rc; if( amt>NBFS-2 ){ zData = (char *)sqlite3DbMallocRaw(db, amt+2); if( !zData ){ return SQLITE_NOMEM; } pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term; pMem->xDel = 0; }else{ zData = &(pMem->zShort[0]); pMem->flags = MEM_Blob|MEM_Short|MEM_Term; } pMem->z = zData; pMem->enc = 0; pMem->type = SQLITE_BLOB; if( key ){ rc = sqlite3BtreeKey(pCur, offset, amt, zData); }else{ rc = sqlite3BtreeData(pCur, offset, amt, zData); } zData[amt] = 0; zData[amt+1] = 0; if( rc!=SQLITE_OK ){ if( amt>NBFS-2 ){ assert( zData!=pMem->zShort ); assert( pMem->flags & MEM_Dyn ); sqlite3_free(zData); } else { assert( zData==pMem->zShort ); assert( pMem->flags & MEM_Short ); } return rc; } } return SQLITE_OK; }