1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Transactions commit on the last sqlite3_step(), not on sqlite3_finalize().

This allows the sqlite3_step() to return SQLITE_BUSY if the commit is
blocked by a lock.  Ticket #885. (CVS 1928)

FossilOrigin-Name: d1b29156558f1c576002cdb2544dffaa693da39b
This commit is contained in:
drh
2004-09-02 14:57:08 +00:00
parent 66cbd1543b
commit 92f02c31d4
12 changed files with 240 additions and 100 deletions

View File

@ -1,5 +1,5 @@
C Work\saround\sa\sbug\sin\sthe\sBorland\sC++\scompiler.\s\sTicket\s#881.\s(CVS\s1927)
D 2004-09-01T16:12:25
C Transactions\scommit\son\sthe\slast\ssqlite3_step(),\snot\son\ssqlite3_finalize().\nThis\sallows\sthe\ssqlite3_step()\sto\sreturn\sSQLITE_BUSY\sif\sthe\scommit\sis\nblocked\sby\sa\slock.\s\sTicket\s#885.\s(CVS\s1928)
D 2004-09-02T14:57:08
F Makefile.in 65a7c43fcaf9a710d62f120b11b6e435eeb4a450
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@ -40,7 +40,7 @@ F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
F src/insert.c fc1ce65a0fe68f226143de9b43c3582164a92aff
F src/legacy.c 2f3617c61bcdcd1d776154a9cfebf99facda8ad8
F src/main.c b92d44c72298d31e08700b1483ef8827468dac9f
F src/main.c c42b3c1c9e0e401a490ed8f8ce789eb7302a9b69
F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
F src/os.h d1780e0db95cad01f213d48da22ab490eb4fd345
F src/os_common.h cd7eb025fdab7dc91e0e97bf6310f1648205857f
@ -52,7 +52,7 @@ F src/os_unix.c a5625eed7ab071d1715df783f4684945ae538a22
F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13
F src/os_win.c 9e2887825b1a32f0ceb1b73b93ffe29a112cd86f
F src/os_win.h babd4e912967c6b09088cfe38a45e8005a07ba44
F src/pager.c 616563dc510993ab67baa54fc6a2ddacc05175ca
F src/pager.c ae06c85de0db43f61a7a3e5eacad3fd5615daf59
F src/pager.h 67739fe649f33be55dba522ca8a9cc4e42d14f71
F src/parse.y 581a2ce014b843506805b2470c02b7865ad034d5
F src/pragma.c b39177b96bb5f7354511468c933357ce65a0dd4c
@ -75,16 +75,16 @@ F src/update.c bbe126c67529bd699016af2d72bc4ceb8fd41527
F src/utf.c 328890099db492dda5620ee5f924e244c6e57ff7
F src/util.c d5aaf211543fb6e285654fada50252c857ac78aa
F src/vacuum.c 9978a5760c2c430bc5b5e66505a02dad76f25813
F src/vdbe.c 28b0ea2a8c534fc39e15e41db0437fcc3b5f2e9b
F src/vdbe.c 45f659497b479f001c2f4e8251474aba3975b9f8
F src/vdbe.h e081c72cd0f7c19d49b1927460aeefcf0fbc85ac
F src/vdbeInt.h aadadddc8cfad6aa5a5445c849f70d881276fe34
F src/vdbeInt.h f8df57a9dc272967991f806e612628e0aa57e705
F src/vdbeapi.c 854732720c2cfc6ff76b28eef6253ac84a5408bc
F src/vdbeaux.c 022c484dba235d2dcbb1faca0f1943702f4232ed
F src/vdbeaux.c 77eaaf62b8b3acad4a2ef351e3c44ecffc67faf6
F src/vdbemem.c ef9ac7d32acfe4bce5c5b408b1294c8d9e0cdb56
F src/where.c a84eee276cd072158224da6b5f30733df2d56027
F test/all.test 929bfa932b55e75c96fe2203f7650ba451c1862c
F test/attach.test feb2ce54e78688df4c84553416d5aec3b2a0112e
F test/attach2.test 9be9656bc1e929b224861960299920c76d45b14d
F test/attach2.test 32ca2c1a5a347a7404219a11f9f84739a63d2582
F test/attach3.test 6d060986ff004ebb89e1876a331d96c6bb62269e
F test/auth.test e74b015545f608c06d5b84d17acdf7146eb818af
F test/bigfile.test 62722ac4b420dfbcdceb137b8634e2cf2865fe27
@ -97,8 +97,9 @@ F test/btree4.test 3797b4305694c7af6828675b0f4b1424b8ca30e4
F test/btree5.test 8e5ff32c02e685d36516c6499add9375fe1377f2
F test/btree6.test a5ede6bfbbb2ec8b27e62813612c0f28e8f3e027
F test/btree7.test 429b96cfef5b51a7d512cfb4b5b3e453384af293
F test/capi2.test 78f2c486689fcc80394a24c2cc32725330ab6299
F test/capi3.test e2d47b59c1ca5be2e5986fb77f716a7fdd228e25
F test/capi2.test 53e3f399074d5654f26d55b32ccaca7b5b619933
F test/capi3.test 9258ca75fc98d89477015dcd70aa3d2757b142b8
F test/capi3b.test 458044d8c250c129ddfd77c6265a6923bc008b5e
F test/collate1.test f79736d2ebf5492167ee4d1f4ab4c09dda776b03
F test/collate2.test c1a3b41f761b28853c5696037f92de928f93233b
F test/collate3.test e60b428e07ec945492ba90ff1c895902ee3a8a50
@ -153,7 +154,7 @@ F test/pager3.test 16f546293bb751b8151dc17df613fca938bbec8b
F test/pragma.test 66a66b7f3b273b93325c9a5794acb418f52fdcbf
F test/printf.test 5a30fb0d736148fca64cb1b7ed0390be7414e024
F test/progress.test 76c722f090b1ccb575e7e4e203a71608c5763beb x
F test/quick.test 2e9af7203555ea894af654adf0794157434928fb
F test/quick.test 212a9cd4c40c72c7c4780fef1c2fbe5d1cb34ce6
F test/quote.test 6d75cf635d93ba2484dc9cb378d88cbae9dc2c62
F test/rollback.test 4097328d44510277244ef4fa51b22b2f11d7ef4c
F test/rowid.test b3d059f5c8d8874fa1c31030e0636f67405d20ea
@ -246,7 +247,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
P 9c411c3c8dde2061c98513a413ef58c5c2de45af
R 54ca511e52d24afac36ea482ae4bc8ec
P 18af6ba580a5ad50a20955bfe2ebce8e30b1d39e
R 8124409cd5ad134f1cc0a6f820ab9a66
U drh
Z 888aa66dde2c6dec44c62c3082b0fba4
Z 68ff020543a01eac2435ebdc5d559c02

View File

@ -1 +1 @@
18af6ba580a5ad50a20955bfe2ebce8e30b1d39e
d1b29156558f1c576002cdb2544dffaa693da39b

View File

@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.256 2004/08/29 20:08:59 drh Exp $
** $Id: main.c,v 1.257 2004/09/02 14:57:08 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -521,7 +521,6 @@ void sqlite3RollbackAll(sqlite *db){
}
}
sqlite3ResetInternalSchema(db, 0);
/* sqlite3RollbackInternalChanges(db); */
}
/*
@ -987,7 +986,7 @@ int sqlite3_prepare(
** Make a copy of that part of the SQL string since zSQL is const
** and we must pass a zero terminated string to the trace function
** The copy is unnecessary if the tail pointer is pointing at the
** beginnig or end of the SQL string.
** beginning or end of the SQL string.
*/
if( sParse.zTail && sParse.zTail!=zSql && *sParse.zTail ){
char *tmpSql = sqliteStrNDup(zSql, sParse.zTail - zSql);

View File

@ -18,7 +18,7 @@
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.161 2004/08/30 16:52:18 drh Exp $
** @(#) $Id: pager.c,v 1.162 2004/09/02 14:57:08 drh Exp $
*/
#include "os.h" /* Must be first to enable large file support */
#include "sqliteInt.h"
@ -2798,10 +2798,7 @@ int sqlite3pager_commit(Pager *pPager){
/* Jump here if anything goes wrong during the commit process.
*/
commit_abort:
rc = sqlite3pager_rollback(pPager);
if( rc==SQLITE_OK ){
rc = SQLITE_FULL;
}
sqlite3pager_rollback(pPager);
return rc;
}

View File

@ -43,7 +43,7 @@
** 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.412 2004/08/31 13:45:12 drh Exp $
** $Id: vdbe.c,v 1.413 2004/09/02 14:57:09 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -621,12 +621,12 @@ case OP_Return: {
** Exit immediately. All open cursors, Lists, Sorts, etc are closed
** automatically.
**
** P1 is the result code returned by sqlite3_exec(). For a normal
** halt, this should be SQLITE_OK (0). For errors, it can be some
** other value. If P1!=0 then P2 will determine whether or not to
** rollback the current transaction. Do not rollback if P2==OE_Fail.
** Do the rollback if P2==OE_Rollback. If P2==OE_Abort, then back
** out all changes that have occurred during this execution of the
** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(),
** or sqlite3_finalize(). For a normal halt, this should be SQLITE_OK (0).
** For errors, it can be some other value. If P1!=0 then P2 will determine
** whether or not to rollback the current transaction. Do not rollback
** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort,
** then back out all changes that have occurred during this execution of the
** VDBE, but do not rollback the transaction.
**
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
@ -634,17 +634,21 @@ case OP_Return: {
** is the same as executing Halt.
*/
case OP_Halt: {
p->magic = VDBE_MAGIC_HALT;
p->pTos = pTos;
if( pOp->p1!=SQLITE_OK ){
p->rc = pOp->p1;
p->pc = pc;
p->errorAction = pOp->p2;
if( pOp->p3 ){
sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0);
return SQLITE_ERROR;
}else{
p->rc = SQLITE_OK;
return SQLITE_DONE;
}
rc = sqlite3VdbeHalt(p);
if( rc==SQLITE_BUSY ){
p->rc = SQLITE_BUSY;
return SQLITE_BUSY;
}else if( rc!=SQLITE_OK ){
p->rc = rc;
}
return p->rc ? SQLITE_ERROR : SQLITE_DONE;
}
/* Opcode: Integer P1 * P3
@ -2118,6 +2122,8 @@ case OP_Statement: {
** 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;
@ -2126,7 +2132,7 @@ case OP_AutoCommit: {
assert( i==1 || i==0 );
assert( i==1 || rollback==0 );
assert( db->activeVdbeCnt>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
@ -2138,10 +2144,17 @@ case OP_AutoCommit: {
rc = SQLITE_ERROR;
}else if( i!=db->autoCommit ){
db->autoCommit = i;
p->autoCommitOn |= i;
if( pOp->p2 ){
assert( i==1 );
sqlite3RollbackAll(db);
}else if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
p->pTos = pTos;
p->pc = pc;
db->autoCommit = 1-i;
p->rc = SQLITE_BUSY;
return SQLITE_BUSY;
}
return SQLITE_DONE;
}else{
sqlite3SetString(&p->zErrMsg,
(!i)?"cannot start a transaction within a transaction":(
@ -4451,7 +4464,7 @@ vdbe_halt:
}else{
rc = SQLITE_DONE;
}
p->magic = VDBE_MAGIC_HALT;
sqlite3VdbeHalt(p);
p->pTos = pTos;
return rc;

View File

@ -338,7 +338,6 @@ struct Vdbe {
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 */
u8 changeCntOn; /* True to update the change-counter */
u8 aborted; /* True if ROLLBACK in another VM causes an abort */
int nChange; /* Number of db changes made since last reset */
@ -379,6 +378,7 @@ int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeIdxRowidLen(int,const u8*);
int sqlite3VdbeExec(Vdbe*);
int sqlite3VdbeList(Vdbe*);
int sqlite3VdbeHalt(Vdbe*);
int sqlite3VdbeChangeEncoding(Mem *, int);
int sqlite3VdbeMemCopy(Mem*, const Mem*);
void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);

View File

@ -543,6 +543,9 @@ void sqlite3VdbePrintSql(Vdbe *p){
** as allocating stack space and initializing the program counter.
** After the VDBE has be prepped, it can be executed by one or more
** calls to sqlite3VdbeExec().
**
** This is the only way to move a VDBE from VDBE_MAGIC_INIT to
** VDBE_MAGIC_RUN.
*/
void sqlite3VdbeMakeReady(
Vdbe *p, /* The VDBE */
@ -938,7 +941,11 @@ static int vdbeCommit(sqlite *db){
/* If there are any write-transactions at all, invoke the commit hook */
if( needXcommit && db->xCommitCallback ){
if( db->xCommitCallback(db->pCommitArg) ){
int rc;
sqlite3SafetyOff(db);
rc = db->xCommitCallback(db->pCommitArg);
sqlite3SafetyOn(db);
if( rc ){
return SQLITE_CONSTRAINT;
}
}
@ -1124,6 +1131,8 @@ static void abortOtherActiveVdbes(Vdbe *pVdbe){
** This routine checks that the sqlite3.activeVdbeCnt count variable
** matches the number of vdbe's in the list sqlite3.pVdbe that are
** currently active. An assertion fails if the two counts do not match.
** This is an internal self-check only - it is not an essential processing
** step.
**
** This is a no-op if NDEBUG is defined.
*/
@ -1131,15 +1140,13 @@ static void abortOtherActiveVdbes(Vdbe *pVdbe){
static void checkActiveVdbeCnt(sqlite *db){
Vdbe *p;
int cnt = 0;
p = db->pVdbe;
while( p ){
if( (p->magic==VDBE_MAGIC_RUN && p->pc>=0) || p->magic==VDBE_MAGIC_HALT ){
if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){
cnt++;
}
p = p->pNext;
}
assert( cnt==db->activeVdbeCnt );
}
#else
@ -1147,61 +1154,42 @@ static void checkActiveVdbeCnt(sqlite *db){
#endif
/*
** Clean up a VDBE after execution but do not delete the VDBE just yet.
** Write any error messages into *pzErrMsg. Return the result code.
** This routine is called the when a VDBE tries to halt. If the VDBE
** has made changes and is in autocommit mode, then commit those
** changes. If a rollback is needed, then do the rollback.
**
** After this routine is run, the VDBE should be ready to be executed
** again.
** This routine is the only way to move the state of a VM from
** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT.
**
** Return an error code. If the commit could not complete because of
** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it
** means the close did not happen and needs to be repeated.
*/
int sqlite3VdbeReset(Vdbe *p){
int sqlite3VdbeHalt(Vdbe *p){
sqlite *db = p->db;
int i;
int (*xFunc)(Btree *pBt) = 0; /* Function to call on each btree backend */
if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){
sqlite3Error(p->db, SQLITE_MISUSE, 0 ,0);
return SQLITE_MISUSE;
if( p->magic!=VDBE_MAGIC_RUN ){
/* Already halted. Nothing to do. */
assert( p->magic==VDBE_MAGIC_HALT );
return SQLITE_OK;
}
if( p->zErrMsg ){
sqlite3Error(p->db, p->rc, "%s", p->zErrMsg, 0);
sqliteFree(p->zErrMsg);
p->zErrMsg = 0;
}else if( p->rc ){
sqlite3Error(p->db, p->rc, 0);
}else{
sqlite3Error(p->db, SQLITE_OK, 0);
}
Cleanup(p);
/* What is done now depends on the exit status of the vdbe, the value of
** the sqlite.autoCommit flag and whether or not there are any other
** queries in progress. A transaction or statement transaction may need
** to be committed or rolled back on each open database file.
*/
closeAllCursors(p);
checkActiveVdbeCnt(db);
if( db->autoCommit && db->activeVdbeCnt==1 ){
if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){
/* The auto-commit flag is true, there are no other active queries
** 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.
** 'OR FAIL' constraint. This means a commit is required.
*/
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 */
int rc = vdbeCommit(db);
if( rc==SQLITE_BUSY ){
return SQLITE_BUSY;
}else if( rc!=SQLITE_OK ){
p->rc = rc;
xFunc = sqlite3BtreeRollback;
}
}
}else{
xFunc = sqlite3BtreeRollback;
}
@ -1216,7 +1204,6 @@ int sqlite3VdbeReset(Vdbe *p){
abortOtherActiveVdbes(p);
}
}
p->autoCommitOn = 0;
/* If xFunc is not NULL, then it is one of sqlite3BtreeRollback,
** sqlite3BtreeRollbackStmt or sqlite3BtreeCommitStmt. Call it once on
@ -1242,16 +1229,65 @@ int sqlite3VdbeReset(Vdbe *p){
p->nChange = 0;
}
/* Rollback or commit any schema changes that occurred. */
if( p->rc!=SQLITE_OK ){
sqlite3RollbackInternalChanges(db);
}else if( db->flags & SQLITE_InternChanges ){
sqlite3CommitInternalChanges(db);
}
if( (p->magic==VDBE_MAGIC_RUN && p->pc>=0) || p->magic==VDBE_MAGIC_HALT ){
/* We have successfully halted and closed the VM. Record this fact. */
if( p->pc>=0 ){
db->activeVdbeCnt--;
}
p->magic = VDBE_MAGIC_HALT;
checkActiveVdbeCnt(db);
return SQLITE_OK;
}
/*
** Clean up a VDBE after execution but do not delete the VDBE just yet.
** Write any error messages into *pzErrMsg. Return the result code.
**
** After this routine is run, the VDBE should be ready to be executed
** again.
**
** To look at it another way, this routine resets the state of the
** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to
** VDBE_MAGIC_INIT.
*/
int sqlite3VdbeReset(Vdbe *p){
if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){
sqlite3Error(p->db, SQLITE_MISUSE, 0 ,0);
return SQLITE_MISUSE;
}
/* If the VM did not run to completion or if it encountered an
** error, then it might not have been halted properly. So halt
** it now.
*/
sqlite3VdbeHalt(p);
/* Transfer the error code and error message from the VDBE into the
** main database structure.
*/
if( p->zErrMsg ){
sqlite3Error(p->db, p->rc, "%s", p->zErrMsg, 0);
sqliteFree(p->zErrMsg);
p->zErrMsg = 0;
}else if( p->rc ){
sqlite3Error(p->db, p->rc, 0);
}else{
sqlite3Error(p->db, SQLITE_OK, 0);
}
/* Reclaim all memory used by the VDBE
*/
Cleanup(p);
/* Save profiling information from this VDBE run.
*/
assert( p->pTos<&p->aStack[p->pc<0?0:p->pc] || sqlite3_malloc_failed==1 );
#ifdef VDBE_PROFILE
{

View File

@ -12,7 +12,7 @@
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: attach2.test,v 1.25 2004/08/18 16:05:20 drh Exp $
# $Id: attach2.test,v 1.26 2004/09/02 14:57:09 drh Exp $
#
set testdir [file dirname $argv0]
@ -263,7 +263,6 @@ do_test attach2-4.9 {
lock_status 4.9.1 db {main shared temp closed file2 shared}
lock_status 4.9.2 db2 {main reserved temp closed file2 reserved}
btree_breakpoint
do_test attach2-4.10 {
# We cannot commit db2 while db is holding a read-lock
catchsql {COMMIT} db2
@ -273,7 +272,6 @@ lock_status 4.10.1 db {main shared temp closed file2 shared}
lock_status 4.10.2 db2 {main pending temp closed file2 reserved}
set sqlite_os_trace 0
btree_breakpoint
do_test attach2-4.11 {
# db is able to commit.
catchsql {COMMIT}

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this script testing the callback-free C/C++ API.
#
# $Id: capi2.test,v 1.18 2004/06/30 06:30:26 danielk1977 Exp $
# $Id: capi2.test,v 1.19 2004/09/02 14:57:09 drh Exp $
#
set testdir [file dirname $argv0]
@ -203,7 +203,8 @@ do_test capi2-3.10 {
# Update for v3 - the change has not actually happened until the query is
# finalized. Is this going to cause trouble for anyone? Lee Nelson maybe?
do_test capi2-3.10b {db changes} {0}
# (Later:) The change now happens just before SQLITE_DONE is returned.
do_test capi2-3.10b {db changes} {1}
do_test capi2-3.11 {
sqlite3_finalize $VM
} {SQLITE_OK}
@ -220,8 +221,9 @@ do_test capi2-3.13 {
} {SQLITE_ERROR 0 {} {}}
# Update for v3: Preparing a statement does not affect the change counter.
# (Test result changes from 0 to 1).
do_test capi2-3.13b {db changes} {1}
# (Test result changes from 0 to 1). (Later:) change counter updates occur
# when sqlite3_step returns, not at finalize time.
do_test capi2-3.13b {db changes} {0}
do_test capi2-3.14 {
list [sqlite3_finalize $VM] [sqlite3_errmsg $DB]

View File

@ -11,7 +11,7 @@
# 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.20 2004/07/22 15:02:26 drh Exp $
# $Id: capi3.test,v 1.21 2004/09/02 14:57:09 drh Exp $
#
set testdir [file dirname $argv0]
@ -536,7 +536,7 @@ if {![sqlite3 -has-codec]} {
btree_close_cursor $::bc
btree_commit $::bt
btree_close $::bt
} {}
} {};
do_test capi3-8.5 {
db close
sqlite3 db test.db

90
test/capi3b.test Normal file
View File

@ -0,0 +1,90 @@
# 2004 September 2
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script testing the callback-free C/C++ API and in
# particular the behavior of sqlite3_step() when trying to commit
# with lock contention.
#
# $Id: capi3b.test,v 1.1 2004/09/02 14:57:09 drh Exp $
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
db close
set DB [sqlite3 db test.db]
set DB2 [sqlite3 db2 test.db]
# Create some data in the database
#
do_test capi3b-1.1 {
execsql {
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(1);
INSERT INTO t1 VALUES(2);
SELECT * FROM t1
}
} {1 2}
# Make sure the second database connection can see the data
#
do_test capi3b-1.2 {
execsql {
SELECT * FROM t1
} db2
} {1 2}
# First database connection acquires a shared lock
#
do_test capi3b-1.3 {
execsql {
BEGIN;
SELECT * FROM t1;
}
} {1 2}
# Second database connection tries to write. The sqlite3_step()
# function returns SQLITE_BUSY because it cannot commit.
#
do_test capi3b-1.4 {
set VM [sqlite3_prepare $DB2 {INSERT INTO t1 VALUES(3)} -1 TAIL]
sqlite3_step $VM
} SQLITE_BUSY
# The sqlite3_step call can be repeated multiple times.
#
do_test capi3b-1.5.1 {
sqlite3_step $VM
} SQLITE_BUSY
do_test capi3b-1.5.2 {
sqlite3_step $VM
} SQLITE_BUSY
# The first connection closes its transaction. This allows the second
# connections sqlite3_step to succeed.
#
do_test capi3b-1.6 {
execsql COMMIT
sqlite3_step $VM
} SQLITE_DONE
do_test capi3b-1.7 {
sqlite3_finalize $VM
} SQLITE_OK
do_test capi3b-1.8 {
execsql {SELECT * FROM t1} db2
} {1 2 3}
do_test capi3b-1.9 {
execsql {SELECT * FROM t1}
} {1 2 3}
catch {db2 close}
finish_test

View File

@ -10,7 +10,7 @@
#***********************************************************************
# This file runs all tests.
#
# $Id: quick.test,v 1.29 2004/08/30 16:52:19 drh Exp $
# $Id: quick.test,v 1.30 2004/09/02 14:57:09 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -21,6 +21,10 @@ set ISQUICK 1
set EXCLUDE {
all.test
btree2.test
btree3.test
btree4.test
btree5.test
btree6.test
corrupt.test
crash.test
malloc.test