aboutsummaryrefslogtreecommitdiff
path: root/src/vdbeblob.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2016-01-20 11:33:37 +0000
committerdrh <drh@noemail.net>2016-01-20 11:33:37 +0000
commit20f272c96f2b67c3a3fa6784dcf14a2d5439791e (patch)
tree7b39797e2f7a70fb8d331904f2a563c522a1aca3 /src/vdbeblob.c
parentcb75bff3f7fe12fd3d5dd94acd2832ef1e0dcb65 (diff)
parent5c3aa0517ed8a837e4d70cacbaca5d9e267e0fc3 (diff)
downloadsqlite-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.c115
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;