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:
parent
cc8c5fe18a
commit
42dcba4d28
39 changed files with 2180 additions and 1711 deletions
1
Changes
1
Changes
|
@ -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
|
||||
|
|
4
attach.c
4
attach.c
|
@ -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{
|
||||
|
|
10
bitvec.c
10
bitvec.c
|
@ -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;
|
||||
|
|
99
btmutex.c
99
btmutex.c
|
@ -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
200
btree.c
|
@ -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, ¬Used);
|
||||
}
|
||||
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
41
btree.h
|
@ -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
|
||||
|
||||
|
||||
|
|
6
build.c
6
build.c
|
@ -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
6
date.c
|
@ -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
120
expr.c
|
@ -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
92
func.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
532
keywordhash.h
532
keywordhash.h
|
@ -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
5
main.c
|
@ -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;
|
||||
|
|
30
memjournal.c
30
memjournal.c
|
@ -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;
|
||||
}
|
||||
|
|
44
notify.c
44
notify.c
|
@ -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
145
opcodes.c
|
@ -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
302
opcodes.h
|
@ -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,}
|
||||
|
|
52
os_unix.c
52
os_unix.c
|
@ -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 ),
|
||||
|
|
16
os_win.c
16
os_win.c
|
@ -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
70
pager.c
|
@ -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 ){
|
||||
|
|
27
pragma.c
27
pragma.c
|
@ -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);
|
||||
|
|
13
prepare.c
13
prepare.c
|
@ -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;
|
||||
}
|
||||
|
|
27
printf.c
27
printf.c
|
@ -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;
|
||||
|
|
4
rowset.c
4
rowset.c
|
@ -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));
|
||||
|
|
11
select.c
11
select.c
|
@ -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;
|
||||
}
|
||||
|
|
46
sqlite3.h
46
sqlite3.h
|
@ -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;
|
||||
|
||||
|
|
58
sqliteInt.h
58
sqliteInt.h
|
@ -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
33
table.c
|
@ -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
56
utf.c
|
@ -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;
|
||||
|
|
8
vacuum.c
8
vacuum.c
|
@ -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
18
vdbe.c
|
@ -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
5
vdbe.h
|
@ -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*);
|
||||
|
||||
|
|
|
@ -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*);
|
||||
|
|
96
vdbeapi.c
96
vdbeapi.c
|
@ -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
|
||||
|
|
61
vdbeaux.c
61
vdbeaux.c
|
@ -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;
|
||||
|
|
10
vdbemem.c
10
vdbemem.c
|
@ -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
8
vtab.c
|
@ -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) );
|
||||
|
|
8
walker.c
8
walker.c
|
@ -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
11
where.c
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue