mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-11 01:42:22 +03:00
Improvements to the way sqlite3VdbeAddOpList() works, resulting in a slightly
smaller and faster binary. FossilOrigin-Name: 88ceb588bcdb3ca86d0c58cfdeb61b5fe070872f
This commit is contained in:
113
src/vdbeblob.c
113
src/vdbeblob.c
@@ -115,38 +115,6 @@ int sqlite3_blob_open(
|
||||
){
|
||||
int nAttempt = 0;
|
||||
int iCol; /* Index of zColumn in row-record */
|
||||
|
||||
/* This VDBE program seeks a btree cursor to the identified
|
||||
** db/table/row entry. The reason for using a vdbe program instead
|
||||
** of writing code to use the b-tree layer directly is that the
|
||||
** vdbe program will take advantage of the various transaction,
|
||||
** locking and error handling infrastructure built into the vdbe.
|
||||
**
|
||||
** After seeking the cursor, the vdbe executes an OP_ResultRow.
|
||||
** Code external to the Vdbe then "borrows" the b-tree cursor and
|
||||
** uses it to implement the blob_read(), blob_write() and
|
||||
** blob_bytes() functions.
|
||||
**
|
||||
** The sqlite3_blob_close() function finalizes the vdbe program,
|
||||
** which closes the b-tree cursor and (possibly) commits the
|
||||
** transaction.
|
||||
*/
|
||||
static const int iLn = VDBE_OFFSET_LINENO(4);
|
||||
static const VdbeOpList openBlob[] = {
|
||||
/* {OP_Transaction, 0, 0, 0}, // 0: Inserted separately */
|
||||
{OP_TableLock, 0, 0, 0}, /* 1: Acquire a read or write lock */
|
||||
/* One of the following two instructions is replaced by an OP_Noop. */
|
||||
{OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */
|
||||
{OP_OpenWrite, 0, 0, 0}, /* 3: Open cursor 0 for read/write */
|
||||
{OP_Variable, 1, 1, 1}, /* 4: Push the rowid to the stack */
|
||||
{OP_NotExists, 0, 10, 1}, /* 5: Seek the cursor */
|
||||
{OP_Column, 0, 0, 1}, /* 6 */
|
||||
{OP_ResultRow, 1, 0, 0}, /* 7 */
|
||||
{OP_Goto, 0, 4, 0}, /* 8 */
|
||||
{OP_Close, 0, 0, 0}, /* 9 */
|
||||
{OP_Halt, 0, 0, 0}, /* 10 */
|
||||
};
|
||||
|
||||
int rc = SQLITE_OK;
|
||||
char *zErr = 0;
|
||||
Table *pTab;
|
||||
@@ -265,45 +233,80 @@ int sqlite3_blob_open(
|
||||
pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(pParse);
|
||||
assert( pBlob->pStmt || db->mallocFailed );
|
||||
if( pBlob->pStmt ){
|
||||
|
||||
/* This VDBE program seeks a btree cursor to the identified
|
||||
** db/table/row entry. The reason for using a vdbe program instead
|
||||
** of writing code to use the b-tree layer directly is that the
|
||||
** vdbe program will take advantage of the various transaction,
|
||||
** locking and error handling infrastructure built into the vdbe.
|
||||
**
|
||||
** After seeking the cursor, the vdbe executes an OP_ResultRow.
|
||||
** Code external to the Vdbe then "borrows" the b-tree cursor and
|
||||
** uses it to implement the blob_read(), blob_write() and
|
||||
** blob_bytes() functions.
|
||||
**
|
||||
** The sqlite3_blob_close() function finalizes the vdbe program,
|
||||
** which closes the b-tree cursor and (possibly) commits the
|
||||
** transaction.
|
||||
*/
|
||||
static const int iLn = VDBE_OFFSET_LINENO(3);
|
||||
static const VdbeOpList openBlob[] = {
|
||||
/* {OP_Transaction, 0, 0, 0}, // inserted separately */
|
||||
{OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */
|
||||
{OP_OpenRead, 0, 0, 0}, /* 1: Open cursor 0 for reading */
|
||||
{OP_OpenWrite, 0, 0, 0}, /* 2: Open cursor 0 for read/write */
|
||||
{OP_Variable, 1, 1, 1}, /* 3: Push the rowid to the stack */
|
||||
{OP_NotExists, 0, 10, 1}, /* 4: Seek the cursor */
|
||||
{OP_Column, 0, 0, 1}, /* 5 */
|
||||
{OP_ResultRow, 1, 0, 0}, /* 6 */
|
||||
{OP_Goto, 0, 4, 0}, /* 7 */
|
||||
{OP_Close, 0, 0, 0}, /* 8 */
|
||||
{OP_Halt, 0, 0, 0}, /* 9 */
|
||||
};
|
||||
Vdbe *v = (Vdbe *)pBlob->pStmt;
|
||||
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
|
||||
VdbeOp *aOp;
|
||||
|
||||
sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags,
|
||||
pTab->pSchema->schema_cookie,
|
||||
pTab->pSchema->iGeneration);
|
||||
sqlite3VdbeChangeP5(v, 1);
|
||||
sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn);
|
||||
aOp = sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn);
|
||||
|
||||
/* Make sure a mutex is held on the table to be accessed */
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
|
||||
/* Configure the OP_TableLock instruction */
|
||||
if( db->mallocFailed==0 ){
|
||||
assert( aOp!=0 );
|
||||
/* Configure the OP_TableLock instruction */
|
||||
#ifdef SQLITE_OMIT_SHARED_CACHE
|
||||
sqlite3VdbeChangeToNoop(v, 1);
|
||||
aOp[0].opcode = OP_Noop;
|
||||
#else
|
||||
sqlite3VdbeChangeP1(v, 1, iDb);
|
||||
sqlite3VdbeChangeP2(v, 1, pTab->tnum);
|
||||
sqlite3VdbeChangeP3(v, 1, flags);
|
||||
sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT);
|
||||
aOp[0].p1 = iDb;
|
||||
aOp[0].p2 = pTab->tnum;
|
||||
aOp[0].p3 = flags;
|
||||
sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT);
|
||||
}
|
||||
if( db->mallocFailed==0 ){
|
||||
#endif
|
||||
|
||||
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
|
||||
** parameter of the other to pTab->tnum. */
|
||||
sqlite3VdbeChangeToNoop(v, 3 - flags);
|
||||
sqlite3VdbeChangeP2(v, 2 + flags, pTab->tnum);
|
||||
sqlite3VdbeChangeP3(v, 2 + flags, iDb);
|
||||
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
|
||||
** parameter of the other to pTab->tnum. */
|
||||
aOp[2-flags].opcode = OP_Noop;
|
||||
aOp[1+flags].p2 = pTab->tnum;
|
||||
aOp[1+flags].p3 = iDb;
|
||||
|
||||
/* Configure the number of columns. Configure the cursor to
|
||||
** think that the table has one more column than it really
|
||||
** does. An OP_Column to retrieve this imaginary column will
|
||||
** always return an SQL NULL. This is useful because it means
|
||||
** we can invoke OP_Column to fill in the vdbe cursors type
|
||||
** and offset cache without causing any IO.
|
||||
*/
|
||||
aOp[1+flags].p4type = P4_INT32;
|
||||
aOp[1+flags].p4.i = pTab->nCol+1;
|
||||
aOp[5].p2 = pTab->nCol;
|
||||
|
||||
/* Configure the number of columns. Configure the cursor to
|
||||
** think that the table has one more column than it really
|
||||
** does. An OP_Column to retrieve this imaginary column will
|
||||
** always return an SQL NULL. This is useful because it means
|
||||
** we can invoke OP_Column to fill in the vdbe cursors type
|
||||
** and offset cache without causing any IO.
|
||||
*/
|
||||
sqlite3VdbeChangeP4(v, 2+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
|
||||
sqlite3VdbeChangeP2(v, 6, pTab->nCol);
|
||||
if( !db->mallocFailed ){
|
||||
pParse->nVar = 1;
|
||||
pParse->nMem = 1;
|
||||
pParse->nTab = 1;
|
||||
|
||||
Reference in New Issue
Block a user