/ Check-in [51f04aaf]
Login

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

Overview
Comment:The COMMIT command now works even if there are pending queries, as long as the pending queries are reading and not writing the database. (CVS 5864)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:51f04aaff2803487933b9dfcf39f27a249f18a98
User & Date: drh 2008-11-05 16:37:35
Context
2008-11-05
17:41
Fix memory allocation problems when string length exceeds limits. (CVS 5865) check-in: b568e325 user: drh tags: trunk
16:37
The COMMIT command now works even if there are pending queries, as long as the pending queries are reading and not writing the database. (CVS 5864) check-in: 51f04aaf user: drh tags: trunk
2008-11-04
21:51
Should be 'memjournal.lo' instead of 'memjournal.o'. Ticket #3480. (CVS 5863) check-in: 8b868604 user: shane tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
695
696
697
698
699
700
701

702
703
704
705
706
707
708
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.787 2008/10/28 18:58:20 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
................................................................................
    int newTnum;                /* Rootpage of table being initialized */
    u8 busy;                    /* TRUE if currently initializing */
  } init;
  int nExtension;               /* Number of loaded extensions */
  void **aExtension;            /* Array of shared libraray handles */
  struct Vdbe *pVdbe;           /* List of active virtual machines */
  int activeVdbeCnt;            /* Number of vdbes currently executing */

  void (*xTrace)(void*,const char*);        /* Trace function */
  void *pTraceArg;                          /* Argument to the trace function */
  void (*xProfile)(void*,const char*,u64);  /* Profiling function */
  void *pProfileArg;                        /* Argument to profile function */
  void *pCommitArg;                 /* Argument to xCommitCallback() */   
  int (*xCommitCallback)(void*);    /* Invoked at every commit. */
  void *pRollbackArg;               /* Argument to xRollbackCallback() */   







|







 







>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.788 2008/11/05 16:37:35 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
................................................................................
    int newTnum;                /* Rootpage of table being initialized */
    u8 busy;                    /* TRUE if currently initializing */
  } init;
  int nExtension;               /* Number of loaded extensions */
  void **aExtension;            /* Array of shared libraray handles */
  struct Vdbe *pVdbe;           /* List of active virtual machines */
  int activeVdbeCnt;            /* Number of vdbes currently executing */
  int writeVdbeCnt;             /* Number of active VDBEs that are writing */
  void (*xTrace)(void*,const char*);        /* Trace function */
  void *pTraceArg;                          /* Argument to the trace function */
  void (*xProfile)(void*,const char*,u64);  /* Profiling function */
  void *pProfileArg;                        /* Argument to profile function */
  void *pCommitArg;                 /* Argument to xCommitCallback() */   
  int (*xCommitCallback)(void*);    /* Invoked at every commit. */
  void *pRollbackArg;               /* Argument to xRollbackCallback() */   

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
2389
2390
2391
2392
2393
2394
2395
2396
2397

2398
2399

2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411






2412
2413
2414
2415

2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
**
** 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.785 2008/11/03 20:55:07 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
................................................................................
** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll
** back any currently active btree transactions. If there are any active
** VMs (apart from this one), then the COMMIT or ROLLBACK statement fails.
**
** This instruction causes the VM to halt.
*/
case OP_AutoCommit: {
  u8 i = pOp->p1;
  u8 rollback = pOp->p2;


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

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

  assert( db->activeVdbeCnt>0 );  /* At least this one VM is active */

  if( db->activeVdbeCnt>1 && i && !db->autoCommit ){
    /* If this instruction implements a COMMIT or ROLLBACK, other VMs are
    ** still running, and a transaction is active, return an error indicating
    ** that the other VMs must complete first. 
    */
    sqlite3SetString(&p->zErrMsg, db, "cannot %s transaction - "
        "SQL statements in progress",
        rollback ? "rollback" : "commit");






    rc = SQLITE_BUSY;
  }else if( i!=db->autoCommit ){
    if( pOp->p2 ){
      assert( i==1 );

      sqlite3RollbackAll(db);
      db->autoCommit = 1;
    }else{
      db->autoCommit = i;
      if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
        p->pc = pc;
        db->autoCommit = 1-i;
        p->rc = rc = SQLITE_BUSY;
        goto vdbe_return;
      }
    }
    if( p->rc==SQLITE_OK ){
      rc = SQLITE_DONE;
    }else{
      rc = SQLITE_ERROR;
    }
    goto vdbe_return;
  }else{
    sqlite3SetString(&p->zErrMsg, db,
        (!i)?"cannot start a transaction within a transaction":(
        (rollback)?"cannot rollback - no transaction is active":
                   "cannot commit - no transaction is active"));
         
    rc = SQLITE_ERROR;
  }
  break;
}







|







 







|
|
>

<
>
|



|
|



|
|
|
>
>
>
>
>
>

|

<
>



|


|












|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399

2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421

2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
**
** 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.786 2008/11/05 16:37:35 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
................................................................................
** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll
** back any currently active btree transactions. If there are any active
** VMs (apart from this one), then the COMMIT or ROLLBACK statement fails.
**
** This instruction causes the VM to halt.
*/
case OP_AutoCommit: {
  int desiredAutoCommit = pOp->p1;
  int rollback = pOp->p2;
  int turnOnAC = desiredAutoCommit && !db->autoCommit;


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

  assert( db->activeVdbeCnt>0 );  /* At least this one VM is active */

  if( turnOnAC && rollback && db->activeVdbeCnt>1 ){
    /* If this instruction implements a ROLLBACK and other VMs are
    ** still running, and a transaction is active, return an error indicating
    ** that the other VMs must complete first. 
    */
    sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - "
        "SQL statements in progress");
    rc = SQLITE_BUSY;
  }else if( turnOnAC && !rollback && db->writeVdbeCnt>1 ){
    /* If this instruction implements a COMMIT and other VMs are writing
    ** return an error indicating that the other VMs must complete first. 
    */
    sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - "
        "SQL statements in progress");
    rc = SQLITE_BUSY;
  }else if( desiredAutoCommit!=db->autoCommit ){
    if( pOp->p2 ){

      assert( desiredAutoCommit==1 );
      sqlite3RollbackAll(db);
      db->autoCommit = 1;
    }else{
      db->autoCommit = desiredAutoCommit;
      if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
        p->pc = pc;
        db->autoCommit = 1-desiredAutoCommit;
        p->rc = rc = SQLITE_BUSY;
        goto vdbe_return;
      }
    }
    if( p->rc==SQLITE_OK ){
      rc = SQLITE_DONE;
    }else{
      rc = SQLITE_ERROR;
    }
    goto vdbe_return;
  }else{
    sqlite3SetString(&p->zErrMsg, db,
        (!desiredAutoCommit)?"cannot start a transaction within a transaction":(
        (rollback)?"cannot rollback - no transaction is active":
                   "cannot commit - no transaction is active"));
         
    rc = SQLITE_ERROR;
  }
  break;
}

Changes to src/vdbeInt.h.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
315
316
317
318
319
320
321


322
323
324
325
326
327
328
*************************************************************************
** This is the header file for information that is private to the
** VDBE.  This information used to all be at the top of the single
** source code file "vdbe.c".  When that file became too big (over
** 6000 lines long) it was split up into several smaller files and
** this header information was factored out.
**
** $Id: vdbeInt.h,v 1.156 2008/11/03 20:55:07 drh Exp $
*/
#ifndef _VDBEINT_H_
#define _VDBEINT_H_

/*
** intToKey() and keyToInt() used to transform the rowid.  But with
** the latest versions of the design they are no-ops.
................................................................................
  char *zErrMsg;          /* Error message written here */
  Mem *pResultSet;        /* Pointer to an array of results */
  u8 explain;             /* True if EXPLAIN present on SQL command */
  u8 changeCntOn;         /* True to update the change-counter */
  u8 expired;             /* True if the VM needs to be recompiled */
  u8 minWriteFileFormat;  /* Minimum file format for writable database files */
  u8 inVtabMethod;        /* See comments above */


  int nChange;            /* Number of db changes made since last reset */
  i64 startTime;          /* Time when query started - used for profiling */
  int btreeMask;          /* Bitmask of db->aDb[] entries referenced */
  BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */
  int aCounter[2];        /* Counters used by sqlite3_stmt_status() */
  int nSql;             /* Number of bytes in zSql */
  char *zSql;           /* Text of the SQL statement that generated this */







|







 







>
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
*************************************************************************
** This is the header file for information that is private to the
** VDBE.  This information used to all be at the top of the single
** source code file "vdbe.c".  When that file became too big (over
** 6000 lines long) it was split up into several smaller files and
** this header information was factored out.
**
** $Id: vdbeInt.h,v 1.157 2008/11/05 16:37:35 drh Exp $
*/
#ifndef _VDBEINT_H_
#define _VDBEINT_H_

/*
** intToKey() and keyToInt() used to transform the rowid.  But with
** the latest versions of the design they are no-ops.
................................................................................
  char *zErrMsg;          /* Error message written here */
  Mem *pResultSet;        /* Pointer to an array of results */
  u8 explain;             /* True if EXPLAIN present on SQL command */
  u8 changeCntOn;         /* True to update the change-counter */
  u8 expired;             /* True if the VM needs to be recompiled */
  u8 minWriteFileFormat;  /* Minimum file format for writable database files */
  u8 inVtabMethod;        /* See comments above */
  u8 usesStmtJournal;     /* True if uses a statement journal */
  u8 readOnly;            /* True for read-only statements */
  int nChange;            /* Number of db changes made since last reset */
  i64 startTime;          /* Time when query started - used for profiling */
  int btreeMask;          /* Bitmask of db->aDb[] entries referenced */
  BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */
  int aCounter[2];        /* Counters used by sqlite3_stmt_status() */
  int nSql;             /* Number of bytes in zSql */
  char *zSql;           /* Text of the SQL statement that generated this */

Changes to src/vdbeapi.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
464
465
466
467
468
469
470

471
472
473
474
475
476
477
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code use to implement APIs that are part of the
** VDBE.
**
** $Id: vdbeapi.c,v 1.147 2008/10/13 10:37:50 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"

#if 0 && defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)
/*
** The following structure contains pointers to the end points of a
................................................................................
      double rNow;
      sqlite3OsCurrentTime(db->pVfs, &rNow);
      p->startTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0;
    }
#endif

    db->activeVdbeCnt++;

    p->pc = 0;
    stmtLruRemove(p);
  }
#ifndef SQLITE_OMIT_EXPLAIN
  if( p->explain ){
    rc = sqlite3VdbeList(p);
  }else







|







 







>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code use to implement APIs that are part of the
** VDBE.
**
** $Id: vdbeapi.c,v 1.148 2008/11/05 16:37:35 drh Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"

#if 0 && defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)
/*
** The following structure contains pointers to the end points of a
................................................................................
      double rNow;
      sqlite3OsCurrentTime(db->pVfs, &rNow);
      p->startTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0;
    }
#endif

    db->activeVdbeCnt++;
    if( p->readOnly==0 ) db->writeVdbeCnt++;
    p->pc = 0;
    stmtLruRemove(p);
  }
#ifndef SQLITE_OMIT_EXPLAIN
  if( p->explain ){
    rc = sqlite3VdbeList(p);
  }else

Changes to src/vdbeaux.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
263
264
265
266
267
268
269


270
271
272
273
274
275
276
...
279
280
281
282
283
284
285

286
287


288
289
290
291
292
293
294
...
309
310
311
312
313
314
315

316
317
318
319
320
321
322
....
1450
1451
1452
1453
1454
1455
1456

1457
1458
1459
1460

1461
1462
1463
1464

1465
1466
1467
1468
1469
1470
1471
....
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587

1588
1589
1590
1591
1592
1593
1594
....
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
....
1679
1680
1681
1682
1683
1684
1685




1686
1687
1688
1689
1690
1691
1692
**
*************************************************************************
** This file contains code used for creating, destroying, and populating
** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
**
** $Id: vdbeaux.c,v 1.416 2008/11/04 14:25:06 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"



................................................................................
static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
  int i;
  int nMaxArgs = 0;
  Op *pOp;
  int *aLabel = p->aLabel;
  int doesStatementRollback = 0;
  int hasStatementBegin = 0;


  for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
    u8 opcode = pOp->opcode;

    if( opcode==OP_Function || opcode==OP_AggStep ){
      if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
#ifndef SQLITE_OMIT_VIRTUALTABLE
    }else if( opcode==OP_VUpdate ){
................................................................................
    }
    if( opcode==OP_Halt ){
      if( pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort ){
        doesStatementRollback = 1;
      }
    }else if( opcode==OP_Statement ){
      hasStatementBegin = 1;

    }else if( opcode==OP_Destroy ){
      doesStatementRollback = 1;


#ifndef SQLITE_OMIT_VIRTUALTABLE
    }else if( opcode==OP_VUpdate || opcode==OP_VRename ){
      doesStatementRollback = 1;
    }else if( opcode==OP_VFilter ){
      int n;
      assert( p->nOp - i >= 3 );
      assert( pOp[-1].opcode==OP_Integer );
................................................................................

  /* If we never rollback a statement transaction, then statement
  ** transactions are not needed.  So change every OP_Statement
  ** opcode into an OP_Noop.  This avoid a call to sqlite3OsOpenExclusive()
  ** which can be expensive on some platforms.
  */
  if( hasStatementBegin && !doesStatementRollback ){

    for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
      if( pOp->opcode==OP_Statement ){
        pOp->opcode = OP_Noop;
      }
    }
  }
}
................................................................................
**
** This is a no-op if NDEBUG is defined.
*/
#ifndef NDEBUG
static void checkActiveVdbeCnt(sqlite3 *db){
  Vdbe *p;
  int cnt = 0;

  p = db->pVdbe;
  while( p ){
    if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){
      cnt++;

    }
    p = p->pNext;
  }
  assert( cnt==db->activeVdbeCnt );

}
#else
#define checkActiveVdbeCnt(x)
#endif

/*
** For every Btree that in database connection db which 
................................................................................
    sqlite3BtreeMutexArrayEnter(&p->aMutex);

    /* Check for one of the special errors */
    mrc = p->rc & 0xff;
    isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
                     || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
    if( isSpecialError ){
      /* This loop does static analysis of the query to see which of the
      ** following three categories it falls into:
      **
      **     Read-only
      **     Query with statement journal
      **     Query without statement journal
      **
      ** We could do something more elegant than this static analysis (i.e.
      ** store the type of query as part of the compliation phase), but 
      ** handling malloc() or IO failure is a fairly obscure edge case so 
      ** this is probably easier. Todo: Might be an opportunity to reduce 
      ** code size a very small amount though...
      */
      int notReadOnly = 0;
      int isStatement = 0;
      assert(p->aOp || p->nOp==0);
      for(i=0; i<p->nOp; i++){ 
        switch( p->aOp[i].opcode ){
          case OP_Transaction:
            notReadOnly |= p->aOp[i].p2;
            break;
          case OP_Statement:
            isStatement = 1;
            break;
        }
      }

   
      /* If the query was read-only, we need do no rollback at all. Otherwise,
      ** proceed with the special handling.
      */
      if( notReadOnly || mrc!=SQLITE_INTERRUPT ){
        if( p->rc==SQLITE_IOERR_BLOCKED && isStatement ){
          xFunc = sqlite3BtreeRollbackStmt;
          p->rc = SQLITE_BUSY;
        } else if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && isStatement ){

          xFunc = sqlite3BtreeRollbackStmt;
        }else{
          /* We are forced to roll back the active transaction. Before doing
          ** so, abort any other statements this handle currently has active.
          */
          invalidateCursorsOnModifiedBtrees(db);
          sqlite3RollbackAll(db);
................................................................................
      }
    }
  
    /* If the auto-commit flag is set and this is the only active vdbe, then
    ** we do either a commit or rollback of the current transaction. 
    **
    ** Note: This block also runs if one of the special errors handled 
    ** above has occured. 
    */
    if( db->autoCommit && db->activeVdbeCnt==1 ){
      if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
        /* The auto-commit flag is true, and the vdbe program was 
        ** successful or hit an 'OR FAIL' constraint. This means a commit 
        ** is required.
        */
        int rc = vdbeCommit(db, p);
        if( rc==SQLITE_BUSY ){
................................................................................
    /* Release the locks */
    sqlite3BtreeMutexArrayLeave(&p->aMutex);
  }

  /* We have successfully halted and closed the VM.  Record this fact. */
  if( p->pc>=0 ){
    db->activeVdbeCnt--;




  }
  p->magic = VDBE_MAGIC_HALT;
  checkActiveVdbeCnt(db);
  if( p->db->mallocFailed ){
    p->rc = SQLITE_NOMEM;
  }








|







 







>
>







 







>


>
>







 







>







 







>




>




>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



|
|


|
>







 







|

|







 







>
>
>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
...
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
....
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
....
1554
1555
1556
1557
1558
1559
1560




























1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
....
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
....
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
**
*************************************************************************
** This file contains code used for creating, destroying, and populating
** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
**
** $Id: vdbeaux.c,v 1.417 2008/11/05 16:37:35 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"



................................................................................
static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
  int i;
  int nMaxArgs = 0;
  Op *pOp;
  int *aLabel = p->aLabel;
  int doesStatementRollback = 0;
  int hasStatementBegin = 0;
  p->readOnly = 1;
  p->usesStmtJournal = 0;
  for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
    u8 opcode = pOp->opcode;

    if( opcode==OP_Function || opcode==OP_AggStep ){
      if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
#ifndef SQLITE_OMIT_VIRTUALTABLE
    }else if( opcode==OP_VUpdate ){
................................................................................
    }
    if( opcode==OP_Halt ){
      if( pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort ){
        doesStatementRollback = 1;
      }
    }else if( opcode==OP_Statement ){
      hasStatementBegin = 1;
      p->usesStmtJournal = 1;
    }else if( opcode==OP_Destroy ){
      doesStatementRollback = 1;
    }else if( opcode==OP_Transaction && pOp->p2!=0 ){
      p->readOnly = 0;
#ifndef SQLITE_OMIT_VIRTUALTABLE
    }else if( opcode==OP_VUpdate || opcode==OP_VRename ){
      doesStatementRollback = 1;
    }else if( opcode==OP_VFilter ){
      int n;
      assert( p->nOp - i >= 3 );
      assert( pOp[-1].opcode==OP_Integer );
................................................................................

  /* If we never rollback a statement transaction, then statement
  ** transactions are not needed.  So change every OP_Statement
  ** opcode into an OP_Noop.  This avoid a call to sqlite3OsOpenExclusive()
  ** which can be expensive on some platforms.
  */
  if( hasStatementBegin && !doesStatementRollback ){
    p->usesStmtJournal = 0;
    for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
      if( pOp->opcode==OP_Statement ){
        pOp->opcode = OP_Noop;
      }
    }
  }
}
................................................................................
**
** This is a no-op if NDEBUG is defined.
*/
#ifndef NDEBUG
static void checkActiveVdbeCnt(sqlite3 *db){
  Vdbe *p;
  int cnt = 0;
  int nWrite = 0;
  p = db->pVdbe;
  while( p ){
    if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){
      cnt++;
      if( p->readOnly==0 ) nWrite++;
    }
    p = p->pNext;
  }
  assert( cnt==db->activeVdbeCnt );
  assert( nWrite==db->writeVdbeCnt );
}
#else
#define checkActiveVdbeCnt(x)
#endif

/*
** For every Btree that in database connection db which 
................................................................................
    sqlite3BtreeMutexArrayEnter(&p->aMutex);

    /* Check for one of the special errors */
    mrc = p->rc & 0xff;
    isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
                     || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
    if( isSpecialError ){




























      /* If the query was read-only, we need do no rollback at all. Otherwise,
      ** proceed with the special handling.
      */
      if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){
        if( p->rc==SQLITE_IOERR_BLOCKED && p->usesStmtJournal ){
          xFunc = sqlite3BtreeRollbackStmt;
          p->rc = SQLITE_BUSY;
        }else if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL)
                   && p->usesStmtJournal ){
          xFunc = sqlite3BtreeRollbackStmt;
        }else{
          /* We are forced to roll back the active transaction. Before doing
          ** so, abort any other statements this handle currently has active.
          */
          invalidateCursorsOnModifiedBtrees(db);
          sqlite3RollbackAll(db);
................................................................................
      }
    }
  
    /* If the auto-commit flag is set and this is the only active vdbe, then
    ** we do either a commit or rollback of the current transaction. 
    **
    ** Note: This block also runs if one of the special errors handled 
    ** above has occurred. 
    */
    if( db->autoCommit && db->writeVdbeCnt==(p->readOnly==0) ){
      if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
        /* The auto-commit flag is true, and the vdbe program was 
        ** successful or hit an 'OR FAIL' constraint. This means a commit 
        ** is required.
        */
        int rc = vdbeCommit(db, p);
        if( rc==SQLITE_BUSY ){
................................................................................
    /* Release the locks */
    sqlite3BtreeMutexArrayLeave(&p->aMutex);
  }

  /* We have successfully halted and closed the VM.  Record this fact. */
  if( p->pc>=0 ){
    db->activeVdbeCnt--;
    if( !p->readOnly ){
      db->writeVdbeCnt--;
    }
    assert( db->activeVdbeCnt>=db->writeVdbeCnt );
  }
  p->magic = VDBE_MAGIC_HALT;
  checkActiveVdbeCnt(db);
  if( p->db->mallocFailed ){
    p->rc = SQLITE_NOMEM;
  }

Changes to test/capi3.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
829
830
831
832
833
834
835




836
837
838
839
840
841
842
843
844
845
846




847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
...
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script testing the callback-free C/C++ API.
#
# $Id: capi3.test,v 1.68 2008/10/30 15:03:16 drh Exp $
#

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

# Return the UTF-16 representation of the supplied UTF-8 string $str.
# If $nt is true, append two 0x00 bytes as a nul terminator.
................................................................................
do_test capi3-11.1.1 {
  sqlite3_get_autocommit $DB
} 0
do_test capi3-11.2 {
  set STMT [sqlite3_prepare $DB "SELECT func(b, a) FROM t1" -1 TAIL]
  sqlite3_step $STMT
} {SQLITE_ROW}




do_test capi3-11.3.1 {
  catchsql {
    COMMIT;
  }
} {1 {cannot commit transaction - SQL statements in progress}}
do_test capi3-11.3.2 {
  sqlite3_extended_errcode $DB
} {SQLITE_BUSY}
do_test capi3-11.3.3 {
  sqlite3_get_autocommit $DB
} 0




do_test capi3-11.4 {
  sqlite3_step $STMT
} {SQLITE_ERROR}
do_test capi3-11.5 {
  sqlite3_finalize $STMT
} {SQLITE_ERROR}
do_test capi3-11.6 {
  catchsql {
    SELECT * FROM t1;
  }
} {0 {1 int 2 notatype}}
do_test capi3-11.6.1 {
  sqlite3_get_autocommit $DB
} 0
do_test capi3-11.7 {
  catchsql {
    COMMIT;
  }
} {0 {}}
do_test capi3-11.7.1 {
  sqlite3_get_autocommit $DB
} 1
do_test capi3-11.8 {
  execsql {
    CREATE TABLE t2(a);
    INSERT INTO t2 VALUES(1);
    INSERT INTO t2 VALUES(2);
................................................................................
  sqlite3_step $STMT
} {SQLITE_ROW}
do_test capi3-11.20 {
  catchsql {
    BEGIN;
    COMMIT;
  }
} {1 {cannot commit transaction - SQL statements in progress}}
do_test capi3-11.20 {
  sqlite3_reset $STMT
  catchsql {
    COMMIT;
  }
} {0 {}}
do_test capi3-11.21 {
  sqlite3_finalize $STMT
} {SQLITE_OK}

# The following tests - capi3-12.* - check that its Ok to start a
# transaction while other VMs are active, and that its Ok to execute
# atomic updates in the same situation 







|







 







>
>
>
>




|


|


|
>
>
>
>











<
<
<

<
<
<
<
<







 







|





|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865



866





867
868
869
870
871
872
873
...
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script testing the callback-free C/C++ API.
#
# $Id: capi3.test,v 1.69 2008/11/05 16:37:35 drh Exp $
#

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

# Return the UTF-16 representation of the supplied UTF-8 string $str.
# If $nt is true, append two 0x00 bytes as a nul terminator.
................................................................................
do_test capi3-11.1.1 {
  sqlite3_get_autocommit $DB
} 0
do_test capi3-11.2 {
  set STMT [sqlite3_prepare $DB "SELECT func(b, a) FROM t1" -1 TAIL]
  sqlite3_step $STMT
} {SQLITE_ROW}

# As of 3.6.5 a COMMIT is OK during while a query is still running -
# as long as it is a read-only query and not an incremental BLOB write.
#
do_test capi3-11.3.1 {
  catchsql {
    COMMIT;
  }
} {0 {}}
do_test capi3-11.3.2 {
  sqlite3_extended_errcode $DB
} {SQLITE_OK}
do_test capi3-11.3.3 {
  sqlite3_get_autocommit $DB
} 1
do_test capi3-11.3.4 {
  db eval {PRAGMA lock_status}
} {main shared temp closed}

do_test capi3-11.4 {
  sqlite3_step $STMT
} {SQLITE_ERROR}
do_test capi3-11.5 {
  sqlite3_finalize $STMT
} {SQLITE_ERROR}
do_test capi3-11.6 {
  catchsql {
    SELECT * FROM t1;
  }
} {0 {1 int 2 notatype}}



do_test capi3-11.7 {





  sqlite3_get_autocommit $DB
} 1
do_test capi3-11.8 {
  execsql {
    CREATE TABLE t2(a);
    INSERT INTO t2 VALUES(1);
    INSERT INTO t2 VALUES(2);
................................................................................
  sqlite3_step $STMT
} {SQLITE_ROW}
do_test capi3-11.20 {
  catchsql {
    BEGIN;
    COMMIT;
  }
} {0 {}}
do_test capi3-11.20 {
  sqlite3_reset $STMT
  catchsql {
    COMMIT;
  }
} {1 {cannot commit - no transaction is active}}
do_test capi3-11.21 {
  sqlite3_finalize $STMT
} {SQLITE_OK}

# The following tests - capi3-12.* - check that its Ok to start a
# transaction while other VMs are active, and that its Ok to execute
# atomic updates in the same situation 

Changes to test/capi3c.test.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
784
785
786
787
788
789
790




791
792
793
794
795
796



797
798




799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
...
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
#
#***********************************************************************
# This file implements regression tests for SQLite library.  
#
# This is a copy of the capi3.test file that has been adapted to
# test the new sqlite3_prepare_v2 interface.
#
# $Id: capi3c.test,v 1.21 2008/10/30 15:03:16 drh Exp $
#

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

# Return the UTF-16 representation of the supplied UTF-8 string $str.
# If $nt is true, append two 0x00 bytes as a nul terminator.
................................................................................
do_test capi3c-11.1.1 {
  sqlite3_get_autocommit $DB
} 0
do_test capi3c-11.2 {
  set STMT [sqlite3_prepare_v2 $DB "SELECT func(b, a) FROM t1" -1 TAIL]
  sqlite3_step $STMT
} {SQLITE_ROW}




do_test capi3c-11.3 {
  catchsql {
    COMMIT;
  }
} {1 {cannot commit transaction - SQL statements in progress}}
do_test capi3c-11.3.1 {



  sqlite3_get_autocommit $DB
} 0




do_test capi3c-11.4 {
  sqlite3_step $STMT
} {SQLITE_ERROR}
do_test capi3c-11.5 {
  sqlite3_finalize $STMT
} {SQLITE_ERROR}
do_test capi3c-11.6 {
  catchsql {
    SELECT * FROM t1;
  }
} {0 {1 int 2 notatype}}
do_test capi3c-11.6.1 {
  sqlite3_get_autocommit $DB
} 0
do_test capi3c-11.7 {
  catchsql {
    COMMIT;
  }
} {0 {}}
do_test capi3c-11.7.1 {
  sqlite3_get_autocommit $DB
} 1
do_test capi3c-11.8 {
  execsql {
    CREATE TABLE t2(a);
    INSERT INTO t2 VALUES(1);
    INSERT INTO t2 VALUES(2);
................................................................................
  sqlite3_step $STMT
} {SQLITE_ROW}
do_test capi3c-11.20 {
  catchsql {
    BEGIN;
    COMMIT;
  }
} {1 {cannot commit transaction - SQL statements in progress}}
do_test capi3c-11.20 {
  sqlite3_reset $STMT
  catchsql {
    COMMIT;
  }
} {0 {}}
do_test capi3c-11.21 {
  sqlite3_finalize $STMT
} {SQLITE_OK}

# The following tests - capi3c-12.* - check that its Ok to start a
# transaction while other VMs are active, and that its Ok to execute
# atomic updates in the same situation 







|







 







>
>
>
>
|



|
|
>
>
>

|
>
>
>
>











<
<
<

<
<
<
<
<







 







|





|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820



821





822
823
824
825
826
827
828
...
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
#
#***********************************************************************
# This file implements regression tests for SQLite library.  
#
# This is a copy of the capi3.test file that has been adapted to
# test the new sqlite3_prepare_v2 interface.
#
# $Id: capi3c.test,v 1.22 2008/11/05 16:37:35 drh Exp $
#

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

# Return the UTF-16 representation of the supplied UTF-8 string $str.
# If $nt is true, append two 0x00 bytes as a nul terminator.
................................................................................
do_test capi3c-11.1.1 {
  sqlite3_get_autocommit $DB
} 0
do_test capi3c-11.2 {
  set STMT [sqlite3_prepare_v2 $DB "SELECT func(b, a) FROM t1" -1 TAIL]
  sqlite3_step $STMT
} {SQLITE_ROW}

# As of 3.6.5 a COMMIT is OK during while a query is still running -
# as long as it is a read-only query and not an incremental BLOB write.
#
do_test capi3-11.3.1 {
  catchsql {
    COMMIT;
  }
} {0 {}}
do_test capi3-11.3.2 {
  sqlite3_extended_errcode $DB
} {SQLITE_OK}
do_test capi3-11.3.3 {
  sqlite3_get_autocommit $DB
} 1
do_test capi3-11.3.4 {
  db eval {PRAGMA lock_status}
} {main shared temp closed}

do_test capi3c-11.4 {
  sqlite3_step $STMT
} {SQLITE_ERROR}
do_test capi3c-11.5 {
  sqlite3_finalize $STMT
} {SQLITE_ERROR}
do_test capi3c-11.6 {
  catchsql {
    SELECT * FROM t1;
  }
} {0 {1 int 2 notatype}}



do_test capi3c-11.7 {





  sqlite3_get_autocommit $DB
} 1
do_test capi3c-11.8 {
  execsql {
    CREATE TABLE t2(a);
    INSERT INTO t2 VALUES(1);
    INSERT INTO t2 VALUES(2);
................................................................................
  sqlite3_step $STMT
} {SQLITE_ROW}
do_test capi3c-11.20 {
  catchsql {
    BEGIN;
    COMMIT;
  }
} {0 {}}
do_test capi3c-11.20 {
  sqlite3_reset $STMT
  catchsql {
    COMMIT;
  }
} {1 {cannot commit - no transaction is active}}
do_test capi3c-11.21 {
  sqlite3_finalize $STMT
} {SQLITE_OK}

# The following tests - capi3c-12.* - check that its Ok to start a
# transaction while other VMs are active, and that its Ok to execute
# atomic updates in the same situation 

Changes to test/incrblob.test.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
446
447
448
449
450
451
452
453
454


455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# $Id: incrblob.test,v 1.22 2008/10/02 14:49:02 danielk1977 Exp $
#

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

ifcapable {!autovacuum || !pragma || !incrblob} {
  finish_test
................................................................................
} {10}
do_test incrblob-6.9 {
  seek $::blob 0
  puts -nonewline $::blob "invocation"
  flush $::blob
} {}

# At this point rollback or commit should be illegal (because 
# there is an open blob channel).


do_test incrblob-6.10 {
  catchsql {
    ROLLBACK;
  } db2
} {1 {cannot rollback transaction - SQL statements in progress}}
do_test incrblob-6.11 {
  catchsql {
    COMMIT;
  } db2
} {1 {cannot commit transaction - SQL statements in progress}}

do_test incrblob-6.12 {
  execsql {
    SELECT * FROM blobs WHERE rowid = 4;
  }
} {}
do_test incrblob-6.13 {
  close $::blob
  execsql {
    COMMIT;
  } db2
} {}
do_test incrblob-6.14 {
  execsql {
    SELECT * FROM blobs WHERE rowid = 4;
  }
} {a different invocation}
db2 close







|







 







|
|
>
>









|








<
<
<







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474



475
476
477
478
479
480
481
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# $Id: incrblob.test,v 1.23 2008/11/05 16:37:35 drh Exp $
#

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

ifcapable {!autovacuum || !pragma || !incrblob} {
  finish_test
................................................................................
} {10}
do_test incrblob-6.9 {
  seek $::blob 0
  puts -nonewline $::blob "invocation"
  flush $::blob
} {}

# At this point rollback should be illegal (because 
# there is an open blob channel).  But commit is allowed because
# the blob is read-only.
#
do_test incrblob-6.10 {
  catchsql {
    ROLLBACK;
  } db2
} {1 {cannot rollback transaction - SQL statements in progress}}
do_test incrblob-6.11 {
  catchsql {
    COMMIT;
  } db2
} {0 {}}

do_test incrblob-6.12 {
  execsql {
    SELECT * FROM blobs WHERE rowid = 4;
  }
} {}
do_test incrblob-6.13 {
  close $::blob



} {}
do_test incrblob-6.14 {
  execsql {
    SELECT * FROM blobs WHERE rowid = 4;
  }
} {a different invocation}
db2 close

Changes to test/tkt3080.test.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
..
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#***********************************************************************
#
# Ticket #3080
#
# Make sure that application-defined functions are able to recursively
# invoke SQL statements that create and drop virtual tables.
#
# $Id: tkt3080.test,v 1.1 2008/04/28 17:12:11 drh Exp $
#

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

do_test tkt3080.1 {
  db function execsql execsql
................................................................................
    SELECT execsql(x) FROM t1 WHERE rowid=2;
  }
} {1 {database table is locked}}
do_test tkt3080.4 {
  db eval {
    SELECT name FROM sqlite_master;
  }
} {t1 t2}

ifcapable vtab {
  register_echo_module [sqlite3_connection_pointer db]
  do_test tkt3080.10 {
     set sql {
       CREATE VIRTUAL TABLE t4 USING echo(t2);
       INSERT INTO t4 VALUES(123);
................................................................................
       DELETE FROM t1;
       INSERT INTO t1 VALUES($sql);
     }
     db eval {
       SELECT execsql(x) FROM t1
     }
     execsql {SELECT name FROM sqlite_master}
  } {t1 t2}
  do_test tkt3080.11 {
     execsql {SELECT * FROM t2}
  } {123}
}
  


finish_test







|







 







|







 







|








10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
..
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#***********************************************************************
#
# Ticket #3080
#
# Make sure that application-defined functions are able to recursively
# invoke SQL statements that create and drop virtual tables.
#
# $Id: tkt3080.test,v 1.2 2008/11/05 16:37:35 drh Exp $
#

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

do_test tkt3080.1 {
  db function execsql execsql
................................................................................
    SELECT execsql(x) FROM t1 WHERE rowid=2;
  }
} {1 {database table is locked}}
do_test tkt3080.4 {
  db eval {
    SELECT name FROM sqlite_master;
  }
} {t1 t2 t3}

ifcapable vtab {
  register_echo_module [sqlite3_connection_pointer db]
  do_test tkt3080.10 {
     set sql {
       CREATE VIRTUAL TABLE t4 USING echo(t2);
       INSERT INTO t4 VALUES(123);
................................................................................
       DELETE FROM t1;
       INSERT INTO t1 VALUES($sql);
     }
     db eval {
       SELECT execsql(x) FROM t1
     }
     execsql {SELECT name FROM sqlite_master}
  } {t1 t2 t3}
  do_test tkt3080.11 {
     execsql {SELECT * FROM t2}
  } {123}
}
  


finish_test

Changes to test/trans3.test.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
..
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
#
#***********************************************************************
#
# This file implements regression tests for SQLite library.  The
# focus of this script is the response of COMMIT and ROLLBACK when
# statements are still pending.
#
# $Id: trans3.test,v 1.1 2008/11/03 21:40:00 drh Exp $
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
unset -nocomplain ecode

do_test trans3-1.1 {
  db eval {
................................................................................
  }
} {1 2 3}
do_test trans3-1.2 {
  db eval BEGIN
  db eval {INSERT INTO t1 VALUES(4);}
  set ::ecode {}
  set x [catch {
     db eval {SELECT * FROM t1} {
        if {[catch {db eval COMMIT} errmsg]} {
           set ::ecode [sqlite3_extended_errcode db]
           error $errmsg
        }
     }
  } errmsg]
  lappend x $errmsg
} {1 {cannot commit transaction - SQL statements in progress}}
do_test trans3-1.3 {
  set ::ecode
} {SQLITE_BUSY}



do_test trans3-1.4 {
  db eval COMMIT
  db eval {SELECT * FROM t1}
} {1 2 3 4}
do_test trans3-1.5 {
  db eval BEGIN
  db eval {INSERT INTO t1 VALUES(5);}
  set ::ecode {}
  set x [catch {







|







 







|







|


|
>
>
>

<







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
..
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
#
#***********************************************************************
#
# This file implements regression tests for SQLite library.  The
# focus of this script is the response of COMMIT and ROLLBACK when
# statements are still pending.
#
# $Id: trans3.test,v 1.2 2008/11/05 16:37:35 drh Exp $
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
unset -nocomplain ecode

do_test trans3-1.1 {
  db eval {
................................................................................
  }
} {1 2 3}
do_test trans3-1.2 {
  db eval BEGIN
  db eval {INSERT INTO t1 VALUES(4);}
  set ::ecode {}
  set x [catch {
     db eval {SELECT * FROM t1 LIMIT 1} {
        if {[catch {db eval COMMIT} errmsg]} {
           set ::ecode [sqlite3_extended_errcode db]
           error $errmsg
        }
     }
  } errmsg]
  lappend x $errmsg
} {0 {}}
do_test trans3-1.3 {
  set ::ecode
} {}
do_test trans3-1.3.1 {
  sqlite3_get_autocommit db
} 1
do_test trans3-1.4 {

  db eval {SELECT * FROM t1}
} {1 2 3 4}
do_test trans3-1.5 {
  db eval BEGIN
  db eval {INSERT INTO t1 VALUES(5);}
  set ::ecode {}
  set x [catch {