/ Check-in [39b4ba95]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:If a commit fails due to lock contention right after the COMMIT command, take the database back out of autocommit mode. Do not rollback. This gives the user the chance to try the COMMIT again. (CVS 1551)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 39b4ba95c4a16b28b5e8c7a3331e09cb5796e258
User & Date: drh 2004-06-09 21:01:11
Context
2004-06-09
23:15
Website changes for version 2.8.14. (CVS 1553) check-in: 73afa14a user: drh tags: trunk
21:01
If a commit fails due to lock contention right after the COMMIT command, take the database back out of autocommit mode. Do not rollback. This gives the user the chance to try the COMMIT again. (CVS 1551) check-in: 39b4ba95 user: drh tags: trunk
20:03
Turn on the atomic multifile commit logic. It does not work right yet, but it has at least stopped failing asserts. (CVS 1550) check-in: 3674b25e user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
2274
2275
2276
2277
2278
2279
2280

2281
2282
2283
2284
2285
2286
2287
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.362 2004/06/09 20:03:10 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
  u8 rollback = pOp->p2;

  assert( i==1 || i==0 );
  assert( i==1 || rollback==0 );

  if( i!=db->autoCommit ){
    db->autoCommit = i;

    if( pOp->p2 ){
      sqlite3RollbackAll(db);
    }
  }else{
    sqlite3SetString(&p->zErrMsg,
        (!i)?"cannot start a transaction within a transaction":(
        (rollback)?"cannot rollback - no transaction is active":







|







 







>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.363 2004/06/09 21:01:11 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
  u8 rollback = pOp->p2;

  assert( i==1 || i==0 );
  assert( i==1 || rollback==0 );

  if( i!=db->autoCommit ){
    db->autoCommit = i;
    p->autoCommitOn |= i;
    if( pOp->p2 ){
      sqlite3RollbackAll(db);
    }
  }else{
    sqlite3SetString(&p->zErrMsg,
        (!i)?"cannot start a transaction within a transaction":(
        (rollback)?"cannot rollback - no transaction is active":

Changes to src/vdbeInt.h.

319
320
321
322
323
324
325
326
327
328

329

330
331
332
333
334
335
336
  unsigned uniqueCnt;     /* Used by OP_MakeRecord when P2!=0 */
  int errorAction;        /* Recovery action to do in case of an error */
  int inTempTrans;        /* True if temp database is transactioned */
  int returnStack[100];   /* Return address stack for OP_Gosub & OP_Return */
  int returnDepth;        /* Next unused element in returnStack[] */
  int nResColumn;         /* Number of columns in one row of the result set */
  char **azResColumn;     /* Values for one row of result */ 
  u8 resOnStack;          /* True if there are result values on the stack */
  int popStack;           /* Pop the stack this much on entry to VdbeExec() */
  char *zErrMsg;          /* Error message written here */

  u8 explain;             /* True if EXPLAIN present on SQL command */

};

/*
** The following are allowed values for Vdbe.magic
*/
#define VDBE_MAGIC_INIT     0x26bceaa5    /* Building a VDBE program */
#define VDBE_MAGIC_RUN      0xbdf20da3    /* VDBE is ready to execute */







<


>

>







319
320
321
322
323
324
325

326
327
328
329
330
331
332
333
334
335
336
337
  unsigned uniqueCnt;     /* Used by OP_MakeRecord when P2!=0 */
  int errorAction;        /* Recovery action to do in case of an error */
  int inTempTrans;        /* True if temp database is transactioned */
  int returnStack[100];   /* Return address stack for OP_Gosub & OP_Return */
  int returnDepth;        /* Next unused element in returnStack[] */
  int nResColumn;         /* Number of columns in one row of the result set */
  char **azResColumn;     /* Values for one row of result */ 

  int popStack;           /* Pop the stack this much on entry to VdbeExec() */
  char *zErrMsg;          /* Error message written here */
  u8 resOnStack;          /* True if there are result values on the stack */
  u8 explain;             /* True if EXPLAIN present on SQL command */
  u8 autoCommitOn;        /* True if autocommit got turned on by this program */
};

/*
** The following are allowed values for Vdbe.magic
*/
#define VDBE_MAGIC_INIT     0x26bceaa5    /* Building a VDBE program */
#define VDBE_MAGIC_RUN      0xbdf20da3    /* VDBE is ready to execute */

Changes to src/vdbeaux.c.

967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
....
1130
1131
1132
1133
1134
1135
1136










1137

1138
1139
1140
1141
1142
1143
1144
    OsFile master;

    /* Select a master journal file name */
    do {
      u32 random;
      sqliteFree(zMaster);
      sqlite3Randomness(sizeof(random), &random);
      zMaster = sqlite3MPrintf("%s-mj%08X", zMainFile, random);
      if( !zMaster ){
        return SQLITE_NOMEM;
      }
    }while( sqlite3OsFileExists(zMaster) );

    /* Open the master journal. */
    assert( strlen(zMaster)<db->nMaster );
................................................................................
      ** using this handle and the vdbe program was successful or hit an
      ** 'OR FAIL' constraint. This means a commit is required, which is
      ** handled a little differently from the other options.
      */
      p->rc = vdbeCommit(db);
      if( p->rc!=SQLITE_OK ){
        sqlite3Error(p->db, p->rc, 0);










        xFunc = sqlite3BtreeRollback;

      }
    }else{
      xFunc = sqlite3BtreeRollback;
    }
  }else{
    if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){
      xFunc = sqlite3BtreeCommitStmt;







|







 







>
>
>
>
>
>
>
>
>
>
|
>







967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
....
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
    OsFile master;

    /* Select a master journal file name */
    do {
      u32 random;
      sqliteFree(zMaster);
      sqlite3Randomness(sizeof(random), &random);
      zMaster = sqlite3MPrintf("%s-mj%08X", zMainFile, random&0x7fffffff);
      if( !zMaster ){
        return SQLITE_NOMEM;
      }
    }while( sqlite3OsFileExists(zMaster) );

    /* Open the master journal. */
    assert( strlen(zMaster)<db->nMaster );
................................................................................
      ** using this handle and the vdbe program was successful or hit an
      ** 'OR FAIL' constraint. This means a commit is required, which is
      ** handled a little differently from the other options.
      */
      p->rc = vdbeCommit(db);
      if( p->rc!=SQLITE_OK ){
        sqlite3Error(p->db, p->rc, 0);
        if( p->rc==SQLITE_BUSY && p->autoCommitOn ){
          /* If we just now have turned autocommit on (meaning we just have
          ** finished executing a COMMIT command) but the commit fails due
          ** to lock contention, autocommit back off.  This gives the user
          ** the opportunity to try again after the lock that was preventing
          ** the commit has cleared. */
          db->autoCommit = 0;
        }else{
          /* If the command just executed was not a COMMIT command, then
          ** rollback whatever the results of that command were */
          xFunc = sqlite3BtreeRollback;
        }
      }
    }else{
      xFunc = sqlite3BtreeRollback;
    }
  }else{
    if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){
      xFunc = sqlite3BtreeCommitStmt;

Changes to test/attach2.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
259
260
261
262
263
264
265


266
267

268
269

270
271
















272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: attach2.test,v 1.14 2004/06/09 17:37:29 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl


# Ticket #354
................................................................................
    INSERT INTO t1 VALUES(1, 2)
  }
} {1 {database is locked}}

lock_status 4.9.1 db {main shared temp reserved file2 shared}
lock_status 4.9.2 db2 {main reserved temp reserved file2 reserved}



do_test attach2-4.10 {
  # Release the locks held by handle 'db2'

  execsql {COMMIT} db2
} {}


lock_status 4.10.1 db {main shared temp reserved file2 shared}
















lock_status 4.10.2 db2 {main unlocked temp unlocked file2 unlocked}

do_test attach2-4.11 {
  execsql {SELECT * FROM file2.t1}
} {1 2}
do_test attach2-4.12 {
  execsql {INSERT INTO t1 VALUES(1, 2)}
} {}
do_test attach2-4.13 {
  # Release the locks held by handle 'db'
  execsql {ROLLBACK}
} {}
do_test attach2-4.14 {
  execsql {SELECT * FROM t1} db2
} {}

db close
db2 close
file delete -force test2.db

finish_test







|







 







>
>

<
>
|
<
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

|


|


|
<
<
<
<

|






8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
259
260
261
262
263
264
265
266
267
268

269
270

271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298




299
300
301
302
303
304
305
306
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: attach2.test,v 1.15 2004/06/09 21:01:12 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl


# Ticket #354
................................................................................
    INSERT INTO t1 VALUES(1, 2)
  }
} {1 {database is locked}}

lock_status 4.9.1 db {main shared temp reserved file2 shared}
lock_status 4.9.2 db2 {main reserved temp reserved file2 reserved}

set sqlite_os_trace 0
btree_breakpoint
do_test attach2-4.10 {

  # We cannot commit db2 while db is holding a read-lock
  catchsql {COMMIT} db2

} {1 {database is locked}}

lock_status 4.10.1 db {main shared temp reserved file2 shared}
lock_status 4.10.2 db2 {main reserved temp reserved file2 reserved}

do_test attach2-4.11 {
  # db is able to commit.
  catchsql {COMMIT}
} {0 {}}

lock_status 4.11.1 db {main unlocked temp unlocked file2 unlocked}
lock_status 4.11.2 db2 {main reserved temp reserved file2 reserved}

do_test attach2-4.12 {
  # Now we can commit db2
  catchsql {COMMIT} db2
} {0 {}}

lock_status 4.12.1 db {main unlocked temp unlocked file2 unlocked}
lock_status 4.12.2 db2 {main unlocked temp unlocked file2 unlocked}

do_test attach2-4.13 {
  execsql {SELECT * FROM file2.t1}
} {1 2}
do_test attach2-4.14 {
  execsql {INSERT INTO t1 VALUES(1, 2)}
} {}
do_test attach2-4.15 {




  execsql {SELECT * FROM t1} db2
} {1 2 1 2}

db close
db2 close
file delete -force test2.db

finish_test