mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-22 20:22:44 +03:00
Update the sessions branch with the latest trunk changes.
FossilOrigin-Name: d09355050a74344c1cb6d303af9f601cd41e2368
This commit is contained in:
51
src/btree.c
51
src/btree.c
@@ -2517,6 +2517,29 @@ page1_init_failed:
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
/*
|
||||
** Return the number of cursors open on pBt. This is for use
|
||||
** in assert() expressions, so it is only compiled if NDEBUG is not
|
||||
** defined.
|
||||
**
|
||||
** Only write cursors are counted if wrOnly is true. If wrOnly is
|
||||
** false then all cursors are counted.
|
||||
**
|
||||
** For the purposes of this routine, a cursor is any cursor that
|
||||
** is capable of reading or writing to the databse. Cursors that
|
||||
** have been tripped into the CURSOR_FAULT state are not counted.
|
||||
*/
|
||||
static int countValidCursors(BtShared *pBt, int wrOnly){
|
||||
BtCursor *pCur;
|
||||
int r = 0;
|
||||
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
|
||||
if( (wrOnly==0 || pCur->wrFlag) && pCur->eState!=CURSOR_FAULT ) r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** 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
|
||||
@@ -2527,7 +2550,7 @@ page1_init_failed:
|
||||
*/
|
||||
static void unlockBtreeIfUnused(BtShared *pBt){
|
||||
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||
assert( pBt->pCursor==0 || pBt->inTransaction>TRANS_NONE );
|
||||
assert( countValidCursors(pBt,0)==0 || pBt->inTransaction>TRANS_NONE );
|
||||
if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){
|
||||
assert( pBt->pPage1->aData );
|
||||
assert( sqlite3PagerRefcount(pBt->pPager)==1 );
|
||||
@@ -3255,7 +3278,6 @@ static void btreeEndTransaction(Btree *p){
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
pBt->bDoTruncate = 0;
|
||||
#endif
|
||||
btreeClearHasContent(pBt);
|
||||
if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){
|
||||
/* If there are other active statements that belong to this database
|
||||
** handle, downgrade to a read-only transaction. The other statements
|
||||
@@ -3330,6 +3352,7 @@ int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){
|
||||
return rc;
|
||||
}
|
||||
pBt->inTransaction = TRANS_READ;
|
||||
btreeClearHasContent(pBt);
|
||||
}
|
||||
|
||||
btreeEndTransaction(p);
|
||||
@@ -3351,27 +3374,6 @@ int sqlite3BtreeCommit(Btree *p){
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
/*
|
||||
** Return the number of write-cursors open on this handle. This is for use
|
||||
** in assert() expressions, so it is only compiled if NDEBUG is not
|
||||
** defined.
|
||||
**
|
||||
** For the purposes of this routine, a write-cursor is any cursor that
|
||||
** is capable of writing to the databse. That means the cursor was
|
||||
** originally opened for writing and the cursor has not be disabled
|
||||
** by having its state changed to CURSOR_FAULT.
|
||||
*/
|
||||
static int countWriteCursors(BtShared *pBt){
|
||||
BtCursor *pCur;
|
||||
int r = 0;
|
||||
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
|
||||
if( pCur->wrFlag && pCur->eState!=CURSOR_FAULT ) r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This routine sets the state to CURSOR_FAULT and the error
|
||||
** code to errCode for every cursor on BtShared that pBtree
|
||||
@@ -3451,8 +3453,9 @@ int sqlite3BtreeRollback(Btree *p, int tripCode){
|
||||
pBt->nPage = nPage;
|
||||
releasePage(pPage1);
|
||||
}
|
||||
assert( countWriteCursors(pBt)==0 );
|
||||
assert( countValidCursors(pBt, 1)==0 );
|
||||
pBt->inTransaction = TRANS_READ;
|
||||
btreeClearHasContent(pBt);
|
||||
}
|
||||
|
||||
btreeEndTransaction(p);
|
||||
|
||||
18
src/build.c
18
src/build.c
@@ -2659,10 +2659,8 @@ Index *sqlite3CreateIndex(
|
||||
for(i=0; i<pList->nExpr; i++){
|
||||
Expr *pExpr = pList->a[i].pExpr;
|
||||
if( pExpr ){
|
||||
CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr);
|
||||
if( pColl ){
|
||||
nExtra += (1 + sqlite3Strlen30(pColl->zName));
|
||||
}
|
||||
assert( pExpr->op==TK_COLLATE );
|
||||
nExtra += (1 + sqlite3Strlen30(pExpr->u.zToken));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2723,7 +2721,6 @@ Index *sqlite3CreateIndex(
|
||||
const char *zColName = pListItem->zName;
|
||||
Column *pTabCol;
|
||||
int requestedSortOrder;
|
||||
CollSeq *pColl; /* Collating sequence */
|
||||
char *zColl; /* Collation sequence name */
|
||||
|
||||
for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
|
||||
@@ -2736,11 +2733,10 @@ Index *sqlite3CreateIndex(
|
||||
goto exit_create_index;
|
||||
}
|
||||
pIndex->aiColumn[i] = j;
|
||||
if( pListItem->pExpr
|
||||
&& (pColl = sqlite3ExprCollSeq(pParse, pListItem->pExpr))!=0
|
||||
){
|
||||
if( pListItem->pExpr ){
|
||||
int nColl;
|
||||
zColl = pColl->zName;
|
||||
assert( pListItem->pExpr->op==TK_COLLATE );
|
||||
zColl = pListItem->pExpr->u.zToken;
|
||||
nColl = sqlite3Strlen30(zColl) + 1;
|
||||
assert( nExtra>=nColl );
|
||||
memcpy(zExtra, zColl, nColl);
|
||||
@@ -2749,9 +2745,7 @@ Index *sqlite3CreateIndex(
|
||||
nExtra -= nColl;
|
||||
}else{
|
||||
zColl = pTab->aCol[j].zColl;
|
||||
if( !zColl ){
|
||||
zColl = "BINARY";
|
||||
}
|
||||
if( !zColl ) zColl = "BINARY";
|
||||
}
|
||||
if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
|
||||
goto exit_create_index;
|
||||
|
||||
@@ -116,12 +116,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
|
||||
}
|
||||
assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
|
||||
if( op==TK_COLLATE ){
|
||||
if( db->init.busy ){
|
||||
/* Do not report errors when parsing while the schema */
|
||||
pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0);
|
||||
}else{
|
||||
pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
|
||||
}
|
||||
pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
|
||||
break;
|
||||
}
|
||||
if( p->pTab!=0
|
||||
|
||||
@@ -848,6 +848,12 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){
|
||||
return SQLITE_BUSY;
|
||||
}
|
||||
|
||||
/* If a transaction is open, roll it back. This also ensures that if
|
||||
** any database schemas have been modified by the current transaction
|
||||
** they are reset. And that the required b-tree mutex is held to make
|
||||
** the the pager rollback and schema reset an atomic operation. */
|
||||
sqlite3RollbackAll(db, SQLITE_OK);
|
||||
|
||||
#ifdef SQLITE_ENABLE_SQLLOG
|
||||
if( sqlite3GlobalConfig.xSqllog ){
|
||||
/* Closing the handle. Fourth parameter is passed the value 2. */
|
||||
@@ -1002,6 +1008,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
|
||||
int inTrans = 0;
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
sqlite3BeginBenignMalloc();
|
||||
sqlite3BtreeEnterAll(db);
|
||||
for(i=0; i<db->nDb; i++){
|
||||
Btree *p = db->aDb[i].pBt;
|
||||
if( p ){
|
||||
@@ -1019,6 +1026,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
|
||||
sqlite3ExpirePreparedStatements(db);
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
}
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
|
||||
/* Any deferred constraint violations have now been resolved. */
|
||||
db->nDeferredCons = 0;
|
||||
|
||||
Reference in New Issue
Block a user