1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-22 20:22:44 +03:00

Merge in all trunk changes up through the 3.7.17 release.

FossilOrigin-Name: 14ab6675e5eab3761256a06dad23d2b11220788a
This commit is contained in:
drh
2013-05-20 15:14:42 +00:00
33 changed files with 695 additions and 123 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -902,6 +902,12 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
** go ahead and free all resources.
*/
/* If a transaction is open, roll it back. This also ensures that if
** any database schemas have been modified by an uncommitted transaction
** they are reset. And that the required b-tree mutex is held to make
** the pager rollback and schema reset an atomic operation. */
sqlite3RollbackAll(db, SQLITE_OK);
/* Free any outstanding Savepoint structures. */
sqlite3CloseSavepoints(db);
@@ -1002,6 +1008,15 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
int inTrans = 0;
assert( sqlite3_mutex_held(db->mutex) );
sqlite3BeginBenignMalloc();
/* Obtain all b-tree mutexes before making any calls to BtreeRollback().
** This is important in case the transaction being rolled back has
** modified the database schema. If the b-tree mutexes are not taken
** here, then another shared-cache connection might sneak in between
** the database rollback and schema reset, which can cause false
** corruption reports in some cases. */
sqlite3BtreeEnterAll(db);
for(i=0; i<db->nDb; i++){
Btree *p = db->aDb[i].pBt;
if( p ){
@@ -1019,6 +1034,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
sqlite3ExpirePreparedStatements(db);
sqlite3ResetAllSchemasOfConnection(db);
}
sqlite3BtreeLeaveAll(db);
/* Any deferred constraint violations have now been resolved. */
db->nDeferredCons = 0;

View File

@@ -5153,7 +5153,7 @@ static int fillInUnixFile(
pNew->pVfs = pVfs;
pNew->zPath = zFilename;
pNew->ctrlFlags = (u8)ctrlFlags;
pNew->mmapSizeMax = sqlite3GlobalConfig.mxMmap;
pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
"psow", SQLITE_POWERSAFE_OVERWRITE) ){
pNew->ctrlFlags |= UNIXFILE_PSOW;

View File

@@ -2937,8 +2937,6 @@ static int winDeviceCharacteristics(sqlite3_file *id){
((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
}
#ifndef SQLITE_OMIT_WAL
/*
** Windows will only let you create file view mappings
** on allocation size granularity boundaries.
@@ -2947,6 +2945,8 @@ static int winDeviceCharacteristics(sqlite3_file *id){
*/
SYSTEM_INFO winSysInfo;
#ifndef SQLITE_OMIT_WAL
/*
** Helper functions to obtain and relinquish the global mutex. The
** global mutex is used to protect the winLockInfo objects used by
@@ -4246,7 +4246,7 @@ static int winOpen(
pFile->pMapRegion = 0;
pFile->mmapSize = 0;
pFile->mmapSizeActual = 0;
pFile->mmapSizeMax = sqlite3GlobalConfig.mxMmap;
pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap;
#endif
OpenCounter(+1);

View File

@@ -1159,8 +1159,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** re-evaluated for each reference to it.
*/
sNC.pEList = p->pEList;
if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
sNC.ncFlags |= NC_AsMaybe;
if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
sNC.ncFlags &= ~NC_AsMaybe;

View File

@@ -681,6 +681,30 @@ static int sqlite_test_close(
return TCL_OK;
}
/*
** Usage: sqlite3_close_v2 DB
**
** Closes the database opened by sqlite3_open.
*/
static int sqlite_test_close_v2(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
sqlite3 *db;
int rc;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" FILENAME\"", 0);
return TCL_ERROR;
}
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
rc = sqlite3_close_v2(db);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
return TCL_OK;
}
/*
** Implementation of the x_coalesce() function.
** Return the first argument non-NULL argument.
@@ -6077,6 +6101,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
#endif
{ "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
{ "sqlite3_close_v2", (Tcl_CmdProc*)sqlite_test_close_v2 },
{ "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
{ "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
{ "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },

View File

@@ -69,13 +69,13 @@
** the xNextSystemCall() VFS method.
*/
#include "sqliteInt.h"
#include "sqlite3.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "sqliteInt.h"
#if SQLITE_OS_UNIX
/* From main.c */

View File

@@ -142,14 +142,14 @@ char *sqlite3VdbeExpandSql(
#endif
nOut = pVar->n;
#ifdef SQLITE_TRACE_SIZE_LIMIT
if( n>SQLITE_TRACE_SIZE_LIMIT ){
if( nOut>SQLITE_TRACE_SIZE_LIMIT ){
nOut = SQLITE_TRACE_SIZE_LIMIT;
while( nOut<pVar->n && (pVar->z[n]&0xc0)==0x80 ){ n++; }
while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; }
}
#endif
sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z);
#ifdef SQLITE_TRACE_SIZE_LIMIT
if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-n);
if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut);
#endif
#ifndef SQLITE_OMIT_UTF16
if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8);
@@ -169,7 +169,7 @@ char *sqlite3VdbeExpandSql(
}
sqlite3StrAccumAppend(&out, "'", 1);
#ifdef SQLITE_TRACE_SIZE_LIMIT
if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-n);
if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut);
#endif
}
}