1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
--- src/vdbe.c
+++ src/vdbe.c
@@ -1215,7 +1215,10 @@
** The statement transaction is never a top-level transaction. Hence
** the RELEASE call below can never fail.
*/
- assert( p->iStatement==0 || db->flags&SQLITE_CountRows );
+ /* assert( p->iStatement==0 || db->flags&SQLITE_CountRows );
+ * This assert does not hold true when read/write incrblobs are used with
+ * Berkeley DB because p->iStatement is set to true in order to create a
+ * statement transaction that is donated to the incrblob cursor. BDB */
rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE);
if( NEVER(rc!=SQLITE_OK) ){
break;
@@ -3001,7 +3004,7 @@
goto abort_due_to_error;
}
- if( pOp->p2 && p->usesStmtJournal
+ if( pOp->p2 && (!db->aVTrans || p->usesStmtJournal)
&& (db->autoCommit==0 || db->nVdbeRead>1)
){
assert( sqlite3BtreeIsInTrans(pBt) );
@@ -6273,6 +6276,14 @@
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(rc, "statement aborts at %d: [%s] %s",
pc, p->zSql, p->zErrMsg);
+ /* Force a rollback if a locked or busy error happens. BDBSQL*/
+ if ( p->rc == SQLITE_LOCKED || p->rc == SQLITE_BUSY ) {
+ p->errorAction = OE_Abort;
+ if (p->readOnly) {
+ db->nStatement++;
+ p->iStatement = db->nStatement + db->nSavepoint;
+ }
+ }
sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
rc = SQLITE_ERROR;
--- src/vdbeblob.c
+++ src/vdbeblob.c
@@ -156,6 +156,7 @@
Table *pTab;
Parse *pParse = 0;
Incrblob *pBlob = 0;
+ int iDb;
flags = !!flags; /* flags = (flags ? 1 : 0); */
*ppBlob = 0;
@@ -259,7 +260,7 @@
assert( pBlob->pStmt || db->mallocFailed );
if( pBlob->pStmt ){
Vdbe *v = (Vdbe *)pBlob->pStmt;
- int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob);
@@ -307,6 +308,10 @@
pParse->nTab = 1;
sqlite3VdbeMakeReady(v, pParse);
}
+ /* This will prevent the statement transaction from being committed,
+ * which would invalidate the incrblob cursor. BDB */
+ if( flags )
+ v->iStatement = db->nSavepoint + 1;
}
pBlob->flags = flags;
|