aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2013-08-19 12:49:06 +0000
committerdrh <drh@noemail.net>2013-08-19 12:49:06 +0000
commitdb78b96111f93c7b183744c76f687ad84e14c567 (patch)
tree455cba36272a9eaede190e1c5257bd0fb7d27cf3 /src
parent700a7fdf833ce71ee46da1292f96e82afa2dd2f2 (diff)
parent77dfd5bb447381a23791abb35569d39046281f59 (diff)
downloadsqlite-db78b96111f93c7b183744c76f687ad84e14c567.tar.gz
sqlite-db78b96111f93c7b183744c76f687ad84e14c567.zip
Merge in all the latest updates and enhancements from trunk.
FossilOrigin-Name: 67587a3348b84424b2ab1f2df1ea923a5168e2e4
Diffstat (limited to 'src')
-rw-r--r--src/attach.c1
-rw-r--r--src/btree.c9
-rw-r--r--src/btree.h2
-rw-r--r--src/build.c2
-rw-r--r--src/expr.c10
-rw-r--r--src/main.c22
-rw-r--r--src/mem5.c8
-rw-r--r--src/pager.c85
-rw-r--r--src/pager.h14
-rw-r--r--src/pragma.c44
-rw-r--r--src/resolve.c44
-rw-r--r--src/shell.c1
-rw-r--r--src/sqlite.h.in2
-rw-r--r--src/sqliteInt.h53
-rw-r--r--src/tclsqlite.c23
-rw-r--r--src/test_autoext.c2
-rw-r--r--src/test_demovfs.c2
-rw-r--r--src/test_fs.c4
-rw-r--r--src/test_intarray.h3
-rw-r--r--src/test_multiplex.h2
-rw-r--r--src/vdbe.c1
-rw-r--r--src/where.c34
22 files changed, 231 insertions, 137 deletions
diff --git a/src/attach.c b/src/attach.c
index b8e12199b..87c15ae3d 100644
--- a/src/attach.c
+++ b/src/attach.c
@@ -158,6 +158,7 @@ static void attachFunc(
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
sqlite3BtreeSecureDelete(aNew->pBt,
sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
+ sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK));
}
aNew->safety_level = 3;
aNew->zName = sqlite3DbStrDup(db, zName);
diff --git a/src/btree.c b/src/btree.c
index 9b7837879..ac0a8cf2c 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -2165,17 +2165,14 @@ int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){
** probability of damage to near zero but with a write performance reduction.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-int sqlite3BtreeSetSafetyLevel(
+int sqlite3BtreeSetPagerFlags(
Btree *p, /* The btree to set the safety level on */
- int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */
- int fullSync, /* PRAGMA fullfsync. */
- int ckptFullSync /* PRAGMA checkpoint_fullfync */
+ unsigned pgFlags /* Various PAGER_* flags */
){
BtShared *pBt = p->pBt;
assert( sqlite3_mutex_held(p->db->mutex) );
- assert( level>=1 && level<=3 );
sqlite3BtreeEnter(p);
- sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync, ckptFullSync);
+ sqlite3PagerSetFlags(pBt->pPager, pgFlags);
sqlite3BtreeLeave(p);
return SQLITE_OK;
}
diff --git a/src/btree.h b/src/btree.h
index ace0f8cd2..33b3ed1f0 100644
--- a/src/btree.h
+++ b/src/btree.h
@@ -64,7 +64,7 @@ int sqlite3BtreeOpen(
int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetCacheSize(Btree*,int);
int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
-int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
+int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
int sqlite3BtreeSyncDisabled(Btree*);
int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
int sqlite3BtreeGetPageSize(Btree*);
diff --git a/src/build.c b/src/build.c
index f5ea5be4b..023901738 100644
--- a/src/build.c
+++ b/src/build.c
@@ -2866,7 +2866,7 @@ Index *sqlite3CreateIndex(
** the zStmt variable
*/
if( pStart ){
- int n = (pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
+ int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
if( pName->z[n-1]==';' ) n--;
/* A named index with an explicit CREATE INDEX statement */
zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
diff --git a/src/expr.c b/src/expr.c
index 3857d5d84..5c5297c18 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1734,15 +1734,17 @@ int sqlite3CodeSubselect(
dest.affSdst = (u8)affinity;
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
pExpr->x.pSelect->iLimit = 0;
+ testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){
sqlite3DbFree(pParse->db, pKeyInfo);
return 0;
}
pEList = pExpr->x.pSelect->pEList;
- if( pKeyInfo && ALWAYS(pEList!=0 && pEList->nExpr>0) ){
- pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
- pEList->a[0].pExpr);
- }
+ assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
+ assert( pEList!=0 );
+ assert( pEList->nExpr>0 );
+ pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
+ pEList->a[0].pExpr);
}else if( ALWAYS(pExpr->x.pList!=0) ){
/* Case 2: expr IN (exprlist)
**
diff --git a/src/main.c b/src/main.c
index c4ba03849..1f01853c6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -117,6 +117,9 @@ char *sqlite3_data_directory = 0;
int sqlite3_initialize(void){
MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
int rc; /* Result code */
+#ifdef SQLITE_EXTRA_INIT
+ int bRunExtraInit = 0; /* Extra initialization needed */
+#endif
#ifdef SQLITE_OMIT_WSD
rc = sqlite3_wsd_init(4096, 24);
@@ -214,6 +217,9 @@ int sqlite3_initialize(void){
sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
sqlite3GlobalConfig.isInit = 1;
+#ifdef SQLITE_EXTRA_INIT
+ bRunExtraInit = 1;
+#endif
}
sqlite3GlobalConfig.inProgress = 0;
}
@@ -254,7 +260,7 @@ int sqlite3_initialize(void){
** compile-time option.
*/
#ifdef SQLITE_EXTRA_INIT
- if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){
+ if( bRunExtraInit ){
int SQLITE_EXTRA_INIT(const char*);
rc = SQLITE_EXTRA_INIT(0);
}
@@ -442,8 +448,8 @@ int sqlite3_config(int op, ...){
memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m));
}else{
/* The heap pointer is not NULL, then install one of the
- ** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor
- ** ENABLE_MEMSYS5 is defined, return an error.
+ ** mem5.c/mem3.c methods. The enclosing #if guarantees at
+ ** least one of these methods is currently enabled.
*/
#ifdef SQLITE_ENABLE_MEMSYS3
sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3();
@@ -462,7 +468,7 @@ int sqlite3_config(int op, ...){
break;
}
- /* Record a pointer to the logger funcction and its first argument.
+ /* Record a pointer to the logger function and its first argument.
** The default is NULL. Logging is disabled if the function pointer is
** NULL.
*/
@@ -2199,20 +2205,20 @@ int sqlite3ParseUri(
zFile = sqlite3_malloc(nByte);
if( !zFile ) return SQLITE_NOMEM;
+ iIn = 5;
+#ifndef SQLITE_ALLOW_URI_AUTHORITY
/* Discard the scheme and authority segments of the URI. */
if( zUri[5]=='/' && zUri[6]=='/' ){
iIn = 7;
while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
-
if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
*pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s",
iIn-7, &zUri[7]);
rc = SQLITE_ERROR;
goto parse_uri_out;
}
- }else{
- iIn = 5;
}
+#endif
/* Copy the filename and any query parameters into the zFile buffer.
** Decode %HH escape codes along the way.
@@ -2476,7 +2482,7 @@ static int openDatabase(
db->nextAutovac = -1;
db->szMmap = sqlite3GlobalConfig.szMmap;
db->nextPagesize = 0;
- db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger
+ db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger | SQLITE_CacheSpill
#if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX
| SQLITE_AutoIndex
#endif
diff --git a/src/mem5.c b/src/mem5.c
index 783cef617..5f99ebf43 100644
--- a/src/mem5.c
+++ b/src/mem5.c
@@ -130,13 +130,13 @@ static SQLITE_WSD struct Mem5Global {
} mem5;
/*
-** Access the static variable through a macro for SQLITE_OMIT_WSD
+** Access the static variable through a macro for SQLITE_OMIT_WSD.
*/
#define mem5 GLOBAL(struct Mem5Global, mem5)
/*
** Assuming mem5.zPool is divided up into an array of Mem5Link
-** structures, return a pointer to the idx-th such lik.
+** structures, return a pointer to the idx-th such link.
*/
#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.szAtom]))
@@ -232,7 +232,7 @@ static int memsys5UnlinkFirst(int iLogsize){
** Return a block of memory of at least nBytes in size.
** Return NULL if unable. Return NULL if nBytes==0.
**
-** The caller guarantees that nByte positive.
+** The caller guarantees that nByte is positive.
**
** The caller has obtained a mutex prior to invoking this
** routine so there is never any chance that two or more
@@ -354,7 +354,7 @@ static void memsys5FreeUnsafe(void *pOld){
}
/*
-** Allocate nBytes of memory
+** Allocate nBytes of memory.
*/
static void *memsys5Malloc(int nBytes){
sqlite3_int64 *p = 0;
diff --git a/src/pager.c b/src/pager.c
index b20822896..77a7d86a0 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -454,6 +454,13 @@ struct PagerSavepoint {
};
/*
+** Bits of the Pager.doNotSpill flag. See further description below.
+*/
+#define SPILLFLAG_OFF 0x01 /* Never spill cache. Set via pragma */
+#define SPILLFLAG_ROLLBACK 0x02 /* Current rolling back, so do not spill */
+#define SPILLFLAG_NOSYNC 0x04 /* Spill is ok, but do not sync */
+
+/*
** A open page cache is an instance of struct Pager. A description of
** some of the more important member variables follows:
**
@@ -519,19 +526,21 @@ struct PagerSavepoint {
** journal file from being successfully finalized, the setMaster flag
** is cleared anyway (and the pager will move to ERROR state).
**
-** doNotSpill, doNotSyncSpill
+** doNotSpill
**
-** These two boolean variables control the behavior of cache-spills
-** (calls made by the pcache module to the pagerStress() routine to
-** write cached data to the file-system in order to free up memory).
+** This variables control the behavior of cache-spills (calls made by
+** the pcache module to the pagerStress() routine to write cached data
+** to the file-system in order to free up memory).
**
-** When doNotSpill is non-zero, writing to the database from pagerStress()
-** is disabled altogether. This is done in a very obscure case that
+** When bits SPILLFLAG_OFF or SPILLFLAG_ROLLBACK of doNotSpill are set,
+** writing to the database from pagerStress() is disabled altogether.
+** The SPILLFLAG_ROLLBACK case is done in a very obscure case that
** comes up during savepoint rollback that requires the pcache module
** to allocate a new page to prevent the journal file from being written
-** while it is being traversed by code in pager_playback().
+** while it is being traversed by code in pager_playback(). The SPILLFLAG_OFF
+** case is a user preference.
**
-** If doNotSyncSpill is non-zero, writing to the database from pagerStress()
+** If the SPILLFLAG_NOSYNC bit is set, writing to the database from pagerStress()
** is permitted, but syncing the journal file is not. This flag is set
** by sqlite3PagerWrite() when the file-system sector-size is larger than
** the database page-size in order to prevent a journal sync from happening
@@ -635,7 +644,6 @@ struct Pager {
u8 changeCountDone; /* Set after incrementing the change-counter */
u8 setMaster; /* True if a m-j name has been written to jrnl */
u8 doNotSpill; /* Do not spill the cache when non-zero */
- u8 doNotSyncSpill; /* Do not do a spill that requires jrnl sync */
u8 subjInMemory; /* True to use in-memory sub-journals */
Pgno dbSize; /* Number of pages in the database */
Pgno dbOrigSize; /* dbSize before the current transaction */
@@ -2295,11 +2303,11 @@ static int pager_playback_one_page(
** requiring a journal-sync before it is written.
*/
assert( isSavepnt );
- assert( pPager->doNotSpill==0 );
- pPager->doNotSpill++;
+ assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 );
+ pPager->doNotSpill |= SPILLFLAG_ROLLBACK;
rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1);
- assert( pPager->doNotSpill==1 );
- pPager->doNotSpill--;
+ assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 );
+ pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK;
if( rc!=SQLITE_OK ) return rc;
pPg->flags &= ~PGHDR_NEED_READ;
sqlite3PcacheMakeDirty(pPg);
@@ -3404,9 +3412,12 @@ void sqlite3PagerShrink(Pager *pPager){
}
/*
-** Adjust the robustness of the database to damage due to OS crashes
-** or power failures by changing the number of syncs()s when writing
-** the rollback journal. There are three levels:
+** Adjust settings of the pager to those specified in the pgFlags parameter.
+**
+** The "level" in pgFlags & PAGER_SYNCHRONOUS_MASK sets the robustness
+** of the database to damage due to OS crashes or power failures by
+** changing the number of syncs()s when writing the journals.
+** There are three levels:
**
** OFF sqlite3OsSync() is never called. This is the default
** for temporary and transient files.
@@ -3447,22 +3458,21 @@ void sqlite3PagerShrink(Pager *pPager){
** and FULL=3.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-void sqlite3PagerSetSafetyLevel(
+void sqlite3PagerSetFlags(
Pager *pPager, /* The pager to set safety level for */
- int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */
- int bFullFsync, /* PRAGMA fullfsync */
- int bCkptFullFsync /* PRAGMA checkpoint_fullfsync */
+ unsigned pgFlags /* Various flags */
){
+ unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK;
assert( level>=1 && level<=3 );
pPager->noSync = (level==1 || pPager->tempFile) ?1:0;
pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0;
if( pPager->noSync ){
pPager->syncFlags = 0;
pPager->ckptSyncFlags = 0;
- }else if( bFullFsync ){
+ }else if( pgFlags & PAGER_FULLFSYNC ){
pPager->syncFlags = SQLITE_SYNC_FULL;
pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
- }else if( bCkptFullFsync ){
+ }else if( pgFlags & PAGER_CKPT_FULLFSYNC ){
pPager->syncFlags = SQLITE_SYNC_NORMAL;
pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
}else{
@@ -3473,6 +3483,11 @@ void sqlite3PagerSetSafetyLevel(
if( pPager->fullSync ){
pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS;
}
+ if( pgFlags & PAGER_CACHESPILL ){
+ pPager->doNotSpill &= ~SPILLFLAG_OFF;
+ }else{
+ pPager->doNotSpill |= SPILLFLAG_OFF;
+ }
}
#endif
@@ -4373,13 +4388,14 @@ static int pagerStress(void *p, PgHdr *pPg){
assert( pPg->pPager==pPager );
assert( pPg->flags&PGHDR_DIRTY );
- /* The doNotSyncSpill flag is set during times when doing a sync of
+ /* The doNotSpill NOSYNC bit is set during times when doing a sync of
** journal (and adding a new header) is not allowed. This occurs
** during calls to sqlite3PagerWrite() while trying to journal multiple
** pages belonging to the same sector.
**
- ** The doNotSpill flag inhibits all cache spilling regardless of whether
- ** or not a sync is required. This is set during a rollback.
+ ** The doNotSpill ROLLBACK and OFF bits inhibits all cache spilling
+ ** regardless of whether or not a sync is required. This is set during
+ ** a rollback or by user request, respectively.
**
** Spilling is also prohibited when in an error state since that could
** lead to database corruption. In the current implementaton it
@@ -4389,8 +4405,13 @@ static int pagerStress(void *p, PgHdr *pPg){
** test for the error state as a safeguard against future changes.
*/
if( NEVER(pPager->errCode) ) return SQLITE_OK;
- if( pPager->doNotSpill ) return SQLITE_OK;
- if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
+ testcase( pPager->doNotSpill & SPILLFLAG_ROLLBACK );
+ testcase( pPager->doNotSpill & SPILLFLAG_OFF );
+ testcase( pPager->doNotSpill & SPILLFLAG_NOSYNC );
+ if( pPager->doNotSpill
+ && ((pPager->doNotSpill & (SPILLFLAG_ROLLBACK|SPILLFLAG_OFF))!=0
+ || (pPg->flags & PGHDR_NEED_SYNC)!=0)
+ ){
return SQLITE_OK;
}
@@ -5744,13 +5765,13 @@ int sqlite3PagerWrite(DbPage *pDbPage){
int ii; /* Loop counter */
int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */
- /* Set the doNotSyncSpill flag to 1. This is because we cannot allow
+ /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
** a journal header to be written between the pages journaled by
** this function.
*/
assert( !MEMDB );
- assert( pPager->doNotSyncSpill==0 );
- pPager->doNotSyncSpill++;
+ assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 );
+ pPager->doNotSpill |= SPILLFLAG_NOSYNC;
/* This trick assumes that both the page-size and sector-size are
** an integer power of 2. It sets variable pg1 to the identifier
@@ -5809,8 +5830,8 @@ int sqlite3PagerWrite(DbPage *pDbPage){
}
}
- assert( pPager->doNotSyncSpill==1 );
- pPager->doNotSyncSpill--;
+ assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 );
+ pPager->doNotSpill &= ~SPILLFLAG_NOSYNC;
}else{
rc = pager_write(pDbPage);
}
diff --git a/src/pager.h b/src/pager.h
index 6f659136e..5528be14e 100644
--- a/src/pager.h
+++ b/src/pager.h
@@ -85,6 +85,18 @@ typedef struct PgHdr DbPage;
#define PAGER_ACQUIRE_READONLY 0x02 /* Read-only page is acceptable */
/*
+** Flags for sqlite3PagerSetFlags()
+*/
+#define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */
+#define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */
+#define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */
+#define PAGER_SYNCHRONOUS_MASK 0x03 /* Mask for three values above */
+#define PAGER_FULLFSYNC 0x04 /* PRAGMA fullfsync=ON */
+#define PAGER_CKPT_FULLFSYNC 0x08 /* PRAGMA checkpoint_fullfsync=ON */
+#define PAGER_CACHESPILL 0x10 /* PRAGMA cache_spill=ON */
+#define PAGER_FLAGS_MASK 0x1c /* All above except SYNCHRONOUS */
+
+/*
** The remainder of this file contains the declarations of the functions
** that make up the Pager sub-system API. See source code comments for
** a detailed description of each routine.
@@ -110,7 +122,7 @@ int sqlite3PagerMaxPageCount(Pager*, int);
void sqlite3PagerSetCachesize(Pager*, int);
void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
void sqlite3PagerShrink(Pager*);
-void sqlite3PagerSetSafetyLevel(Pager*,int,int,int);
+void sqlite3PagerSetFlags(Pager*,unsigned);
int sqlite3PagerLockingMode(Pager *, int);
int sqlite3PagerSetJournalMode(Pager *, int);
int sqlite3PagerGetJournalMode(Pager*);
diff --git a/src/pragma.c b/src/pragma.c
index f152220d4..f0f7b5b66 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -158,6 +158,34 @@ static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){
sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
}
+
+/*
+** Set the safety_level and pager flags for pager iDb. Or if iDb<0
+** set these values for all pagers.
+*/
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+static void setAllPagerFlags(sqlite3 *db){
+ if( db->autoCommit ){
+ Db *pDb = db->aDb;
+ int n = db->nDb;
+ assert( SQLITE_FullFSync==PAGER_FULLFSYNC );
+ assert( SQLITE_CkptFullFSync==PAGER_CKPT_FULLFSYNC );
+ assert( SQLITE_CacheSpill==PAGER_CACHESPILL );
+ assert( (PAGER_FULLFSYNC | PAGER_CKPT_FULLFSYNC | PAGER_CACHESPILL)
+ == PAGER_FLAGS_MASK );
+ assert( (pDb->safety_level & PAGER_SYNCHRONOUS_MASK)==pDb->safety_level );
+ while( (n--) > 0 ){
+ if( pDb->pBt ){
+ sqlite3BtreeSetPagerFlags(pDb->pBt,
+ pDb->safety_level | (db->flags & PAGER_FLAGS_MASK) );
+ }
+ pDb++;
+ }
+ }
+}
+#endif
+
+
#ifndef SQLITE_OMIT_FLAG_PRAGMAS
/*
** Check to see if zRight and zLeft refer to a pragma that queries
@@ -176,6 +204,7 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
{ "legacy_file_format", SQLITE_LegacyFileFmt },
{ "fullfsync", SQLITE_FullFSync },
{ "checkpoint_fullfsync", SQLITE_CkptFullFSync },
+ { "cache_spill", SQLITE_CacheSpill },
{ "reverse_unordered_selects", SQLITE_ReverseOrder },
{ "query_only", SQLITE_QueryOnly },
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
@@ -966,6 +995,7 @@ void sqlite3Pragma(
"Safety level may not be changed inside a transaction");
}else{
pDb->safety_level = getSafetyLevel(zRight,0,1)+1;
+ setAllPagerFlags(db);
}
}
}else
@@ -973,8 +1003,7 @@ void sqlite3Pragma(
#ifndef SQLITE_OMIT_FLAG_PRAGMAS
if( flagPragma(pParse, zLeft, zRight) ){
- /* The flagPragma() subroutine also generates any necessary code
- ** there is nothing more to do here */
+ setAllPagerFlags(db);
}else
#endif /* SQLITE_OMIT_FLAG_PRAGMAS */
@@ -1805,17 +1834,6 @@ void sqlite3Pragma(
{/* Empty ELSE clause */}
- /*
- ** Reset the safety level, in case the fullfsync flag or synchronous
- ** setting changed.
- */
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
- if( db->autoCommit ){
- sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level,
- (db->flags&SQLITE_FullFSync)!=0,
- (db->flags&SQLITE_CkptFullFSync)!=0);
- }
-#endif
pragma_out:
sqlite3DbFree(db, zLeft);
sqlite3DbFree(db, zRight);
diff --git a/src/resolve.c b/src/resolve.c
index a194a2655..43a3870e2 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -55,7 +55,7 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
** column reference is so that the column reference will be recognized as
** usable by indices within the WHERE clause processing logic.
**
-** Hack: The TK_AS operator is inhibited if zType[0]=='G'. This means
+** The TK_AS operator is inhibited if zType[0]=='G'. This means
** that in a GROUP BY clause, the expression is evaluated twice. Hence:
**
** SELECT random()%5 AS x, count(*) FROM tab GROUP BY x
@@ -65,8 +65,9 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
**
** The result of random()%5 in the GROUP BY clause is probably different
-** from the result in the result-set. We might fix this someday. Or
-** then again, we might not...
+** from the result in the result-set. On the other hand Standard SQL does
+** not allow the GROUP BY clause to contain references to result-set columns.
+** So this should never come up in well-formed queries.
**
** If the reference is followed by a COLLATE operator, then make sure
** the COLLATE operator is preserved. For example:
@@ -396,10 +397,16 @@ static int lookupName(
** forms the result set entry ("a+b" in the example) and return immediately.
** Note that the expression in the result set should have already been
** resolved by the time the WHERE clause is resolved.
+ **
+ ** The ability to use an output result-set column in the WHERE, GROUP BY,
+ ** or HAVING clauses, or as part of a larger expression in the ORDRE BY
+ ** clause is not standard SQL. This is a (goofy) SQLite extension, that
+ ** is supported for backwards compatibility only. TO DO: Issue a warning
+ ** on sqlite3_log() whenever the capability is used.
*/
if( (pEList = pNC->pEList)!=0
&& zTab==0
- && ((pNC->ncFlags & NC_AsMaybe)==0 || cnt==0)
+ && cnt==0
){
for(j=0; j<pEList->nExpr; j++){
char *zAs = pEList->a[j].zName;
@@ -961,7 +968,7 @@ static int resolveCompoundOrderBy(
/*
** Check every term in the ORDER BY or GROUP BY clause pOrderBy of
** the SELECT statement pSelect. If any term is reference to a
-** result set expression (as determined by the ExprList.a.iCol field)
+** result set expression (as determined by the ExprList.a.iOrderByCol field)
** then convert that term into a copy of the corresponding result set
** column.
**
@@ -1009,7 +1016,7 @@ int sqlite3ResolveOrderGroupBy(
** If the order-by term is an integer I between 1 and N (where N is the
** number of columns in the result set of the SELECT) then the expression
** in the resolution is a copy of the I-th result-set expression. If
-** the order-by term is an identify that corresponds to the AS-name of
+** the order-by term is an identifier that corresponds to the AS-name of
** a result-set expression, then the term resolves to a copy of the
** result-set expression. Otherwise, the expression is resolved in
** the usual way - using sqlite3ResolveExprNames().
@@ -1035,16 +1042,19 @@ static int resolveOrderGroupBy(
pParse = pNC->pParse;
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
Expr *pE = pItem->pExpr;
- iCol = resolveAsName(pParse, pSelect->pEList, pE);
- if( iCol>0 ){
- /* If an AS-name match is found, mark this ORDER BY column as being
- ** a copy of the iCol-th result-set column. The subsequent call to
- ** sqlite3ResolveOrderGroupBy() will convert the expression to a
- ** copy of the iCol-th result-set expression. */
- pItem->iOrderByCol = (u16)iCol;
- continue;
+ Expr *pE2 = sqlite3ExprSkipCollate(pE);
+ if( zType[0]!='G' ){
+ iCol = resolveAsName(pParse, pSelect->pEList, pE2);
+ if( iCol>0 ){
+ /* If an AS-name match is found, mark this ORDER BY column as being
+ ** a copy of the iCol-th result-set column. The subsequent call to
+ ** sqlite3ResolveOrderGroupBy() will convert the expression to a
+ ** copy of the iCol-th result-set expression. */
+ pItem->iOrderByCol = (u16)iCol;
+ continue;
+ }
}
- if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){
+ if( sqlite3ExprIsInteger(pE2, &iCol) ){
/* The ORDER BY term is an integer constant. Again, set the column
** number so that sqlite3ResolveOrderGroupBy() will convert the
** order-by term to a copy of the result-set expression */
@@ -1187,7 +1197,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
return WRC_Abort;
}
- /* Add the expression list to the name-context before parsing the
+ /* Add the output column list to the name-context before parsing the
** other expressions in the SELECT statement. This is so that
** expressions in the WHERE clause (etc.) can refer to expressions by
** aliases in the result set.
@@ -1196,10 +1206,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** re-evaluated for each reference to it.
*/
sNC.pEList = p->pEList;
- sNC.ncFlags |= NC_AsMaybe;
if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
- sNC.ncFlags &= ~NC_AsMaybe;
/* The ORDER BY and GROUP BY clauses may not refer to terms in
** outer queries
diff --git a/src/shell.c b/src/shell.c
index 4a59c667a..c811057ae 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -2902,6 +2902,7 @@ static int process_input(struct callback_data *p, FILE *in){
if( nSql==0 ){
int i;
for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
+ assert( nAlloc>0 && zSql!=0 );
memcpy(zSql, zLine+i, nLine+1-i);
startline = lineno;
nSql = nLine-i;
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 551a11857..08aae5494 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -7323,4 +7323,4 @@ SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
#ifdef __cplusplus
} /* End of the 'extern "C"' block */
#endif
-#endif
+#endif /* _SQLITE3_H_ */
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index b16295904..32057eeba 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -980,32 +980,33 @@ struct sqlite3 {
*/
#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
#define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */
-#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */
-#define SQLITE_ShortColNames 0x00000008 /* Show short columns names */
-#define SQLITE_CountRows 0x00000010 /* Count rows changed by INSERT, */
+#define SQLITE_FullFSync 0x00000004 /* Use full fsync on the backend */
+#define SQLITE_CkptFullFSync 0x00000008 /* Use full fsync for checkpoint */
+#define SQLITE_CacheSpill 0x00000010 /* OK to spill pager cache */
+#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */
+#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */
+#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */
/* DELETE, or UPDATE and return */
/* the count using a callback. */
-#define SQLITE_NullCallback 0x00000020 /* Invoke the callback once if the */
+#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */
/* result set is empty */
-#define SQLITE_SqlTrace 0x00000040 /* Debug print SQL as it executes */
-#define SQLITE_VdbeListing 0x00000080 /* Debug listings of VDBE programs */
-#define SQLITE_WriteSchema 0x00000100 /* OK to update SQLITE_MASTER */
-#define SQLITE_VdbeAddopTrace 0x00000200 /* Trace sqlite3VdbeAddOp() calls */
-#define SQLITE_IgnoreChecks 0x00000400 /* Do not enforce check constraints */
-#define SQLITE_ReadUncommitted 0x0000800 /* For shared-cache mode */
-#define SQLITE_LegacyFileFmt 0x00001000 /* Create new databases in format 1 */
-#define SQLITE_FullFSync 0x00002000 /* Use full fsync on the backend */
-#define SQLITE_CkptFullFSync 0x00004000 /* Use full fsync for checkpoint */
-#define SQLITE_RecoveryMode 0x00008000 /* Ignore schema errors */
-#define SQLITE_ReverseOrder 0x00010000 /* Reverse unordered SELECTs */
-#define SQLITE_RecTriggers 0x00020000 /* Enable recursive triggers */
-#define SQLITE_ForeignKeys 0x00040000 /* Enforce foreign key constraints */
-#define SQLITE_AutoIndex 0x00080000 /* Enable automatic indexes */
-#define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */
-#define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */
-#define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */
-#define SQLITE_DeferFKs 0x00800000 /* Defer all FK constraints */
-#define SQLITE_QueryOnly 0x01000000 /* Disable database changes */
+#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */
+#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */
+#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */
+#define SQLITE_VdbeAddopTrace 0x00001000 /* Trace sqlite3VdbeAddOp() calls */
+#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */
+#define SQLITE_ReadUncommitted 0x0004000 /* For shared-cache mode */
+#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */
+#define SQLITE_RecoveryMode 0x00010000 /* Ignore schema errors */
+#define SQLITE_ReverseOrder 0x00020000 /* Reverse unordered SELECTs */
+#define SQLITE_RecTriggers 0x00040000 /* Enable recursive triggers */
+#define SQLITE_ForeignKeys 0x00080000 /* Enforce foreign key constraints */
+#define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */
+#define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */
+#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */
+#define SQLITE_EnableTrigger 0x00800000 /* True to enable triggers */
+#define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */
+#define SQLITE_QueryOnly 0x02000000 /* Disable database changes */
/*
@@ -2014,7 +2015,7 @@ struct SrcList {
struct NameContext {
Parse *pParse; /* The parser */
SrcList *pSrcList; /* One or more tables used to resolve names */
- ExprList *pEList; /* Optional list of named expressions */
+ ExprList *pEList; /* Optional list of result-set columns */
AggInfo *pAggInfo; /* Information about aggregates at this level */
NameContext *pNext; /* Next outer name context. NULL for outermost */
int nRef; /* Number of names resolved by this context */
@@ -2029,9 +2030,7 @@ struct NameContext {
#define NC_HasAgg 0x02 /* One or more aggregate functions seen */
#define NC_IsCheck 0x04 /* True if resolving names in a CHECK constraint */
#define NC_InAggFunc 0x08 /* True if analyzing arguments to an agg func */
-#define NC_AsMaybe 0x10 /* Resolve to AS terms of the result set only
- ** if no other resolution is available */
-#define NC_PartIdx 0x20 /* True if resolving a partial index WHERE */
+#define NC_PartIdx 0x10 /* True if resolving a partial index WHERE */
/*
** An instance of the following structure contains all information
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index 78a03083b..322f84986 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -41,6 +41,18 @@
#endif
#include <ctype.h>
+/* Used to get the current process ID */
+#if !defined(_WIN32)
+# include <unistd.h>
+# define GETPID getpid
+#elif !defined(_WIN32_WCE)
+# ifndef SQLITE_AMALGAMATION
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# endif
+# define GETPID (int)GetCurrentProcessId
+#endif
+
/*
* Windows needs to know which symbols to export. Unix does not.
* BUILD_sqlite should be undefined for Unix.
@@ -3898,7 +3910,16 @@ static void init_all(Tcl_Interp *interp){
#define TCLSH_MAIN main /* Needed to fake out mktclapp */
int TCLSH_MAIN(int argc, char **argv){
Tcl_Interp *interp;
-
+
+#if !defined(_WIN32_WCE)
+ if( getenv("BREAK") ){
+ fprintf(stderr,
+ "attach debugger to process %d and press any key to continue.\n",
+ GETPID());
+ fgetc(stdin);
+ }
+#endif
+
/* Call sqlite3_shutdown() once before doing anything else. This is to
** test that sqlite3_shutdown() can be safely called by a process before
** sqlite3_initialize() is. */
diff --git a/src/test_autoext.c b/src/test_autoext.c
index 4a5a5caa0..a5236d239 100644
--- a/src/test_autoext.c
+++ b/src/test_autoext.c
@@ -208,13 +208,13 @@ int Sqlitetest_autoext_Init(Tcl_Interp *interp){
autoExtCubeObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "sqlite3_auto_extension_broken",
autoExtBrokenObjCmd, 0, 0);
-#endif
Tcl_CreateObjCommand(interp, "sqlite3_cancel_auto_extension_sqr",
cancelAutoExtSqrObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "sqlite3_cancel_auto_extension_cube",
cancelAutoExtCubeObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "sqlite3_cancel_auto_extension_broken",
cancelAutoExtBrokenObjCmd, 0, 0);
+#endif
Tcl_CreateObjCommand(interp, "sqlite3_reset_auto_extension",
resetAutoExtObjCmd, 0, 0);
return TCL_OK;
diff --git a/src/test_demovfs.c b/src/test_demovfs.c
index 637627071..c63b0a8b7 100644
--- a/src/test_demovfs.c
+++ b/src/test_demovfs.c
@@ -536,7 +536,7 @@ static int demoFullPathname(
if( zPath[0]=='/' ){
zDir[0] = '\0';
}else{
- getcwd(zDir, sizeof(zDir));
+ if( getcwd(zDir, sizeof(zDir))==0 ) return SQLITE_IOERR;
}
zDir[MAXPATHNAME] = '\0';
diff --git a/src/test_fs.c b/src/test_fs.c
index 478cad80b..417c81b49 100644
--- a/src/test_fs.c
+++ b/src/test_fs.c
@@ -195,6 +195,7 @@ static int fsColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
const char *zFile = (const char *)sqlite3_column_text(pCur->pStmt, 1);
struct stat sbuf;
int fd;
+ int n;
fd = open(zFile, O_RDONLY);
if( fd<0 ) return SQLITE_IOERR;
@@ -214,8 +215,9 @@ static int fsColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
pCur->nAlloc = nNew;
}
- read(fd, pCur->zBuf, sbuf.st_size);
+ n = (int)read(fd, pCur->zBuf, sbuf.st_size);
close(fd);
+ if( n!=sbuf.st_size ) return SQLITE_ERROR;
pCur->nBuf = sbuf.st_size;
pCur->zBuf[pCur->nBuf] = '\0';
diff --git a/src/test_intarray.h b/src/test_intarray.h
index 691337d1a..6d26235a8 100644
--- a/src/test_intarray.h
+++ b/src/test_intarray.h
@@ -75,6 +75,8 @@
** action to free the intarray objects.
*/
#include "sqlite3.h"
+#ifndef _INTARRAY_H_
+#define _INTARRAY_H_
/*
** Make sure we can call this stuff from C++.
@@ -123,3 +125,4 @@ int sqlite3_intarray_bind(
#ifdef __cplusplus
} /* End of the 'extern "C"' block */
#endif
+#endif /* _INTARRAY_H_ */
diff --git a/src/test_multiplex.h b/src/test_multiplex.h
index b7e1afea5..9fe2f0f2b 100644
--- a/src/test_multiplex.h
+++ b/src/test_multiplex.h
@@ -96,4 +96,4 @@ extern int sqlite3_multiplex_shutdown(void);
} /* End of the 'extern "C"' block */
#endif
-#endif
+#endif /* _TEST_MULTIPLEX_H */
diff --git a/src/vdbe.c b/src/vdbe.c
index efbd182f2..75b9d2cff 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -6294,6 +6294,7 @@ vdbe_error_halt:
** top. */
vdbe_return:
db->lastRowid = lastRowid;
+ testcase( nVmStep>0 );
p->aCounter[SQLITE_STMTSTATUS_VM_STEP-1] += (int)nVmStep;
sqlite3VdbeLeave(p);
return rc;
diff --git a/src/where.c b/src/where.c
index 2bf3aaecb..92a9d3eb8 100644
--- a/src/where.c
+++ b/src/where.c
@@ -33,7 +33,7 @@
# define WHERETRACE(K,X)
#endif
-/* Forward reference
+/* Forward references
*/
typedef struct WhereClause WhereClause;
typedef struct WhereMaskSet WhereMaskSet;
@@ -55,14 +55,15 @@ typedef struct WhereOrSet WhereOrSet;
** So all costs can be stored in a 16-bit unsigned integer without risk
** of overflow.
**
-** Costs are estimates, so don't go to the computational trouble to compute
-** 10*log2(X) exactly. Instead, a close estimate is used. Any value of
-** X<=1 is stored as 0. X=2 is 10. X=3 is 16. X=1000 is 99. etc.
+** Costs are estimates, so no effort is made to compute 10*log2(X) exactly.
+** Instead, a close estimate is used. Any value of X<=1 is stored as 0.
+** X=2 is 10. X=3 is 16. X=1000 is 99. etc.
**
** The tool/wherecosttest.c source file implements a command-line program
-** that will convert between WhereCost to integers and do addition and
-** multiplication on WhereCost values. That command-line program is a
-** useful utility to have around when working with this module.
+** that will convert WhereCosts to integers, convert integers to WhereCosts
+** and do addition and multiplication on WhereCost values. The wherecosttest
+** command-line program is a useful utility to have around when working with
+** this module.
*/
typedef unsigned short int WhereCost;
@@ -165,8 +166,8 @@ struct WhereOrCost {
};
/* The WhereOrSet object holds a set of possible WhereOrCosts that
-** correspond to the subquery(s) of OR-clause processing. At most
-** favorable N_OR_COST elements are retained.
+** correspond to the subquery(s) of OR-clause processing. Only the
+** best N_OR_COST elements are retained.
*/
#define N_OR_COST 3
struct WhereOrSet {
@@ -232,9 +233,9 @@ struct WherePath {
**
** (t1.X <op> <expr>) OR (t1.Y <op> <expr>) OR ....
**
-** In this second case, wtFlag as the TERM_ORINFO set and eOperator==WO_OR
+** In this second case, wtFlag has the TERM_ORINFO bit set and eOperator==WO_OR
** and the WhereTerm.u.pOrInfo field points to auxiliary information that
-** is collected about the
+** is collected about the OR clause.
**
** If a term in the WHERE clause does not match either of the two previous
** categories, then eOperator==0. The WhereTerm.pExpr field is still set
@@ -746,7 +747,7 @@ static void createMask(WhereMaskSet *pMaskSet, int iCursor){
}
/*
-** These routine walk (recursively) an expression tree and generates
+** These routines walk (recursively) an expression tree and generate
** a bitmask indicating which tables are used in that expression
** tree.
*/
@@ -1263,10 +1264,10 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
** From another point of view, "indexable" means that the subterm could
** potentially be used with an index if an appropriate index exists.
** This analysis does not consider whether or not the index exists; that
-** is something the bestIndex() routine will determine. This analysis
-** only looks at whether subterms appropriate for indexing exist.
+** is decided elsewhere. This analysis only looks at whether subterms
+** appropriate for indexing exist.
**
-** All examples A through E above all satisfy case 2. But if a term
+** All examples A through E above satisfy case 2. But if a term
** also statisfies case 1 (such as B) we know that the optimizer will
** always prefer case 1, so in that case we pretend that case 2 is not
** satisfied.
@@ -1933,7 +1934,7 @@ static int isDistinctRedundant(
}
/*
-** The (an approximate) sum of two WhereCosts. This computation is
+** Find (an approximate) sum of two WhereCosts. This computation is
** not a simple "+" operator because WhereCost is stored as a logarithmic
** value.
**
@@ -4854,6 +4855,7 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
pWCEnd = pWC->a + pWC->nTerm;
pNew = pBuilder->pNew;
+ memset(&sSum, 0, sizeof(sSum));
for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
if( (pTerm->eOperator & WO_OR)!=0