mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Bug fix: sqlite_exec() would sometimes return SQLITE_PROTOCOL when it
should have returned SQLITE_BUSY. There was also a deadlock that the previous bug was masking. (CVS 322) FossilOrigin-Name: 585ed5ebf1c1afc8ae1d569b121208018d8ecd49
This commit is contained in:
54
src/btree.c
54
src/btree.c
@@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.41 2001/11/23 00:24:12 drh Exp $
|
||||
** $Id: btree.c,v 1.42 2001/12/05 00:21:20 drh Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** For a detailed discussion of BTrees, refer to
|
||||
@@ -676,6 +676,24 @@ page1_init_failed:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** If there are no outstanding cursors and we are not in the middle
|
||||
** of a transaction but there is a read lock on the database, then
|
||||
** this routine unrefs the first page of the database file which
|
||||
** has the effect of releasing the read lock.
|
||||
**
|
||||
** If there are any outstanding cursors, this routine is a no-op.
|
||||
**
|
||||
** If there is a transaction in progress, this routine is a no-op.
|
||||
*/
|
||||
static void unlockBtreeIfUnused(Btree *pBt){
|
||||
if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){
|
||||
sqlitepager_unref(pBt->page1);
|
||||
pBt->page1 = 0;
|
||||
pBt->inTrans = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a new database by initializing the first two pages of the
|
||||
** file.
|
||||
@@ -725,33 +743,19 @@ int sqliteBtreeBeginTrans(Btree *pBt){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if( !sqlitepager_isreadonly(pBt->pPager) ){
|
||||
rc = sqlitepager_write(pBt->page1);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
if( sqlitepager_isreadonly(pBt->pPager) ){
|
||||
return SQLITE_READONLY;
|
||||
}
|
||||
rc = sqlitepager_write(pBt->page1);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = newDatabase(pBt);
|
||||
}
|
||||
pBt->inTrans = 1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** If there are no outstanding cursors and we are not in the middle
|
||||
** of a transaction but there is a read lock on the database, then
|
||||
** this routine unrefs the first page of the database file which
|
||||
** has the effect of releasing the read lock.
|
||||
**
|
||||
** If there are any outstanding cursors, this routine is a no-op.
|
||||
**
|
||||
** If there is a transaction in progress, this routine is a no-op.
|
||||
*/
|
||||
static void unlockBtreeIfUnused(Btree *pBt){
|
||||
if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){
|
||||
sqlitepager_unref(pBt->page1);
|
||||
pBt->page1 = 0;
|
||||
pBt->inTrans = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
pBt->inTrans = 1;
|
||||
}else{
|
||||
unlockBtreeIfUnused(pBt);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -25,7 +25,7 @@
|
||||
** ROLLBACK
|
||||
** PRAGMA
|
||||
**
|
||||
** $Id: build.c,v 1.57 2001/11/22 00:01:27 drh Exp $
|
||||
** $Id: build.c,v 1.58 2001/12/05 00:21:20 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -553,7 +553,7 @@ void sqliteAddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){
|
||||
*/
|
||||
static void changeCookie(sqlite *db){
|
||||
if( db->next_cookie==db->schema_cookie ){
|
||||
db->next_cookie = db->schema_cookie + sqliteRandomByte(db) + 1;
|
||||
db->next_cookie = db->schema_cookie + sqliteRandomByte() + 1;
|
||||
db->flags |= SQLITE_InternChanges;
|
||||
}
|
||||
}
|
||||
|
@@ -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.50 2001/11/23 00:24:12 drh Exp $
|
||||
** $Id: main.c,v 1.51 2001/12/05 00:21:20 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -265,7 +265,7 @@ sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
|
||||
if( db==0 ) goto no_mem_on_open;
|
||||
sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0);
|
||||
sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0);
|
||||
db->nextRowid = sqliteRandomInteger(db);
|
||||
db->nextRowid = sqliteRandomInteger();
|
||||
|
||||
/* Open the backend database driver */
|
||||
rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe);
|
||||
|
4
src/os.h
4
src/os.h
@@ -59,8 +59,8 @@ int sqliteOsLock(OsFile, int wrlock);
|
||||
int sqliteOsUnlock(OsFile);
|
||||
int sqliteOsRandomSeed(char*);
|
||||
int sqliteOsSleep(int ms);
|
||||
void sqliteOsEnterMutex();
|
||||
void sqliteOsLeaveMutex();
|
||||
void sqliteOsEnterMutex(void);
|
||||
void sqliteOsLeaveMutex(void);
|
||||
|
||||
|
||||
|
||||
|
15
src/pager.c
15
src/pager.c
@@ -18,7 +18,7 @@
|
||||
** file simultaneously, or one process from reading the database while
|
||||
** another is writing.
|
||||
**
|
||||
** @(#) $Id: pager.c,v 1.31 2001/11/22 00:01:27 drh Exp $
|
||||
** @(#) $Id: pager.c,v 1.32 2001/12/05 00:21:20 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "pager.h"
|
||||
@@ -955,13 +955,20 @@ int sqlitepager_write(void *pData){
|
||||
}
|
||||
sqliteOsUnlock(pPager->fd);
|
||||
if( sqliteOsLock(pPager->fd, 1)!=SQLITE_OK ){
|
||||
sqliteOsUnlock(pPager->fd);
|
||||
rc = sqliteOsLock(pPager->fd, 0);
|
||||
sqliteFree(pPager->aInJournal);
|
||||
sqliteOsClose(pPager->jfd);
|
||||
sqliteOsDelete(pPager->zJournal);
|
||||
pPager->journalOpen = 0;
|
||||
pPager->state = SQLITE_UNLOCK;
|
||||
pPager->errMask |= PAGER_ERR_LOCK;
|
||||
return SQLITE_PROTOCOL;
|
||||
if( rc ){
|
||||
pPager->state = SQLITE_UNLOCK;
|
||||
pPager->errMask |= PAGER_ERR_LOCK;
|
||||
return SQLITE_PROTOCOL;
|
||||
}else{
|
||||
pPager->state = SQLITE_READLOCK;
|
||||
return SQLITE_BUSY;
|
||||
}
|
||||
}
|
||||
pPager->state = SQLITE_WRITELOCK;
|
||||
sqlitepager_pagecount(pPager);
|
||||
|
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.71 2001/11/22 00:01:27 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.72 2001/12/05 00:21:20 drh Exp $
|
||||
*/
|
||||
#include "sqlite.h"
|
||||
#include "hash.h"
|
||||
@@ -519,8 +519,8 @@ void sqliteExprResolveInSelect(Parse*, Expr*);
|
||||
int sqliteExprAnalyzeAggregates(Parse*, Expr*);
|
||||
void sqliteParseInfoReset(Parse*);
|
||||
Vdbe *sqliteGetVdbe(Parse*);
|
||||
int sqliteRandomByte();
|
||||
int sqliteRandomInteger();
|
||||
int sqliteRandomByte(void);
|
||||
int sqliteRandomInteger(void);
|
||||
void sqliteBeginTransaction(Parse*);
|
||||
void sqliteCommitTransaction(Parse*);
|
||||
void sqliteRollbackTransaction(Parse*);
|
||||
|
Reference in New Issue
Block a user