1
0
mirror of https://github.com/sqlite/sqlite.git synced 2026-10-23 21:49:02 +03:00

Merge updates from trunk.

FossilOrigin-Name: 4ab1ffd45d4c25368b9b393a3336068b747d8b22
This commit is contained in:
mistachkin
2012-03-19 23:32:26 +00:00
21 changed files with 363 additions and 112 deletions

View File

@@ -932,6 +932,7 @@ static int loadStat3(sqlite3 *db, const char *zDb){
int eType; /* Datatype of a sample */
IndexSample *pSample; /* A slot in pIdx->aSample[] */
assert( db->lookaside.bEnabled==0 );
if( !sqlite3FindTable(db, "sqlite_stat3", zDb) ){
return SQLITE_OK;
}
@@ -958,7 +959,7 @@ static int loadStat3(sqlite3 *db, const char *zDb){
if( pIdx==0 ) continue;
assert( pIdx->nSample==0 );
pIdx->nSample = nSample;
pIdx->aSample = sqlite3MallocZero( nSample*sizeof(IndexSample) );
pIdx->aSample = sqlite3DbMallocZero(db, nSample*sizeof(IndexSample));
pIdx->avgEq = pIdx->aiRowEst[1];
if( pIdx->aSample==0 ){
db->mallocFailed = 1;
@@ -1031,7 +1032,7 @@ static int loadStat3(sqlite3 *db, const char *zDb){
if( n < 1){
pSample->u.z = 0;
}else{
pSample->u.z = sqlite3Malloc(n);
pSample->u.z = sqlite3DbMallocRaw(db, n);
if( pSample->u.z==0 ){
db->mallocFailed = 1;
sqlite3_finalize(pStmt);
@@ -1107,7 +1108,10 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
/* Load the statistics from the sqlite_stat3 table. */
#ifdef SQLITE_ENABLE_STAT3
if( rc==SQLITE_OK ){
int lookasideEnabled = db->lookaside.bEnabled;
db->lookaside.bEnabled = 0;
rc = loadStat3(db, sInfo.zDatabase);
db->lookaside.bEnabled = lookasideEnabled;
}
#endif

View File

@@ -2725,35 +2725,27 @@ int sqlite3_extended_result_codes(sqlite3 *db, int onoff){
*/
int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
int rc = SQLITE_ERROR;
int iDb;
Btree *pBtree;
sqlite3_mutex_enter(db->mutex);
if( zDbName==0 ){
iDb = 0;
}else{
for(iDb=0; iDb<db->nDb; iDb++){
if( strcmp(db->aDb[iDb].zName, zDbName)==0 ) break;
}
}
if( iDb<db->nDb ){
Btree *pBtree = db->aDb[iDb].pBt;
if( pBtree ){
Pager *pPager;
sqlite3_file *fd;
sqlite3BtreeEnter(pBtree);
pPager = sqlite3BtreePager(pBtree);
assert( pPager!=0 );
fd = sqlite3PagerFile(pPager);
assert( fd!=0 );
if( op==SQLITE_FCNTL_FILE_POINTER ){
*(sqlite3_file**)pArg = fd;
rc = SQLITE_OK;
}else if( fd->pMethods ){
rc = sqlite3OsFileControl(fd, op, pArg);
}else{
rc = SQLITE_NOTFOUND;
}
sqlite3BtreeLeave(pBtree);
pBtree = sqlite3DbNameToBtree(db, zDbName);
if( pBtree ){
Pager *pPager;
sqlite3_file *fd;
sqlite3BtreeEnter(pBtree);
pPager = sqlite3BtreePager(pBtree);
assert( pPager!=0 );
fd = sqlite3PagerFile(pPager);
assert( fd!=0 );
if( op==SQLITE_FCNTL_FILE_POINTER ){
*(sqlite3_file**)pArg = fd;
rc = SQLITE_OK;
}else if( fd->pMethods ){
rc = sqlite3OsFileControl(fd, op, pArg);
}else{
rc = SQLITE_NOTFOUND;
}
sqlite3BtreeLeave(pBtree);
}
sqlite3_mutex_leave(db->mutex);
return rc;
@@ -3049,15 +3041,34 @@ sqlite3_int64 sqlite3_uri_int64(
}
/*
** Return the filename of the database associated with a database
** connection.
** Return the Btree pointer identified by zDbName. Return NULL if not found.
*/
const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
int i;
for(i=0; i<db->nDb; i++){
if( db->aDb[i].pBt && sqlite3StrICmp(zDbName, db->aDb[i].zName)==0 ){
return sqlite3BtreeGetFilename(db->aDb[i].pBt);
if( db->aDb[i].pBt
&& (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zName)==0)
){
return db->aDb[i].pBt;
}
}
return 0;
}
/*
** Return the filename of the database associated with a database
** connection.
*/
const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
return pBt ? sqlite3BtreeGetFilename(pBt) : 0;
}
/*
** Return 1 if database is read-only or 0 if read/write. Return -1 if
** no such database exists.
*/
int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
return pBt ? sqlite3PagerIsreadonly(sqlite3BtreePager(pBt)) : -1;
}

View File

@@ -4530,6 +4530,15 @@ sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
*/
const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
/*
** CAPI3REF: Determine if a database is read-only
**
** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N
** of connection D is read-only, 0 if it is read/write, or -1 if N is not
** the name of a database on connection D.
*/
int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
/*
** CAPI3REF: Find the next prepared statement
**

View File

@@ -2701,6 +2701,7 @@ void sqlite3AddCollateType(Parse*, Token*);
void sqlite3EndTable(Parse*,Token*,Token*,Select*);
int sqlite3ParseUri(const char*,const char*,unsigned int*,
sqlite3_vfs**,char**,char **);
Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
int sqlite3CodeOnce(Parse *);
Bitvec *sqlite3BitvecCreate(u32);

View File

@@ -4665,6 +4665,30 @@ static int test_db_filename(
return TCL_OK;
}
/*
** Usage: sqlite3_db_readonly DB DBNAME
**
** Return 1 or 0 if DBNAME is readonly or not. Return -1 if DBNAME does
** not exist.
*/
static int test_db_readonly(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
sqlite3 *db;
const char *zDbName;
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
zDbName = Tcl_GetString(objv[2]);
Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_db_readonly(db, zDbName)));
return TCL_OK;
}
/*
** Usage: sqlite3_soft_heap_limit ?N?
**
@@ -6055,6 +6079,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_release_memory", test_release_memory, 0},
{ "sqlite3_db_release_memory", test_db_release_memory, 0},
{ "sqlite3_db_filename", test_db_filename, 0},
{ "sqlite3_db_readonly", test_db_readonly, 0},
{ "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
{ "sqlite3_thread_cleanup", test_thread_cleanup, 0},
{ "sqlite3_pager_refcounts", test_pager_refcounts, 0},

View File

@@ -216,11 +216,11 @@ int sqlite3Dequote(char *z){
** Some systems have stricmp(). Others have strcasecmp(). Because
** there is no consistency, we will define our own.
**
** IMPLEMENTATION-OF: R-20522-24639 The sqlite3_strnicmp() API allows
** applications and extensions to compare the contents of two buffers
** containing UTF-8 strings in a case-independent fashion, using the same
** definition of case independence that SQLite uses internally when
** comparing identifiers.
** IMPLEMENTATION-OF: R-30243-02494 The sqlite3_stricmp() and
** sqlite3_strnicmp() APIs allow applications and extensions to compare
** the contents of two buffers containing UTF-8 strings in a
** case-independent fashion, using the same definition of "case
** independence" that SQLite uses internally when comparing identifiers.
*/
int sqlite3_stricmp(const char *zLeft, const char *zRight){
register unsigned char *a, *b;

View File

@@ -3802,8 +3802,7 @@ static Bitmask codeOneLoopStart(
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
int iLevel, /* Which level of pWInfo->a[] should be coded */
u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
Bitmask notReady, /* Which tables are currently available */
Expr *pWhere /* Complete WHERE clause */
Bitmask notReady /* Which tables are currently available */
){
int j, k; /* Loop counters */
int iCur; /* The VDBE cursor for the table */
@@ -4342,10 +4341,25 @@ static Bitmask codeOneLoopStart(
** Then for every term xN, evaluate as the subexpression: xN AND z
** That way, terms in y that are factored into the disjunction will
** be picked up by the recursive calls to sqlite3WhereBegin() below.
**
** Actually, each subexpression is converted to "xN AND w" where w is
** the "interesting" terms of z - terms that did not originate in the
** ON or USING clause of a LEFT JOIN, and terms that are usable as
** indices.
*/
if( pWC->nTerm>1 ){
pAndExpr = sqlite3ExprAlloc(pParse->db, TK_AND, 0, 0);
pAndExpr->pRight = pWhere;
int iTerm;
for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
Expr *pExpr = pWC->a[iTerm].pExpr;
if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue;
if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr);
}
if( pAndExpr ){
pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0);
}
}
for(ii=0; ii<pOrWc->nTerm; ii++){
@@ -4387,7 +4401,10 @@ static Bitmask codeOneLoopStart(
}
}
}
sqlite3DbFree(pParse->db, pAndExpr);
if( pAndExpr ){
pAndExpr->pLeft = 0;
sqlite3ExprDelete(pParse->db, pAndExpr);
}
sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
sqlite3VdbeResolveLabel(v, iLoopBody);
@@ -5043,7 +5060,7 @@ WhereInfo *sqlite3WhereBegin(
for(i=0; i<nTabList; i++){
pLevel = &pWInfo->a[i];
explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags);
notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady, pWhere);
notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady);
pWInfo->iContinue = pLevel->addrCont;
}