diff options
author | drh <drh@noemail.net> | 2016-01-20 11:33:37 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2016-01-20 11:33:37 +0000 |
commit | 20f272c96f2b67c3a3fa6784dcf14a2d5439791e (patch) | |
tree | 7b39797e2f7a70fb8d331904f2a563c522a1aca3 /src/vdbeblob.c | |
parent | cb75bff3f7fe12fd3d5dd94acd2832ef1e0dcb65 (diff) | |
parent | 5c3aa0517ed8a837e4d70cacbaca5d9e267e0fc3 (diff) | |
download | sqlite-20f272c96f2b67c3a3fa6784dcf14a2d5439791e.tar.gz sqlite-20f272c96f2b67c3a3fa6784dcf14a2d5439791e.zip |
Merge recent enhancements from trunk.
FossilOrigin-Name: 327af5f644a49b2f41d5456958f9d61a2b704e1c
Diffstat (limited to 'src/vdbeblob.c')
-rw-r--r-- | src/vdbeblob.c | 115 |
1 files changed, 59 insertions, 56 deletions
diff --git a/src/vdbeblob.c b/src/vdbeblob.c index c64f815e2..7d343d742 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -117,38 +117,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; @@ -269,45 +237,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(4); + static const VdbeOpList openBlob[] = { + /* addr/ofst */ + /* {OP_Transaction, 0, 0, 0}, // 0/ inserted separately */ + {OP_TableLock, 0, 0, 0}, /* 1/0: Acquire a read or write lock */ + {OP_OpenRead, 0, 0, 0}, /* 2/1: Open a cursor */ + {OP_Variable, 1, 1, 0}, /* 3/2: Move ?1 into reg[1] */ + {OP_NotExists, 0, 8, 1}, /* 4/3: Seek the cursor */ + {OP_Column, 0, 0, 1}, /* 5/4 */ + {OP_ResultRow, 1, 0, 0}, /* 6/5 */ + {OP_Goto, 0, 3, 0}, /* 7/6 */ + {OP_Close, 0, 0, 0}, /* 8/7 */ + {OP_Halt, 0, 0, 0}, /* 9/8 */ + }; 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); - - /* 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 ){ + /* Remove either the OP_OpenWrite or OpenRead. Set the P2 + ** parameter of the other to pTab->tnum. */ + if( flags ) aOp[1].opcode = OP_OpenWrite; + aOp[1].p2 = pTab->tnum; + aOp[1].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].p4type = P4_INT32; + aOp[1].p4.i = pTab->nCol+1; + aOp[4].p2 = pTab->nCol; + pParse->nVar = 1; pParse->nMem = 1; pParse->nTab = 1; |