1
0
Fork 0
mirror of https://github.com/DBD-SQLite/DBD-SQLite synced 2025-06-07 14:19:10 -04:00

updated bundled SQLite to 3.6.13

This commit is contained in:
Darren Duncan 2009-04-13 18:36:10 +00:00
parent cc8c5fe18a
commit 42dcba4d28
39 changed files with 2180 additions and 1711 deletions

View file

@ -1,6 +1,7 @@
Changes for Perl extension DBD-SQLite.
1.22_05 Sat 11 Apr 2009
- Updated to SQLite 3.6.13 (DUNCAND)
- Setting svn:eol-style to native to prevent EOL issues (ADAMK)
1.22_04 Sat 11 Apr 2009

View file

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
** $Id: attach.c,v 1.83 2009/02/19 14:39:25 danielk1977 Exp $
** $Id: attach.c,v 1.84 2009/04/08 13:51:51 drh Exp $
*/
#include "sqliteInt.h"
@ -488,7 +488,7 @@ int sqlite3FixExpr(
Expr *pExpr /* The expression to be fixed to one database */
){
while( pExpr ){
if( ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_SpanOnly) ) break;
if( ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_SpanToken) ) break;
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
}else{

View file

@ -34,7 +34,7 @@
** start of a transaction, and is thus usually less than a few thousand,
** but can be as large as 2 billion for a really big database.
**
** @(#) $Id: bitvec.c,v 1.13 2009/01/20 17:06:27 danielk1977 Exp $
** @(#) $Id: bitvec.c,v 1.14 2009/04/01 23:49:04 drh Exp $
*/
#include "sqliteInt.h"
@ -94,8 +94,9 @@
*/
struct Bitvec {
u32 iSize; /* Maximum bit index. Max iSize is 4,294,967,296. */
u32 nSet; /* Number of bits that are set - only valid for aHash element */
/* Max nSet is BITVEC_NINT. For BITVEC_SZ of 512, this would be 125. */
u32 nSet; /* Number of bits that are set - only valid for aHash
** element. Max is BITVEC_NINT. For BITVEC_SZ of 512,
** this would be 125. */
u32 iDivisor; /* Number of bits handled by each apSub[] entry. */
/* Should >=0 for apSub element. */
/* Max iDivisor is max(u32) / BITVEC_NPTR + 1. */
@ -377,7 +378,8 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
** is found.
*/
rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
+ sqlite3BitvecTest(pBitvec, 0);
+ sqlite3BitvecTest(pBitvec, 0)
+ (sqlite3BitvecSize(pBitvec) - sz);
for(i=1; i<=sz; i++){
if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
rc = i;

View file

@ -10,7 +10,7 @@
**
*************************************************************************
**
** $Id: btmutex.c,v 1.13 2009/03/05 04:20:32 shane Exp $
** $Id: btmutex.c,v 1.15 2009/04/10 12:55:17 danielk1977 Exp $
**
** This file contains code used to implement mutexes on Btree objects.
** This code really belongs in btree.c. But btree.c is getting too
@ -18,8 +18,37 @@
** a good breakout.
*/
#include "btreeInt.h"
#if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE)
#ifndef SQLITE_OMIT_SHARED_CACHE
#if SQLITE_THREADSAFE
/*
** Obtain the BtShared mutex associated with B-Tree handle p. Also,
** set BtShared.db to the database handle associated with p and the
** p->locked boolean to true.
*/
static void lockBtreeMutex(Btree *p){
assert( p->locked==0 );
assert( sqlite3_mutex_notheld(p->pBt->mutex) );
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3_mutex_enter(p->pBt->mutex);
p->pBt->db = p->db;
p->locked = 1;
}
/*
** Release the BtShared mutex associated with B-Tree handle p and
** clear the p->locked boolean.
*/
static void unlockBtreeMutex(Btree *p){
assert( p->locked==1 );
assert( sqlite3_mutex_held(p->pBt->mutex) );
assert( sqlite3_mutex_held(p->db->mutex) );
assert( p->db==p->pBt->db );
sqlite3_mutex_leave(p->pBt->mutex);
p->locked = 0;
}
/*
** Enter a mutex on the given BTree object.
@ -57,6 +86,10 @@ void sqlite3BtreeEnter(Btree *p){
/* We should already hold a lock on the database connection */
assert( sqlite3_mutex_held(p->db->mutex) );
/* Unless the database is sharable and unlocked, then BtShared.db
** should already be set correctly. */
assert( (p->locked==0 && p->sharable) || p->pBt->db==p->db );
if( !p->sharable ) return;
p->wantToLock++;
if( p->locked ) return;
@ -66,6 +99,7 @@ void sqlite3BtreeEnter(Btree *p){
** procedure that follows. Just be sure not to block.
*/
if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){
p->pBt->db = p->db;
p->locked = 1;
return;
}
@ -80,16 +114,13 @@ void sqlite3BtreeEnter(Btree *p){
assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt );
assert( !pLater->locked || pLater->wantToLock>0 );
if( pLater->locked ){
sqlite3_mutex_leave(pLater->pBt->mutex);
pLater->locked = 0;
unlockBtreeMutex(pLater);
}
}
sqlite3_mutex_enter(p->pBt->mutex);
p->locked = 1;
lockBtreeMutex(p);
for(pLater=p->pNext; pLater; pLater=pLater->pNext){
if( pLater->wantToLock ){
sqlite3_mutex_enter(pLater->pBt->mutex);
pLater->locked = 1;
lockBtreeMutex(pLater);
}
}
}
@ -102,25 +133,25 @@ void sqlite3BtreeLeave(Btree *p){
assert( p->wantToLock>0 );
p->wantToLock--;
if( p->wantToLock==0 ){
assert( p->locked );
sqlite3_mutex_leave(p->pBt->mutex);
p->locked = 0;
unlockBtreeMutex(p);
}
}
}
#ifndef NDEBUG
/*
** Return true if the BtShared mutex is held on the btree.
**
** This routine makes no determination one way or another if the
** database connection mutex is held.
** Return true if the BtShared mutex is held on the btree, or if the
** B-Tree is not marked as sharable.
**
** This routine is used only from within assert() statements.
*/
int sqlite3BtreeHoldsMutex(Btree *p){
return (p->sharable==0 ||
(p->locked && p->wantToLock && sqlite3_mutex_held(p->pBt->mutex)));
assert( p->sharable==0 || p->locked==0 || p->wantToLock>0 );
assert( p->sharable==0 || p->locked==0 || p->db==p->pBt->db );
assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->pBt->mutex) );
assert( p->sharable==0 || p->locked==0 || sqlite3_mutex_held(p->db->mutex) );
return (p->sharable==0 || p->locked);
}
#endif
@ -160,6 +191,7 @@ void sqlite3BtreeEnterAll(sqlite3 *db){
assert( sqlite3_mutex_held(db->mutex) );
for(i=0; i<db->nDb; i++){
p = db->aDb[i].pBt;
assert( !p || (p->locked==0 && p->sharable) || p->pBt->db==p->db );
if( p && p->sharable ){
p->wantToLock++;
if( !p->locked ){
@ -168,13 +200,11 @@ void sqlite3BtreeEnterAll(sqlite3 *db){
while( p->locked && p->pNext ) p = p->pNext;
for(pLater = p->pNext; pLater; pLater=pLater->pNext){
if( pLater->locked ){
sqlite3_mutex_leave(pLater->pBt->mutex);
pLater->locked = 0;
unlockBtreeMutex(pLater);
}
}
while( p ){
sqlite3_mutex_enter(p->pBt->mutex);
p->locked++;
lockBtreeMutex(p);
p = p->pNext;
}
}
@ -191,9 +221,7 @@ void sqlite3BtreeLeaveAll(sqlite3 *db){
assert( p->wantToLock>0 );
p->wantToLock--;
if( p->wantToLock==0 ){
assert( p->locked );
sqlite3_mutex_leave(p->pBt->mutex);
p->locked = 0;
unlockBtreeMutex(p);
}
}
}
@ -282,8 +310,7 @@ void sqlite3BtreeMutexArrayEnter(BtreeMutexArray *pArray){
p->wantToLock++;
if( !p->locked && p->sharable ){
sqlite3_mutex_enter(p->pBt->mutex);
p->locked = 1;
lockBtreeMutex(p);
}
}
}
@ -305,11 +332,23 @@ void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){
p->wantToLock--;
if( p->wantToLock==0 && p->locked ){
sqlite3_mutex_leave(p->pBt->mutex);
p->locked = 0;
unlockBtreeMutex(p);
}
}
}
#endif /* SQLITE_THREADSAFE && !SQLITE_OMIT_SHARED_CACHE */
#else
void sqlite3BtreeEnter(Btree *p){
p->pBt->db = p->db;
}
void sqlite3BtreeEnterAll(sqlite3 *db){
int i;
for(i=0; i<db->nDb; i++){
Btree *p = db->aDb[i].pBt;
if( p ){
p->pBt->db = p->db;
}
}
}
#endif /* if SQLITE_THREADSAFE */
#endif /* ifndef SQLITE_OMIT_SHARED_CACHE */

200
btree.c
View file

@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.582 2009/03/30 18:50:05 danielk1977 Exp $
** $Id: btree.c,v 1.595 2009/04/11 16:06:15 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
@ -103,6 +103,13 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
assert( p->db!=0 );
/* If requesting a write-lock, then the Btree must have an open write
** transaction on this file. And, obviously, for this to be so there
** must be an open write transaction on the file itself.
*/
assert( eLock==READ_LOCK || (p==pBt->pWriter && p->inTrans==TRANS_WRITE) );
assert( eLock==READ_LOCK || pBt->inTransaction==TRANS_WRITE );
/* This is a no-op if the shared-cache is not enabled */
if( !p->sharable ){
return SQLITE_OK;
@ -138,8 +145,18 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
iTab==MASTER_ROOT
){
for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
if( pIter->pBtree!=p && pIter->iTable==iTab &&
(pIter->eLock!=eLock || eLock!=READ_LOCK) ){
/* The condition (pIter->eLock!=eLock) in the following if(...)
** statement is a simplification of:
**
** (eLock==WRITE_LOCK || pIter->eLock==WRITE_LOCK)
**
** since we know that if eLock==WRITE_LOCK, then no other connection
** may hold a WRITE_LOCK on any table in this file (since there can
** only be a single writer).
*/
assert( pIter->eLock==READ_LOCK || pIter->eLock==WRITE_LOCK );
assert( eLock==READ_LOCK || pIter->pBtree==p || pIter->eLock==READ_LOCK);
if( pIter->pBtree!=p && pIter->iTable==iTab && pIter->eLock!=eLock ){
sqlite3ConnectionBlocked(p->db, pIter->pBtree->db);
if( eLock==WRITE_LOCK ){
assert( p==pBt->pWriter );
@ -231,6 +248,10 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
/*
** Release all the table locks (locks obtained via calls to
** the setSharedCacheTableLock() procedure) held by Btree handle p.
**
** This function assumes that handle p has an open read or write
** transaction. If it does not, then the BtShared.isPending variable
** may be incorrectly cleared.
*/
static void clearAllSharedCacheTableLocks(Btree *p){
BtShared *pBt = p->pBt;
@ -238,10 +259,12 @@ static void clearAllSharedCacheTableLocks(Btree *p){
assert( sqlite3BtreeHoldsMutex(p) );
assert( p->sharable || 0==*ppIter );
assert( p->inTrans>0 );
while( *ppIter ){
BtLock *pLock = *ppIter;
assert( pBt->isExclusive==0 || pBt->pWriter==pLock->pBtree );
assert( pLock->pBtree->inTrans>=pLock->eLock );
if( pLock->pBtree==p ){
*ppIter = pLock->pNext;
sqlite3_free(pLock);
@ -848,72 +871,74 @@ static int defragmentPage(MemPage *pPage){
}
/*
** Allocate nByte bytes of space on a page.
** Allocate nByte bytes of space from within the B-Tree page passed
** as the first argument. Return the index into pPage->aData[] of the
** first byte of allocated space.
**
** Return the index into pPage->aData[] of the first byte of
** the new allocation. The caller guarantees that there is enough
** space. This routine will never fail.
** The caller guarantees that the space between the end of the cell-offset
** array and the start of the cell-content area is at least nByte bytes
** in size. So this routine can never fail.
**
** If the page contains nBytes of free space but does not contain
** nBytes of contiguous free space, then this routine automatically
** calls defragmentPage() to consolidate all free space before
** allocating the new chunk.
** If there are already 60 or more bytes of fragments within the page,
** the page is defragmented before returning. If this were not done there
** is a chance that the number of fragmented bytes could eventually
** overflow the single-byte field of the page-header in which this value
** is stored.
*/
static int allocateSpace(MemPage *pPage, int nByte){
int addr, pc, hdr;
int size;
int nFrag;
const int hdr = pPage->hdrOffset; /* Local cache of pPage->hdrOffset */
u8 * const data = pPage->aData; /* Local cache of pPage->aData */
int nFrag; /* Number of fragmented bytes on pPage */
int top;
int nCell;
int cellOffset;
unsigned char *data;
data = pPage->aData;
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( pPage->pBt );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( nByte>=0 ); /* Minimum cell size is 4 */
assert( pPage->nFree>=nByte );
assert( pPage->nOverflow==0 );
pPage->nFree -= (u16)nByte;
hdr = pPage->hdrOffset;
/* Assert that the space between the cell-offset array and the
** cell-content area is greater than nByte bytes.
*/
assert( nByte <= (
get2byte(&data[hdr+5])-(hdr+8+(pPage->leaf?0:4)+2*get2byte(&data[hdr+3]))
));
pPage->nFree -= (u16)nByte;
nFrag = data[hdr+7];
if( nFrag<60 ){
/* Search the freelist looking for a slot big enough to satisfy the
** space request. */
addr = hdr+1;
while( (pc = get2byte(&data[addr]))>0 ){
size = get2byte(&data[pc+2]);
if( nFrag>=60 ){
defragmentPage(pPage);
}else{
/* Search the freelist looking for a free slot big enough to satisfy
** the request. The allocation is made from the first free slot in
** the list that is large enough to accomadate it.
*/
int pc, addr;
for(addr=hdr+1; (pc = get2byte(&data[addr]))>0; addr=pc){
int size = get2byte(&data[pc+2]); /* Size of free slot */
if( size>=nByte ){
int x = size - nByte;
if( size<nByte+4 ){
if( x<4 ){
/* Remove the slot from the free-list. Update the number of
** fragmented bytes within the page. */
memcpy(&data[addr], &data[pc], 2);
data[hdr+7] = (u8)(nFrag + x);
return pc;
}else{
/* The slot remains on the free-list. Reduce its size to account
** for the portion used by the new allocation. */
put2byte(&data[pc+2], x);
return pc + x;
}
return pc + x;
}
addr = pc;
}
}
/* Allocate memory from the gap in between the cell pointer array
** and the cell content area.
*/
top = get2byte(&data[hdr+5]);
nCell = get2byte(&data[hdr+3]);
cellOffset = pPage->cellOffset;
if( nFrag>=60 || cellOffset + 2*nCell > top - nByte ){
defragmentPage(pPage);
top = get2byte(&data[hdr+5]);
}
top -= nByte;
assert( cellOffset + 2*nCell <= top );
top = get2byte(&data[hdr+5]) - nByte;
put2byte(&data[hdr+5], top);
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
return top;
}
@ -1301,10 +1326,11 @@ static void releasePage(MemPage *pPage){
static void pageReinit(DbPage *pData){
MemPage *pPage;
pPage = (MemPage *)sqlite3PagerGetExtra(pData);
assert( sqlite3PagerPageRefcount(pData)>0 );
if( pPage->isInit ){
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
pPage->isInit = 0;
if( sqlite3PagerPageRefcount(pData)>0 ){
if( sqlite3PagerPageRefcount(pData)>1 ){
/* pPage might not be a btree page; it might be an overflow page
** or ptrmap page or a free page. In those cases, the following
** call to sqlite3BtreeInitPage() will likely return SQLITE_CORRUPT.
@ -1379,10 +1405,7 @@ int sqlite3BtreeOpen(
** If this Btree is a candidate for shared cache, try to find an
** existing BtShared object that we can share with
*/
if( isMemdb==0
&& (db->flags & SQLITE_Vtab)==0
&& zFilename && zFilename[0]
){
if( isMemdb==0 && zFilename && zFilename[0] ){
if( sqlite3GlobalConfig.sharedCacheEnabled ){
int nFullPathname = pVfs->mxPathname+1;
char *zFullPathname = sqlite3Malloc(nFullPathname);
@ -1447,6 +1470,7 @@ int sqlite3BtreeOpen(
if( rc!=SQLITE_OK ){
goto btree_open_out;
}
pBt->db = db;
sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
p->pBt = pBt;
@ -1624,7 +1648,6 @@ int sqlite3BtreeClose(Btree *p){
/* Close all cursors opened via this handle. */
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
pBt->db = p->db;
pCur = pBt->pCursor;
while( pCur ){
BtCursor *pTmp = pCur;
@ -1734,6 +1757,8 @@ int sqlite3BtreeSyncDisabled(Btree *p){
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)
/*
** Change the default pages size and the number of reserved bytes per page.
** Or, if the page size has already been fixed, return SQLITE_READONLY
** without changing anything.
**
** The page size must be a power of 2 between 512 and 65536. If the page
** size supplied does not meet this constraint then the page size is not
@ -1746,8 +1771,11 @@ int sqlite3BtreeSyncDisabled(Btree *p){
**
** If parameter nReserve is less than zero, then the number of reserved
** bytes per page is left unchanged.
**
** If the iFix!=0 then the pageSizeFixed flag is set so that the page size
** and autovacuum mode can no longer be changed.
*/
int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve){
int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
int rc = SQLITE_OK;
BtShared *pBt = p->pBt;
assert( nReserve>=-1 && nReserve<=255 );
@ -1769,6 +1797,7 @@ int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve){
rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
}
pBt->usableSize = pBt->pageSize - (u16)nReserve;
if( iFix ) pBt->pageSizeFixed = 1;
sqlite3BtreeLeave(p);
return rc;
}
@ -1869,7 +1898,7 @@ static int lockBtree(BtShared *pBt){
int nPage;
assert( sqlite3_mutex_held(pBt->mutex) );
if( pBt->pPage1 ) return SQLITE_OK;
assert( pBt->pPage1==0 );
rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0);
if( rc!=SQLITE_OK ) return rc;
@ -2097,7 +2126,6 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
int rc = SQLITE_OK;
sqlite3BtreeEnter(p);
pBt->db = p->db;
btreeIntegrity(p);
/* If the btree is already in a write-transaction, or it
@ -2138,11 +2166,14 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
#endif
do {
if( pBt->pPage1==0 ){
do{
rc = lockBtree(pBt);
}while( pBt->pPage1==0 && rc==SQLITE_OK );
}
/* Call lockBtree() until either pBt->pPage1 is populated or
** lockBtree() returns something other than SQLITE_OK. lockBtree()
** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after
** reading page 1 it discovers that the page-size of the database
** file is not pBt->pageSize. In this case lockBtree() will update
** pBt->pageSize to the page-size of the file on disk.
*/
while( pBt->pPage1==0 && SQLITE_OK==(rc = lockBtree(pBt)) );
if( rc==SQLITE_OK && wrflag ){
if( pBt->readOnly ){
@ -2241,7 +2272,7 @@ set_child_ptrmaps_out:
}
/*
** Somewhere on pPage, which is guarenteed to be a btree page, not an overflow
** Somewhere on pPage, which is guaranteed to be a btree page, not an overflow
** page, is a pointer to page iFrom. Modify this pointer so that it points to
** iTo. Parameter eType describes the type of pointer to be modified, as
** follows:
@ -2404,6 +2435,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
Pgno nFreeList; /* Number of pages still on the free-list */
assert( sqlite3_mutex_held(pBt->mutex) );
assert( iLastPg>nFin );
if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){
int rc;
@ -2411,7 +2443,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
Pgno iPtrPage;
nFreeList = get4byte(&pBt->pPage1->aData[36]);
if( nFreeList==0 || nFin==iLastPg ){
if( nFreeList==0 ){
return SQLITE_DONE;
}
@ -2512,7 +2544,6 @@ int sqlite3BtreeIncrVacuum(Btree *p){
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
pBt->db = p->db;
assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE );
if( !pBt->autoVacuum ){
rc = SQLITE_DONE;
@ -2549,16 +2580,18 @@ static int autoVacuumCommit(BtShared *pBt){
const int pgsz = pBt->pageSize;
Pgno nOrig = pagerPagecount(pBt);
if( PTRMAP_ISPAGE(pBt, nOrig) ){
if( PTRMAP_ISPAGE(pBt, nOrig) || nOrig==PENDING_BYTE_PAGE(pBt) ){
/* It is not possible to create a database for which the final page
** is either a pointer-map page or the pending-byte page. If one
** is encountered, this indicates corruption.
*/
return SQLITE_CORRUPT_BKPT;
}
if( nOrig==PENDING_BYTE_PAGE(pBt) ){
nOrig--;
}
nFree = get4byte(&pBt->pPage1->aData[36]);
nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+pgsz/5)/(pgsz/5);
nFin = nOrig - nFree - nPtrmap;
if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<=PENDING_BYTE_PAGE(pBt) ){
if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<PENDING_BYTE_PAGE(pBt) ){
nFin--;
}
while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){
@ -2617,7 +2650,6 @@ int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
if( p->inTrans==TRANS_WRITE ){
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
pBt->db = p->db;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
rc = autoVacuumCommit(pBt);
@ -2651,7 +2683,6 @@ int sqlite3BtreeCommitPhaseTwo(Btree *p){
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
pBt->db = p->db;
btreeIntegrity(p);
/* If the handle has a write-transaction open, commit the shared-btrees
@ -2668,7 +2699,6 @@ int sqlite3BtreeCommitPhaseTwo(Btree *p){
}
pBt->inTransaction = TRANS_READ;
}
clearAllSharedCacheTableLocks(p);
/* If the handle has any kind of transaction open, decrement the transaction
** count of the shared btree. If the transaction count reaches 0, set
@ -2676,6 +2706,7 @@ int sqlite3BtreeCommitPhaseTwo(Btree *p){
** will unlock the pager.
*/
if( p->inTrans!=TRANS_NONE ){
clearAllSharedCacheTableLocks(p);
pBt->nTransaction--;
if( 0==pBt->nTransaction ){
pBt->inTransaction = TRANS_NONE;
@ -2777,7 +2808,6 @@ int sqlite3BtreeRollback(Btree *p){
MemPage *pPage1;
sqlite3BtreeEnter(p);
pBt->db = p->db;
rc = saveAllCursors(pBt, 0, 0);
#ifndef SQLITE_OMIT_SHARED_CACHE
if( rc!=SQLITE_OK ){
@ -2792,7 +2822,6 @@ int sqlite3BtreeRollback(Btree *p){
}
#endif
btreeIntegrity(p);
clearAllSharedCacheTableLocks(p);
if( p->inTrans==TRANS_WRITE ){
int rc2;
@ -2814,6 +2843,7 @@ int sqlite3BtreeRollback(Btree *p){
}
if( p->inTrans!=TRANS_NONE ){
clearAllSharedCacheTableLocks(p);
assert( pBt->nTransaction>0 );
pBt->nTransaction--;
if( 0==pBt->nTransaction ){
@ -2852,7 +2882,6 @@ int sqlite3BtreeBeginStmt(Btree *p, int iStatement){
int rc;
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
pBt->db = p->db;
assert( p->inTrans==TRANS_WRITE );
assert( pBt->readOnly==0 );
assert( iStatement>0 );
@ -2891,7 +2920,6 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
assert( iSavepoint>=0 || (iSavepoint==-1 && op==SAVEPOINT_ROLLBACK) );
sqlite3BtreeEnter(p);
pBt->db = p->db;
rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
if( rc==SQLITE_OK ){
rc = newDatabase(pBt);
@ -3008,7 +3036,6 @@ int sqlite3BtreeCursor(
){
int rc;
sqlite3BtreeEnter(p);
p->pBt->db = p->db;
rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
sqlite3BtreeLeave(p);
return rc;
@ -3066,7 +3093,6 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
int i;
BtShared *pBt = pCur->pBt;
sqlite3BtreeEnter(pBtree);
pBt->db = pBtree->db;
sqlite3BtreeClearCursor(pCur);
if( pCur->pPrev ){
pCur->pPrev->pNext = pCur->pNext;
@ -4044,7 +4070,8 @@ int sqlite3BtreeMoveto(
){
int rc; /* Status code */
UnpackedRecord *pIdxKey; /* Unpacked index key */
UnpackedRecord aSpace[16]; /* Temp space for pIdxKey - to avoid a malloc */
char aSpace[150]; /* Temp space for pIdxKey - to avoid a malloc */
if( pKey ){
assert( nKey==(i64)(int)nKey );
@ -4645,7 +4672,10 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
while( nOvfl-- ){
Pgno iNext = 0;
MemPage *pOvfl = 0;
if( ovflPgno==0 || ovflPgno>pagerPagecount(pBt) ){
if( ovflPgno<2 || ovflPgno>pagerPagecount(pBt) ){
/* 0 is not a legal page number and page 1 cannot be an
** overflow page. Therefore if ovflPgno<2 or past the end of the
** file the database must be corrupt. */
return SQLITE_CORRUPT_BKPT;
}
if( nOvfl ){
@ -5324,13 +5354,13 @@ static int balance_nonroot(BtCursor *pCur){
}
szCell = (u16*)&apCell[nMaxCells];
aCopy[0] = (u8*)&szCell[nMaxCells];
assert( ((aCopy[0] - (u8*)0) & 7)==0 ); /* 8-byte alignment required */
assert( EIGHT_BYTE_ALIGNMENT(aCopy[0]) );
for(i=1; i<NB; i++){
aCopy[i] = &aCopy[i-1][pBt->pageSize+ROUND8(sizeof(MemPage))];
assert( ((aCopy[i] - (u8*)0) & 7)==0 ); /* 8-byte alignment required */
}
aSpace1 = &aCopy[NB-1][pBt->pageSize+ROUND8(sizeof(MemPage))];
assert( ((aSpace1 - (u8*)0) & 7)==0 ); /* 8-byte alignment required */
assert( EIGHT_BYTE_ALIGNMENT(aSpace1) );
if( ISAUTOVACUUM ){
aFrom = &aSpace1[pBt->pageSize];
}
@ -6316,8 +6346,8 @@ int sqlite3BtreeDelete(BtCursor *pCur){
rc = sqlite3BtreeNext(&leafCur, &notUsed);
}
pLeafPage = leafCur.apPage[leafCur.iPage];
assert( pLeafPage->pgno==leafPgno );
assert( leafCur.aiIdx[leafCur.iPage]==0 );
assert( rc!=SQLITE_OK || pLeafPage->pgno==leafPgno );
assert( rc!=SQLITE_OK || leafCur.aiIdx[leafCur.iPage]==0 );
}
if( SQLITE_OK==rc
@ -6481,7 +6511,6 @@ static int btreeCreateTable(Btree *p, int *piTable, int flags){
int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){
int rc;
sqlite3BtreeEnter(p);
p->pBt->db = p->db;
rc = btreeCreateTable(p, piTable, flags);
sqlite3BtreeLeave(p);
return rc;
@ -6553,7 +6582,6 @@ int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
int rc;
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
pBt->db = p->db;
assert( p->inTrans==TRANS_WRITE );
if( (rc = checkForReadConflicts(p, iTable, 0, 1))!=SQLITE_OK ){
/* nothing to do */
@ -6695,7 +6723,6 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
int rc;
sqlite3BtreeEnter(p);
p->pBt->db = p->db;
rc = btreeDropTable(p, iTable, piMoved);
sqlite3BtreeLeave(p);
return rc;
@ -6719,7 +6746,6 @@ int sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
pBt->db = p->db;
/* Reading a meta-data value requires a read-lock on page 1 (and hence
** the sqlite_master table. We grab this lock regardless of whether or
@ -6768,8 +6794,14 @@ int sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
if( idx==4 && *pMeta>0 ) pBt->readOnly = 1;
#endif
/* Grab the read-lock on page 1. */
rc = setSharedCacheTableLock(p, 1, READ_LOCK);
/* If there is currently an open transaction, grab a read-lock
** on page 1 of the database file. This is done to make sure that
** no other connection can modify the meta value just read from
** the database until the transaction is concluded.
*/
if( p->inTrans>0 ){
rc = setSharedCacheTableLock(p, 1, READ_LOCK);
}
sqlite3BtreeLeave(p);
return rc;
}
@ -6784,7 +6816,6 @@ int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
int rc;
assert( idx>=1 && idx<=15 );
sqlite3BtreeEnter(p);
pBt->db = p->db;
assert( p->inTrans==TRANS_WRITE );
assert( pBt->pPage1!=0 );
pP1 = pBt->pPage1->aData;
@ -7258,7 +7289,6 @@ char *sqlite3BtreeIntegrityCheck(
char zErr[100];
sqlite3BtreeEnter(p);
pBt->db = p->db;
nRef = sqlite3PagerRefcount(pBt->pPager);
if( lockBtreeWithRetry(p)!=SQLITE_OK ){
*pnErr = 1;

41
btree.h
View file

@ -13,7 +13,7 @@
** subsystem. See comments in the source code for a detailed description
** of what each interface routine does.
**
** @(#) $Id: btree.h,v 1.111 2009/03/18 10:33:01 danielk1977 Exp $
** @(#) $Id: btree.h,v 1.113 2009/04/10 12:55:17 danielk1977 Exp $
*/
#ifndef _BTREE_H_
#define _BTREE_H_
@ -80,7 +80,7 @@ int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetCacheSize(Btree*,int);
int sqlite3BtreeSetSafetyLevel(Btree*,int,int);
int sqlite3BtreeSyncDisabled(Btree*);
int sqlite3BtreeSetPageSize(Btree*,int,int);
int sqlite3BtreeSetPageSize(Btree*,int,int,int);
int sqlite3BtreeGetPageSize(Btree*);
int sqlite3BtreeMaxPageCount(Btree*,int);
int sqlite3BtreeGetReserve(Btree*);
@ -186,42 +186,39 @@ void sqlite3BtreeCursorList(Btree*);
** use mutexes to access the BtShared structures. So make the
** Enter and Leave procedures no-ops.
*/
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE
#ifndef SQLITE_OMIT_SHARED_CACHE
void sqlite3BtreeEnter(Btree*);
void sqlite3BtreeLeave(Btree*);
#ifndef NDEBUG
/* This routine is used inside assert() statements only. */
int sqlite3BtreeHoldsMutex(Btree*);
void sqlite3BtreeEnterAll(sqlite3*);
#else
# define sqlite3BtreeEnter(X)
# define sqlite3BtreeEnterAll(X)
#endif
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE
void sqlite3BtreeLeave(Btree*);
void sqlite3BtreeEnterCursor(BtCursor*);
void sqlite3BtreeLeaveCursor(BtCursor*);
void sqlite3BtreeEnterAll(sqlite3*);
void sqlite3BtreeLeaveAll(sqlite3*);
#ifndef NDEBUG
/* This routine is used inside assert() statements only. */
int sqlite3BtreeHoldsAllMutexes(sqlite3*);
#endif
void sqlite3BtreeMutexArrayEnter(BtreeMutexArray*);
void sqlite3BtreeMutexArrayLeave(BtreeMutexArray*);
void sqlite3BtreeMutexArrayInsert(BtreeMutexArray*, Btree*);
#else
# define sqlite3BtreeEnter(X)
# define sqlite3BtreeLeave(X)
#ifndef NDEBUG
/* This routine is used inside assert() statements only. */
# define sqlite3BtreeHoldsMutex(X) 1
/* These routines are used inside assert() statements only. */
int sqlite3BtreeHoldsMutex(Btree*);
int sqlite3BtreeHoldsAllMutexes(sqlite3*);
#endif
#else
# define sqlite3BtreeLeave(X)
# define sqlite3BtreeEnterCursor(X)
# define sqlite3BtreeLeaveCursor(X)
# define sqlite3BtreeEnterAll(X)
# define sqlite3BtreeLeaveAll(X)
#ifndef NDEBUG
/* This routine is used inside assert() statements only. */
# define sqlite3BtreeHoldsAllMutexes(X) 1
#endif
# define sqlite3BtreeMutexArrayEnter(X)
# define sqlite3BtreeMutexArrayLeave(X)
# define sqlite3BtreeMutexArrayInsert(X,Y)
# define sqlite3BtreeHoldsMutex(X) 1
# define sqlite3BtreeHoldsAllMutexes(X) 1
#endif

View file

@ -22,7 +22,7 @@
** COMMIT
** ROLLBACK
**
** $Id: build.c,v 1.527 2009/03/31 03:41:57 shane Exp $
** $Id: build.c,v 1.528 2009/04/08 13:51:51 drh Exp $
*/
#include "sqliteInt.h"
@ -1112,9 +1112,7 @@ void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){
** is required by pragma table_info.
*/
sqlite3ExprDelete(db, pCol->pDflt);
pCol->pDflt = sqlite3ExprDup(
db, pExpr, EXPRDUP_REDUCE|EXPRDUP_DISTINCTSPAN
);
pCol->pDflt = sqlite3ExprDup(db, pExpr, EXPRDUP_REDUCE|EXPRDUP_SPAN);
}
}
sqlite3ExprDelete(db, pExpr);

6
date.c
View file

@ -16,7 +16,7 @@
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: date.c,v 1.103 2009/02/04 03:59:25 shane Exp $
** $Id: date.c,v 1.105 2009/04/03 12:04:37 drh Exp $
**
** SQLite processes all times and dates as Julian Day numbers. The
** dates and times are stored as the number of days since noon
@ -953,8 +953,8 @@ static void strftimeFunc(
case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;
case 's': {
sqlite3_snprintf(30,&z[j],"%d",
(int)(x.iJD/1000.0 - 210866760000.0));
sqlite3_snprintf(30,&z[j],"%lld",
(i64)(x.iJD/1000 - 21086676*(i64)10000));
j += sqlite3Strlen30(&z[j]);
break;
}

120
expr.c
View file

@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.424 2009/03/25 16:51:43 drh Exp $
** $Id: expr.c,v 1.426 2009/04/08 13:51:51 drh Exp $
*/
#include "sqliteInt.h"
@ -629,15 +629,18 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
*/
void sqlite3ExprClear(sqlite3 *db, Expr *p){
if( p->token.dyn ) sqlite3DbFree(db, (char*)p->token.z);
if( !ExprHasAnyProperty(p, EP_TokenOnly|EP_SpanOnly) ){
if( !ExprHasAnyProperty(p, EP_TokenOnly|EP_SpanToken) ){
if( p->span.dyn ) sqlite3DbFree(db, (char*)p->span.z);
if( ExprHasProperty(p, EP_Reduced) ){
/* Subtrees are part of the same memory allocation when EP_Reduced set */
if( p->pLeft ) sqlite3ExprClear(db, p->pLeft);
if( p->pRight ) sqlite3ExprClear(db, p->pRight);
}else{
/* Subtrees are separate allocations when EP_Reduced is clear */
sqlite3ExprDelete(db, p->pLeft);
sqlite3ExprDelete(db, p->pRight);
}
/* x.pSelect and x.pList are always separately allocated */
if( ExprHasProperty(p, EP_xIsSelect) ){
sqlite3SelectDelete(db, p->x.pSelect);
}else{
@ -674,7 +677,7 @@ void sqlite3DequoteExpr(Expr *p){
*/
static int exprStructSize(Expr *p){
if( ExprHasProperty(p, EP_TokenOnly) ) return EXPR_TOKENONLYSIZE;
if( ExprHasProperty(p, EP_SpanOnly) ) return EXPR_SPANONLYSIZE;
if( ExprHasProperty(p, EP_SpanToken) ) return EXPR_SPANTOKENSIZE;
if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE;
return EXPR_FULLSIZE;
}
@ -691,8 +694,8 @@ static int dupedExprStructSize(Expr *p, int flags){
nSize = EXPR_FULLSIZE;
}else if( p->pLeft || p->pRight || p->pColl || p->x.pList ){
nSize = EXPR_REDUCEDSIZE;
}else if( flags&(EXPRDUP_SPAN|EXPRDUP_DISTINCTSPAN) ){
nSize = EXPR_SPANONLYSIZE;
}else if( flags&EXPRDUP_SPAN ){
nSize = EXPR_SPANTOKENSIZE;
}else{
nSize = EXPR_TOKENONLYSIZE;
}
@ -708,8 +711,8 @@ static int dupedExprStructSize(Expr *p, int flags){
*/
static int dupedExprNodeSize(Expr *p, int flags){
int nByte = dupedExprStructSize(p, flags) + (p->token.z ? p->token.n + 1 : 0);
if( (flags&EXPRDUP_DISTINCTSPAN)
|| (flags&EXPRDUP_SPAN && (p->token.z!=p->span.z || p->token.n!=p->span.n))
if( (flags&EXPRDUP_SPAN)!=0
&& (p->token.z!=p->span.z || p->token.n!=p->span.n)
){
nByte += p->span.n;
}
@ -736,7 +739,7 @@ static int dupedExprSize(Expr *p, int flags){
if( p ){
nByte = dupedExprNodeSize(p, flags);
if( flags&EXPRDUP_REDUCE ){
int f = flags&(~(EXPRDUP_SPAN|EXPRDUP_DISTINCTSPAN));
int f = flags&(~EXPRDUP_SPAN);
nByte += dupedExprSize(p->pLeft, f) + dupedExprSize(p->pRight, f);
}
}
@ -754,8 +757,7 @@ static int dupedExprSize(Expr *p, int flags){
static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
Expr *pNew = 0; /* Value to return */
if( p ){
const int isRequireDistinctSpan = (flags&EXPRDUP_DISTINCTSPAN);
const int isRequireSpan = (flags&(EXPRDUP_SPAN|EXPRDUP_DISTINCTSPAN));
const int isRequireSpan = (flags&EXPRDUP_SPAN);
const int isReduced = (flags&EXPRDUP_REDUCE);
u8 *zAlloc;
@ -787,11 +789,11 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
}
/* Set the EP_Reduced and EP_TokenOnly flags appropriately. */
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_SpanOnly);
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_SpanToken);
switch( nNewSize ){
case EXPR_REDUCEDSIZE: pNew->flags |= EP_Reduced; break;
case EXPR_TOKENONLYSIZE: pNew->flags |= EP_TokenOnly; break;
case EXPR_SPANONLYSIZE: pNew->flags |= EP_SpanOnly; break;
case EXPR_SPANTOKENSIZE: pNew->flags |= EP_SpanToken; break;
}
/* Copy the p->token string, if any. */
@ -806,9 +808,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){
/* Fill in the pNew->span token, if required. */
if( isRequireSpan ){
if( isRequireDistinctSpan
|| p->token.z!=p->span.z || p->token.n!=p->span.n
){
if( p->token.z!=p->span.z || p->token.n!=p->span.n ){
pNew->span.z = &zAlloc[nNewSize+nToken];
memcpy((char *)pNew->span.z, p->span.z, p->span.n);
pNew->span.dyn = 0;
@ -822,7 +822,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
}
}
if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_SpanOnly)) ){
if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_SpanToken)) ){
/* Fill in the pNew->x.pSelect or pNew->x.pList member. */
if( ExprHasProperty(p, EP_xIsSelect) ){
pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, isReduced);
@ -832,7 +832,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
}
/* Fill in pNew->pLeft and pNew->pRight. */
if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly|EP_SpanOnly) ){
if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly|EP_SpanToken) ){
zAlloc += dupedExprNodeSize(p, flags);
if( ExprHasProperty(pNew, EP_Reduced) ){
pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc);
@ -841,7 +841,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
if( pzBuffer ){
*pzBuffer = zAlloc;
}
}else if( !ExprHasAnyProperty(p, EP_TokenOnly|EP_SpanOnly) ){
}else if( !ExprHasAnyProperty(p, EP_TokenOnly|EP_SpanToken) ){
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
}
@ -1345,11 +1345,17 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
*/
p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
if( isCandidateForInOpt(p) ){
sqlite3 *db = pParse->db;
Index *pIdx;
Expr *pExpr = p->pEList->a[0].pExpr;
int iCol = pExpr->iColumn;
Vdbe *v = sqlite3GetVdbe(pParse);
sqlite3 *db = pParse->db; /* Database connection */
Expr *pExpr = p->pEList->a[0].pExpr; /* Expression <column> */
int iCol = pExpr->iColumn; /* Index of column <column> */
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
Table *pTab = p->pSrc->a[0].pTab; /* Table <table>. */
int iDb; /* Database idx for pTab */
/* Code an OP_VerifyCookie and OP_TableLock for <table>. */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
/* This function is only called from two places. In both cases the vdbe
** has already been allocated. So assume sqlite3GetVdbe() is always
@ -1359,8 +1365,6 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
if( iCol<0 ){
int iMem = ++pParse->nMem;
int iAddr;
Table *pTab = p->pSrc->a[0].pTab;
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3VdbeUsesBtree(v, iDb);
iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
@ -1371,17 +1375,17 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
sqlite3VdbeJumpHere(v, iAddr);
}else{
Index *pIdx; /* Iterator variable */
/* The collation sequence used by the comparison. If an index is to
** be used in place of a temp-table, it must be ordered according
** to this collation sequence.
*/
** to this collation sequence. */
CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pExpr);
/* Check that the affinity that will be used to perform the
** comparison is the same as the affinity of the column. If
** it is not, it is not possible to use any index.
*/
Table *pTab = p->pSrc->a[0].pTab;
char aff = comparisonAffinity(pX);
int affinity_ok = (pTab->aCol[iCol].affinity==aff||aff==SQLITE_AFF_NONE);
@ -1390,7 +1394,6 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
&& (pReq==sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], -1, 0))
&& (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None))
){
int iDb;
int iMem = ++pParse->nMem;
int iAddr;
char *pKey;
@ -2202,31 +2205,34 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
}
case TK_CONST_FUNC:
case TK_FUNCTION: {
ExprList *pList = (
ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_SpanOnly) ? 0 : pExpr->x.pList
);
int nExpr = pList ? pList->nExpr : 0;
FuncDef *pDef;
int nId;
const char *zId;
int constMask = 0;
int i;
u8 enc = ENC(db);
CollSeq *pColl = 0;
ExprList *pFarg; /* List of function arguments */
int nFarg; /* Number of function arguments */
FuncDef *pDef; /* The function definition object */
int nId; /* Length of the function name in bytes */
const char *zId; /* The function name */
int constMask = 0; /* Mask of function arguments that are constant */
int i; /* Loop counter */
u8 enc = ENC(db); /* The text encoding used by this database */
CollSeq *pColl = 0; /* A collating sequence */
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
testcase( op==TK_CONST_FUNC );
testcase( op==TK_FUNCTION );
if( ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_SpanToken) ){
pFarg = 0;
}else{
pFarg = pExpr->x.pList;
}
nFarg = pFarg ? pFarg->nExpr : 0;
zId = (char*)pExpr->token.z;
nId = pExpr->token.n;
pDef = sqlite3FindFunction(db, zId, nId, nExpr, enc, 0);
pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0);
assert( pDef!=0 );
if( pList ){
nExpr = pList->nExpr;
r1 = sqlite3GetTempRange(pParse, nExpr);
sqlite3ExprCodeExprList(pParse, pList, r1, 1);
if( pFarg ){
r1 = sqlite3GetTempRange(pParse, nFarg);
sqlite3ExprCodeExprList(pParse, pFarg, r1, 1);
}else{
nExpr = r1 = 0;
r1 = 0;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Possibly overload the function if the first argument is
@ -2241,18 +2247,18 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
** "glob(B,A). We want to use the A in "A glob B" to test
** for function overloading. But we use the B term in "glob(B,A)".
*/
if( nExpr>=2 && (pExpr->flags & EP_InfixFunc) ){
pDef = sqlite3VtabOverloadFunction(db, pDef, nExpr, pList->a[1].pExpr);
}else if( nExpr>0 ){
pDef = sqlite3VtabOverloadFunction(db, pDef, nExpr, pList->a[0].pExpr);
if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){
pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr);
}else if( nFarg>0 ){
pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr);
}
#endif
for(i=0; i<nExpr && i<32; i++){
if( sqlite3ExprIsConstant(pList->a[i].pExpr) ){
for(i=0; i<nFarg && i<32; i++){
if( sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
constMask |= (1<<i);
}
if( (pDef->flags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
}
}
if( pDef->flags & SQLITE_FUNC_NEEDCOLL ){
@ -2261,11 +2267,11 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
}
sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
(char*)pDef, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nExpr);
if( nExpr ){
sqlite3ReleaseTempRange(pParse, r1, nExpr);
sqlite3VdbeChangeP5(v, (u8)nFarg);
if( nFarg ){
sqlite3ReleaseTempRange(pParse, r1, nFarg);
}
sqlite3ExprCacheAffinityChange(pParse, r1, nExpr);
sqlite3ExprCacheAffinityChange(pParse, r1, nFarg);
break;
}
#ifndef SQLITE_OMIT_SUBQUERY

92
func.c
View file

@ -16,7 +16,7 @@
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.225 2009/03/27 15:26:03 danielk1977 Exp $
** $Id: func.c,v 1.231 2009/04/08 23:04:14 drh Exp $
*/
#include "sqliteInt.h"
#include <stdlib.h>
@ -266,16 +266,22 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
/*
** Allocate nByte bytes of space using sqlite3_malloc(). If the
** allocation fails, call sqlite3_result_error_nomem() to notify
** the database handle that malloc() has failed.
** the database handle that malloc() has failed and return NULL.
** If nByte is larger than the maximum string or blob length, then
** raise an SQLITE_TOOBIG exception and return NULL.
*/
static void *contextMalloc(sqlite3_context *context, i64 nByte){
char *z;
if( nByte>sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3 *db = sqlite3_context_db_handle(context);
assert( nByte>0 );
testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH] );
testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
z = 0;
}else{
z = sqlite3Malloc((int)nByte);
if( !z && nByte>0 ){
if( !z ){
sqlite3_result_error_nomem(context);
}
}
@ -356,8 +362,17 @@ static void randomFunc(
sqlite_int64 r;
UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_randomness(sizeof(r), &r);
if( (r<<1)==0 ) r = 0; /* Prevent 0x8000.... as the result so that we */
/* can always do abs() of the result */
if( r<0 ){
/* We need to prevent a random number of 0x8000000000000000
** (or -9223372036854775808) since when you do abs() of that
** number of you get the same value back again. To do this
** in a way that is testable, mask the sign bit off of negative
** values, resulting in a positive value. Then take the
** 2s complement of that positive value. The end result can
** therefore be no less than -9223372036854775807.
*/
r = -(r ^ (((sqlite3_int64)1)<<63));
}
sqlite3_result_int64(context, r);
}
@ -444,7 +459,7 @@ struct compareInfo {
** whereas only characters less than 0x80 do in ASCII.
*/
#if defined(SQLITE_EBCDIC)
# define sqlite3Utf8Read(A,B,C) (*(A++))
# define sqlite3Utf8Read(A,C) (*(A++))
# define GlogUpperToLower(A) A = sqlite3UpperToLower[A]
#else
# define GlogUpperToLower(A) if( A<0x80 ){ A = sqlite3UpperToLower[A]; }
@ -501,18 +516,18 @@ static int patternCompare(
u8 noCase = pInfo->noCase;
int prevEscape = 0; /* True if the previous character was 'escape' */
while( (c = sqlite3Utf8Read(zPattern,0,&zPattern))!=0 ){
while( (c = sqlite3Utf8Read(zPattern,&zPattern))!=0 ){
if( !prevEscape && c==matchAll ){
while( (c=sqlite3Utf8Read(zPattern,0,&zPattern)) == matchAll
while( (c=sqlite3Utf8Read(zPattern,&zPattern)) == matchAll
|| c == matchOne ){
if( c==matchOne && sqlite3Utf8Read(zString, 0, &zString)==0 ){
if( c==matchOne && sqlite3Utf8Read(zString, &zString)==0 ){
return 0;
}
}
if( c==0 ){
return 1;
}else if( c==esc ){
c = sqlite3Utf8Read(zPattern, 0, &zPattern);
c = sqlite3Utf8Read(zPattern, &zPattern);
if( c==0 ){
return 0;
}
@ -524,17 +539,17 @@ static int patternCompare(
}
return *zString!=0;
}
while( (c2 = sqlite3Utf8Read(zString,0,&zString))!=0 ){
while( (c2 = sqlite3Utf8Read(zString,&zString))!=0 ){
if( noCase ){
GlogUpperToLower(c2);
GlogUpperToLower(c);
while( c2 != 0 && c2 != c ){
c2 = sqlite3Utf8Read(zString, 0, &zString);
c2 = sqlite3Utf8Read(zString, &zString);
GlogUpperToLower(c2);
}
}else{
while( c2 != 0 && c2 != c ){
c2 = sqlite3Utf8Read(zString, 0, &zString);
c2 = sqlite3Utf8Read(zString, &zString);
}
}
if( c2==0 ) return 0;
@ -542,7 +557,7 @@ static int patternCompare(
}
return 0;
}else if( !prevEscape && c==matchOne ){
if( sqlite3Utf8Read(zString, 0, &zString)==0 ){
if( sqlite3Utf8Read(zString, &zString)==0 ){
return 0;
}
}else if( c==matchSet ){
@ -550,20 +565,20 @@ static int patternCompare(
assert( esc==0 ); /* This only occurs for GLOB, not LIKE */
seen = 0;
invert = 0;
c = sqlite3Utf8Read(zString, 0, &zString);
c = sqlite3Utf8Read(zString, &zString);
if( c==0 ) return 0;
c2 = sqlite3Utf8Read(zPattern, 0, &zPattern);
c2 = sqlite3Utf8Read(zPattern, &zPattern);
if( c2=='^' ){
invert = 1;
c2 = sqlite3Utf8Read(zPattern, 0, &zPattern);
c2 = sqlite3Utf8Read(zPattern, &zPattern);
}
if( c2==']' ){
if( c==']' ) seen = 1;
c2 = sqlite3Utf8Read(zPattern, 0, &zPattern);
c2 = sqlite3Utf8Read(zPattern, &zPattern);
}
while( c2 && c2!=']' ){
if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){
c2 = sqlite3Utf8Read(zPattern, 0, &zPattern);
c2 = sqlite3Utf8Read(zPattern, &zPattern);
if( c>=prior_c && c<=c2 ) seen = 1;
prior_c = 0;
}else{
@ -572,7 +587,7 @@ static int patternCompare(
}
prior_c = c2;
}
c2 = sqlite3Utf8Read(zPattern, 0, &zPattern);
c2 = sqlite3Utf8Read(zPattern, &zPattern);
}
if( c2==0 || (seen ^ invert)==0 ){
return 0;
@ -580,7 +595,7 @@ static int patternCompare(
}else if( esc==c && !prevEscape ){
prevEscape = 1;
}else{
c2 = sqlite3Utf8Read(zString, 0, &zString);
c2 = sqlite3Utf8Read(zString, &zString);
if( noCase ){
GlogUpperToLower(c);
GlogUpperToLower(c2);
@ -623,6 +638,7 @@ static void likeFunc(
){
const unsigned char *zA, *zB;
int escape = 0;
int nPat;
sqlite3 *db = sqlite3_context_db_handle(context);
zB = sqlite3_value_text(argv[0]);
@ -631,8 +647,10 @@ static void likeFunc(
/* Limit the length of the LIKE or GLOB pattern to avoid problems
** of deep recursion and N*N behavior in patternCompare().
*/
if( sqlite3_value_bytes(argv[0]) >
db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ){
nPat = sqlite3_value_bytes(argv[0]);
testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] );
testcase( nPat==db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]+1 );
if( nPat > db->aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ){
sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1);
return;
}
@ -649,7 +667,7 @@ static void likeFunc(
"ESCAPE expression must be a single character", -1);
return;
}
escape = sqlite3Utf8Read(zEsc, 0, &zEsc);
escape = sqlite3Utf8Read(zEsc, &zEsc);
}
if( zA && zB ){
struct compareInfo *pInfo = sqlite3_user_data(context);
@ -808,10 +826,13 @@ static void zeroblobFunc(
sqlite3_value **argv
){
i64 n;
sqlite3 *db = sqlite3_context_db_handle(context);
assert( argc==1 );
UNUSED_PARAMETER(argc);
n = sqlite3_value_int64(argv[0]);
if( n>SQLITE_MAX_LENGTH ){
testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH] );
testcase( n==db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
}else{
sqlite3_result_zeroblob(context, (int)n);
@ -877,7 +898,9 @@ static void replaceFunc(
u8 *zOld;
sqlite3 *db = sqlite3_context_db_handle(context);
nOut += nRep - nPattern;
if( nOut>=db->aLimit[SQLITE_LIMIT_LENGTH] ){
testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] );
testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] );
if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
sqlite3DbFree(db, zOut);
return;
@ -961,7 +984,7 @@ static void trimFunc(
int len = 0;
for(i=0; i<nChar; i++){
len = aLen[i];
if( memcmp(zIn, azChar[i], len)==0 ) break;
if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break;
}
if( i>=nChar ) break;
zIn += len;
@ -1155,6 +1178,13 @@ static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && p ){
p->n++;
}
/* The sqlite3_aggregate_count() function is deprecated. But just to make
** sure it still operates correctly, verify that its count agrees with our
** internal count when using count(*) and when the total count can be
** expressed as a 32-bit integer. */
assert( argc==1 || p==0 || p->n>0x7fffffff
|| p->n==sqlite3_aggregate_count(context) );
}
static void countFinalize(sqlite3_context *context){
CountCtx *p;
@ -1203,7 +1233,7 @@ static void minMaxFinalize(sqlite3_context *context){
sqlite3_value *pRes;
pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0);
if( pRes ){
if( pRes->flags ){
if( ALWAYS(pRes->flags) ){
sqlite3_result_value(context, pRes);
}
sqlite3VdbeMemRelease(pRes);
@ -1288,7 +1318,7 @@ static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){
FuncDef *pDef;
pDef = sqlite3FindFunction(db, zName, sqlite3Strlen30(zName),
2, SQLITE_UTF8, 0);
if( pDef ){
if( ALWAYS(pDef) ){
pDef->flags = flagVal;
}
}
@ -1332,7 +1362,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
pDef = sqlite3FindFunction(db, (char*)pExpr->token.z, pExpr->token.n, 2,
SQLITE_UTF8, 0);
if( pDef==0 || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
if( NEVER(pDef==0) || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
return 0;
}

View file

@ -1,266 +1,266 @@
/***** This file contains automatically generated code ******
**
** The code in this file has been automatically generated by
**
** $Header: /sqlite/sqlite/tool/mkkeywordhash.c,v 1.37 2009/02/01 00:00:46 drh Exp $
**
** The code in this file implements a function that determines whether
** or not a given identifier is really an SQL keyword. The same thing
** might be implemented more directly using a hand-written hash table.
** But by using this automatically generated code, the size of the code
** is substantially reduced. This is important for embedded applications
** on platforms with limited memory.
*/
/* Hash score: 171 */
static int keywordCode(const char *z, int n){
/* zText[] encodes 801 bytes of keywords in 541 bytes */
/* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */
/* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */
/* XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY */
/* UNIQUERYATTACHAVINGROUPDATEBEGINNERELEASEBETWEENOTNULLIKE */
/* CASCADELETECASECOLLATECREATECURRENT_DATEDETACHIMMEDIATEJOIN */
/* SERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHENWHERENAME */
/* AFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSS */
/* CURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAILFROMFULLGLOBYIF */
/* ISNULLORDERESTRICTOUTERIGHTROLLBACKROWUNIONUSINGVACUUMVIEW */
/* INITIALLY */
static const char zText[540] = {
'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H',
'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G',
'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A',
'S','E','L','E','C','T','A','B','L','E','F','T','H','E','N','D','E','F',
'E','R','R','A','B','L','E','L','S','E','X','C','E','P','T','R','A','N',
'S','A','C','T','I','O','N','A','T','U','R','A','L','T','E','R','A','I',
'S','E','X','C','L','U','S','I','V','E','X','I','S','T','S','A','V','E',
'P','O','I','N','T','E','R','S','E','C','T','R','I','G','G','E','R','E',
'F','E','R','E','N','C','E','S','C','O','N','S','T','R','A','I','N','T',
'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q',
'U','E','R','Y','A','T','T','A','C','H','A','V','I','N','G','R','O','U',
'P','D','A','T','E','B','E','G','I','N','N','E','R','E','L','E','A','S',
'E','B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C',
'A','S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L',
'A','T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D',
'A','T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E',
'J','O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A',
'L','Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U',
'E','S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','W',
'H','E','R','E','N','A','M','E','A','F','T','E','R','E','P','L','A','C',
'E','A','N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R',
'E','M','E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M',
'M','I','T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U',
'R','R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M',
'A','R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T',
'D','R','O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L',
'O','B','Y','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S',
'T','R','I','C','T','O','U','T','E','R','I','G','H','T','R','O','L','L',
'B','A','C','K','R','O','W','U','N','I','O','N','U','S','I','N','G','V',
'A','C','U','U','M','V','I','E','W','I','N','I','T','I','A','L','L','Y',
};
static const unsigned char aHash[127] = {
70, 99, 112, 68, 0, 43, 0, 0, 76, 0, 71, 0, 0,
41, 12, 72, 15, 0, 111, 79, 49, 106, 0, 19, 0, 0,
116, 0, 114, 109, 0, 22, 87, 0, 9, 0, 0, 64, 65,
0, 63, 6, 0, 47, 84, 96, 0, 113, 95, 0, 0, 44,
0, 97, 24, 0, 17, 0, 117, 48, 23, 0, 5, 104, 25,
90, 0, 0, 119, 100, 55, 118, 52, 7, 50, 0, 85, 0,
94, 26, 0, 93, 0, 0, 0, 89, 86, 91, 82, 103, 14,
38, 102, 0, 75, 0, 18, 83, 105, 31, 0, 115, 74, 107,
56, 45, 78, 0, 0, 88, 39, 0, 110, 0, 35, 0, 0,
28, 0, 80, 53, 58, 0, 20, 57, 0, 51,
};
static const unsigned char aNext[119] = {
0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 3, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 32, 21, 0, 0, 0, 42, 2, 46, 0,
0, 0, 0, 0, 29, 0, 37, 0, 0, 0, 1, 60, 0,
0, 61, 0, 40, 0, 0, 0, 0, 0, 0, 0, 59, 0,
0, 0, 0, 30, 54, 16, 33, 11, 0, 0, 0, 0, 0,
0, 0, 10, 66, 73, 0, 8, 0, 98, 92, 0, 101, 0,
81, 0, 69, 0, 0, 108, 27, 36, 67, 77, 0, 34, 62,
0, 0,
};
static const unsigned char aLen[119] = {
7, 5, 7, 4, 6, 4, 5, 3, 6, 3, 7, 6, 6,
7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6,
11, 2, 7, 5, 5, 9, 6, 9, 9, 7, 10, 10, 4,
6, 2, 3, 4, 9, 2, 6, 5, 6, 6, 5, 6, 5,
5, 7, 7, 3, 7, 4, 4, 7, 3, 6, 4, 7, 6,
12, 6, 9, 4, 6, 5, 4, 7, 6, 5, 6, 7, 5,
4, 5, 6, 5, 7, 3, 7, 13, 2, 2, 4, 6, 6,
8, 5, 17, 12, 7, 8, 8, 2, 4, 4, 4, 4, 4,
2, 2, 6, 5, 8, 5, 5, 8, 3, 5, 5, 6, 4,
9, 3,
};
static const unsigned short int aOffset[119] = {
0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33,
36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81,
86, 95, 96, 101, 105, 109, 117, 122, 128, 136, 142, 152, 159,
162, 162, 165, 167, 167, 171, 176, 179, 184, 189, 194, 197, 203,
206, 210, 217, 223, 223, 226, 229, 233, 234, 238, 244, 248, 255,
261, 273, 279, 288, 290, 296, 301, 303, 310, 315, 320, 326, 332,
337, 341, 344, 350, 354, 361, 363, 370, 372, 374, 383, 387, 393,
399, 407, 412, 412, 428, 435, 442, 443, 450, 454, 458, 462, 466,
469, 471, 473, 479, 483, 491, 495, 500, 508, 511, 516, 521, 527,
531, 536,
};
static const unsigned char aCode[119] = {
TK_REINDEX, TK_INDEX, TK_INDEXED, TK_DESC, TK_ESCAPE,
TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOR,
TK_FOREIGN, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD,
TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE,
TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE,
TK_EXCEPT, TK_TRANSACTION,TK_ON, TK_JOIN_KW, TK_ALTER,
TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT, TK_INTERSECT,
TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO, TK_OFFSET,
TK_OF, TK_SET, TK_TEMP, TK_TEMP, TK_OR,
TK_UNIQUE, TK_QUERY, TK_ATTACH, TK_HAVING, TK_GROUP,
TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RELEASE, TK_BETWEEN,
TK_NOT, TK_NOTNULL, TK_NULL, TK_LIKE_KW, TK_CASCADE,
TK_ASC, TK_DELETE, TK_CASE, TK_COLLATE, TK_CREATE,
TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE, TK_JOIN, TK_INSERT,
TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, TK_ABORT,
TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, TK_WHERE,
TK_RENAME, TK_AFTER, TK_REPLACE, TK_AND, TK_DEFAULT,
TK_AUTOINCR, TK_TO, TK_IN, TK_CAST, TK_COLUMNKW,
TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW,
TK_PRIMARY, TK_DEFERRED, TK_DISTINCT, TK_IS, TK_DROP,
TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, TK_BY,
TK_IF, TK_ISNULL, TK_ORDER, TK_RESTRICT, TK_JOIN_KW,
TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING,
TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL,
};
int h, i;
if( n<2 ) return TK_ID;
h = ((charMap(z[0])*4) ^
(charMap(z[n-1])*3) ^
n) % 127;
for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){
if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){
testcase( i==0 ); /* TK_REINDEX */
testcase( i==1 ); /* TK_INDEX */
testcase( i==2 ); /* TK_INDEXED */
testcase( i==3 ); /* TK_DESC */
testcase( i==4 ); /* TK_ESCAPE */
testcase( i==5 ); /* TK_EACH */
testcase( i==6 ); /* TK_CHECK */
testcase( i==7 ); /* TK_KEY */
testcase( i==8 ); /* TK_BEFORE */
testcase( i==9 ); /* TK_FOR */
testcase( i==10 ); /* TK_FOREIGN */
testcase( i==11 ); /* TK_IGNORE */
testcase( i==12 ); /* TK_LIKE_KW */
testcase( i==13 ); /* TK_EXPLAIN */
testcase( i==14 ); /* TK_INSTEAD */
testcase( i==15 ); /* TK_ADD */
testcase( i==16 ); /* TK_DATABASE */
testcase( i==17 ); /* TK_AS */
testcase( i==18 ); /* TK_SELECT */
testcase( i==19 ); /* TK_TABLE */
testcase( i==20 ); /* TK_JOIN_KW */
testcase( i==21 ); /* TK_THEN */
testcase( i==22 ); /* TK_END */
testcase( i==23 ); /* TK_DEFERRABLE */
testcase( i==24 ); /* TK_ELSE */
testcase( i==25 ); /* TK_EXCEPT */
testcase( i==26 ); /* TK_TRANSACTION */
testcase( i==27 ); /* TK_ON */
testcase( i==28 ); /* TK_JOIN_KW */
testcase( i==29 ); /* TK_ALTER */
testcase( i==30 ); /* TK_RAISE */
testcase( i==31 ); /* TK_EXCLUSIVE */
testcase( i==32 ); /* TK_EXISTS */
testcase( i==33 ); /* TK_SAVEPOINT */
testcase( i==34 ); /* TK_INTERSECT */
testcase( i==35 ); /* TK_TRIGGER */
testcase( i==36 ); /* TK_REFERENCES */
testcase( i==37 ); /* TK_CONSTRAINT */
testcase( i==38 ); /* TK_INTO */
testcase( i==39 ); /* TK_OFFSET */
testcase( i==40 ); /* TK_OF */
testcase( i==41 ); /* TK_SET */
testcase( i==42 ); /* TK_TEMP */
testcase( i==43 ); /* TK_TEMP */
testcase( i==44 ); /* TK_OR */
testcase( i==45 ); /* TK_UNIQUE */
testcase( i==46 ); /* TK_QUERY */
testcase( i==47 ); /* TK_ATTACH */
testcase( i==48 ); /* TK_HAVING */
testcase( i==49 ); /* TK_GROUP */
testcase( i==50 ); /* TK_UPDATE */
testcase( i==51 ); /* TK_BEGIN */
testcase( i==52 ); /* TK_JOIN_KW */
testcase( i==53 ); /* TK_RELEASE */
testcase( i==54 ); /* TK_BETWEEN */
testcase( i==55 ); /* TK_NOT */
testcase( i==56 ); /* TK_NOTNULL */
testcase( i==57 ); /* TK_NULL */
testcase( i==58 ); /* TK_LIKE_KW */
testcase( i==59 ); /* TK_CASCADE */
testcase( i==60 ); /* TK_ASC */
testcase( i==61 ); /* TK_DELETE */
testcase( i==62 ); /* TK_CASE */
testcase( i==63 ); /* TK_COLLATE */
testcase( i==64 ); /* TK_CREATE */
testcase( i==65 ); /* TK_CTIME_KW */
testcase( i==66 ); /* TK_DETACH */
testcase( i==67 ); /* TK_IMMEDIATE */
testcase( i==68 ); /* TK_JOIN */
testcase( i==69 ); /* TK_INSERT */
testcase( i==70 ); /* TK_MATCH */
testcase( i==71 ); /* TK_PLAN */
testcase( i==72 ); /* TK_ANALYZE */
testcase( i==73 ); /* TK_PRAGMA */
testcase( i==74 ); /* TK_ABORT */
testcase( i==75 ); /* TK_VALUES */
testcase( i==76 ); /* TK_VIRTUAL */
testcase( i==77 ); /* TK_LIMIT */
testcase( i==78 ); /* TK_WHEN */
testcase( i==79 ); /* TK_WHERE */
testcase( i==80 ); /* TK_RENAME */
testcase( i==81 ); /* TK_AFTER */
testcase( i==82 ); /* TK_REPLACE */
testcase( i==83 ); /* TK_AND */
testcase( i==84 ); /* TK_DEFAULT */
testcase( i==85 ); /* TK_AUTOINCR */
testcase( i==86 ); /* TK_TO */
testcase( i==87 ); /* TK_IN */
testcase( i==88 ); /* TK_CAST */
testcase( i==89 ); /* TK_COLUMNKW */
testcase( i==90 ); /* TK_COMMIT */
testcase( i==91 ); /* TK_CONFLICT */
testcase( i==92 ); /* TK_JOIN_KW */
testcase( i==93 ); /* TK_CTIME_KW */
testcase( i==94 ); /* TK_CTIME_KW */
testcase( i==95 ); /* TK_PRIMARY */
testcase( i==96 ); /* TK_DEFERRED */
testcase( i==97 ); /* TK_DISTINCT */
testcase( i==98 ); /* TK_IS */
testcase( i==99 ); /* TK_DROP */
testcase( i==100 ); /* TK_FAIL */
testcase( i==101 ); /* TK_FROM */
testcase( i==102 ); /* TK_JOIN_KW */
testcase( i==103 ); /* TK_LIKE_KW */
testcase( i==104 ); /* TK_BY */
testcase( i==105 ); /* TK_IF */
testcase( i==106 ); /* TK_ISNULL */
testcase( i==107 ); /* TK_ORDER */
testcase( i==108 ); /* TK_RESTRICT */
testcase( i==109 ); /* TK_JOIN_KW */
testcase( i==110 ); /* TK_JOIN_KW */
testcase( i==111 ); /* TK_ROLLBACK */
testcase( i==112 ); /* TK_ROW */
testcase( i==113 ); /* TK_UNION */
testcase( i==114 ); /* TK_USING */
testcase( i==115 ); /* TK_VACUUM */
testcase( i==116 ); /* TK_VIEW */
testcase( i==117 ); /* TK_INITIALLY */
testcase( i==118 ); /* TK_ALL */
return aCode[i];
}
}
return TK_ID;
}
int sqlite3KeywordCode(const unsigned char *z, int n){
return keywordCode((char*)z, n);
}
/***** This file contains automatically generated code ******
**
** The code in this file has been automatically generated by
**
** $Header: /sqlite/sqlite/tool/mkkeywordhash.c,v 1.37 2009/02/01 00:00:46 drh Exp $
**
** The code in this file implements a function that determines whether
** or not a given identifier is really an SQL keyword. The same thing
** might be implemented more directly using a hand-written hash table.
** But by using this automatically generated code, the size of the code
** is substantially reduced. This is important for embedded applications
** on platforms with limited memory.
*/
/* Hash score: 171 */
static int keywordCode(const char *z, int n){
/* zText[] encodes 801 bytes of keywords in 541 bytes */
/* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */
/* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */
/* XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY */
/* UNIQUERYATTACHAVINGROUPDATEBEGINNERELEASEBETWEENOTNULLIKE */
/* CASCADELETECASECOLLATECREATECURRENT_DATEDETACHIMMEDIATEJOIN */
/* SERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHENWHERENAME */
/* AFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSS */
/* CURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAILFROMFULLGLOBYIF */
/* ISNULLORDERESTRICTOUTERIGHTROLLBACKROWUNIONUSINGVACUUMVIEW */
/* INITIALLY */
static const char zText[540] = {
'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H',
'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G',
'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A',
'S','E','L','E','C','T','A','B','L','E','F','T','H','E','N','D','E','F',
'E','R','R','A','B','L','E','L','S','E','X','C','E','P','T','R','A','N',
'S','A','C','T','I','O','N','A','T','U','R','A','L','T','E','R','A','I',
'S','E','X','C','L','U','S','I','V','E','X','I','S','T','S','A','V','E',
'P','O','I','N','T','E','R','S','E','C','T','R','I','G','G','E','R','E',
'F','E','R','E','N','C','E','S','C','O','N','S','T','R','A','I','N','T',
'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q',
'U','E','R','Y','A','T','T','A','C','H','A','V','I','N','G','R','O','U',
'P','D','A','T','E','B','E','G','I','N','N','E','R','E','L','E','A','S',
'E','B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C',
'A','S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L',
'A','T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D',
'A','T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E',
'J','O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A',
'L','Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U',
'E','S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','W',
'H','E','R','E','N','A','M','E','A','F','T','E','R','E','P','L','A','C',
'E','A','N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R',
'E','M','E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M',
'M','I','T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U',
'R','R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M',
'A','R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T',
'D','R','O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L',
'O','B','Y','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S',
'T','R','I','C','T','O','U','T','E','R','I','G','H','T','R','O','L','L',
'B','A','C','K','R','O','W','U','N','I','O','N','U','S','I','N','G','V',
'A','C','U','U','M','V','I','E','W','I','N','I','T','I','A','L','L','Y',
};
static const unsigned char aHash[127] = {
70, 99, 112, 68, 0, 44, 0, 0, 76, 0, 71, 0, 0,
41, 12, 72, 15, 0, 111, 79, 49, 106, 0, 19, 0, 0,
116, 0, 114, 109, 0, 22, 87, 0, 9, 0, 0, 64, 65,
0, 63, 6, 0, 47, 84, 96, 0, 113, 95, 0, 0, 43,
0, 97, 24, 0, 17, 0, 117, 48, 23, 0, 5, 104, 25,
90, 0, 0, 119, 100, 55, 118, 52, 7, 50, 0, 85, 0,
94, 26, 0, 93, 0, 0, 0, 89, 86, 91, 82, 103, 14,
38, 102, 0, 75, 0, 18, 83, 105, 31, 0, 115, 74, 107,
56, 45, 78, 0, 0, 88, 39, 0, 110, 0, 35, 0, 0,
28, 0, 80, 53, 58, 0, 20, 57, 0, 51,
};
static const unsigned char aNext[119] = {
0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 32, 0, 21, 0, 0, 0, 42, 3, 46, 0,
0, 0, 0, 0, 29, 0, 37, 0, 0, 0, 1, 60, 0,
0, 61, 0, 40, 0, 0, 0, 0, 0, 0, 0, 59, 0,
0, 0, 0, 30, 54, 16, 33, 11, 0, 0, 0, 0, 0,
0, 0, 10, 66, 73, 0, 8, 0, 98, 92, 0, 101, 0,
81, 0, 69, 0, 0, 108, 27, 36, 67, 77, 0, 34, 62,
0, 0,
};
static const unsigned char aLen[119] = {
7, 7, 5, 4, 6, 4, 5, 3, 6, 3, 7, 6, 6,
7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6,
11, 2, 7, 5, 5, 9, 6, 9, 9, 7, 10, 10, 4,
6, 2, 3, 9, 4, 2, 6, 5, 6, 6, 5, 6, 5,
5, 7, 7, 3, 7, 4, 4, 7, 3, 6, 4, 7, 6,
12, 6, 9, 4, 6, 5, 4, 7, 6, 5, 6, 7, 5,
4, 5, 6, 5, 7, 3, 7, 13, 2, 2, 4, 6, 6,
8, 5, 17, 12, 7, 8, 8, 2, 4, 4, 4, 4, 4,
2, 2, 6, 5, 8, 5, 5, 8, 3, 5, 5, 6, 4,
9, 3,
};
static const unsigned short int aOffset[119] = {
0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33,
36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81,
86, 95, 96, 101, 105, 109, 117, 122, 128, 136, 142, 152, 159,
162, 162, 165, 167, 167, 171, 176, 179, 184, 189, 194, 197, 203,
206, 210, 217, 223, 223, 226, 229, 233, 234, 238, 244, 248, 255,
261, 273, 279, 288, 290, 296, 301, 303, 310, 315, 320, 326, 332,
337, 341, 344, 350, 354, 361, 363, 370, 372, 374, 383, 387, 393,
399, 407, 412, 412, 428, 435, 442, 443, 450, 454, 458, 462, 466,
469, 471, 473, 479, 483, 491, 495, 500, 508, 511, 516, 521, 527,
531, 536,
};
static const unsigned char aCode[119] = {
TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE,
TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOR,
TK_FOREIGN, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD,
TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE,
TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE,
TK_EXCEPT, TK_TRANSACTION,TK_ON, TK_JOIN_KW, TK_ALTER,
TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT, TK_INTERSECT,
TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO, TK_OFFSET,
TK_OF, TK_SET, TK_TEMP, TK_TEMP, TK_OR,
TK_UNIQUE, TK_QUERY, TK_ATTACH, TK_HAVING, TK_GROUP,
TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RELEASE, TK_BETWEEN,
TK_NOT, TK_NOTNULL, TK_NULL, TK_LIKE_KW, TK_CASCADE,
TK_ASC, TK_DELETE, TK_CASE, TK_COLLATE, TK_CREATE,
TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE, TK_JOIN, TK_INSERT,
TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, TK_ABORT,
TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, TK_WHERE,
TK_RENAME, TK_AFTER, TK_REPLACE, TK_AND, TK_DEFAULT,
TK_AUTOINCR, TK_TO, TK_IN, TK_CAST, TK_COLUMNKW,
TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW,
TK_PRIMARY, TK_DEFERRED, TK_DISTINCT, TK_IS, TK_DROP,
TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, TK_BY,
TK_IF, TK_ISNULL, TK_ORDER, TK_RESTRICT, TK_JOIN_KW,
TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_UNION, TK_USING,
TK_VACUUM, TK_VIEW, TK_INITIALLY, TK_ALL,
};
int h, i;
if( n<2 ) return TK_ID;
h = ((charMap(z[0])*4) ^
(charMap(z[n-1])*3) ^
n) % 127;
for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){
if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){
testcase( i==0 ); /* TK_REINDEX */
testcase( i==1 ); /* TK_INDEXED */
testcase( i==2 ); /* TK_INDEX */
testcase( i==3 ); /* TK_DESC */
testcase( i==4 ); /* TK_ESCAPE */
testcase( i==5 ); /* TK_EACH */
testcase( i==6 ); /* TK_CHECK */
testcase( i==7 ); /* TK_KEY */
testcase( i==8 ); /* TK_BEFORE */
testcase( i==9 ); /* TK_FOR */
testcase( i==10 ); /* TK_FOREIGN */
testcase( i==11 ); /* TK_IGNORE */
testcase( i==12 ); /* TK_LIKE_KW */
testcase( i==13 ); /* TK_EXPLAIN */
testcase( i==14 ); /* TK_INSTEAD */
testcase( i==15 ); /* TK_ADD */
testcase( i==16 ); /* TK_DATABASE */
testcase( i==17 ); /* TK_AS */
testcase( i==18 ); /* TK_SELECT */
testcase( i==19 ); /* TK_TABLE */
testcase( i==20 ); /* TK_JOIN_KW */
testcase( i==21 ); /* TK_THEN */
testcase( i==22 ); /* TK_END */
testcase( i==23 ); /* TK_DEFERRABLE */
testcase( i==24 ); /* TK_ELSE */
testcase( i==25 ); /* TK_EXCEPT */
testcase( i==26 ); /* TK_TRANSACTION */
testcase( i==27 ); /* TK_ON */
testcase( i==28 ); /* TK_JOIN_KW */
testcase( i==29 ); /* TK_ALTER */
testcase( i==30 ); /* TK_RAISE */
testcase( i==31 ); /* TK_EXCLUSIVE */
testcase( i==32 ); /* TK_EXISTS */
testcase( i==33 ); /* TK_SAVEPOINT */
testcase( i==34 ); /* TK_INTERSECT */
testcase( i==35 ); /* TK_TRIGGER */
testcase( i==36 ); /* TK_REFERENCES */
testcase( i==37 ); /* TK_CONSTRAINT */
testcase( i==38 ); /* TK_INTO */
testcase( i==39 ); /* TK_OFFSET */
testcase( i==40 ); /* TK_OF */
testcase( i==41 ); /* TK_SET */
testcase( i==42 ); /* TK_TEMP */
testcase( i==43 ); /* TK_TEMP */
testcase( i==44 ); /* TK_OR */
testcase( i==45 ); /* TK_UNIQUE */
testcase( i==46 ); /* TK_QUERY */
testcase( i==47 ); /* TK_ATTACH */
testcase( i==48 ); /* TK_HAVING */
testcase( i==49 ); /* TK_GROUP */
testcase( i==50 ); /* TK_UPDATE */
testcase( i==51 ); /* TK_BEGIN */
testcase( i==52 ); /* TK_JOIN_KW */
testcase( i==53 ); /* TK_RELEASE */
testcase( i==54 ); /* TK_BETWEEN */
testcase( i==55 ); /* TK_NOT */
testcase( i==56 ); /* TK_NOTNULL */
testcase( i==57 ); /* TK_NULL */
testcase( i==58 ); /* TK_LIKE_KW */
testcase( i==59 ); /* TK_CASCADE */
testcase( i==60 ); /* TK_ASC */
testcase( i==61 ); /* TK_DELETE */
testcase( i==62 ); /* TK_CASE */
testcase( i==63 ); /* TK_COLLATE */
testcase( i==64 ); /* TK_CREATE */
testcase( i==65 ); /* TK_CTIME_KW */
testcase( i==66 ); /* TK_DETACH */
testcase( i==67 ); /* TK_IMMEDIATE */
testcase( i==68 ); /* TK_JOIN */
testcase( i==69 ); /* TK_INSERT */
testcase( i==70 ); /* TK_MATCH */
testcase( i==71 ); /* TK_PLAN */
testcase( i==72 ); /* TK_ANALYZE */
testcase( i==73 ); /* TK_PRAGMA */
testcase( i==74 ); /* TK_ABORT */
testcase( i==75 ); /* TK_VALUES */
testcase( i==76 ); /* TK_VIRTUAL */
testcase( i==77 ); /* TK_LIMIT */
testcase( i==78 ); /* TK_WHEN */
testcase( i==79 ); /* TK_WHERE */
testcase( i==80 ); /* TK_RENAME */
testcase( i==81 ); /* TK_AFTER */
testcase( i==82 ); /* TK_REPLACE */
testcase( i==83 ); /* TK_AND */
testcase( i==84 ); /* TK_DEFAULT */
testcase( i==85 ); /* TK_AUTOINCR */
testcase( i==86 ); /* TK_TO */
testcase( i==87 ); /* TK_IN */
testcase( i==88 ); /* TK_CAST */
testcase( i==89 ); /* TK_COLUMNKW */
testcase( i==90 ); /* TK_COMMIT */
testcase( i==91 ); /* TK_CONFLICT */
testcase( i==92 ); /* TK_JOIN_KW */
testcase( i==93 ); /* TK_CTIME_KW */
testcase( i==94 ); /* TK_CTIME_KW */
testcase( i==95 ); /* TK_PRIMARY */
testcase( i==96 ); /* TK_DEFERRED */
testcase( i==97 ); /* TK_DISTINCT */
testcase( i==98 ); /* TK_IS */
testcase( i==99 ); /* TK_DROP */
testcase( i==100 ); /* TK_FAIL */
testcase( i==101 ); /* TK_FROM */
testcase( i==102 ); /* TK_JOIN_KW */
testcase( i==103 ); /* TK_LIKE_KW */
testcase( i==104 ); /* TK_BY */
testcase( i==105 ); /* TK_IF */
testcase( i==106 ); /* TK_ISNULL */
testcase( i==107 ); /* TK_ORDER */
testcase( i==108 ); /* TK_RESTRICT */
testcase( i==109 ); /* TK_JOIN_KW */
testcase( i==110 ); /* TK_JOIN_KW */
testcase( i==111 ); /* TK_ROLLBACK */
testcase( i==112 ); /* TK_ROW */
testcase( i==113 ); /* TK_UNION */
testcase( i==114 ); /* TK_USING */
testcase( i==115 ); /* TK_VACUUM */
testcase( i==116 ); /* TK_VIEW */
testcase( i==117 ); /* TK_INITIALLY */
testcase( i==118 ); /* TK_ALL */
return aCode[i];
}
}
return TK_ID;
}
int sqlite3KeywordCode(const unsigned char *z, int n){
return keywordCode((char*)z, n);
}

5
main.c
View file

@ -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.534 2009/03/23 04:33:32 danielk1977 Exp $
** $Id: main.c,v 1.536 2009/04/09 01:23:49 drh Exp $
*/
#include "sqliteInt.h"
@ -219,6 +219,7 @@ int sqlite3_shutdown(void){
if( sqlite3GlobalConfig.isInit ){
sqlite3_os_end();
}
sqlite3_reset_auto_extension();
sqlite3MallocEnd();
sqlite3MutexEnd();
sqlite3GlobalConfig.isInit = 0;
@ -418,7 +419,7 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
if( pStart ){
int i;
LookasideSlot *p;
assert( sz > sizeof(LookasideSlot*) );
assert( sz > (int)sizeof(LookasideSlot*) );
p = (LookasideSlot*)pStart;
for(i=cnt-1; i>=0; i--){
p->pNext = db->lookaside.pFree;

View file

@ -14,7 +14,7 @@
** The in-memory rollback journal is used to journal transactions for
** ":memory:" databases and when the journal_mode=MEMORY pragma is used.
**
** @(#) $Id: memjournal.c,v 1.8 2008/12/20 02:14:40 drh Exp $
** @(#) $Id: memjournal.c,v 1.11 2009/04/05 12:22:09 drh Exp $
*/
#include "sqliteInt.h"
@ -25,8 +25,13 @@ typedef struct FileChunk FileChunk;
/* Space to hold the rollback journal is allocated in increments of
** this many bytes.
**
** The size chosen is a little less than a power of two. That way,
** the FileChunk object will have a size that almost exactly fills
** a power-of-two allocation. This mimimizes wasted space in power-of-two
** memory allocators.
*/
#define JOURNAL_CHUNKSIZE 1024
#define JOURNAL_CHUNKSIZE ((int)(1024-sizeof(FileChunk*)))
/* Macro to find the minimum of two numeric values.
*/
@ -63,7 +68,8 @@ struct MemJournal {
};
/*
** Read data from the file.
** Read data from the in-memory journal file. This is the implementation
** of the sqlite3_vfs.xRead method.
*/
static int memjrnlRead(
sqlite3_file *pJfd, /* The journal file from which to read */
@ -77,12 +83,13 @@ static int memjrnlRead(
int iChunkOffset;
FileChunk *pChunk;
/* SQLite never tries to read past the end of a rollback journal file */
assert( iOfst+iAmt<=p->endpoint.iOffset );
if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
sqlite3_int64 iOff = 0;
for(pChunk=p->pFirst;
pChunk && (iOff+JOURNAL_CHUNKSIZE)<=iOfst;
ALWAYS(pChunk) && (iOff+JOURNAL_CHUNKSIZE)<=iOfst;
pChunk=pChunk->pNext
){
iOff += JOURNAL_CHUNKSIZE;
@ -185,11 +192,17 @@ static int memjrnlClose(sqlite3_file *pJfd){
/*
** Sync the file.
**
** Syncing an in-memory journal is a no-op. And, in fact, this routine
** is never called in a working implementation. This implementation
** exists purely as a contingency, in case some malfunction in some other
** part of SQLite causes Sync to be called by mistake.
*/
static int memjrnlSync(sqlite3_file *NotUsed, int NotUsed2){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
return SQLITE_OK;
}
static int memjrnlSync(sqlite3_file *NotUsed, int NotUsed2){ /*NO_TEST*/
UNUSED_PARAMETER2(NotUsed, NotUsed2); /*NO_TEST*/
assert( 0 ); /*NO_TEST*/
return SQLITE_OK; /*NO_TEST*/
} /*NO_TEST*/
/*
** Query the size of the file in bytes.
@ -224,6 +237,7 @@ static struct sqlite3_io_methods MemJournalMethods = {
*/
void sqlite3MemJournalOpen(sqlite3_file *pJfd){
MemJournal *p = (MemJournal *)pJfd;
assert( EIGHT_BYTE_ALIGNMENT(p) );
memset(p, 0, sqlite3MemJournalSize());
p->pMethod = &MemJournalMethods;
}

View file

@ -13,7 +13,7 @@
** This file contains the implementation of the sqlite3_unlock_notify()
** API method and its associated functionality.
**
** $Id: notify.c,v 1.2 2009/03/25 16:51:43 drh Exp $
** $Id: notify.c,v 1.4 2009/04/07 22:06:57 drh Exp $
*/
#include "sqliteInt.h"
#include "btreeInt.h"
@ -112,7 +112,7 @@ static void addToBlockedList(sqlite3 *db){
/*
** Obtain the STATIC_MASTER mutex.
*/
static void enterMutex(){
static void enterMutex(void){
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
checkListProperties(0);
}
@ -120,7 +120,7 @@ static void enterMutex(){
/*
** Release the STATIC_MASTER mutex.
*/
static void leaveMutex(){
static void leaveMutex(void){
assertMutexHeld();
checkListProperties(0);
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
@ -128,6 +128,24 @@ static void leaveMutex(){
/*
** Register an unlock-notify callback.
**
** This is called after connection "db" has attempted some operation
** but has received an SQLITE_LOCKED error because another connection
** (call it pOther) in the same process was busy using the same shared
** cache. pOther is found by looking at db->pBlockingConnection.
**
** If there is no blocking connection, the callback is invoked immediately,
** before this routine returns.
**
** If pOther is already blocked on db, then report SQLITE_LOCKED, to indicate
** a deadlock.
**
** Otherwise, make arrangements to invoke xNotify when pOther drops
** its locks.
**
** Each call to this routine overrides any prior callbacks registered
** on the same "db". If xNotify==0 then any prior callbacks are immediately
** cancelled.
*/
int sqlite3_unlock_notify(
sqlite3 *db,
@ -139,7 +157,12 @@ int sqlite3_unlock_notify(
sqlite3_mutex_enter(db->mutex);
enterMutex();
if( 0==db->pBlockingConnection ){
if( xNotify==0 ){
removeFromBlockedList(db);
db->pUnlockConnection = 0;
db->xUnlockNotify = 0;
db->pUnlockArg = 0;
}else if( 0==db->pBlockingConnection ){
/* The blocking transaction has been concluded. Or there never was a
** blocking transaction. In either case, invoke the notify callback
** immediately.
@ -148,7 +171,7 @@ int sqlite3_unlock_notify(
}else{
sqlite3 *p;
for(p=db->pBlockingConnection; p && p!=db; p=p->pUnlockConnection);
for(p=db->pBlockingConnection; p && p!=db; p=p->pUnlockConnection){}
if( p ){
rc = SQLITE_LOCKED; /* Deadlock detected. */
}else{
@ -183,7 +206,8 @@ void sqlite3ConnectionBlocked(sqlite3 *db, sqlite3 *pBlocker){
}
/*
** The transaction opened by database db has just finished. Locks held
** This function is called when
** the transaction opened by database db has just finished. Locks held
** by database connection db have been released.
**
** This function loops through each entry in the blocked connections
@ -204,11 +228,11 @@ void sqlite3ConnectionUnlocked(sqlite3 *db){
void (*xUnlockNotify)(void **, int) = 0; /* Unlock-notify cb to invoke */
int nArg = 0; /* Number of entries in aArg[] */
sqlite3 **pp; /* Iterator variable */
void **aArg; /* Arguments to the unlock callback */
void **aDyn = 0; /* Dynamically allocated space for aArg[] */
void *aStatic[16]; /* Starter space for aArg[]. No malloc required */
void *aStatic[16];
void **aArg = aStatic;
void **aDyn = 0;
aArg = aStatic;
enterMutex(); /* Enter STATIC_MASTER mutex */
/* This loop runs once for each entry in the blocked-connections list. */

145
opcodes.c
View file

@ -3,6 +3,151 @@
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
const char *sqlite3OpcodeName(int i){
static const char *const azName[] = { "?",
/* 1 */ "ReadCookie",
/* 2 */ "AutoCommit",
/* 3 */ "Found",
/* 4 */ "NullRow",
/* 5 */ "Variable",
/* 6 */ "RealAffinity",
/* 7 */ "Sort",
/* 8 */ "Affinity",
/* 9 */ "IfNot",
/* 10 */ "Gosub",
/* 11 */ "NotFound",
/* 12 */ "ResultRow",
/* 13 */ "SeekLe",
/* 14 */ "Rowid",
/* 15 */ "CreateIndex",
/* 16 */ "Explain",
/* 17 */ "Statement",
/* 18 */ "DropIndex",
/* 19 */ "Not",
/* 20 */ "Null",
/* 21 */ "Int64",
/* 22 */ "LoadAnalysis",
/* 23 */ "IdxInsert",
/* 24 */ "VUpdate",
/* 25 */ "Next",
/* 26 */ "SetNumColumns",
/* 27 */ "SeekLt",
/* 28 */ "Rewind",
/* 29 */ "RowSetRead",
/* 30 */ "Last",
/* 31 */ "MustBeInt",
/* 32 */ "IncrVacuum",
/* 33 */ "String",
/* 34 */ "VFilter",
/* 35 */ "Count",
/* 36 */ "Close",
/* 37 */ "AggFinal",
/* 38 */ "RowData",
/* 39 */ "IdxRowid",
/* 40 */ "Pagecount",
/* 41 */ "SeekGe",
/* 42 */ "OpenPseudo",
/* 43 */ "Halt",
/* 44 */ "Compare",
/* 45 */ "NewRowid",
/* 46 */ "IdxLT",
/* 47 */ "SeekGt",
/* 48 */ "MemMax",
/* 49 */ "Function",
/* 50 */ "IntegrityCk",
/* 51 */ "SCopy",
/* 52 */ "IfNeg",
/* 53 */ "NotExists",
/* 54 */ "VDestroy",
/* 55 */ "IdxDelete",
/* 56 */ "Vacuum",
/* 57 */ "Copy",
/* 58 */ "If",
/* 59 */ "Destroy",
/* 60 */ "Jump",
/* 61 */ "AggStep",
/* 62 */ "Clear",
/* 63 */ "Insert",
/* 64 */ "Permutation",
/* 65 */ "VBegin",
/* 66 */ "Or",
/* 67 */ "And",
/* 68 */ "OpenEphemeral",
/* 69 */ "IdxGE",
/* 70 */ "Trace",
/* 71 */ "IsNull",
/* 72 */ "NotNull",
/* 73 */ "Ne",
/* 74 */ "Eq",
/* 75 */ "Gt",
/* 76 */ "Le",
/* 77 */ "Lt",
/* 78 */ "Ge",
/* 79 */ "VRowid",
/* 80 */ "BitAnd",
/* 81 */ "BitOr",
/* 82 */ "ShiftLeft",
/* 83 */ "ShiftRight",
/* 84 */ "Add",
/* 85 */ "Subtract",
/* 86 */ "Multiply",
/* 87 */ "Divide",
/* 88 */ "Remainder",
/* 89 */ "Concat",
/* 90 */ "MakeRecord",
/* 91 */ "Yield",
/* 92 */ "SetCookie",
/* 93 */ "BitNot",
/* 94 */ "String8",
/* 95 */ "Prev",
/* 96 */ "ContextPush",
/* 97 */ "DropTrigger",
/* 98 */ "VColumn",
/* 99 */ "Return",
/* 100 */ "OpenWrite",
/* 101 */ "Integer",
/* 102 */ "Transaction",
/* 103 */ "IfPos",
/* 104 */ "RowSetAdd",
/* 105 */ "CollSeq",
/* 106 */ "Savepoint",
/* 107 */ "VRename",
/* 108 */ "Sequence",
/* 109 */ "ContextPop",
/* 110 */ "HaltIfNull",
/* 111 */ "VCreate",
/* 112 */ "CreateTable",
/* 113 */ "AddImm",
/* 114 */ "DropTable",
/* 115 */ "IsUnique",
/* 116 */ "VOpen",
/* 117 */ "IfZero",
/* 118 */ "Noop",
/* 119 */ "RowKey",
/* 120 */ "Expire",
/* 121 */ "Delete",
/* 122 */ "Blob",
/* 123 */ "Move",
/* 124 */ "Goto",
/* 125 */ "ParseSchema",
/* 126 */ "VNext",
/* 127 */ "Seek",
/* 128 */ "TableLock",
/* 129 */ "VerifyCookie",
/* 130 */ "Real",
/* 131 */ "Column",
/* 132 */ "OpenRead",
/* 133 */ "ResetCount",
/* 134 */ "NotUsed_134",
/* 135 */ "NotUsed_135",
/* 136 */ "NotUsed_136",
/* 137 */ "NotUsed_137",
/* 138 */ "NotUsed_138",
/* 139 */ "NotUsed_139",
/* 140 */ "NotUsed_140",
/* 141 */ "ToText",
/* 142 */ "ToBlob",
/* 143 */ "ToNumeric",
/* 144 */ "ToInt",
/* 145 */ "ToReal",
};
return azName[i];
}

302
opcodes.h
View file

@ -1,143 +1,143 @@
/* Automatically generated. Do not edit */
/* See the mkopcodeh.awk script for details */
#define OP_VRowid 1
#define OP_VFilter 2
#define OP_IfNeg 3
#define OP_ContextPop 4
#define OP_IntegrityCk 5
#define OP_DropTrigger 6
#define OP_DropIndex 7
#define OP_IdxInsert 8
#define OP_Delete 9
#define OP_SeekLt 10
#define OP_OpenEphemeral 11
#define OP_VerifyCookie 12
#define OP_Blob 13
#define OP_RowKey 14
#define OP_IsUnique 15
#define OP_SetNumColumns 16
#define OP_Eq 74 /* same as TK_EQ */
#define OP_VUpdate 17
#define OP_Expire 18
#define OP_NullRow 20
#define OP_OpenPseudo 21
#define OP_OpenWrite 22
#define OP_OpenRead 23
#define OP_Transaction 24
#define OP_AutoCommit 25
#define OP_Copy 26
#define OP_Halt 27
#define OP_VRename 28
#define OP_Vacuum 29
#define OP_RowData 30
#define OP_NotExists 31
#define OP_SetCookie 32
#define OP_Move 33
#define OP_Variable 34
#define OP_Pagecount 35
#define OP_VNext 36
#define OP_VDestroy 37
#define OP_TableLock 38
#define OP_RowSetAdd 39
#define OP_LoadAnalysis 40
#define OP_IdxDelete 41
#define OP_Sort 42
#define OP_ResetCount 43
#define OP_Count 44
#define OP_NotNull 72 /* same as TK_NOTNULL */
#define OP_Ge 78 /* same as TK_GE */
#define OP_Remainder 88 /* same as TK_REM */
#define OP_Divide 87 /* same as TK_SLASH */
#define OP_Integer 45
#define OP_Explain 46
#define OP_IncrVacuum 47
#define OP_AggStep 48
#define OP_CreateIndex 49
#define OP_NewRowid 50
#define OP_And 67 /* same as TK_AND */
#define OP_ShiftLeft 82 /* same as TK_LSHIFT */
#define OP_Real 130 /* same as TK_FLOAT */
#define OP_Return 51
#define OP_Trace 52
#define OP_IfPos 53
#define OP_IdxLT 54
#define OP_Rewind 55
#define OP_SeekGe 56
#define OP_Affinity 57
#define OP_Gt 75 /* same as TK_GT */
#define OP_AddImm 58
#define OP_Subtract 85 /* same as TK_MINUS */
#define OP_Null 59
#define OP_VColumn 60
#define OP_Clear 61
#define OP_IsNull 71 /* same as TK_ISNULL */
#define OP_If 62
#define OP_Permutation 63
#define OP_ToBlob 142 /* same as TK_TO_BLOB */
#define OP_RealAffinity 64
#define OP_HaltIfNull 65
#define OP_Yield 68
#define OP_AggFinal 69
#define OP_IfZero 70
#define OP_Last 79
#define OP_Rowid 90
#define OP_Sequence 91
#define OP_NotFound 92
#define OP_SeekGt 95
#define OP_MakeRecord 96
#define OP_ToText 141 /* same as TK_TO_TEXT */
#define OP_BitAnd 80 /* same as TK_BITAND */
#define OP_Add 84 /* same as TK_PLUS */
#define OP_ResultRow 97
#define OP_String 98
#define OP_Goto 99
#define OP_Noop 100
#define OP_VCreate 101
#define OP_RowSetRead 102
#define OP_DropTable 103
#define OP_IdxRowid 104
#define OP_Insert 105
#define OP_Column 106
#define OP_Not 19 /* same as TK_NOT */
#define OP_Compare 107
#define OP_Le 76 /* same as TK_LE */
#define OP_BitOr 81 /* same as TK_BITOR */
#define OP_Multiply 86 /* same as TK_STAR */
#define OP_String8 94 /* same as TK_STRING */
#define OP_VOpen 108
#define OP_CreateTable 109
#define OP_Found 110
#define OP_Seek 111
#define OP_Close 112
#define OP_Savepoint 113
#define OP_Statement 114
#define OP_IfNot 115
#define OP_ToInt 144 /* same as TK_TO_INT */
#define OP_VBegin 116
#define OP_MemMax 117
#define OP_Next 118
#define OP_Prev 119
#define OP_SeekLe 120
#define OP_ReadCookie 1
#define OP_AutoCommit 2
#define OP_Found 3
#define OP_NullRow 4
#define OP_Lt 77 /* same as TK_LT */
#define OP_Ne 73 /* same as TK_NE */
#define OP_MustBeInt 121
#define OP_ShiftRight 83 /* same as TK_RSHIFT */
#define OP_CollSeq 122
#define OP_Gosub 123
#define OP_ContextPush 124
#define OP_ParseSchema 125
#define OP_Destroy 126
#define OP_IdxGE 127
#define OP_ReadCookie 128
#define OP_BitNot 93 /* same as TK_BITNOT */
#define OP_Or 66 /* same as TK_OR */
#define OP_Jump 129
#define OP_ToReal 145 /* same as TK_TO_REAL */
#define OP_Variable 5
#define OP_RealAffinity 6
#define OP_Sort 7
#define OP_Affinity 8
#define OP_IfNot 9
#define OP_Gosub 10
#define OP_Add 84 /* same as TK_PLUS */
#define OP_NotFound 11
#define OP_ResultRow 12
#define OP_IsNull 71 /* same as TK_ISNULL */
#define OP_SeekLe 13
#define OP_Rowid 14
#define OP_CreateIndex 15
#define OP_Explain 16
#define OP_Statement 17
#define OP_DropIndex 18
#define OP_Null 20
#define OP_ToInt 144 /* same as TK_TO_INT */
#define OP_Int64 21
#define OP_LoadAnalysis 22
#define OP_IdxInsert 23
#define OP_VUpdate 24
#define OP_Next 25
#define OP_SetNumColumns 26
#define OP_ToNumeric 143 /* same as TK_TO_NUMERIC*/
#define OP_Function 131
#define OP_Ge 78 /* same as TK_GE */
#define OP_BitNot 93 /* same as TK_BITNOT */
#define OP_SeekLt 27
#define OP_Rewind 28
#define OP_Multiply 86 /* same as TK_STAR */
#define OP_ToReal 145 /* same as TK_TO_REAL */
#define OP_Gt 75 /* same as TK_GT */
#define OP_RowSetRead 29
#define OP_Last 30
#define OP_MustBeInt 31
#define OP_Ne 73 /* same as TK_NE */
#define OP_IncrVacuum 32
#define OP_String 33
#define OP_VFilter 34
#define OP_Count 35
#define OP_Close 36
#define OP_AggFinal 37
#define OP_RowData 38
#define OP_IdxRowid 39
#define OP_Pagecount 40
#define OP_BitOr 81 /* same as TK_BITOR */
#define OP_NotNull 72 /* same as TK_NOTNULL */
#define OP_SeekGe 41
#define OP_Not 19 /* same as TK_NOT */
#define OP_OpenPseudo 42
#define OP_Halt 43
#define OP_Compare 44
#define OP_NewRowid 45
#define OP_Real 130 /* same as TK_FLOAT */
#define OP_IdxLT 46
#define OP_SeekGt 47
#define OP_MemMax 48
#define OP_Function 49
#define OP_IntegrityCk 50
#define OP_Remainder 88 /* same as TK_REM */
#define OP_SCopy 51
#define OP_ShiftLeft 82 /* same as TK_LSHIFT */
#define OP_IfNeg 52
#define OP_BitAnd 80 /* same as TK_BITAND */
#define OP_Or 66 /* same as TK_OR */
#define OP_NotExists 53
#define OP_VDestroy 54
#define OP_IdxDelete 55
#define OP_Vacuum 56
#define OP_Copy 57
#define OP_If 58
#define OP_Destroy 59
#define OP_Jump 60
#define OP_AggStep 61
#define OP_Clear 62
#define OP_Insert 63
#define OP_Permutation 64
#define OP_VBegin 65
#define OP_OpenEphemeral 68
#define OP_IdxGE 69
#define OP_Trace 70
#define OP_Divide 87 /* same as TK_SLASH */
#define OP_String8 94 /* same as TK_STRING */
#define OP_Concat 89 /* same as TK_CONCAT */
#define OP_SCopy 132
#define OP_Int64 133
#define OP_VRowid 79
#define OP_MakeRecord 90
#define OP_Yield 91
#define OP_SetCookie 92
#define OP_Prev 95
#define OP_ContextPush 96
#define OP_DropTrigger 97
#define OP_And 67 /* same as TK_AND */
#define OP_VColumn 98
#define OP_Return 99
#define OP_OpenWrite 100
#define OP_Integer 101
#define OP_Transaction 102
#define OP_IfPos 103
#define OP_RowSetAdd 104
#define OP_CollSeq 105
#define OP_Savepoint 106
#define OP_VRename 107
#define OP_ToBlob 142 /* same as TK_TO_BLOB */
#define OP_Sequence 108
#define OP_ContextPop 109
#define OP_ShiftRight 83 /* same as TK_RSHIFT */
#define OP_HaltIfNull 110
#define OP_VCreate 111
#define OP_CreateTable 112
#define OP_AddImm 113
#define OP_ToText 141 /* same as TK_TO_TEXT */
#define OP_DropTable 114
#define OP_IsUnique 115
#define OP_VOpen 116
#define OP_IfZero 117
#define OP_Noop 118
#define OP_RowKey 119
#define OP_Expire 120
#define OP_Delete 121
#define OP_Subtract 85 /* same as TK_MINUS */
#define OP_Blob 122
#define OP_Move 123
#define OP_Goto 124
#define OP_ParseSchema 125
#define OP_Eq 74 /* same as TK_EQ */
#define OP_VNext 126
#define OP_Seek 127
#define OP_Le 76 /* same as TK_LE */
#define OP_TableLock 128
#define OP_VerifyCookie 129
#define OP_Column 131
#define OP_OpenRead 132
#define OP_ResetCount 133
/* The following opcode values are never used */
#define OP_NotUsed_134 134
@ -160,22 +160,22 @@
#define OPFLG_IN3 0x0010 /* in3: P3 is an input */
#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */
#define OPFLG_INITIALIZER {\
/* 0 */ 0x00, 0x02, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00,\
/* 8 */ 0x08, 0x00, 0x11, 0x00, 0x00, 0x02, 0x00, 0x11,\
/* 16 */ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,\
/* 24 */ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x11,\
/* 32 */ 0x10, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x08,\
/* 40 */ 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01,\
/* 48 */ 0x00, 0x02, 0x02, 0x04, 0x00, 0x05, 0x11, 0x01,\
/* 56 */ 0x11, 0x00, 0x04, 0x02, 0x00, 0x00, 0x05, 0x00,\
/* 64 */ 0x04, 0x10, 0x2c, 0x2c, 0x04, 0x00, 0x05, 0x05,\
/* 72 */ 0x05, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x01,\
/* 0 */ 0x00, 0x02, 0x00, 0x11, 0x00, 0x00, 0x04, 0x01,\
/* 8 */ 0x00, 0x05, 0x01, 0x11, 0x00, 0x11, 0x02, 0x02,\
/* 16 */ 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x00, 0x08,\
/* 24 */ 0x00, 0x01, 0x00, 0x11, 0x01, 0x21, 0x01, 0x05,\
/* 32 */ 0x01, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02,\
/* 40 */ 0x02, 0x11, 0x00, 0x00, 0x00, 0x02, 0x11, 0x11,\
/* 48 */ 0x0c, 0x00, 0x00, 0x04, 0x05, 0x11, 0x00, 0x00,\
/* 56 */ 0x00, 0x04, 0x05, 0x02, 0x01, 0x00, 0x00, 0x00,\
/* 64 */ 0x00, 0x00, 0x2c, 0x2c, 0x00, 0x11, 0x00, 0x05,\
/* 72 */ 0x05, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x02,\
/* 80 */ 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,\
/* 88 */ 0x2c, 0x2c, 0x02, 0x02, 0x11, 0x04, 0x02, 0x11,\
/* 96 */ 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x21, 0x00,\
/* 104 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x08,\
/* 112 */ 0x00, 0x00, 0x00, 0x05, 0x00, 0x0c, 0x01, 0x01,\
/* 120 */ 0x11, 0x05, 0x00, 0x01, 0x00, 0x00, 0x02, 0x11,\
/* 128 */ 0x02, 0x01, 0x02, 0x00, 0x04, 0x02, 0x00, 0x00,\
/* 88 */ 0x2c, 0x2c, 0x00, 0x04, 0x10, 0x04, 0x02, 0x01,\
/* 96 */ 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x05,\
/* 104 */ 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00,\
/* 112 */ 0x02, 0x04, 0x00, 0x11, 0x00, 0x05, 0x00, 0x00,\
/* 120 */ 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x08,\
/* 128 */ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\
/* 144 */ 0x04, 0x04,}

View file

@ -43,7 +43,7 @@
** * Definitions of sqlite3_vfs objects for all locking methods
** plus implementations of sqlite3_os_init() and sqlite3_os_end().
**
** $Id: os_unix.c,v 1.248 2009/03/30 07:39:35 danielk1977 Exp $
** $Id: os_unix.c,v 1.250 2009/04/07 05:35:04 chw Exp $
*/
#include "sqliteInt.h"
#if SQLITE_OS_UNIX /* This file is used on unix only */
@ -2213,8 +2213,8 @@ static int semClose(sqlite3_file *id) {
unixEnterMutex();
releaseLockInfo(pFile->pLock);
releaseOpenCnt(pFile->pOpen);
closeUnixFile(id);
unixLeaveMutex();
closeUnixFile(id);
}
return SQLITE_OK;
}
@ -3207,7 +3207,7 @@ IOMETHODS(
dotlockCheckReservedLock /* xCheckReservedLock method */
)
#if SQLITE_ENABLE_LOCKING_STYLE
#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
IOMETHODS(
flockIoFinder, /* Finder function name */
flockIoMethods, /* sqlite3_io_methods object name */
@ -3331,6 +3331,44 @@ static const sqlite3_io_methods *(*const autolockIoFinder)(const char*,int)
#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
#if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE
/*
** This "finder" function attempts to determine the best locking strategy
** for the database file "filePath". It then returns the sqlite3_io_methods
** object that implements that strategy.
**
** This is for VXWorks only.
*/
static const sqlite3_io_methods *autolockIoFinderImpl(
const char *filePath, /* name of the database file */
int fd /* file descriptor open on the database file */
){
struct flock lockInfo;
if( !filePath ){
/* If filePath==NULL that means we are dealing with a transient file
** that does not need to be locked. */
return &nolockIoMethods;
}
/* Test if fcntl() is supported and use POSIX style locks.
** Otherwise fall back to the named semaphore method.
*/
lockInfo.l_len = 1;
lockInfo.l_start = 0;
lockInfo.l_whence = SEEK_SET;
lockInfo.l_type = F_RDLCK;
if( fcntl(fd, F_GETLK, &lockInfo)!=-1 ) {
return &posixIoMethods;
}else{
return &semIoMethods;
}
}
static const sqlite3_io_methods *(*const autolockIoFinder)(const char*,int)
= autolockIoFinderImpl;
#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */
/*
** An abstract type for a pointer to a IO method finder function:
*/
@ -3613,7 +3651,7 @@ static int unixOpen(
int flags, /* Input flags to control the opening */
int *pOutFlags /* Output flags returned to SQLite core */
){
int fd = 0; /* File descriptor returned by open() */
int fd = -1; /* File descriptor returned by open() */
int dirfd = -1; /* Directory file descriptor */
int openFlags = 0; /* Flags to pass to open() */
int eType = flags&0xFFFFFF00; /* Type of file to open */
@ -3716,7 +3754,7 @@ static int unixOpen(
}
#endif
assert(fd!=0);
assert( fd>=0 );
if( isOpenDirectory ){
rc = openDirectory(zPath, &dirfd);
if( rc!=SQLITE_OK ){
@ -5061,7 +5099,7 @@ int sqlite3_os_init(void){
** array cannot be const.
*/
static sqlite3_vfs aVfs[] = {
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
#if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__))
UNIXVFS("unix", autolockIoFinder ),
#else
UNIXVFS("unix", posixIoFinder ),
@ -5073,8 +5111,10 @@ int sqlite3_os_init(void){
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
UNIXVFS("unix-posix", posixIoFinder ),
#if !OS_VXWORKS
UNIXVFS("unix-flock", flockIoFinder ),
#endif
#endif
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
UNIXVFS("unix-afp", afpIoFinder ),
UNIXVFS("unix-proxy", proxyIoFinder ),

View file

@ -12,7 +12,7 @@
**
** This file contains code that is specific to windows.
**
** $Id: os_win.c,v 1.153 2009/03/31 03:41:57 shane Exp $
** $Id: os_win.c,v 1.154 2009/04/09 14:27:07 chw Exp $
*/
#include "sqliteInt.h"
#if SQLITE_OS_WIN /* This file is used for windows only */
@ -1587,7 +1587,7 @@ static int getSectorSize(
DWORD bytesPerSector = SQLITE_DEFAULT_SECTOR_SIZE;
char zFullpath[MAX_PATH+1];
int rc;
DWORD dwRet = 0;
DWORD dwRet = 0, dwDummy;
/*
** We need to get the full path name of the file
@ -1611,10 +1611,10 @@ static int getSectorSize(
}
}
dwRet = GetDiskFreeSpaceW((WCHAR*)zConverted,
NULL,
&dwDummy,
&bytesPerSector,
NULL,
NULL);
&dwDummy,
&dwDummy);
#if SQLITE_OS_WINCE==0
}else{
int i;
@ -1628,10 +1628,10 @@ static int getSectorSize(
}
}
dwRet = GetDiskFreeSpaceA((CHAR*)zConverted,
NULL,
&dwDummy,
&bytesPerSector,
NULL,
NULL);
&dwDummy,
&dwDummy);
#endif
}
free(zConverted);

70
pager.c
View file

@ -18,7 +18,7 @@
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.576 2009/03/31 02:54:40 drh Exp $
** @(#) $Id: pager.c,v 1.580 2009/04/11 16:27:50 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
@ -2024,11 +2024,11 @@ static int pager_playback(Pager *pPager, int isHot){
pPager->journalOff = szJ;
break;
}else{
/* If we are unable to rollback, then the database is probably
** going to end up being corrupt. It is corrupt to us, anyhow.
** Perhaps the next process to come along can fix it....
/* If we are unable to rollback, quit and return the error
** code. This will cause the pager to enter the error state
** so that no further harm will be done. Perhaps the next
** process to come along will be able to rollback the database.
*/
rc = SQLITE_CORRUPT_BKPT;
goto end_playback;
}
}
@ -3114,9 +3114,9 @@ int sqlite3PagerOpen(
** source file journal.c).
*/
if( sqlite3JournalSize(pVfs)>sqlite3MemJournalSize() ){
journalFileSize = sqlite3JournalSize(pVfs);
journalFileSize = ROUND8(sqlite3JournalSize(pVfs));
}else{
journalFileSize = sqlite3MemJournalSize();
journalFileSize = ROUND8(sqlite3MemJournalSize());
}
/* Set the output variable to NULL in case an error occurs. */
@ -3172,23 +3172,25 @@ int sqlite3PagerOpen(
** Journal file name (nPathname+8+1 bytes)
*/
pPtr = (u8 *)sqlite3MallocZero(
sizeof(*pPager) + /* Pager structure */
pcacheSize + /* PCache object */
pVfs->szOsFile + /* The main db file */
journalFileSize * 2 + /* The two journal files */
nPathname + 1 + /* zFilename */
nPathname + 8 + 1 /* zJournal */
ROUND8(sizeof(*pPager)) + /* Pager structure */
ROUND8(pcacheSize) + /* PCache object */
ROUND8(pVfs->szOsFile) + /* The main db file */
journalFileSize * 2 + /* The two journal files */
nPathname + 1 + /* zFilename */
nPathname + 8 + 1 /* zJournal */
);
assert( EIGHT_BYTE_ALIGNMENT(journalFileSize) );
if( !pPtr ){
sqlite3_free(zPathname);
return SQLITE_NOMEM;
}
pPager = (Pager*)(pPtr);
pPager->pPCache = (PCache*)(pPtr += sizeof(*pPager));
pPager->fd = (sqlite3_file*)(pPtr += pcacheSize);
pPager->sjfd = (sqlite3_file*)(pPtr += pVfs->szOsFile);
pPager->pPCache = (PCache*)(pPtr += ROUND8(sizeof(*pPager)));
pPager->fd = (sqlite3_file*)(pPtr += ROUND8(pcacheSize));
pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile));
pPager->jfd = (sqlite3_file*)(pPtr += journalFileSize);
pPager->zFilename = (char*)(pPtr += journalFileSize);
assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
/* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
if( zPathname ){
@ -5074,14 +5076,11 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
assert( !pPgOld || pPgOld->nRef==1 );
if( pPgOld ){
pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
sqlite3PcacheDrop(pPgOld);
}
origPgno = pPg->pgno;
sqlite3PcacheMove(pPg, pgno);
if( pPgOld ){
sqlite3PcacheDrop(pPgOld);
}
sqlite3PcacheMakeDirty(pPg);
pPager->dbModified = 1;
@ -5186,30 +5185,33 @@ int sqlite3PagerLockingMode(Pager *pPager, int eMode){
** PAGER_JOURNALMODE_MEMORY
**
** If the parameter is not _QUERY, then the journal-mode is set to the
** value specified.
** value specified. Except, an in-memory database can only have its
** journal mode set to _OFF or _MEMORY. Attempts to change the journal
** mode of an in-memory database to something other than _OFF or _MEMORY
** are silently ignored.
**
** The returned indicate the current (possibly updated) journal-mode.
*/
int sqlite3PagerJournalMode(Pager *pPager, int eMode){
if( !MEMDB ){
assert( eMode==PAGER_JOURNALMODE_QUERY
|| eMode==PAGER_JOURNALMODE_DELETE
|| eMode==PAGER_JOURNALMODE_TRUNCATE
|| eMode==PAGER_JOURNALMODE_PERSIST
|| eMode==PAGER_JOURNALMODE_OFF
|| eMode==PAGER_JOURNALMODE_MEMORY );
assert( PAGER_JOURNALMODE_QUERY<0 );
if( eMode>=0 ){
pPager->journalMode = (u8)eMode;
}else{
assert( eMode==PAGER_JOURNALMODE_QUERY );
}
assert( eMode==PAGER_JOURNALMODE_QUERY
|| eMode==PAGER_JOURNALMODE_DELETE
|| eMode==PAGER_JOURNALMODE_TRUNCATE
|| eMode==PAGER_JOURNALMODE_PERSIST
|| eMode==PAGER_JOURNALMODE_OFF
|| eMode==PAGER_JOURNALMODE_MEMORY );
assert( PAGER_JOURNALMODE_QUERY<0 );
if( eMode>=0 && (!MEMDB || eMode==PAGER_JOURNALMODE_MEMORY
|| eMode==PAGER_JOURNALMODE_OFF) ){
pPager->journalMode = (u8)eMode;
}
return (int)pPager->journalMode;
}
/*
** Get/set the size-limit used for persistent journal files.
**
** Setting the size limit to -1 means no limit is enforced.
** An attempt to set a limit smaller than -1 is a no-op.
*/
i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){
if( iLimit>=-1 ){

1608
parse.c

File diff suppressed because it is too large Load diff

View file

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.204 2009/02/23 16:52:08 drh Exp $
** $Id: pragma.c,v 1.209 2009/04/07 22:05:43 drh Exp $
*/
#include "sqliteInt.h"
@ -144,14 +144,16 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){
/*
** Generate code to return a single integer value.
*/
static void returnSingleInt(Parse *pParse, const char *zLabel, int value){
static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){
Vdbe *v = sqlite3GetVdbe(pParse);
int mem = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, value, mem);
if( pParse->explain==0 ){
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC);
i64 *pI64 = sqlite3DbMallocRaw(pParse->db, sizeof(value));
if( pI64 ){
memcpy(pI64, &value, sizeof(value));
}
sqlite3VdbeAddOp4(v, OP_Int64, 0, mem, 0, (char*)pI64, P4_INT64);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
}
@ -369,7 +371,7 @@ void sqlite3Pragma(
** buffer that the pager module resizes using sqlite3_realloc().
*/
db->nextPagesize = atoi(zRight);
if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1) ){
if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){
db->mallocFailed = 1;
}
}
@ -531,14 +533,11 @@ void sqlite3Pragma(
Pager *pPager = sqlite3BtreePager(pDb->pBt);
i64 iLimit = -2;
if( zRight ){
int iLimit32 = atoi(zRight);
if( iLimit32<-1 ){
iLimit32 = -1;
}
iLimit = iLimit32;
sqlite3Atoi64(zRight, &iLimit);
if( iLimit<-1 ) iLimit = -1;
}
iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
returnSingleInt(pParse, "journal_size_limit", (int)iLimit);
returnSingleInt(pParse, "journal_size_limit", iLimit);
}else
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
@ -1079,7 +1078,6 @@ void sqlite3Pragma(
cnt++;
}
}
if( cnt==0 ) continue;
/* Make sure sufficient number of registers have been allocated */
if( pParse->nMem < cnt+4 ){
@ -1152,7 +1150,6 @@ void sqlite3Pragma(
{ OP_Concat, 3, 2, 2},
{ OP_ResultRow, 2, 1, 0},
};
if( pIdx->tnum==0 ) continue;
addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeJumpHere(v, addr);

View file

@ -13,7 +13,7 @@
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.114 2009/03/24 15:08:10 drh Exp $
** $Id: prepare.c,v 1.116 2009/04/02 18:32:27 drh Exp $
*/
#include "sqliteInt.h"
@ -528,11 +528,8 @@ static int sqlite3Prepare(
int rc = SQLITE_OK;
int i;
assert( ppStmt );
*ppStmt = 0;
if( sqlite3SafetyOn(db) ){
return SQLITE_MISUSE;
}
if( sqlite3SafetyOn(db) ) return SQLITE_MISUSE;
assert( ppStmt && *ppStmt==0 );
assert( !db->mallocFailed );
assert( sqlite3_mutex_held(db->mutex) );
@ -671,6 +668,8 @@ static int sqlite3LockAndPrepare(
const char **pzTail /* OUT: End of parsed string */
){
int rc;
assert( ppStmt!=0 );
*ppStmt = 0;
if( !sqlite3SafetyCheckOk(db) ){
return SQLITE_MISUSE;
}
@ -773,6 +772,8 @@ static int sqlite3Prepare16(
const char *zTail8 = 0;
int rc = SQLITE_OK;
assert( ppStmt );
*ppStmt = 0;
if( !sqlite3SafetyCheckOk(db) ){
return SQLITE_MISUSE;
}

View file

@ -5,7 +5,7 @@
** an historical reference. Most of the "enhancements" have been backed
** out so that the functionality is now the same as standard printf().
**
** $Id: printf.c,v 1.99 2008/12/10 19:26:24 drh Exp $
** $Id: printf.c,v 1.102 2009/04/08 16:10:04 drh Exp $
**
**************************************************************************
**
@ -77,6 +77,8 @@
#define etSQLESCAPE3 15 /* %w -> Strings with '\"' doubled */
#define etORDINAL 16 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
#define etINVALID 0 /* Any unrecognized conversion type */
/*
** An "etByte" is an 8-bit unsigned value.
@ -133,6 +135,9 @@ static const et_info fmtinfo[] = {
{ 'n', 0, 0, etSIZE, 0, 0 },
{ '%', 0, 0, etPERCENT, 0, 0 },
{ 'p', 16, 0, etPOINTER, 0, 1 },
/* All the rest have the FLAG_INTERN bit set and are thus for internal
** use only */
{ 'T', 0, 2, etTOKEN, 0, 0 },
{ 'S', 0, 2, etSRCLIST, 0, 0 },
{ 'r', 10, 3, etORDINAL, 0, 0 },
@ -335,7 +340,8 @@ void sqlite3VXPrintf(
flag_long = flag_longlong = 0;
}
/* Fetch the info entry for the field */
infop = 0;
infop = &fmtinfo[0];
xtype = etINVALID;
for(idx=0; idx<ArraySize(fmtinfo); idx++){
if( c==fmtinfo[idx].fmttype ){
infop = &fmtinfo[idx];
@ -348,9 +354,6 @@ void sqlite3VXPrintf(
}
}
zExtra = 0;
if( infop==0 ){
return;
}
/* Limit the precision to prevent overflowing buf[] during conversion */
@ -688,6 +691,10 @@ void sqlite3VXPrintf(
length = width = 0;
break;
}
default: {
assert( xtype==etINVALID );
return;
}
}/* End switch over the format type */
/*
** The text of the conversion is pointed to by "bufpt" and is
@ -721,13 +728,16 @@ void sqlite3VXPrintf(
** Append N bytes of text from z to the StrAccum object.
*/
void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
assert( z!=0 || N==0 );
if( p->tooBig | p->mallocFailed ){
testcase(p->tooBig);
testcase(p->mallocFailed);
return;
}
if( N<0 ){
N = sqlite3Strlen30(z);
}
if( N==0 || z==0 ){
if( N==0 || NEVER(z==0) ){
return;
}
if( p->nChar+N >= p->nAlloc ){
@ -816,12 +826,13 @@ char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
char *z;
char zBase[SQLITE_PRINT_BUF_SIZE];
StrAccum acc;
assert( db!=0 );
sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH);
db->aLimit[SQLITE_LIMIT_LENGTH]);
acc.db = db;
sqlite3VXPrintf(&acc, 1, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
if( acc.mallocFailed && db ){
if( acc.mallocFailed ){
db->mallocFailed = 1;
}
return z;

View file

@ -25,7 +25,7 @@
** Big chunks of rowid/next-ptr pairs are allocated at a time, to
** reduce the malloc overhead.
**
** $Id: rowset.c,v 1.3 2009/01/13 20:14:16 drh Exp $
** $Id: rowset.c,v 1.4 2009/04/01 19:35:55 drh Exp $
*/
#include "sqliteInt.h"
@ -120,7 +120,7 @@ void sqlite3RowSetClear(RowSet *p){
void sqlite3RowSetInsert(RowSet *p, i64 rowid){
struct RowSetEntry *pEntry;
struct RowSetEntry *pLast;
if( p==0 ) return; /* Must have been a malloc failure */
assert( p!=0 );
if( p->nFresh==0 ){
struct RowSetChunk *pNew;
pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew));

View file

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.506 2009/03/31 03:41:57 shane Exp $
** $Id: select.c,v 1.507 2009/04/02 16:59:47 drh Exp $
*/
#include "sqliteInt.h"
@ -2555,6 +2555,12 @@ static void substSelect(
** (19) The subquery does not use LIMIT or the outer query does not
** have a WHERE clause.
**
** (20) If the sub-query is a compound select, then it must not use
** an ORDER BY clause. Ticket #3773. We could relax this constraint
** somewhat by saying that the terms of the ORDER BY clause must
** appear as unmodified result columns in the outer query. But
** have other optimizations in mind to deal with that case.
**
** In this routine, the "p" parameter is a pointer to the outer query.
** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
@ -2665,6 +2671,9 @@ static int flattenSubquery(
** queries.
*/
if( pSub->pPrior ){
if( pSub->pOrderBy ){
return 0; /* Restriction 20 */
}
if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
return 0;
}

View file

@ -30,7 +30,7 @@
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
** @(#) $Id: sqlite.h.in,v 1.436 2009/03/20 13:15:30 drh Exp $
** @(#) $Id: sqlite.h.in,v 1.440 2009/04/06 15:55:04 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
@ -99,8 +99,8 @@ extern "C" {
**
** Requirements: [H10011] [H10014]
*/
#define SQLITE_VERSION "3.6.12"
#define SQLITE_VERSION_NUMBER 3006012
#define SQLITE_VERSION "3.6.13"
#define SQLITE_VERSION_NUMBER 3006013
/*
** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100>
@ -382,7 +382,6 @@ int sqlite3_exec(
#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8))
#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8) )
/*
@ -462,8 +461,9 @@ int sqlite3_exec(
**
** When the SQLITE_SYNC_DATAONLY flag is used, it means that the
** sync operation only needs to flush data to mass storage. Inode
** information need not be flushed. The SQLITE_SYNC_NORMAL flag means
** to use normal fsync() semantics. The SQLITE_SYNC_FULL flag means
** information need not be flushed. If the lower four bits of the flag
** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics.
** If the lower four bits equal SQLITE_SYNC_FULL, that means
** to use Mac OS X style fullsync instead of fsync().
*/
#define SQLITE_SYNC_NORMAL 0x00002
@ -2229,7 +2229,8 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** program using one of these routines.
**
** The first argument, "db", is a [database connection] obtained from a
** prior call to [sqlite3_open()], [sqlite3_open_v2()] or [sqlite3_open16()].
** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or
** [sqlite3_open16()]. The database connection must not have been closed.
**
** The second argument, "zSql", is the statement to be compiled, encoded
** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2()
@ -2246,17 +2247,18 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** is equal to the number of bytes in the input string <i>including</i>
** the nul-terminator bytes.
**
** *pzTail is made to point to the first byte past the end of the
** first SQL statement in zSql. These routines only compile the first
** statement in zSql, so *pzTail is left pointing to what remains
** uncompiled.
** If pzTail is not NULL then *pzTail is made to point to the first byte
** past the end of the first SQL statement in zSql. These routines only
** compile the first statement in zSql, so *pzTail is left pointing to
** what remains uncompiled.
**
** *ppStmt is left pointing to a compiled [prepared statement] that can be
** executed using [sqlite3_step()]. If there is an error, *ppStmt is set
** to NULL. If the input text contains no SQL (if the input is an empty
** string or a comment) then *ppStmt is set to NULL.
** {A13018} The calling procedure is responsible for deleting the compiled
** The calling procedure is responsible for deleting the compiled
** SQL statement using [sqlite3_finalize()] after it has finished with it.
** ppStmt may not be NULL.
**
** On success, [SQLITE_OK] is returned, otherwise an [error code] is returned.
**
@ -3630,10 +3632,24 @@ int sqlite3_sleep(int);
** is a NULL pointer, then SQLite performs a search for an appropriate
** temporary file directory.
**
** It is not safe to modify this variable once a [database connection]
** has been opened. It is intended that this variable be set once
** It is not safe to read or modify this variable in more than one
** thread at a time. It is not safe to read or modify this variable
** if a [database connection] is being used at the same time in a separate
** thread.
** It is intended that this variable be set once
** as part of process initialization and before any SQLite interface
** routines have been call and remain unchanged thereafter.
** routines have been called and that this variable remain unchanged
** thereafter.
**
** The [temp_store_directory pragma] may modify this variable and cause
** it to point to memory obtained from [sqlite3_malloc]. Furthermore,
** the [temp_store_directory pragma] always assumes that any string
** that this variable points to is held in memory obtained from
** [sqlite3_malloc] and the pragma may attempt to free that memory
** using [sqlite3_free].
** Hence, if this variable is modified directly, either it should be
** made NULL or made to point to memory obtained from [sqlite3_malloc]
** or else the use of the [temp_store_directory pragma] should be avoided.
*/
SQLITE_EXTERN char *sqlite3_temp_directory;

View file

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.848 2009/03/25 16:51:43 drh Exp $
** @(#) $Id: sqliteInt.h,v 1.854 2009/04/08 13:51:51 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@ -455,6 +455,11 @@ extern const int sqlite3one;
*/
#define ROUNDDOWN8(x) ((x)&~7)
/*
** Assert that the pointer X is aligned to an 8-byte boundary.
*/
#define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0)
/*
** An instance of the following structure is used to store the busy-handler
** callback for a given sqlite handle.
@ -831,6 +836,13 @@ struct sqlite3 {
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
/* The following variables are all protected by the STATIC_MASTER
** mutex, not by sqlite3.mutex. They are used by code in notify.c.
**
** When X.pUnlockConnection==Y, that means that X is waiting for Y to
** unlock so that it can proceed.
**
** When X.pBlockingConnection==Y, that means that something that X tried
** tried to do recently failed with an SQLITE_LOCKED error due to locks
** held by Y.
*/
sqlite3 *pBlockingConnection; /* Connection that caused SQLITE_LOCKED */
sqlite3 *pUnlockConnection; /* Connection to watch for unlock */
@ -875,7 +887,6 @@ struct sqlite3 {
#define SQLITE_RecoveryMode 0x00040000 /* Ignore schema errors */
#define SQLITE_SharedCache 0x00080000 /* Cache sharing is enabled */
#define SQLITE_Vtab 0x00100000 /* There exists a virtual table */
#define SQLITE_CommitBusy 0x00200000 /* In the process of committing */
#define SQLITE_ReverseOrder 0x00400000 /* Reverse unordered SELECTs */
@ -1441,19 +1452,18 @@ struct AggInfo {
**
** ALLOCATION NOTES:
**
** Expr structures may be stored as part of the in-memory database schema,
** for example as part of trigger, view or table definitions. In this case,
** the amount of memory consumed by complex expressions may be significant.
** For this reason, less than sizeof(Expr) bytes may be allocated for some
** Expr structs stored as part of the in-memory database schema.
** Expr objects can use a lot of memory space in database schema. To
** help reduce memory requirements, sometimes an Expr object will be
** truncated. And to reduce the number of memory allocations, sometimes
** two or more Expr objects will be stored in a single memory allocation,
** together with Expr.token and/or Expr.span strings.
**
** If the EP_Reduced flag is set in Expr.flags, then only EXPR_REDUCEDSIZE
** bytes of space are allocated for the expression structure. This is enough
** space to store all fields up to and including the "Token span;" field.
**
** If the EP_TokenOnly flag is set in Expr.flags, then only EXPR_TOKENONLYSIZE
** bytes of space are allocated for the expression structure. This is enough
** space to store all fields up to and including the "Token token;" field.
** If the EP_Reduced, EP_SpanToken, and EP_TokenOnly flags are set when
** an Expr object is truncated. When EP_Reduced is set, then all
** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees
** are contained within the same memory allocation. Note, however, that
** the subtrees in Expr.x.pList or Expr.x.pSelect are always separately
** allocated, regardless of whether or not EP_Reduced is set.
*/
struct Expr {
u8 op; /* Operation performed by this node */
@ -1469,7 +1479,7 @@ struct Expr {
Token span; /* Complete text of the expression */
/* If the EP_SpanOnly flag is set in the Expr.flags mask, then no
/* If the EP_SpanToken flag is set in the Expr.flags mask, then no
** space is allocated for the fields below this point. An attempt to
** access them will result in a segfault or malfunction.
*********************************************************************/
@ -1517,7 +1527,7 @@ struct Expr {
#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
#define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
#define EP_SpanOnly 0x8000 /* Expr struct is EXPR_SPANONLYSIZE bytes only */
#define EP_SpanToken 0x8000 /* Expr size is EXPR_SPANTOKENSIZE bytes */
/*
** The following are the meanings of bits in the Expr.vvaFlags field.
@ -1542,18 +1552,17 @@ struct Expr {
** struct, an Expr struct with the EP_Reduced flag set in Expr.flags
** and an Expr struct with the EP_TokenOnly flag set.
*/
#define EXPR_FULLSIZE sizeof(Expr)
#define EXPR_REDUCEDSIZE offsetof(Expr,iTable)
#define EXPR_TOKENONLYSIZE offsetof(Expr,span)
#define EXPR_SPANONLYSIZE offsetof(Expr,pLeft)
#define EXPR_FULLSIZE sizeof(Expr) /* Full size */
#define EXPR_REDUCEDSIZE offsetof(Expr,iTable) /* Common features */
#define EXPR_SPANTOKENSIZE offsetof(Expr,pLeft) /* Fewer features */
#define EXPR_TOKENONLYSIZE offsetof(Expr,span) /* Smallest possible */
/*
** Flags passed to the sqlite3ExprDup() function. See the header comment
** above sqlite3ExprDup() for details.
*/
#define EXPRDUP_REDUCE 0x0001
#define EXPRDUP_SPAN 0x0002
#define EXPRDUP_DISTINCTSPAN 0x0004
#define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */
#define EXPRDUP_SPAN 0x0002 /* Make a copy of Expr.span */
/*
** A list of expressions. Each expression may optionally have a
@ -2533,6 +2542,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
# define sqlite3DropTriggerPtr(A,B)
# define sqlite3UnlinkAndDeleteTrigger(A,B,C)
# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J,K,L) 0
# define sqlite3TriggerList(X, Y) 0
#endif
int sqlite3JoinType(Parse*, Token*, Token*, Token*);
@ -2564,7 +2574,7 @@ int sqlite3GetInt32(const char *, int*);
int sqlite3FitsIn64Bits(const char *, int);
int sqlite3Utf16ByteLen(const void *pData, int nChar);
int sqlite3Utf8CharLen(const char *pData, int nByte);
int sqlite3Utf8Read(const u8*, const u8*, const u8**);
int sqlite3Utf8Read(const u8*, const u8**);
/*
** Routines to read and write variable-length integers. These used to

33
table.c
View file

@ -16,7 +16,7 @@
** These routines are in a separate files so that they will not be linked
** if they are not used.
**
** $Id: table.c,v 1.39 2009/01/19 20:49:10 drh Exp $
** $Id: table.c,v 1.40 2009/04/10 14:28:00 drh Exp $
*/
#include "sqliteInt.h"
#include <stdlib.h>
@ -29,14 +29,13 @@
** to the callback function is uses to build the result.
*/
typedef struct TabResult {
char **azResult;
char *zErrMsg;
int nResult;
int nAlloc;
int nRow;
int nColumn;
int nData;
int rc;
char **azResult; /* Accumulated output */
char *zErrMsg; /* Error message text, if an error occurs */
int nAlloc; /* Slots allocated for azResult[] */
int nRow; /* Number of rows in the result */
int nColumn; /* Number of columns in the result */
int nData; /* Slots used in azResult[]. (nRow+1)*nColumn */
int rc; /* Return code from sqlite3_exec() */
} TabResult;
/*
@ -45,10 +44,10 @@ typedef struct TabResult {
** memory as necessary.
*/
static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
TabResult *p = (TabResult*)pArg;
int need;
int i;
char *z;
TabResult *p = (TabResult*)pArg; /* Result accumulator */
int need; /* Slots needed in p->azResult[] */
int i; /* Loop counter */
char *z; /* A single column of result */
/* Make sure there is enough space in p->azResult to hold everything
** we need to remember from this invocation of the callback.
@ -58,9 +57,9 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
}else{
need = nCol;
}
if( p->nData + need >= p->nAlloc ){
if( p->nData + need > p->nAlloc ){
char **azNew;
p->nAlloc = p->nAlloc*2 + need + 1;
p->nAlloc = p->nAlloc*2 + need;
azNew = sqlite3_realloc( p->azResult, sizeof(char*)*p->nAlloc );
if( azNew==0 ) goto malloc_failed;
p->azResult = azNew;
@ -134,7 +133,6 @@ int sqlite3_get_table(
if( pnRow ) *pnRow = 0;
if( pzErrMsg ) *pzErrMsg = 0;
res.zErrMsg = 0;
res.nResult = 0;
res.nRow = 0;
res.nColumn = 0;
res.nData = 1;
@ -168,13 +166,12 @@ int sqlite3_get_table(
}
if( res.nAlloc>res.nData ){
char **azNew;
azNew = sqlite3_realloc( res.azResult, sizeof(char*)*(res.nData+1) );
azNew = sqlite3_realloc( res.azResult, sizeof(char*)*res.nData );
if( azNew==0 ){
sqlite3_free_table(&res.azResult[1]);
db->errCode = SQLITE_NOMEM;
return SQLITE_NOMEM;
}
res.nAlloc = res.nData+1;
res.azResult = azNew;
}
*pazResult = &res.azResult[1];

56
utf.c
View file

@ -12,7 +12,7 @@
** This file contains routines used to translate between UTF-8,
** UTF-16, UTF-16BE, and UTF-16LE.
**
** $Id: utf.c,v 1.71 2009/03/31 03:41:57 shane Exp $
** $Id: utf.c,v 1.73 2009/04/01 18:40:32 drh Exp $
**
** Notes on UTF-8:
**
@ -110,22 +110,20 @@ static const unsigned char sqlite3Utf8Trans1[] = {
#define READ_UTF16LE(zIn, c){ \
c = (*zIn++); \
c += ((*zIn++)<<8); \
if( c>=0xD800 && c<0xE000 ){ \
if( c>=0xD800 && c<0xE000 ){ \
int c2 = (*zIn++); \
c2 += ((*zIn++)<<8); \
c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
if( (c & 0xFFFF0000)==0 ) c = 0xFFFD; \
} \
}
#define READ_UTF16BE(zIn, c){ \
c = ((*zIn++)<<8); \
c += (*zIn++); \
if( c>=0xD800 && c<0xE000 ){ \
if( c>=0xD800 && c<0xE000 ){ \
int c2 = ((*zIn++)<<8); \
c2 += (*zIn++); \
c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
if( (c & 0xFFFF0000)==0 ) c = 0xFFFD; \
} \
}
@ -168,13 +166,25 @@ static const unsigned char sqlite3Utf8Trans1[] = {
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
}
int sqlite3Utf8Read(
const unsigned char *z, /* First byte of UTF-8 character */
const unsigned char *zTerm, /* Pretend this byte is 0x00 */
const unsigned char *zIn, /* First byte of UTF-8 character */
const unsigned char **pzNext /* Write first byte past UTF-8 char here */
){
int c;
READ_UTF8(z, zTerm, c);
*pzNext = z;
/* Same as READ_UTF8() above but without the zTerm parameter.
** For this routine, we assume the UTF8 string is always zero-terminated.
*/
c = *(zIn++);
if( c>=0xc0 ){
c = sqlite3Utf8Trans1[c-0xc0];
while( (*zIn & 0xc0)==0x80 ){
c = (c<<6) + (0x3f & *(zIn++));
}
if( c<0x80
|| (c&0xFFFFF800)==0xD800
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; }
}
*pzNext = zIn;
return c;
}
@ -341,7 +351,8 @@ int sqlite3VdbeMemHandleBom(Mem *pMem){
int rc = SQLITE_OK;
u8 bom = 0;
if( pMem->n<0 || pMem->n>1 ){
assert( pMem->n>=0 );
if( pMem->n>1 ){
u8 b1 = *(u8 *)pMem->z;
u8 b2 = *(((u8 *)pMem->z) + 1);
if( b1==0xFE && b2==0xFF ){
@ -407,11 +418,10 @@ int sqlite3Utf8CharLen(const char *zIn, int nByte){
int sqlite3Utf8To8(unsigned char *zIn){
unsigned char *zOut = zIn;
unsigned char *zStart = zIn;
unsigned char *zTerm = &zIn[sqlite3Strlen30((char *)zIn)];
u32 c;
while( zIn[0] ){
c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn);
c = sqlite3Utf8Read(zIn, (const u8**)&zIn);
if( c!=0xfffd ){
WRITE_UTF8(zOut, c);
}
@ -445,15 +455,13 @@ char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte){
}
/*
** pZ is a UTF-16 encoded unicode string. If nChar is less than zero,
** return the number of bytes up to (but not including), the first pair
** of consecutive 0x00 bytes in pZ. If nChar is not less than zero,
** then return the number of bytes in the first nChar unicode characters
** in pZ (or up until the first pair of 0x00 bytes, whichever comes first).
** pZ is a UTF-16 encoded unicode string at least nChar characters long.
** Return the number of bytes in the first nChar unicode characters
** in pZ. nChar must be non-negative.
*/
int sqlite3Utf16ByteLen(const void *zIn, int nChar){
unsigned int c = 1;
char const *z = zIn;
int c;
unsigned char const *z = zIn;
int n = 0;
if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
/* Using an "if (SQLITE_UTF16NATIVE==SQLITE_UTF16BE)" construct here
@ -465,17 +473,17 @@ int sqlite3Utf16ByteLen(const void *zIn, int nChar){
** which branch will be followed. It is therefore assumed that no runtime
** penalty is paid for this "if" statement.
*/
while( c && ((nChar<0) || n<nChar) ){
while( n<nChar ){
READ_UTF16BE(z, c);
n++;
}
}else{
while( c && ((nChar<0) || n<nChar) ){
while( n<nChar ){
READ_UTF16LE(z, c);
n++;
}
}
return (int)(z-(char const *)zIn)-((c==0)?2:0);
return (int)(z-(unsigned char const *)zIn);
}
#if defined(SQLITE_TEST)
@ -488,7 +496,6 @@ void sqlite3UtfSelfTest(void){
unsigned int i, t;
unsigned char zBuf[20];
unsigned char *z;
unsigned char *zTerm;
int n;
unsigned int c;
@ -498,9 +505,8 @@ void sqlite3UtfSelfTest(void){
n = (int)(z-zBuf);
assert( n>0 && n<=4 );
z[0] = 0;
zTerm = z;
z = zBuf;
c = sqlite3Utf8Read(z, zTerm, (const u8**)&z);
c = sqlite3Utf8Read(z, (const u8**)&z);
t = i;
if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD;
if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;

View file

@ -14,7 +14,7 @@
** Most of the code in this file may be omitted by defining the
** SQLITE_OMIT_VACUUM macro.
**
** $Id: vacuum.c,v 1.86 2009/02/03 16:51:25 danielk1977 Exp $
** $Id: vacuum.c,v 1.87 2009/04/02 20:16:59 drh Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
@ -140,8 +140,8 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
}
#endif
if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes)
|| (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes))
if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes, 0)
|| (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0))
|| db->mallocFailed
){
rc = SQLITE_NOMEM;
@ -268,7 +268,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
}
if( rc==SQLITE_OK ){
rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes);
rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1);
}
end_of_vacuum:

18
vdbe.c
View file

@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.828 2009/03/23 17:11:27 danielk1977 Exp $
** $Id: vdbe.c,v 1.832 2009/04/10 12:55:17 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
@ -562,11 +562,13 @@ int sqlite3VdbeExec(
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
int nProgressOps = 0; /* Opcodes executed since progress callback. */
#endif
UnpackedRecord aTempRec[16]; /* Space to hold a transient UnpackedRecord */
/* Temporary space into which to unpack a record. */
char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
assert( db->magic==SQLITE_MAGIC_BUSY );
sqlite3BtreeMutexArrayEnter(&p->aMutex);
sqlite3VdbeMutexArrayEnter(p);
if( p->rc==SQLITE_NOMEM ){
/* This happens if a malloc() inside a call to sqlite3_column_text() or
** sqlite3_column_text16() failed. */
@ -2365,7 +2367,11 @@ case OP_MakeRecord: {
case OP_Count: { /* out2-prerelease */
i64 nEntry;
BtCursor *pCrsr = p->apCsr[pOp->p1]->pCursor;
rc = sqlite3BtreeCount(pCrsr, &nEntry);
if( pCrsr ){
rc = sqlite3BtreeCount(pCrsr, &nEntry);
}else{
nEntry = 0;
}
pOut->flags = MEM_Int;
pOut->u.i = nEntry;
break;
@ -4149,11 +4155,13 @@ case OP_IdxRowid: { /* out2-prerelease */
BtCursor *pCrsr;
VdbeCursor *pC;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
i64 rowid;
rc = sqlite3VdbeCursorMoveto(pC);
if( rc ) goto abort_due_to_error;
assert( pC->deferredMoveto==0 );
assert( pC->isTable==0 );
if( !pC->nullRow ){

5
vdbe.h
View file

@ -15,7 +15,7 @@
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
** $Id: vdbe.h,v 1.140 2009/02/19 14:39:25 danielk1977 Exp $
** $Id: vdbe.h,v 1.141 2009/04/10 00:56:29 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
@ -187,8 +187,7 @@ void sqlite3VdbeSwap(Vdbe*,Vdbe*);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
int sqlite3VdbeReleaseMemory(int);
#endif
UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,
UnpackedRecord*,int);
UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,char*,int);
void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*);
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);

View file

@ -15,7 +15,7 @@
** 6000 lines long) it was split up into several smaller files and
** this header information was factored out.
**
** $Id: vdbeInt.h,v 1.166 2009/03/18 10:33:02 danielk1977 Exp $
** $Id: vdbeInt.h,v 1.167 2009/04/10 12:55:17 danielk1977 Exp $
*/
#ifndef _VDBEINT_H_
#define _VDBEINT_H_
@ -379,6 +379,12 @@ int sqlite3VdbeCloseStatement(Vdbe *, int);
int sqlite3VdbeReleaseBuffers(Vdbe *p);
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
void sqlite3VdbeMutexArrayEnter(Vdbe *p);
#else
# define sqlite3VdbeMutexArrayEnter(p)
#endif
int sqlite3VdbeMemTranslate(Mem*, u8);
#ifdef SQLITE_DEBUG
void sqlite3VdbePrintSql(Vdbe*);

View file

@ -13,7 +13,7 @@
** This file contains code use to implement APIs that are part of the
** VDBE.
**
** $Id: vdbeapi.c,v 1.156 2009/03/25 15:43:09 danielk1977 Exp $
** $Id: vdbeapi.c,v 1.161 2009/04/10 23:11:31 drh Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
@ -443,7 +443,7 @@ static int sqlite3Step(Vdbe *p){
}
if( p->pc<=0 && p->expired ){
if( p->rc==SQLITE_OK ){
if( ALWAYS(p->rc==SQLITE_OK) ){
p->rc = SQLITE_SCHEMA;
}
rc = SQLITE_ERROR;
@ -559,7 +559,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){
sqlite3_reset(pStmt);
v->expired = 0;
}
if( rc==SQLITE_SCHEMA && v->isPrepareV2 && db->pErr ){
if( rc==SQLITE_SCHEMA && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
/* This case occurs after failing to recompile an sql statement.
** The error message from the SQL compiler has already been loaded
** into the database handle. This block copies the error message
@ -618,7 +618,7 @@ void sqlite3InvalidFunction(
const char *zName = context->pFunc->zName;
char *zErr;
UNUSED_PARAMETER2(NotUsed, NotUsed2);
zErr = sqlite3MPrintf(0,
zErr = sqlite3_mprintf(
"unable to use function %s in the requested context", zName);
sqlite3_result_error(context, zErr, -1);
sqlite3_free(zErr);
@ -764,7 +764,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
}else{
/* ((double)0) In case of SQLITE_OMIT_FLOATING_POINT... */
static const Mem nullMem = {{0}, (double)0, 0, "", 0, MEM_Null, SQLITE_NULL, 0, 0, 0 };
if( pVm && pVm->db ){
if( pVm && ALWAYS(pVm->db) ){
sqlite3_mutex_enter(pVm->db->mutex);
sqlite3Error(pVm->db, SQLITE_RANGE, 0);
}
@ -904,24 +904,23 @@ static const void *columnName(
const void *ret = 0;
Vdbe *p = (Vdbe *)pStmt;
int n;
sqlite3 *db = p->db;
if( p!=0 ){
n = sqlite3_column_count(pStmt);
if( N<n && N>=0 ){
N += useType*n;
sqlite3_mutex_enter(p->db->mutex);
ret = xFunc(&p->aColName[N]);
/* A malloc may have failed inside of the xFunc() call. If this
** is the case, clear the mallocFailed flag and return NULL.
*/
if( p->db && p->db->mallocFailed ){
p->db->mallocFailed = 0;
ret = 0;
}
sqlite3_mutex_leave(p->db->mutex);
assert( db!=0 );
n = sqlite3_column_count(pStmt);
if( N<n && N>=0 ){
N += useType*n;
sqlite3_mutex_enter(db->mutex);
assert( db->mallocFailed==0 );
ret = xFunc(&p->aColName[N]);
/* A malloc may have failed inside of the xFunc() call. If this
** is the case, clear the mallocFailed flag and return NULL.
*/
if( db->mallocFailed ){
db->mallocFailed = 0;
ret = 0;
}
sqlite3_mutex_leave(db->mutex);
}
return ret;
}
@ -1161,8 +1160,8 @@ int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
rc = sqlite3VdbeChangeEncoding(&p->aVar[i-1], ENC(p->db));
}
sqlite3_mutex_leave(p->db->mutex);
rc = sqlite3ApiExit(p->db, rc);
}
rc = sqlite3ApiExit(p->db, rc);
return rc;
}
int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
@ -1192,18 +1191,21 @@ int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
*/
static void createVarMap(Vdbe *p){
if( !p->okVar ){
int j;
Op *pOp;
sqlite3_mutex_enter(p->db->mutex);
if( !p->okVar ){
int j;
Op *pOp;
for(j=0, pOp=p->aOp; j<p->nOp; j++, pOp++){
if( pOp->opcode==OP_Variable ){
assert( pOp->p1>0 && pOp->p1<=p->nVar );
p->azVar[pOp->p1-1] = pOp->p4.z;
}
/* The race condition here is harmless. If two threads call this
** routine on the same Vdbe at the same time, they both might end
** up initializing the Vdbe.azVar[] array. That is a little extra
** work but it results in the same answer.
*/
for(j=0, pOp=p->aOp; j<p->nOp; j++, pOp++){
if( pOp->opcode==OP_Variable ){
assert( pOp->p1>0 && pOp->p1<=p->nVar );
p->azVar[pOp->p1-1] = pOp->p4.z;
}
p->okVar = 1;
}
p->okVar = 1;
sqlite3_mutex_leave(p->db->mutex);
}
}
@ -1248,36 +1250,40 @@ int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
/*
** Transfer all bindings from the first statement over to the second.
** If the two statements contain a different number of bindings, then
** an SQLITE_ERROR is returned.
*/
int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
Vdbe *pFrom = (Vdbe*)pFromStmt;
Vdbe *pTo = (Vdbe*)pToStmt;
int i, rc = SQLITE_OK;
if( (pFrom->magic!=VDBE_MAGIC_RUN && pFrom->magic!=VDBE_MAGIC_HALT)
|| (pTo->magic!=VDBE_MAGIC_RUN && pTo->magic!=VDBE_MAGIC_HALT)
|| pTo->db!=pFrom->db ){
return SQLITE_MISUSE;
}
if( pFrom->nVar!=pTo->nVar ){
return SQLITE_ERROR;
}
int i;
assert( pTo->db==pFrom->db );
assert( pTo->nVar==pFrom->nVar );
sqlite3_mutex_enter(pTo->db->mutex);
for(i=0; rc==SQLITE_OK && i<pFrom->nVar; i++){
for(i=0; i<pFrom->nVar; i++){
sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]);
}
sqlite3_mutex_leave(pTo->db->mutex);
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
return rc;
return SQLITE_OK;
}
#ifndef SQLITE_OMIT_DEPRECATED
/*
** Deprecated external interface. Internal/core SQLite code
** should call sqlite3TransferBindings.
**
** Is is misuse to call this routine with statements from different
** database connections. But as this is a deprecated interface, we
** will not bother to check for that condition.
**
** If the two statements contain a different number of bindings, then
** an SQLITE_ERROR is returned. Nothing else can go wrong, so otherwise
** SQLITE_OK is returned.
*/
int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
Vdbe *pFrom = (Vdbe*)pFromStmt;
Vdbe *pTo = (Vdbe*)pToStmt;
if( pFrom->nVar!=pTo->nVar ){
return SQLITE_ERROR;
}
return sqlite3TransferBindings(pFromStmt, pToStmt);
}
#endif

View file

@ -14,7 +14,7 @@
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
**
** $Id: vdbeaux.c,v 1.446 2009/03/25 15:43:09 danielk1977 Exp $
** $Id: vdbeaux.c,v 1.451 2009/04/10 15:42:36 shane Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
@ -1023,6 +1023,7 @@ static void allocSpace(
u8 *pEnd, /* Pointer to 1 byte past the end of *ppFrom buffer */
int *pnByte /* If allocation cannot be made, increment *pnByte */
){
assert( EIGHT_BYTE_ALIGNMENT(*ppFrom) );
if( (*(void**)pp)==0 ){
nByte = ROUND8(nByte);
if( (pEnd - *ppFrom)>=nByte ){
@ -1096,6 +1097,9 @@ void sqlite3VdbeMakeReady(
if( isExplain && nMem<10 ){
nMem = 10;
}
zCsr += (zCsr - (u8*)0)&7;
assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
if( zEnd<zCsr ) zEnd = zCsr;
do {
memset(zCsr, 0, zEnd-zCsr);
@ -1606,6 +1610,33 @@ int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
return rc;
}
/*
** If SQLite is compiled to support shared-cache mode and to be threadsafe,
** this routine obtains the mutex associated with each BtShared structure
** that may be accessed by the VM passed as an argument. In doing so it
** sets the BtShared.db member of each of the BtShared structures, ensuring
** that the correct busy-handler callback is invoked if required.
**
** If SQLite is not threadsafe but does support shared-cache mode, then
** sqlite3BtreeEnterAll() is invoked to set the BtShared.db variables
** of all of BtShared structures accessible via the database handle
** associated with the VM. Of course only a subset of these structures
** will be accessed by the VM, and we could use Vdbe.btreeMask to figure
** that subset out, but there is no advantage to doing so.
**
** If SQLite is not threadsafe and does not support shared-cache mode, this
** function is a no-op.
*/
#ifndef SQLITE_OMIT_SHARED_CACHE
void sqlite3VdbeMutexArrayEnter(Vdbe *p){
#if SQLITE_THREADSAFE
sqlite3BtreeMutexArrayEnter(&p->aMutex);
#else
sqlite3BtreeEnterAll(p->db);
#endif
}
#endif
/*
** This routine is called the when a VDBE tries to halt. If the VDBE
** has made changes and is in autocommit mode, then commit those
@ -1655,7 +1686,7 @@ int sqlite3VdbeHalt(Vdbe *p){
int isSpecialError; /* Set to true if a 'special' error */
/* Lock all btrees used by the statement */
sqlite3BtreeMutexArrayEnter(&p->aMutex);
sqlite3VdbeMutexArrayEnter(p);
/* Check for one of the special errors */
mrc = p->rc & 0xff;
@ -2316,30 +2347,40 @@ UnpackedRecord *sqlite3VdbeRecordUnpack(
KeyInfo *pKeyInfo, /* Information about the record format */
int nKey, /* Size of the binary record */
const void *pKey, /* The binary record */
UnpackedRecord *pSpace,/* Space available to hold resulting object */
char *pSpace, /* Unaligned space available to hold the object */
int szSpace /* Size of pSpace[] in bytes */
){
const unsigned char *aKey = (const unsigned char *)pKey;
UnpackedRecord *p;
int nByte, d;
UnpackedRecord *p; /* The unpacked record that we will return */
int nByte; /* Memory space needed to hold p, in bytes */
int d;
u32 idx;
u16 u; /* Unsigned loop counter */
u16 u; /* Unsigned loop counter */
u32 szHdr;
Mem *pMem;
int nOff; /* Increase pSpace by this much to 8-byte align it */
assert( sizeof(Mem)>sizeof(*p) );
nByte = sizeof(Mem)*(pKeyInfo->nField+2);
/*
** We want to shift the pointer pSpace up such that it is 8-byte aligned.
** Thus, we need to calculate a value, nOff, between 0 and 7, to shift
** it by. If pSpace is already 8-byte aligned, nOff should be zero.
*/
nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7;
pSpace += nOff;
szSpace -= nOff;
nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1);
if( nByte>szSpace ){
p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);
if( p==0 ) return 0;
p->flags = UNPACKED_NEED_FREE | UNPACKED_NEED_DESTROY;
}else{
p = pSpace;
p = (UnpackedRecord*)pSpace;
p->flags = UNPACKED_NEED_DESTROY;
}
p->pKeyInfo = pKeyInfo;
p->nField = pKeyInfo->nField + 1;
p->aMem = pMem = &((Mem*)p)[1];
p->aMem = pMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
idx = getVarint32(aKey, szHdr);
d = szHdr;
u = 0;

View file

@ -15,7 +15,7 @@
** only within the VDBE. Interface routines refer to a Mem using the
** name sqlite_value
**
** $Id: vdbemem.c,v 1.139 2009/03/29 15:12:10 drh Exp $
** $Id: vdbemem.c,v 1.140 2009/04/05 12:22:09 drh Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
@ -209,6 +209,7 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){
assert( !(fg&(MEM_Str|MEM_Blob)) );
assert( fg&(MEM_Int|MEM_Real) );
assert( (pMem->flags&MEM_RowSet)==0 );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
if( sqlite3VdbeMemGrow(pMem, nByte, 0) ){
@ -345,6 +346,7 @@ static i64 doubleToInt64(double r){
i64 sqlite3VdbeIntValue(Mem *pMem){
int flags;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
flags = pMem->flags;
if( flags & MEM_Int ){
return pMem->u.i;
@ -373,6 +375,7 @@ i64 sqlite3VdbeIntValue(Mem *pMem){
*/
double sqlite3VdbeRealValue(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
if( pMem->flags & MEM_Real ){
return pMem->r;
}else if( pMem->flags & MEM_Int ){
@ -403,6 +406,7 @@ void sqlite3VdbeIntegerAffinity(Mem *pMem){
assert( pMem->flags & MEM_Real );
assert( (pMem->flags & MEM_RowSet)==0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
pMem->u.i = doubleToInt64(pMem->r);
if( pMem->r==(double)pMem->u.i ){
@ -416,6 +420,8 @@ void sqlite3VdbeIntegerAffinity(Mem *pMem){
int sqlite3VdbeMemIntegerify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( (pMem->flags & MEM_RowSet)==0 );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
pMem->u.i = sqlite3VdbeIntValue(pMem);
MemSetTypeFlag(pMem, MEM_Int);
return SQLITE_OK;
@ -427,6 +433,8 @@ int sqlite3VdbeMemIntegerify(Mem *pMem){
*/
int sqlite3VdbeMemRealify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
pMem->r = sqlite3VdbeRealValue(pMem);
MemSetTypeFlag(pMem, MEM_Real);
return SQLITE_OK;

8
vtab.c
View file

@ -11,11 +11,16 @@
*************************************************************************
** This file contains code used to help implement virtual tables.
**
** $Id: vtab.c,v 1.84 2009/03/24 15:08:10 drh Exp $
** $Id: vtab.c,v 1.85 2009/04/11 16:27:20 drh Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"
/*
** The actual function that does the work of creating a new module.
** This function implements the sqlite3_create_module() and
** sqlite3_create_module_v2() interfaces.
*/
static int createModule(
sqlite3 *db, /* Database in which module is registered */
const char *zName, /* Name assigned to this module */
@ -97,6 +102,7 @@ void sqlite3VtabLock(sqlite3_vtab *pVtab){
** disconnect the virtual table.
*/
void sqlite3VtabUnlock(sqlite3 *db, sqlite3_vtab *pVtab){
assert( pVtab->nRef>0 );
pVtab->nRef--;
assert(db);
assert( sqlite3SafetyCheckOk(db) );

View file

@ -12,7 +12,7 @@
** This file contains routines used for walking the parser tree for
** an SQL statement.
**
** $Id: walker.c,v 1.2 2009/02/19 14:39:25 danielk1977 Exp $
** $Id: walker.c,v 1.4 2009/04/08 13:51:52 drh Exp $
*/
#include "sqliteInt.h"
#include <stdlib.h>
@ -41,8 +41,12 @@
int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
int rc;
if( pExpr==0 ) return WRC_Continue;
testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
testcase( ExprHasProperty(pExpr, EP_SpanToken) );
testcase( ExprHasProperty(pExpr, EP_Reduced) );
rc = pWalker->xExprCallback(pWalker, pExpr);
if( rc==WRC_Continue ){
if( rc==WRC_Continue
&& !ExprHasAnyProperty(pExpr,EP_TokenOnly|EP_SpanToken) ){
if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
if( ExprHasProperty(pExpr, EP_xIsSelect) ){

11
where.c
View file

@ -16,7 +16,7 @@
** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.379 2009/03/29 00:15:54 drh Exp $
** $Id: where.c,v 1.382 2009/04/07 13:48:12 drh Exp $
*/
#include "sqliteInt.h"
@ -26,7 +26,7 @@
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
int sqlite3WhereTrace = 0;
#endif
#if 0
#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
# define WHERETRACE(X) if(sqlite3WhereTrace) sqlite3DebugPrintf X
#else
# define WHERETRACE(X)
@ -1762,6 +1762,13 @@ static void bestIndex(
if( pProbe==0 &&
findTerm(pWC, iCur, -1, 0, WO_EQ|WO_IN|WO_LT|WO_LE|WO_GT|WO_GE,0)==0 &&
(pOrderBy==0 || !sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev)) ){
if( pParse->db->flags & SQLITE_ReverseOrder ){
/* For application testing, randomly reverse the output order for
** SELECT statements that omit the ORDER BY clause. This will help
** to find cases where
*/
pCost->plan.wsFlags |= WHERE_REVERSE;
}
return;
}
pCost->rCost = SQLITE_BIG_DBL;