This commit is contained in:
vladimir%pobox.com 2005-08-20 01:23:48 +00:00
Родитель fcf4d7234a
Коммит 9e163a98f6
51 изменённых файлов: 5267 добавлений и 3777 удалений

Просмотреть файл

@ -12,10 +12,10 @@
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Oracle Corporation code.
# The Original Code is sqlite3 code.
#
# The Initial Developer of the Original Code is
# Oracle Corporation
# sqlite3
# Portions created by the Initial Developer are Copyright (C) 2004
# the Initial Developer. All Rights Reserved.
#
@ -48,8 +48,6 @@ LIBRARY_NAME = sqlite3_s
MODULE_NAME = sqlite3
FORCE_STATIC_LIB = 1
VERSION = 3.2.1
EXPORTS = sqlite3.h
CSRCS = \
@ -58,6 +56,7 @@ CSRCS = \
auth.c \
btree.c \
build.c \
callback.c \
date.c \
delete.c \
experimental.c \
@ -68,14 +67,13 @@ CSRCS = \
legacy.c \
main.c \
opcodes.c \
os_mac.c \
os_test.c \
os_unix.c \
os_win.c \
os_os2.c \
pager.c \
parse.c \
pragma.c \
prepare.c \
printf.c \
random.c \
select.c \
@ -100,9 +98,6 @@ endif
include $(topsrcdir)/config/rules.mk
sqlite3.h: sqlite.h.in
sed -e "s/--VERS--/$(VERSION)/" $(srcdir)/sqlite.h.in > sqlite3.h
sqlite-shell.$(OBJ_SUFFIX): shell.c
$(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)

Просмотреть файл

@ -12,7 +12,7 @@
** This file contains C code routines that used to generate VDBE code
** that implements the ALTER TABLE command.
**
** $Id: alter.c,v 1.2 2005-03-30 21:49:20 vladimir%pobox.com Exp $
** $Id: alter.c,v 1.3 2005-08-20 01:23:48 vladimir%pobox.com Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -538,6 +538,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
}
pNew->iDb = iDb;
pNew->addColOffset = pTab->addColOffset;
pNew->nRef = 1;
/* Begin a transaction and increment the schema cookie. */
sqlite3BeginWriteOperation(pParse, 0, iDb);

Просмотреть файл

@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.256 2005/03/29 13:17:46 drh Exp $
** $Id: btree.c,v 1.261 2005/05/24 20:19:58 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
@ -211,11 +211,11 @@
#include "os.h"
#include <assert.h>
/*
** This macro rounds values up so that if the value is an address it
** is guaranteed to be an address that is aligned to an 8-byte boundary.
/* Round up a number to the next larger multiple of 8. This is used
** to force 8-byte alignment on 64-bit architectures.
*/
#define FORCE_ALIGNMENT(X) (((X)+7)&~7)
#define ROUND8(x) ((x+7)&~7)
/* The following value is the maximum cell size assuming a maximum page
** size give above.
@ -308,7 +308,6 @@ struct Btree {
u8 autoVacuum; /* True if database supports auto-vacuum */
#endif
u16 pageSize; /* Total number of bytes on a page */
u16 psAligned; /* pageSize rounded up to a multiple of 8 */
u16 usableSize; /* Number of usable bytes on each page */
int maxLocal; /* Maximum local payload in non-LEAFDATA tables */
int minLocal; /* Minimum local payload in non-LEAFDATA tables */
@ -714,7 +713,7 @@ static void _pageIntegrity(MemPage *pPage){
used = sqliteMallocRaw( pPage->pBt->pageSize );
if( used==0 ) return;
usableSize = pPage->pBt->usableSize;
assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->psAligned] );
assert( pPage->aData==&((unsigned char*)pPage)[-pPage->pBt->pageSize] );
hdr = pPage->hdrOffset;
assert( hdr==(pPage->pgno==1 ? 100 : 0) );
assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) );
@ -1017,7 +1016,7 @@ static int initPage(
assert( pBt!=0 );
assert( pParent==0 || pParent->pBt==pBt );
assert( pPage->pgno==sqlite3pager_pagenumber(pPage->aData) );
assert( pPage->aData == &((unsigned char*)pPage)[-pBt->psAligned] );
assert( pPage->aData == &((unsigned char*)pPage)[-pBt->pageSize] );
if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){
/* The parent page should never change unless the file is corrupt */
return SQLITE_CORRUPT; /* bkpt-CORRUPT */
@ -1085,7 +1084,7 @@ static void zeroPage(MemPage *pPage, int flags){
int first;
assert( sqlite3pager_pagenumber(data)==pPage->pgno );
assert( &data[pBt->psAligned] == (unsigned char*)pPage );
assert( &data[pBt->pageSize] == (unsigned char*)pPage );
assert( sqlite3pager_iswriteable(data) );
memset(&data[hdr], 0, pBt->usableSize - hdr);
data[hdr] = flags;
@ -1114,7 +1113,7 @@ static int getPage(Btree *pBt, Pgno pgno, MemPage **ppPage){
MemPage *pPage;
rc = sqlite3pager_get(pBt->pPager, pgno, (void**)&aData);
if( rc ) return rc;
pPage = (MemPage*)&aData[pBt->psAligned];
pPage = (MemPage*)&aData[pBt->pageSize];
pPage->aData = aData;
pPage->pBt = pBt;
pPage->pgno = pgno;
@ -1153,7 +1152,7 @@ static void releasePage(MemPage *pPage){
if( pPage ){
assert( pPage->aData );
assert( pPage->pBt );
assert( &pPage->aData[pPage->pBt->psAligned]==(unsigned char*)pPage );
assert( &pPage->aData[pPage->pBt->pageSize]==(unsigned char*)pPage );
sqlite3pager_unref(pPage->aData);
}
}
@ -1164,7 +1163,9 @@ static void releasePage(MemPage *pPage){
** happens.
*/
static void pageDestructor(void *pData, int pageSize){
MemPage *pPage = (MemPage*)&((char*)pData)[FORCE_ALIGNMENT(pageSize)];
MemPage *pPage;
assert( (pageSize & 7)==0 );
pPage = (MemPage*)&((char*)pData)[pageSize];
if( pPage->pParent ){
MemPage *pParent = pPage->pParent;
pPage->pParent = 0;
@ -1182,7 +1183,9 @@ static void pageDestructor(void *pData, int pageSize){
** page to agree with the restored data.
*/
static void pageReinit(void *pData, int pageSize){
MemPage *pPage = (MemPage*)&((char*)pData)[FORCE_ALIGNMENT(pageSize)];
MemPage *pPage;
assert( (pageSize & 7)==0 );
pPage = (MemPage*)&((char*)pData)[pageSize];
if( pPage->isInit ){
pPage->isInit = 0;
initPage(pPage, pPage->pParent);
@ -1216,8 +1219,6 @@ int sqlite3BtreeOpen(
assert( sizeof(u32)==4 );
assert( sizeof(u16)==2 );
assert( sizeof(Pgno)==4 );
assert( sizeof(ptr)==sizeof(char*) );
assert( sizeof(uptr)==sizeof(ptr) );
pBt = sqliteMalloc( sizeof(*pBt) );
if( pBt==0 ){
@ -1238,7 +1239,8 @@ int sqlite3BtreeOpen(
pBt->readOnly = sqlite3pager_isreadonly(pBt->pPager);
sqlite3pager_read_fileheader(pBt->pPager, sizeof(zDbHeader), zDbHeader);
pBt->pageSize = get2byte(&zDbHeader[16]);
if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE ){
if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
|| ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
pBt->pageSize = SQLITE_DEFAULT_PAGE_SIZE;
pBt->maxEmbedFrac = 64; /* 25% */
pBt->minEmbedFrac = 32; /* 12.5% */
@ -1270,7 +1272,7 @@ int sqlite3BtreeOpen(
#endif
}
pBt->usableSize = pBt->pageSize - nReserve;
pBt->psAligned = FORCE_ALIGNMENT(pBt->pageSize);
assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */
sqlite3pager_set_pagesize(pBt->pPager, pBt->pageSize);
*ppBtree = pBt;
return SQLITE_OK;
@ -1357,9 +1359,8 @@ int sqlite3BtreeSetPageSize(Btree *pBt, int pageSize, int nReserve){
}
if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
((pageSize-1)&pageSize)==0 ){
pBt->pageSize = pageSize;
pBt->psAligned = FORCE_ALIGNMENT(pageSize);
sqlite3pager_set_pagesize(pBt->pPager, pageSize);
assert( (pageSize & 7)==0 );
pBt->pageSize = sqlite3pager_set_pagesize(pBt->pPager, pageSize);
}
pBt->usableSize = pBt->pageSize - nReserve;
return SQLITE_OK;
@ -1418,7 +1419,7 @@ int sqlite3BtreeGetAutoVacuum(Btree *pBt){
** if there is a locking protocol violation.
*/
static int lockBtree(Btree *pBt){
int rc;
int rc, pageSize;
MemPage *pPage1;
if( pBt->pPage1 ) return SQLITE_OK;
rc = getPage(pBt, 1, &pPage1);
@ -1437,12 +1438,16 @@ static int lockBtree(Btree *pBt){
if( page1[18]>1 || page1[19]>1 ){
goto page1_init_failed;
}
pBt->pageSize = get2byte(&page1[16]);
pBt->usableSize = pBt->pageSize - page1[20];
pageSize = get2byte(&page1[16]);
if( ((pageSize-1)&pageSize)!=0 ){
goto page1_init_failed;
}
assert( (pageSize & 7)==0 );
pBt->pageSize = pageSize;
pBt->usableSize = pageSize - page1[20];
if( pBt->usableSize<500 ){
goto page1_init_failed;
}
pBt->psAligned = FORCE_ALIGNMENT(pBt->pageSize);
pBt->maxEmbedFrac = page1[21];
pBt->minEmbedFrac = page1[22];
pBt->minLeafFrac = page1[23];
@ -1509,7 +1514,7 @@ static void unlockBtreeIfUnused(Btree *pBt){
if( pBt->inTrans==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){
if( pBt->pPage1->aData==0 ){
MemPage *pPage = pBt->pPage1;
pPage->aData = &((char*)pPage)[-pBt->psAligned];
pPage->aData = &((char*)pPage)[-pBt->pageSize];
pPage->pBt = pBt;
pPage->pgno = 1;
}
@ -3381,7 +3386,7 @@ static int reparentPage(Btree *pBt, Pgno pgno, MemPage *pNewParent, int idx){
assert( pBt->pPager!=0 );
aData = sqlite3pager_lookup(pBt->pPager, pgno);
if( aData ){
pThis = (MemPage*)&aData[pBt->psAligned];
pThis = (MemPage*)&aData[pBt->pageSize];
assert( pThis->aData==aData );
if( pThis->isInit ){
if( pThis->pParent!=pNewParent ){
@ -3888,15 +3893,19 @@ static int balance_nonroot(MemPage *pPage){
nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
}
/* Make nMaxCells a multiple of 2 in order to preserve 8-byte
** alignment */
nMaxCells = (nMaxCells + 1)&~1;
/*
** Allocate space for memory structures
*/
apCell = sqliteMallocRaw(
nMaxCells*sizeof(u8*) /* apCell */
+ nMaxCells*sizeof(int) /* szCell */
+ sizeof(MemPage)*NB /* aCopy */
+ pBt->psAligned*(5+NB) /* aSpace */
+ (ISAUTOVACUUM ? nMaxCells : 0) /* aFrom */
+ ROUND8(sizeof(MemPage))*NB /* aCopy */
+ pBt->pageSize*(5+NB) /* aSpace */
+ (ISAUTOVACUUM ? nMaxCells : 0) /* aFrom */
);
if( apCell==0 ){
rc = SQLITE_NOMEM;
@ -3904,13 +3913,16 @@ static int balance_nonroot(MemPage *pPage){
}
szCell = (int*)&apCell[nMaxCells];
aCopy[0] = (u8*)&szCell[nMaxCells];
assert( ((aCopy[0] - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */
for(i=1; i<NB; i++){
aCopy[i] = &aCopy[i-1][pBt->psAligned+sizeof(MemPage)];
aCopy[i] = &aCopy[i-1][pBt->pageSize+ROUND8(sizeof(MemPage))];
assert( ((aCopy[i] - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */
}
aSpace = &aCopy[NB-1][pBt->psAligned+sizeof(MemPage)];
aSpace = &aCopy[NB-1][pBt->pageSize+ROUND8(sizeof(MemPage))];
assert( ((aSpace - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
aFrom = &aSpace[5*pBt->psAligned];
aFrom = &aSpace[5*pBt->pageSize];
}
#endif
@ -3921,10 +3933,12 @@ static int balance_nonroot(MemPage *pPage){
** process of being overwritten.
*/
for(i=0; i<nOld; i++){
MemPage *p = apCopy[i] = (MemPage*)&aCopy[i][pBt->psAligned];
p->aData = &((u8*)p)[-pBt->psAligned];
memcpy(p->aData, apOld[i]->aData, pBt->psAligned + sizeof(MemPage));
p->aData = &((u8*)p)[-pBt->psAligned];
MemPage *p = apCopy[i] = (MemPage*)&aCopy[i][pBt->pageSize];
p->aData = &((u8*)p)[-pBt->pageSize];
memcpy(p->aData, apOld[i]->aData, pBt->pageSize + sizeof(MemPage));
/* The memcpy() above changes the value of p->aData so we have to
** set it again. */
p->aData = &((u8*)p)[-pBt->pageSize];
}
/*
@ -3982,7 +3996,7 @@ static int balance_nonroot(MemPage *pPage){
szCell[nCell] = sz;
pTemp = &aSpace[iSpace];
iSpace += sz;
assert( iSpace<=pBt->psAligned*5 );
assert( iSpace<=pBt->pageSize*5 );
memcpy(pTemp, apDiv[i], sz);
apCell[nCell] = pTemp+leafCorrection;
#ifndef SQLITE_OMIT_AUTOVACUUM
@ -4207,13 +4221,13 @@ static int balance_nonroot(MemPage *pPage){
pCell = &aSpace[iSpace];
fillInCell(pParent, pCell, 0, info.nKey, 0, 0, &sz);
iSpace += sz;
assert( iSpace<=pBt->psAligned*5 );
assert( iSpace<=pBt->pageSize*5 );
pTemp = 0;
}else{
pCell -= 4;
pTemp = &aSpace[iSpace];
iSpace += sz;
assert( iSpace<=pBt->psAligned*5 );
assert( iSpace<=pBt->pageSize*5 );
}
rc = insertCell(pParent, nxDiv, pCell, sz, pTemp, 4);
if( rc!=SQLITE_OK ) goto balance_cleanup;

Просмотреть файл

@ -22,7 +22,7 @@
** COMMIT
** ROLLBACK
**
** $Id: build.c,v 1.318 2005/03/29 03:10:59 danielk1977 Exp $
** $Id: build.c,v 1.326 2005/06/12 21:35:52 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -266,9 +266,10 @@ static void sqliteDeleteIndex(sqlite3 *db, Index *p){
}
/*
** Unlink the given index from its table, then remove
** the index from the index hash table and free its memory
** structures.
** For the index called zIdxName which is found in the database iDb,
** unlike that index from its Table then remove the index from
** the index hash table and free all memory structures associated
** with the index.
*/
void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){
Index *pIndex;
@ -426,6 +427,13 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
if( pTable==0 ) return;
/* Do not delete the table until the reference count reaches zero. */
pTable->nRef--;
if( pTable->nRef>0 ){
return;
}
assert( pTable->nRef==0 );
/* Delete all indices associated with this table
*/
for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
@ -496,7 +504,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
** is obtained from sqliteMalloc() and must be freed by the calling
** function.
**
** Tokens are really just pointers into the original SQL text and so
** Tokens are often just pointers into the original SQL text and so
** are not \000 terminated and are not persistent. The returned string
** is \000 terminated and is persistent.
*/
@ -598,6 +606,7 @@ int sqlite3TwoPartName(
*/
int sqlite3CheckObjectName(Parse *pParse, const char *zName){
if( !pParse->db->init.busy && pParse->nested==0
&& (pParse->db->flags & SQLITE_WriteSchema)==0
&& 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
return SQLITE_ERROR;
@ -727,6 +736,7 @@ void sqlite3StartTable(
pTable->iPKey = -1;
pTable->pIndex = 0;
pTable->iDb = iDb;
pTable->nRef = 1;
if( pParse->pNewTable ) sqlite3DeleteTable(db, pParse->pNewTable);
pParse->pNewTable = pTable;
@ -781,10 +791,10 @@ void sqlite3StartTable(
sqlite3VdbeAddOp(v, OP_CreateTable, iDb, 0);
}
sqlite3OpenMasterTable(v, iDb);
sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0);
sqlite3VdbeAddOp(v, OP_NewRowid, 0, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0);
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
sqlite3VdbeAddOp(v, OP_Insert, 0, 0);
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
}
@ -1075,154 +1085,6 @@ void sqlite3AddCollateType(Parse *pParse, const char *zType, int nType){
}
}
/*
** Locate and return an entry from the db.aCollSeq hash table. If the entry
** specified by zName and nName is not found and parameter 'create' is
** true, then create a new entry. Otherwise return NULL.
**
** Each pointer stored in the sqlite3.aCollSeq hash table contains an
** array of three CollSeq structures. The first is the collation sequence
** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be.
**
** Stored immediately after the three collation sequences is a copy of
** the collation sequence name. A pointer to this string is stored in
** each collation sequence structure.
*/
static CollSeq * findCollSeqEntry(
sqlite3 *db,
const char *zName,
int nName,
int create
){
CollSeq *pColl;
if( nName<0 ) nName = strlen(zName);
pColl = sqlite3HashFind(&db->aCollSeq, zName, nName);
if( 0==pColl && create ){
pColl = sqliteMalloc( 3*sizeof(*pColl) + nName + 1 );
if( pColl ){
CollSeq *pDel = 0;
pColl[0].zName = (char*)&pColl[3];
pColl[0].enc = SQLITE_UTF8;
pColl[1].zName = (char*)&pColl[3];
pColl[1].enc = SQLITE_UTF16LE;
pColl[2].zName = (char*)&pColl[3];
pColl[2].enc = SQLITE_UTF16BE;
memcpy(pColl[0].zName, zName, nName);
pColl[0].zName[nName] = 0;
pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl);
/* If a malloc() failure occured in sqlite3HashInsert(), it will
** return the pColl pointer to be deleted (because it wasn't added
** to the hash table).
*/
assert( !pDel || (sqlite3_malloc_failed && pDel==pColl) );
sqliteFree(pDel);
}
}
return pColl;
}
/*
** Parameter zName points to a UTF-8 encoded string nName bytes long.
** Return the CollSeq* pointer for the collation sequence named zName
** for the encoding 'enc' from the database 'db'.
**
** If the entry specified is not found and 'create' is true, then create a
** new entry. Otherwise return NULL.
*/
CollSeq *sqlite3FindCollSeq(
sqlite3 *db,
u8 enc,
const char *zName,
int nName,
int create
){
CollSeq *pColl = findCollSeqEntry(db, zName, nName, create);
assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
if( pColl ) pColl += enc-1;
return pColl;
}
/*
** Invoke the 'collation needed' callback to request a collation sequence
** in the database text encoding of name zName, length nName.
** If the collation sequence
*/
static void callCollNeeded(sqlite3 *db, const char *zName, int nName){
assert( !db->xCollNeeded || !db->xCollNeeded16 );
if( nName<0 ) nName = strlen(zName);
if( db->xCollNeeded ){
char *zExternal = sqliteStrNDup(zName, nName);
if( !zExternal ) return;
db->xCollNeeded(db->pCollNeededArg, db, (int)db->enc, zExternal);
sqliteFree(zExternal);
}
#ifndef SQLITE_OMIT_UTF16
if( db->xCollNeeded16 ){
char const *zExternal;
sqlite3_value *pTmp = sqlite3GetTransientValue(db);
sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC);
zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE);
if( !zExternal ) return;
db->xCollNeeded16(db->pCollNeededArg, db, (int)db->enc, zExternal);
}
#endif
}
/*
** This routine is called if the collation factory fails to deliver a
** collation function in the best encoding but there may be other versions
** of this collation function (for other text encodings) available. Use one
** of these instead if they exist. Avoid a UTF-8 <-> UTF-16 conversion if
** possible.
*/
static int synthCollSeq(Parse *pParse, CollSeq *pColl){
CollSeq *pColl2;
char *z = pColl->zName;
int n = strlen(z);
sqlite3 *db = pParse->db;
int i;
static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 };
for(i=0; i<3; i++){
pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, n, 0);
if( pColl2->xCmp!=0 ){
memcpy(pColl, pColl2, sizeof(CollSeq));
return SQLITE_OK;
}
}
if( pParse->nErr==0 ){
sqlite3ErrorMsg(pParse, "no such collation sequence: %.*s", n, z);
}
pParse->nErr++;
return SQLITE_ERROR;
}
/*
** This routine is called on a collation sequence before it is used to
** check that it is defined. An undefined collation sequence exists when
** a database is loaded that contains references to collation sequences
** that have not been defined by sqlite3_create_collation() etc.
**
** If required, this routine calls the 'collation needed' callback to
** request a definition of the collating sequence. If this doesn't work,
** an equivalent collating sequence that uses a text encoding different
** from the main database is substituted, if one is available.
*/
int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
if( pColl && !pColl->xCmp ){
/* No collation sequence of this type for this encoding is registered.
** Call the collation factory to see if it can supply us with one.
*/
callCollNeeded(pParse->db, pColl->zName, strlen(pColl->zName));
if( !pColl->xCmp && synthCollSeq(pParse, pColl) ){
return SQLITE_ERROR;
}
}
return SQLITE_OK;
}
/*
** Call sqlite3CheckCollSeq() for all collating sequences in an index,
** in order to verify that all the necessary collating sequences are
@ -1255,33 +1117,22 @@ int sqlite3CheckIndexCollSeq(Parse *pParse, Index *pIdx){
** pParse.
*/
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){
u8 enc = pParse->db->enc;
u8 initbusy = pParse->db->init.busy;
CollSeq *pColl = sqlite3FindCollSeq(pParse->db, enc, zName, nName, initbusy);
if( nName<0 ) nName = strlen(zName);
sqlite3 *db = pParse->db;
u8 enc = db->enc;
u8 initbusy = db->init.busy;
CollSeq *pColl = sqlite3FindCollSeq(db, enc, zName, nName, initbusy);
if( !initbusy && (!pColl || !pColl->xCmp) ){
/* No collation sequence of this type for this encoding is registered.
** Call the collation factory to see if it can supply us with one.
*/
callCollNeeded(pParse->db, zName, nName);
pColl = sqlite3FindCollSeq(pParse->db, enc, zName, nName, 0);
if( pColl && !pColl->xCmp ){
/* There may be a version of the collation sequence that requires
** translation between encodings. Search for it with synthCollSeq().
*/
if( synthCollSeq(pParse, pColl) ){
return 0;
pColl = sqlite3GetCollSeq(db, pColl, zName, nName);
if( !pColl ){
if( nName<0 ){
nName = strlen(zName);
}
sqlite3ErrorMsg(pParse, "no such collation sequence: %.*s", nName, zName);
pColl = 0;
}
}
/* If nothing has been found, write the error message into pParse */
if( !initbusy && (!pColl || !pColl->xCmp) ){
if( pParse->nErr==0 ){
sqlite3ErrorMsg(pParse, "no such collation sequence: %.*s", nName, zName);
}
pColl = 0;
}
return pColl;
}
@ -1510,7 +1361,7 @@ void sqlite3EndTable(
if( pSelect ){
zStmt = createTableStmt(p);
}else{
n = Addr(pEnd->z) - Addr(pParse->sNameToken.z) + 1;
n = pEnd->z - pParse->sNameToken.z + 1;
zStmt = sqlite3MPrintf("CREATE %s %.*s", zType2, n, pParse->sNameToken.z);
}
@ -1605,6 +1456,11 @@ void sqlite3CreateView(
DbFixer sFix;
Token *pName;
if( pParse->nVar>0 ){
sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
sqlite3SelectDelete(pSelect);
return;
}
sqlite3StartTable(pParse, pBegin, pName1, pName2, isTemp, 1);
p = pParse->pNewTable;
if( p==0 || pParse->nErr ){
@ -2152,7 +2008,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0);
sqlite3GenerateIndexKey(v, pIndex, iTab);
isUnique = pIndex->onError!=OE_None;
sqlite3VdbeAddOp(v, OP_IdxPut, iIdx, isUnique);
sqlite3VdbeAddOp(v, OP_IdxInsert, iIdx, isUnique);
if( isUnique ){
sqlite3VdbeChangeP3(v, -1, "indexed columns are not unique", P3_STATIC);
}
@ -2463,7 +2319,7 @@ void sqlite3CreateIndex(
/* A named index with an explicit CREATE INDEX statement */
zStmt = sqlite3MPrintf("CREATE%s INDEX %.*s",
onError==OE_None ? "" : " UNIQUE",
Addr(pEnd->z) - Addr(pName->z) + 1,
pEnd->z - pName->z + 1,
pName->z);
}else{
/* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
@ -2737,9 +2593,7 @@ void sqlite3SrcListDelete(SrcList *pList){
sqliteFree(pItem->zDatabase);
sqliteFree(pItem->zName);
sqliteFree(pItem->zAlias);
if( pItem->pTab && pItem->pTab->isTransient ){
sqlite3DeleteTable(0, pItem->pTab);
}
sqlite3DeleteTable(0, pItem->pTab);
sqlite3SelectDelete(pItem->pSelect);
sqlite3ExprDelete(pItem->pOn);
sqlite3IdListDelete(pItem->pUsing);
@ -2909,19 +2763,6 @@ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
}
}
#ifndef SQLITE_OMIT_UTF16
/*
** Return the transient sqlite3_value object used for encoding conversions
** during SQL compilation.
*/
sqlite3_value *sqlite3GetTransientValue(sqlite3 *db){
if( !db->pValue ){
db->pValue = sqlite3ValueNew();
}
return db->pValue;
}
#endif
/*
** Check to see if pIndex uses the collating sequence pColl. Return
** true if it does and false if it does not.

306
db/sqlite3/src/callback.c Normal file
Просмотреть файл

@ -0,0 +1,306 @@
/*
** 2005 May 23
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains functions used to access the internal hash tables
** of user defined functions and collation sequences.
**
** $Id: callback.c,v 1.1 2005-08-20 01:23:48 vladimir%pobox.com Exp $
*/
#include "sqliteInt.h"
/*
** Invoke the 'collation needed' callback to request a collation sequence
** in the database text encoding of name zName, length nName.
** If the collation sequence
*/
static void callCollNeeded(sqlite3 *db, const char *zName, int nName){
assert( !db->xCollNeeded || !db->xCollNeeded16 );
if( nName<0 ) nName = strlen(zName);
if( db->xCollNeeded ){
char *zExternal = sqliteStrNDup(zName, nName);
if( !zExternal ) return;
db->xCollNeeded(db->pCollNeededArg, db, (int)db->enc, zExternal);
sqliteFree(zExternal);
}
#ifndef SQLITE_OMIT_UTF16
if( db->xCollNeeded16 ){
char const *zExternal;
sqlite3_value *pTmp = sqlite3GetTransientValue(db);
sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC);
zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE);
if( !zExternal ) return;
db->xCollNeeded16(db->pCollNeededArg, db, (int)db->enc, zExternal);
}
#endif
}
/*
** This routine is called if the collation factory fails to deliver a
** collation function in the best encoding but there may be other versions
** of this collation function (for other text encodings) available. Use one
** of these instead if they exist. Avoid a UTF-8 <-> UTF-16 conversion if
** possible.
*/
static int synthCollSeq(sqlite3 *db, CollSeq *pColl){
CollSeq *pColl2;
char *z = pColl->zName;
int n = strlen(z);
int i;
static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 };
for(i=0; i<3; i++){
pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, n, 0);
if( pColl2->xCmp!=0 ){
memcpy(pColl, pColl2, sizeof(CollSeq));
return SQLITE_OK;
}
}
return SQLITE_ERROR;
}
/*
** This function is responsible for invoking the collation factory callback
** or substituting a collation sequence of a different encoding when the
** requested collation sequence is not available in the database native
** encoding.
**
** If it is not NULL, then pColl must point to the database native encoding
** collation sequence with name zName, length nName.
**
** The return value is either the collation sequence to be used in database
** db for collation type name zName, length nName, or NULL, if no collation
** sequence can be found.
*/
CollSeq *sqlite3GetCollSeq(
sqlite3* db,
CollSeq *pColl,
const char *zName,
int nName
){
CollSeq *p;
p = pColl;
if( !p ){
p = sqlite3FindCollSeq(db, db->enc, zName, nName, 0);
}
if( !p || !p->xCmp ){
/* No collation sequence of this type for this encoding is registered.
** Call the collation factory to see if it can supply us with one.
*/
callCollNeeded(db, zName, nName);
p = sqlite3FindCollSeq(db, db->enc, zName, nName, 0);
}
if( p && !p->xCmp && synthCollSeq(db, p) ){
p = 0;
}
assert( !p || p->xCmp );
return p;
}
/*
** This routine is called on a collation sequence before it is used to
** check that it is defined. An undefined collation sequence exists when
** a database is loaded that contains references to collation sequences
** that have not been defined by sqlite3_create_collation() etc.
**
** If required, this routine calls the 'collation needed' callback to
** request a definition of the collating sequence. If this doesn't work,
** an equivalent collating sequence that uses a text encoding different
** from the main database is substituted, if one is available.
*/
int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
if( pColl ){
const char *zName = pColl->zName;
CollSeq *p = sqlite3GetCollSeq(pParse->db, pColl, zName, -1);
if( !p ){
if( pParse->nErr==0 ){
sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
}
pParse->nErr++;
return SQLITE_ERROR;
}
}
return SQLITE_OK;
}
/*
** Locate and return an entry from the db.aCollSeq hash table. If the entry
** specified by zName and nName is not found and parameter 'create' is
** true, then create a new entry. Otherwise return NULL.
**
** Each pointer stored in the sqlite3.aCollSeq hash table contains an
** array of three CollSeq structures. The first is the collation sequence
** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be.
**
** Stored immediately after the three collation sequences is a copy of
** the collation sequence name. A pointer to this string is stored in
** each collation sequence structure.
*/
static CollSeq * findCollSeqEntry(
sqlite3 *db,
const char *zName,
int nName,
int create
){
CollSeq *pColl;
if( nName<0 ) nName = strlen(zName);
pColl = sqlite3HashFind(&db->aCollSeq, zName, nName);
if( 0==pColl && create ){
pColl = sqliteMalloc( 3*sizeof(*pColl) + nName + 1 );
if( pColl ){
CollSeq *pDel = 0;
pColl[0].zName = (char*)&pColl[3];
pColl[0].enc = SQLITE_UTF8;
pColl[1].zName = (char*)&pColl[3];
pColl[1].enc = SQLITE_UTF16LE;
pColl[2].zName = (char*)&pColl[3];
pColl[2].enc = SQLITE_UTF16BE;
memcpy(pColl[0].zName, zName, nName);
pColl[0].zName[nName] = 0;
pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl);
/* If a malloc() failure occured in sqlite3HashInsert(), it will
** return the pColl pointer to be deleted (because it wasn't added
** to the hash table).
*/
assert( !pDel || (sqlite3_malloc_failed && pDel==pColl) );
sqliteFree(pDel);
}
}
return pColl;
}
/*
** Parameter zName points to a UTF-8 encoded string nName bytes long.
** Return the CollSeq* pointer for the collation sequence named zName
** for the encoding 'enc' from the database 'db'.
**
** If the entry specified is not found and 'create' is true, then create a
** new entry. Otherwise return NULL.
*/
CollSeq *sqlite3FindCollSeq(
sqlite3 *db,
u8 enc,
const char *zName,
int nName,
int create
){
CollSeq *pColl = findCollSeqEntry(db, zName, nName, create);
assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
if( pColl ) pColl += enc-1;
return pColl;
}
/*
** Locate a user function given a name, a number of arguments and a flag
** indicating whether the function prefers UTF-16 over UTF-8. Return a
** pointer to the FuncDef structure that defines that function, or return
** NULL if the function does not exist.
**
** If the createFlag argument is true, then a new (blank) FuncDef
** structure is created and liked into the "db" structure if a
** no matching function previously existed. When createFlag is true
** and the nArg parameter is -1, then only a function that accepts
** any number of arguments will be returned.
**
** If createFlag is false and nArg is -1, then the first valid
** function found is returned. A function is valid if either xFunc
** or xStep is non-zero.
**
** If createFlag is false, then a function with the required name and
** number of arguments may be returned even if the eTextRep flag does not
** match that requested.
*/
FuncDef *sqlite3FindFunction(
sqlite3 *db, /* An open database */
const char *zName, /* Name of the function. Not null-terminated */
int nName, /* Number of characters in the name */
int nArg, /* Number of arguments. -1 means any number */
u8 enc, /* Preferred text encoding */
int createFlag /* Create new entry if true and does not otherwise exist */
){
FuncDef *p; /* Iterator variable */
FuncDef *pFirst; /* First function with this name */
FuncDef *pBest = 0; /* Best match found so far */
int bestmatch = 0;
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
if( nArg<-1 ) nArg = -1;
pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName);
for(p=pFirst; p; p=p->pNext){
/* During the search for the best function definition, bestmatch is set
** as follows to indicate the quality of the match with the definition
** pointed to by pBest:
**
** 0: pBest is NULL. No match has been found.
** 1: A variable arguments function that prefers UTF-8 when a UTF-16
** encoding is requested, or vice versa.
** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is
** requested, or vice versa.
** 3: A variable arguments function using the same text encoding.
** 4: A function with the exact number of arguments requested that
** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
** 5: A function with the exact number of arguments requested that
** prefers UTF-16LE when UTF-16BE is requested, or vice versa.
** 6: An exact match.
**
** A larger value of 'matchqual' indicates a more desirable match.
*/
if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){
int match = 1; /* Quality of this match */
if( p->nArg==nArg || nArg==-1 ){
match = 4;
}
if( enc==p->iPrefEnc ){
match += 2;
}
else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) ||
(enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){
match += 1;
}
if( match>bestmatch ){
pBest = p;
bestmatch = match;
}
}
}
/* If the createFlag parameter is true, and the seach did not reveal an
** exact match for the name, number of arguments and encoding, then add a
** new entry to the hash table and return it.
*/
if( createFlag && bestmatch<6 &&
(pBest = sqliteMalloc(sizeof(*pBest)+nName+1)) ){
pBest->nArg = nArg;
pBest->pNext = pFirst;
pBest->zName = (char*)&pBest[1];
pBest->iPrefEnc = enc;
memcpy(pBest->zName, zName, nName);
pBest->zName[nName] = 0;
if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){
sqliteFree(pBest);
return 0;
}
}
if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){
return pBest;
}
return 0;
}

Просмотреть файл

@ -1,9 +0,0 @@
#ifndef _sqlite3_config_h
#define _sqlite3_config_h
#include "prcpucfg.h"
#define SQLITE_PTR_SZ PR_BYTES_PER_WORD
#endif /* _sqlite3_config_h */

Просмотреть файл

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.102 2005/03/16 12:15:21 danielk1977 Exp $
** $Id: delete.c,v 1.106 2005/06/12 21:35:52 drh Exp $
*/
#include "sqliteInt.h"
@ -27,7 +27,11 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
struct SrcList_item *pItem;
for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
pTab = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase);
sqlite3DeleteTable(pParse->db, pItem->pTab);
pItem->pTab = pTab;
if( pTab ){
pTab->nRef++;
}
}
return pTab;
}
@ -230,12 +234,12 @@ void sqlite3DeleteFrom(
/* Begin the database scan
*/
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
if( pWInfo==0 ) goto delete_from_cleanup;
/* Remember the rowid of every item to be deleted.
*/
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
if( db->flags & SQLITE_CountRows ){
sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
@ -264,21 +268,21 @@ void sqlite3DeleteFrom(
*/
if( triggers_exist ){
addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
if( !isView ){
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
sqlite3OpenTableForReading(v, iCur, pTab);
}
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
sqlite3VdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
sqlite3VdbeAddOp(v, OP_Insert, oldIdx, 0);
if( !isView ){
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
(void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab,
-1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
addr);
addr);
}
if( !isView ){
@ -312,7 +316,7 @@ void sqlite3DeleteFrom(
}
(void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1,
oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
addr);
addr);
}
/* End of the delete loop */
@ -428,7 +432,7 @@ void sqlite3GenerateIndexKey(
int j;
Table *pTab = pIdx->pTable;
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
for(j=0; j<pIdx->nColumn; j++){
int idx = pIdx->aiColumn[j];
if( idx==pTab->iPKey ){

Просмотреть файл

@ -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.197 2005/03/21 03:53:38 danielk1977 Exp $
** $Id: expr.c,v 1.206 2005/06/12 21:35:52 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -138,7 +138,7 @@ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
*/
static int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
char aff = sqlite3ExprAffinity(pExpr2);
return (((int)sqlite3CompareAffinity(pExpr1, aff))<<8)+(jumpIfNull?1:0);
return ((int)sqlite3CompareAffinity(pExpr1, aff))+(jumpIfNull?0x100:0);
}
/*
@ -265,7 +265,7 @@ void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){
assert( pLeft->dyn==0 || pLeft->z[pLeft->n]==0 );
if( pLeft->dyn==0 && pRight->dyn==0 ){
pExpr->span.z = pLeft->z;
pExpr->span.n = pRight->n + Addr(pRight->z) - Addr(pLeft->z);
pExpr->span.n = pRight->n + (pRight->z - pLeft->z);
}else{
pExpr->span.z = 0;
}
@ -474,14 +474,15 @@ SrcList *sqlite3SrcListDup(SrcList *p){
for(i=0; i<p->nSrc; i++){
struct SrcList_item *pNewItem = &pNew->a[i];
struct SrcList_item *pOldItem = &p->a[i];
Table *pTab;
pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase);
pNewItem->zName = sqliteStrDup(pOldItem->zName);
pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias);
pNewItem->jointype = pOldItem->jointype;
pNewItem->iCursor = pOldItem->iCursor;
pNewItem->pTab = pOldItem->pTab;
if( pNewItem->pTab ){
pNewItem->pTab->isTransient = 0;
pTab = pNewItem->pTab = pOldItem->pTab;
if( pTab ){
pTab->nRef++;
}
pNewItem->pSelect = sqlite3SelectDup(pOldItem->pSelect);
pNewItem->pOn = sqlite3ExprDup(pOldItem->pOn);
@ -529,7 +530,6 @@ Select *sqlite3SelectDup(Select *p){
pNew->iLimit = -1;
pNew->iOffset = -1;
pNew->ppOpenTemp = 0;
pNew->pFetch = 0;
pNew->isResolved = p->isResolved;
pNew->isAgg = p->isAgg;
return pNew;
@ -791,7 +791,6 @@ static int lookupName(
SrcList *pSrcList = pNC->pSrcList;
ExprList *pEList = pNC->pEList;
pNC->nRef++;
/* assert( zTab==0 || pEList==0 ); */
if( pSrcList ){
for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
@ -819,6 +818,7 @@ static int lookupName(
}
for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
IdList *pUsing;
cnt++;
pExpr->iTable = pItem->iCursor;
pMatch = pItem;
@ -827,6 +827,25 @@ static int lookupName(
pExpr->iColumn = j==pTab->iPKey ? -1 : j;
pExpr->affinity = pTab->aCol[j].affinity;
pExpr->pColl = pTab->aCol[j].pColl;
if( pItem->jointype & JT_NATURAL ){
/* If this match occurred in the left table of a natural join,
** then skip the right table to avoid a duplicate match */
pItem++;
i++;
}
if( (pUsing = pItem->pUsing)!=0 ){
/* If this match occurs on a column that is in the USING clause
** of a join, skip the search of the right table of the join
** to avoid a duplicate match there. */
int k;
for(k=0; k<pUsing->nId; k++){
if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
pItem++;
i++;
break;
}
}
}
break;
}
}
@ -899,9 +918,9 @@ static int lookupName(
pExpr->op = TK_AS;
pExpr->iColumn = j;
pExpr->pLeft = sqlite3ExprDup(pEList->a[j].pExpr);
sqliteFree(zCol);
cnt = 1;
assert( zTab==0 && zDb==0 );
return 0;
goto lookupname_end_2;
}
}
}
@ -920,6 +939,9 @@ static int lookupName(
** Z is a string literal if it doesn't match any column names. In that
** case, we need to return right away and not make any changes to
** pExpr.
**
** Because no reference was made to outer contexts, the pNC->nRef
** fields are not changed in any context.
*/
if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
sqliteFree(zCol);
@ -966,62 +988,30 @@ lookupname_end:
*/
sqliteFree(zDb);
sqliteFree(zTab);
sqliteFree(zCol);
sqlite3ExprDelete(pExpr->pLeft);
pExpr->pLeft = 0;
sqlite3ExprDelete(pExpr->pRight);
pExpr->pRight = 0;
pExpr->op = TK_COLUMN;
lookupname_end_2:
sqliteFree(zCol);
if( cnt==1 ){
assert( pNC!=0 );
sqlite3AuthRead(pParse, pExpr, pNC->pSrcList);
if( pMatch && !pMatch->pSelect ){
pExpr->pTab = pMatch->pTab;
}
}
return cnt!=1;
}
/*
** pExpr is a node that defines a function of some kind. It might
** be a syntactic function like "count(x)" or it might be a function
** that implements an operator, like "a LIKE b".
**
** This routine makes *pzName point to the name of the function and
** *pnName hold the number of characters in the function name.
*/
static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){
switch( pExpr->op ){
case TK_FUNCTION: {
*pzName = pExpr->token.z;
*pnName = pExpr->token.n;
break;
}
case TK_LIKE: {
*pzName = "like";
*pnName = 4;
break;
}
case TK_GLOB: {
*pzName = "glob";
*pnName = 4;
break;
}
case TK_CTIME: {
*pzName = "current_time";
*pnName = 12;
break;
}
case TK_CDATE: {
*pzName = "current_date";
*pnName = 12;
break;
}
case TK_CTIMESTAMP: {
*pzName = "current_timestamp";
*pnName = 17;
break;
/* Increment the nRef value on all name contexts from TopNC up to
** the point where the name matched. */
for(;;){
assert( pTopNC!=0 );
pTopNC->nRef++;
if( pTopNC==pNC ) break;
pTopNC = pTopNC->pNext;
}
return 0;
} else {
return 1;
}
}
@ -1099,11 +1089,7 @@ static int nameResolverStep(void *pArg, Expr *pExpr){
/* Resolve function names
*/
case TK_CTIME:
case TK_CTIMESTAMP:
case TK_CDATE:
case TK_GLOB:
case TK_LIKE:
case TK_CONST_FUNC:
case TK_FUNCTION: {
ExprList *pList = pExpr->pList; /* The argument list */
int n = pList ? pList->nExpr : 0; /* Number of arguments */
@ -1116,7 +1102,8 @@ static int nameResolverStep(void *pArg, Expr *pExpr){
FuncDef *pDef; /* Information about the function */
int enc = pParse->db->enc; /* The database encoding */
getFunctionName(pExpr, &zId, &nId);
zId = pExpr->token.z;
nId = pExpr->token.n;
pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
if( pDef==0 ){
pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
@ -1322,8 +1309,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
/* Evaluate the expression and insert it into the temp table */
sqlite3ExprCode(pParse, pE2);
sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1);
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
sqlite3VdbeAddOp(v, OP_PutStrKey, pExpr->iTable, 0);
sqlite3VdbeAddOp(v, OP_IdxInsert, pExpr->iTable, 0);
}
}
sqlite3VdbeChangeP3(v, addr, (void *)&keyInfo, P3_KEYINFO);
@ -1395,7 +1381,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
int op;
if( v==0 ) return;
if( pExpr==0 ){
sqlite3VdbeAddOp(v, OP_String8, 0, 0); /* Empty expression evals to NULL */
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
return;
}
op = pExpr->op;
@ -1407,7 +1393,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn);
sqlite3ColumnDefault(v, pExpr->pTab, pExpr->iColumn);
}else{
sqlite3VdbeAddOp(v, OP_Recno, pExpr->iTable, 0);
sqlite3VdbeAddOp(v, OP_Rowid, pExpr->iTable, 0);
}
break;
}
@ -1423,6 +1409,10 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3VdbeDequoteP3(v, -1);
break;
}
case TK_NULL: {
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
break;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
assert( TK_BLOB==OP_HexBlob );
@ -1431,10 +1421,6 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
break;
}
#endif
case TK_NULL: {
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
break;
}
case TK_VARIABLE: {
sqlite3VdbeAddOp(v, OP_Variable, pExpr->iTable, 0);
if( pExpr->token.n>1 ){
@ -1532,11 +1518,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
break;
}
case TK_CDATE:
case TK_CTIME:
case TK_CTIMESTAMP:
case TK_GLOB:
case TK_LIKE:
case TK_CONST_FUNC:
case TK_FUNCTION: {
ExprList *pList = pExpr->pList;
int nExpr = pList ? pList->nExpr : 0;
@ -1547,7 +1529,8 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
int i;
u8 enc = pParse->db->enc;
CollSeq *pColl = 0;
getFunctionName(pExpr, &zId, &nId);
zId = pExpr->token.z;
nId = pExpr->token.n;
pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
assert( pDef!=0 );
nExpr = sqlite3ExprCodeExprList(pParse, pList);
@ -1594,7 +1577,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
addr = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+4); /* addr + 0 */
sqlite3VdbeAddOp(v, OP_Pop, 2, 0);
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
sqlite3VdbeAddOp(v, OP_Goto, 0, addr+7);
sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1); /* addr + 4 */
sqlite3VdbeAddOp(v, OP_Found, pExpr->iTable, addr+7);
@ -1664,7 +1647,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
if( pExpr->pRight ){
sqlite3ExprCode(pParse, pExpr->pRight);
}else{
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
}
sqlite3VdbeResolveLabel(v, expr_end_label);
break;
@ -2086,104 +2069,3 @@ int sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
walkExprTree(pExpr, analyzeAggregate, pNC);
return pNC->pParse->nErr - nErr;
}
/*
** Locate a user function given a name, a number of arguments and a flag
** indicating whether the function prefers UTF-16 over UTF-8. Return a
** pointer to the FuncDef structure that defines that function, or return
** NULL if the function does not exist.
**
** If the createFlag argument is true, then a new (blank) FuncDef
** structure is created and liked into the "db" structure if a
** no matching function previously existed. When createFlag is true
** and the nArg parameter is -1, then only a function that accepts
** any number of arguments will be returned.
**
** If createFlag is false and nArg is -1, then the first valid
** function found is returned. A function is valid if either xFunc
** or xStep is non-zero.
**
** If createFlag is false, then a function with the required name and
** number of arguments may be returned even if the eTextRep flag does not
** match that requested.
*/
FuncDef *sqlite3FindFunction(
sqlite3 *db, /* An open database */
const char *zName, /* Name of the function. Not null-terminated */
int nName, /* Number of characters in the name */
int nArg, /* Number of arguments. -1 means any number */
u8 enc, /* Preferred text encoding */
int createFlag /* Create new entry if true and does not otherwise exist */
){
FuncDef *p; /* Iterator variable */
FuncDef *pFirst; /* First function with this name */
FuncDef *pBest = 0; /* Best match found so far */
int bestmatch = 0;
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
if( nArg<-1 ) nArg = -1;
pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName);
for(p=pFirst; p; p=p->pNext){
/* During the search for the best function definition, bestmatch is set
** as follows to indicate the quality of the match with the definition
** pointed to by pBest:
**
** 0: pBest is NULL. No match has been found.
** 1: A variable arguments function that prefers UTF-8 when a UTF-16
** encoding is requested, or vice versa.
** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is
** requested, or vice versa.
** 3: A variable arguments function using the same text encoding.
** 4: A function with the exact number of arguments requested that
** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
** 5: A function with the exact number of arguments requested that
** prefers UTF-16LE when UTF-16BE is requested, or vice versa.
** 6: An exact match.
**
** A larger value of 'matchqual' indicates a more desirable match.
*/
if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){
int match = 1; /* Quality of this match */
if( p->nArg==nArg || nArg==-1 ){
match = 4;
}
if( enc==p->iPrefEnc ){
match += 2;
}
else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) ||
(enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){
match += 1;
}
if( match>bestmatch ){
pBest = p;
bestmatch = match;
}
}
}
/* If the createFlag parameter is true, and the seach did not reveal an
** exact match for the name, number of arguments and encoding, then add a
** new entry to the hash table and return it.
*/
if( createFlag && bestmatch<6 &&
(pBest = sqliteMalloc(sizeof(*pBest)+nName+1)) ){
pBest->nArg = nArg;
pBest->pNext = pFirst;
pBest->zName = (char*)&pBest[1];
pBest->iPrefEnc = enc;
memcpy(pBest->zName, zName, nName);
pBest->zName[nName] = 0;
if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){
sqliteFree(pBest);
return 0;
}
}
if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){
return pBest;
}
return 0;
}

Просмотреть файл

@ -16,7 +16,7 @@
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.96 2005/02/15 21:36:18 drh Exp $
** $Id: func.c,v 1.98 2005/05/24 12:01:02 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -1035,4 +1035,9 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
}
}
sqlite3RegisterDateTimeFunctions(db);
#ifdef SQLITE_SSE
{
sqlite3SseFunctions(db);
}
#endif
}

Просмотреть файл

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.138 2005/03/21 01:20:58 drh Exp $
** $Id: insert.c,v 1.139 2005/06/12 21:35:52 drh Exp $
*/
#include "sqliteInt.h"
@ -308,7 +308,7 @@ void sqlite3Insert(
sqlite3VdbeAddOp(v, OP_Column, iCur, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
sqlite3VdbeAddOp(v, OP_Ne, 28417, base+12);
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_MemStore, counterRowid, 1);
sqlite3VdbeAddOp(v, OP_Column, iCur, 1);
sqlite3VdbeAddOp(v, OP_MemStore, counterMem, 1);
@ -363,9 +363,9 @@ void sqlite3Insert(
sqlite3VdbeResolveLabel(v, iInsertBlock);
sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
sqlite3TableAffinityStr(v, pTab);
sqlite3VdbeAddOp(v, OP_NewRecno, srcTab, 0);
sqlite3VdbeAddOp(v, OP_NewRowid, srcTab, 0);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
sqlite3VdbeAddOp(v, OP_PutIntKey, srcTab, 0);
sqlite3VdbeAddOp(v, OP_Insert, srcTab, 0);
sqlite3VdbeAddOp(v, OP_Return, 0, 0);
/* The following code runs first because the GOTO at the very top
@ -547,7 +547,7 @@ void sqlite3Insert(
if( !isView ){
sqlite3TableAffinityStr(v, pTab);
}
sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);
/* Fire BEFORE or INSTEAD OF triggers */
if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_BEFORE, pTab,
@ -565,7 +565,7 @@ void sqlite3Insert(
}
/* Push the record number for the new entry onto the stack. The
** record number is a randomly generate integer created by NewRecno
** record number is a randomly generate integer created by NewRowid
** except when the table has an INTEGER PRIMARY KEY column, in which
** case the record number is the same as that column.
*/
@ -578,15 +578,15 @@ void sqlite3Insert(
}else{
sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr);
}
/* If the PRIMARY KEY expression is NULL, then use OP_NewRecno
/* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
** to generate a unique primary key value.
*/
sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp(v, OP_NewRecno, base, counterMem);
sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
}else{
sqlite3VdbeAddOp(v, OP_NewRecno, base, counterMem);
sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
if( pTab->autoInc ){
@ -603,7 +603,7 @@ void sqlite3Insert(
** Whenever this column is read, the record number will be substituted
** in its place. So will fill this column with a NULL to avoid
** taking up data space with information that will never be used. */
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
continue;
}
if( pColumn==0 ){
@ -690,11 +690,11 @@ void sqlite3Insert(
sqlite3VdbeAddOp(v, OP_MemLoad, counterRowid, 0);
sqlite3VdbeAddOp(v, OP_NotNull, -1, base+7);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp(v, OP_NewRecno, iCur, 0);
sqlite3VdbeAddOp(v, OP_NewRowid, iCur, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
sqlite3VdbeAddOp(v, OP_MemLoad, counterMem, 0);
sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0);
sqlite3VdbeAddOp(v, OP_PutIntKey, iCur, 0);
sqlite3VdbeAddOp(v, OP_Insert, iCur, 0);
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
#endif
@ -724,11 +724,11 @@ insert_cleanup:
** When this routine is called, the stack contains (from bottom to top)
** the following values:
**
** 1. The recno of the row to be updated before the update. This
** 1. The rowid of the row to be updated before the update. This
** value is omitted unless we are doing an UPDATE that involves a
** change to the record number.
**
** 2. The recno of the row after the update.
** 2. The rowid of the row after the update.
**
** 3. The data in the first column of the entry after the update.
**
@ -736,9 +736,9 @@ insert_cleanup:
**
** N. The data in the last column of the entry after the update.
**
** The old recno shown as entry (1) above is omitted unless both isUpdate
** and recnoChng are 1. isUpdate is true for UPDATEs and false for
** INSERTs and recnoChng is true if the record number is being changed.
** The old rowid shown as entry (1) above is omitted unless both isUpdate
** and rowidChng are 1. isUpdate is true for UPDATEs and false for
** INSERTs and rowidChng is true if the record number is being changed.
**
** The code generated by this routine pushes additional entries onto
** the stack which are the keys for new index entries for the new record.
@ -802,7 +802,7 @@ void sqlite3GenerateConstraintChecks(
Table *pTab, /* the table into which we are inserting */
int base, /* Index of a read/write cursor pointing at pTab */
char *aIdxUsed, /* Which indices are used. NULL means all are used */
int recnoChng, /* True if the record number will change */
int rowidChng, /* True if the record number will change */
int isUpdate, /* True for UPDATE, False for INSERT */
int overrideError, /* Override onError to this if not OE_Default */
int ignoreDest /* Jump to this label on an OE_Ignore resolution */
@ -818,7 +818,7 @@ void sqlite3GenerateConstraintChecks(
int seenReplace = 0;
int jumpInst1=0, jumpInst2;
int contAddr;
int hasTwoRecnos = (isUpdate && recnoChng);
int hasTwoRowids = (isUpdate && rowidChng);
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
@ -857,7 +857,7 @@ void sqlite3GenerateConstraintChecks(
break;
}
case OE_Ignore: {
sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0);
sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);
break;
}
@ -878,7 +878,7 @@ void sqlite3GenerateConstraintChecks(
** of the new record does not previously exist. Except, if this
** is an UPDATE and the primary key is not changing, that is OK.
*/
if( recnoChng ){
if( rowidChng ){
onError = pTab->keyConf;
if( overrideError!=OE_Default ){
onError = overrideError;
@ -908,7 +908,7 @@ void sqlite3GenerateConstraintChecks(
case OE_Replace: {
sqlite3GenerateRowIndexDelete(pParse->db, v, pTab, base, 0);
if( isUpdate ){
sqlite3VdbeAddOp(v, OP_Dup, nCol+hasTwoRecnos, 1);
sqlite3VdbeAddOp(v, OP_Dup, nCol+hasTwoRowids, 1);
sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
}
seenReplace = 1;
@ -916,7 +916,7 @@ void sqlite3GenerateConstraintChecks(
}
case OE_Ignore: {
assert( seenReplace==0 );
sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0);
sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);
break;
}
@ -967,7 +967,7 @@ void sqlite3GenerateConstraintChecks(
/* Check to see if the new index entry will be unique */
sqlite3VdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRecnos, 1);
sqlite3VdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRowids, 1);
jumpInst2 = sqlite3VdbeAddOp(v, OP_IsUnique, base+iCur+1, 0);
/* Generate code that executes if the new index entry is not unique */
@ -1004,14 +1004,14 @@ void sqlite3GenerateConstraintChecks(
}
case OE_Ignore: {
assert( seenReplace==0 );
sqlite3VdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRecnos, 0);
sqlite3VdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRowids, 0);
sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);
break;
}
case OE_Replace: {
sqlite3GenerateRowDelete(pParse->db, v, pTab, base, 0);
if( isUpdate ){
sqlite3VdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1);
sqlite3VdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRowids, 1);
sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
}
seenReplace = 1;
@ -1031,7 +1031,7 @@ void sqlite3GenerateConstraintChecks(
** This routine generates code to finish the INSERT or UPDATE operation
** that was started by a prior call to sqlite3GenerateConstraintChecks.
** The stack must contain keys for all active indices followed by data
** and the recno for the new entry. This routine creates the new
** and the rowid for the new entry. This routine creates the new
** entries in all indices and in the main table.
**
** The arguments to this routine should be the same as the first six
@ -1042,7 +1042,7 @@ void sqlite3CompleteInsertion(
Table *pTab, /* the table into which we are inserting */
int base, /* Index of a read/write cursor pointing at pTab */
char *aIdxUsed, /* Which indices are used. NULL means all are used */
int recnoChng, /* True if the record number will change */
int rowidChng, /* True if the record number will change */
int isUpdate, /* True for UPDATE, False for INSERT */
int newIdx /* Index of NEW table for triggers. -1 if none */
){
@ -1058,7 +1058,7 @@ void sqlite3CompleteInsertion(
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
for(i=nIdx-1; i>=0; i--){
if( aIdxUsed && aIdxUsed[i]==0 ) continue;
sqlite3VdbeAddOp(v, OP_IdxPut, base+i+1, 0);
sqlite3VdbeAddOp(v, OP_IdxInsert, base+i+1, 0);
}
sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
sqlite3TableAffinityStr(v, pTab);
@ -1066,7 +1066,7 @@ void sqlite3CompleteInsertion(
if( newIdx>=0 ){
sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);
}
#endif
if( pParse->nested ){
@ -1074,9 +1074,9 @@ void sqlite3CompleteInsertion(
}else{
pik_flags = (OPFLAG_NCHANGE|(isUpdate?0:OPFLAG_LASTROWID));
}
sqlite3VdbeAddOp(v, OP_PutIntKey, base, pik_flags);
sqlite3VdbeAddOp(v, OP_Insert, base, pik_flags);
if( isUpdate && recnoChng ){
if( isUpdate && rowidChng ){
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
}
}

Просмотреть файл

@ -1,83 +1,83 @@
/* Hash score: 151 */
/* Hash score: 153 */
static int keywordCode(const char *z, int n){
static const char zText[510] =
static const char zText[515] =
"ABORTABLEFTEMPORARYADDATABASELECTHENDEFAULTRANSACTIONATURALTER"
"AISEACHECKEYAFTEREFERENCESCAPELSEXCEPTRIGGEREINDEXCLUSIVEXISTS"
"TATEMENTANDEFERRABLEXPLAINITIALLYATTACHAVINGLOBEFOREIGNORENAME"
"AUTOINCREMENTBEGINNEREPLACEBETWEENOTNULLIKEBYCASCADEFERREDELETE"
"CASECOLLATECOLUMNCOMMITCONFLICTCONSTRAINTERSECTCREATECROSSCURRENT_DATE"
"CURRENT_TIMESTAMPRAGMATCHDESCDETACHDISTINCTDROPRIMARYFAILIMIT"
"FROMFULLGROUPDATEIMMEDIATEINSERTINSTEADINTOFFSETISNULLJOINORDER"
"ESTRICTOUTERIGHTROLLBACKROWHENUNIONUNIQUEUSINGVACUUMVALUESVIEW"
"HERE";
"AISEACHECKEYAFTEREFERENCESCAPELSEXCEPTRIGGEREGEXPLAINITIALLYAND"
"EFERRABLEXCLUSIVEXISTSTATEMENTATTACHAVINGLOBEFOREIGNOREINDEXAUTOINCREMENT"
"BEGINNERENAMEBETWEENOTNULLIKEBYCASCADEFERREDELETECASECOLLATECOLUMN"
"COMMITCONFLICTCONSTRAINTERSECTCREATECROSSCURRENT_DATECURRENT_TIMESTAMP"
"RAGMATCHDESCDETACHDISTINCTDROPRIMARYFAILIMITFROMFULLGROUPDATE"
"IMMEDIATEINSERTINSTEADINTOFFSETISNULLJOINORDEREPLACEOUTERESTRICT"
"RIGHTROLLBACKROWHENUNIONUNIQUEUSINGVACUUMVALUESVIEWHERE";
static const unsigned char aHash[127] = {
89, 79, 101, 88, 0, 4, 0, 0, 108, 0, 75, 0, 0,
92, 44, 0, 90, 0, 100, 103, 94, 0, 0, 10, 0, 0,
107, 0, 104, 98, 0, 11, 47, 0, 41, 0, 0, 63, 69,
0, 62, 19, 0, 0, 33, 81, 0, 102, 72, 0, 0, 30,
0, 60, 34, 0, 8, 0, 109, 38, 12, 0, 76, 40, 25,
64, 0, 0, 37, 80, 52, 36, 49, 20, 86, 0, 31, 0,
73, 26, 0, 70, 0, 0, 0, 0, 46, 65, 22, 85, 35,
67, 84, 0, 1, 0, 9, 51, 57, 18, 0, 106, 74, 96,
89, 79, 102, 88, 0, 4, 0, 0, 109, 0, 75, 0, 0,
92, 43, 0, 90, 0, 101, 104, 94, 0, 0, 10, 0, 0,
108, 0, 105, 100, 0, 28, 47, 0, 40, 0, 0, 63, 69,
0, 62, 19, 0, 0, 32, 81, 0, 103, 72, 0, 0, 34,
0, 60, 33, 0, 8, 0, 110, 37, 12, 0, 76, 39, 25,
64, 0, 0, 31, 80, 52, 30, 49, 20, 86, 0, 35, 0,
73, 26, 0, 70, 0, 0, 0, 0, 46, 65, 22, 85, 29,
67, 84, 0, 1, 0, 9, 98, 57, 18, 0, 107, 74, 96,
53, 6, 83, 0, 0, 48, 91, 0, 99, 0, 68, 0, 0,
15, 0, 110, 50, 55, 0, 2, 54, 0, 105,
15, 0, 111, 50, 55, 0, 2, 54, 0, 106,
};
static const unsigned char aNext[110] = {
static const unsigned char aNext[111] = {
0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0,
0, 0, 0, 5, 13, 0, 7, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0,
0, 16, 0, 23, 45, 0, 0, 0, 0, 28, 58, 0, 0,
0, 0, 0, 0, 0, 0, 71, 42, 0, 0, 24, 59, 21,
0, 78, 0, 66, 0, 0, 82, 29, 0, 0, 0, 0, 0,
0, 0, 39, 93, 95, 0, 0, 97, 14, 27, 77, 0, 56,
87, 0, 32, 0, 61, 0,
0, 11, 0, 0, 0, 7, 0, 5, 13, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0,
0, 16, 0, 23, 51, 0, 0, 0, 0, 44, 58, 0, 0,
0, 0, 0, 0, 0, 0, 71, 41, 0, 0, 24, 59, 21,
0, 78, 0, 66, 0, 0, 82, 45, 0, 0, 0, 0, 0,
0, 0, 38, 93, 95, 0, 0, 97, 0, 14, 27, 77, 0,
56, 87, 0, 36, 0, 61, 0,
};
static const unsigned char aLen[110] = {
static const unsigned char aLen[111] = {
5, 5, 4, 4, 9, 2, 3, 8, 2, 6, 4, 3, 7,
11, 2, 7, 5, 5, 4, 5, 3, 5, 10, 6, 4, 6,
7, 7, 5, 9, 6, 9, 3, 10, 7, 9, 3, 6, 6,
4, 6, 3, 7, 6, 6, 13, 2, 2, 5, 5, 7, 7,
7, 6, 7, 9, 3, 3, 10, 9, 6, 9, 6, 6, 4,
6, 3, 7, 6, 7, 5, 13, 2, 2, 5, 5, 6, 7,
3, 7, 4, 4, 2, 7, 3, 8, 6, 4, 7, 6, 6,
8, 10, 9, 6, 5, 12, 12, 17, 6, 5, 4, 6, 8,
2, 4, 7, 4, 5, 4, 4, 5, 6, 9, 6, 7, 4,
2, 6, 3, 6, 4, 5, 8, 5, 5, 8, 3, 4, 5,
6, 5, 6, 6, 4, 5,
2, 6, 3, 6, 4, 5, 7, 5, 8, 5, 8, 3, 4,
5, 6, 5, 6, 6, 4, 5,
};
static const unsigned short int aOffset[110] = {
static const unsigned short int aOffset[111] = {
0, 4, 7, 10, 10, 14, 19, 21, 26, 27, 32, 34, 36,
42, 51, 52, 57, 61, 65, 67, 71, 74, 78, 86, 91, 94,
99, 105, 107, 110, 118, 123, 132, 134, 143, 148, 153, 157, 162,
167, 170, 172, 172, 176, 180, 186, 188, 190, 199, 202, 206, 213,
219, 219, 222, 225, 229, 231, 232, 236, 243, 249, 253, 260, 266,
272, 280, 287, 296, 302, 307, 319, 319, 335, 339, 344, 348, 354,
355, 362, 365, 372, 375, 380, 384, 388, 391, 397, 406, 412, 419,
422, 422, 425, 428, 434, 438, 442, 450, 454, 459, 467, 469, 473,
478, 484, 489, 495, 501, 504,
99, 105, 108, 113, 118, 122, 124, 133, 141, 146, 155, 160, 165,
168, 170, 170, 174, 178, 180, 185, 187, 189, 198, 201, 205, 211,
217, 217, 220, 223, 227, 229, 230, 234, 241, 247, 251, 258, 264,
270, 278, 285, 294, 300, 305, 317, 317, 333, 337, 342, 346, 352,
353, 360, 363, 370, 373, 378, 382, 386, 389, 395, 404, 410, 417,
420, 420, 423, 426, 432, 436, 440, 447, 451, 459, 464, 472, 474,
478, 483, 489, 494, 500, 506, 509,
};
static const unsigned char aCode[110] = {
static const unsigned char aCode[111] = {
TK_ABORT, TK_TABLE, TK_JOIN_KW, TK_TEMP, TK_TEMP,
TK_OR, TK_ADD, TK_DATABASE, TK_AS, TK_SELECT,
TK_THEN, TK_END, TK_DEFAULT, TK_TRANSACTION,TK_ON,
TK_JOIN_KW, TK_ALTER, TK_RAISE, TK_EACH, TK_CHECK,
TK_KEY, TK_AFTER, TK_REFERENCES, TK_ESCAPE, TK_ELSE,
TK_EXCEPT, TK_TRIGGER, TK_REINDEX, TK_INDEX, TK_EXCLUSIVE,
TK_EXISTS, TK_STATEMENT, TK_AND, TK_DEFERRABLE, TK_EXPLAIN,
TK_INITIALLY, TK_ALL, TK_ATTACH, TK_HAVING, TK_GLOB,
TK_BEFORE, TK_FOR, TK_FOREIGN, TK_IGNORE, TK_RENAME,
TK_EXCEPT, TK_TRIGGER, TK_LIKE_KW, TK_EXPLAIN, TK_INITIALLY,
TK_ALL, TK_AND, TK_DEFERRABLE, TK_EXCLUSIVE, TK_EXISTS,
TK_STATEMENT, TK_ATTACH, TK_HAVING, TK_LIKE_KW, TK_BEFORE,
TK_FOR, TK_FOREIGN, TK_IGNORE, TK_REINDEX, TK_INDEX,
TK_AUTOINCR, TK_TO, TK_IN, TK_BEGIN, TK_JOIN_KW,
TK_REPLACE, TK_BETWEEN, TK_NOT, TK_NOTNULL, TK_NULL,
TK_LIKE, TK_BY, TK_CASCADE, TK_ASC, TK_DEFERRED,
TK_RENAME, TK_BETWEEN, TK_NOT, TK_NOTNULL, TK_NULL,
TK_LIKE_KW, TK_BY, TK_CASCADE, TK_ASC, TK_DEFERRED,
TK_DELETE, TK_CASE, TK_COLLATE, TK_COLUMNKW, TK_COMMIT,
TK_CONFLICT, TK_CONSTRAINT, TK_INTERSECT, TK_CREATE, TK_JOIN_KW,
TK_CDATE, TK_CTIME, TK_CTIMESTAMP, TK_PRAGMA, TK_MATCH,
TK_CTIME_KW, TK_CTIME_KW, TK_CTIME_KW, TK_PRAGMA, TK_MATCH,
TK_DESC, TK_DETACH, TK_DISTINCT, TK_IS, TK_DROP,
TK_PRIMARY, TK_FAIL, TK_LIMIT, TK_FROM, TK_JOIN_KW,
TK_GROUP, TK_UPDATE, TK_IMMEDIATE, TK_INSERT, TK_INSTEAD,
TK_INTO, TK_OF, TK_OFFSET, TK_SET, TK_ISNULL,
TK_JOIN, TK_ORDER, TK_RESTRICT, TK_JOIN_KW, TK_JOIN_KW,
TK_ROLLBACK, TK_ROW, TK_WHEN, TK_UNION, TK_UNIQUE,
TK_USING, TK_VACUUM, TK_VALUES, TK_VIEW, TK_WHERE,
TK_JOIN, TK_ORDER, TK_REPLACE, TK_JOIN_KW, TK_RESTRICT,
TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_WHEN, TK_UNION,
TK_UNIQUE, TK_USING, TK_VACUUM, TK_VALUES, TK_VIEW,
TK_WHERE,
};
int h, i;
if( n<2 ) return TK_ID;

Просмотреть файл

@ -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.284 2005/03/29 03:10:59 danielk1977 Exp $
** $Id: main.c,v 1.293 2005/05/26 16:23:34 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -35,366 +35,19 @@ const int sqlite3one = 1;
static sqlite3 *pDbList = 0;
#endif
/*
** Fill the InitData structure with an error message that indicates
** that the database is corrupt.
#ifndef SQLITE_OMIT_UTF16
/*
** Return the transient sqlite3_value object used for encoding conversions
** during SQL compilation.
*/
static void corruptSchema(InitData *pData, const char *zExtra){
if( !sqlite3_malloc_failed ){
sqlite3SetString(pData->pzErrMsg, "malformed database schema",
zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);
sqlite3_value *sqlite3GetTransientValue(sqlite3 *db){
if( !db->pValue ){
db->pValue = sqlite3ValueNew();
}
return db->pValue;
}
/*
** This is the callback routine for the code that initializes the
** database. See sqlite3Init() below for additional information.
** This routine is also called from the OP_ParseSchema opcode of the VDBE.
**
** Each callback contains the following information:
**
** argv[0] = name of thing being created
** argv[1] = root page number for table or index. NULL for trigger or view.
** argv[2] = SQL text for the CREATE statement.
** argv[3] = "1" for temporary files, "0" for main database, "2" or more
** for auxiliary database files.
**
*/
int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){
InitData *pData = (InitData*)pInit;
sqlite3 *db = pData->db;
int iDb;
assert( argc==4 );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[1]==0 || argv[3]==0 ){
corruptSchema(pData, 0);
return 1;
}
iDb = atoi(argv[3]);
assert( iDb>=0 && iDb<db->nDb );
if( argv[2] && argv[2][0] ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
** But because db->init.busy is set to 1, no VDBE code is generated
** or executed. All the parser does is build the internal data
** structures that describe the table, index, or view.
*/
char *zErr;
int rc;
assert( db->init.busy );
db->init.iDb = iDb;
db->init.newTnum = atoi(argv[1]);
rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
db->init.iDb = 0;
if( SQLITE_OK!=rc ){
corruptSchema(pData, zErr);
sqlite3_free(zErr);
return rc;
}
}else{
/* If the SQL column is blank it means this is an index that
** was created to be the PRIMARY KEY or to fulfill a UNIQUE
** constraint for a CREATE TABLE. The index should have already
** been created when we processed the CREATE TABLE. All we have
** to do here is record the root page number for that index.
*/
Index *pIndex;
pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName);
if( pIndex==0 || pIndex->tnum!=0 ){
/* This can occur if there exists an index on a TEMP table which
** has the same name as another index on a permanent index. Since
** the permanent table is hidden by the TEMP table, we can also
** safely ignore the index on the permanent table.
*/
/* Do Nothing */;
}else{
pIndex->tnum = atoi(argv[1]);
}
}
return 0;
}
/*
** Attempt to read the database schema and initialize internal
** data structures for a single database file. The index of the
** database file is given by iDb. iDb==0 is used for the main
** database. iDb==1 should never be used. iDb>=2 is used for
** auxiliary databases. Return one of the SQLITE_ error codes to
** indicate success or failure.
*/
static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
int rc;
BtCursor *curMain;
int size;
Table *pTab;
char const *azArg[5];
char zDbNum[30];
int meta[10];
InitData initData;
char const *zMasterSchema;
char const *zMasterName = SCHEMA_TABLE(iDb);
/*
** The master database table has a structure like this
*/
static const char master_schema[] =
"CREATE TABLE sqlite_master(\n"
" type text,\n"
" name text,\n"
" tbl_name text,\n"
" rootpage integer,\n"
" sql text\n"
")"
;
#ifndef SQLITE_OMIT_TEMPDB
static const char temp_master_schema[] =
"CREATE TEMP TABLE sqlite_temp_master(\n"
" type text,\n"
" name text,\n"
" tbl_name text,\n"
" rootpage integer,\n"
" sql text\n"
")"
;
#else
#define temp_master_schema 0
#endif
assert( iDb>=0 && iDb<db->nDb );
/* zMasterSchema and zInitScript are set to point at the master schema
** and initialisation script appropriate for the database being
** initialised. zMasterName is the name of the master table.
*/
if( !OMIT_TEMPDB && iDb==1 ){
zMasterSchema = temp_master_schema;
}else{
zMasterSchema = master_schema;
}
zMasterName = SCHEMA_TABLE(iDb);
/* Construct the schema tables. */
sqlite3SafetyOff(db);
azArg[0] = zMasterName;
azArg[1] = "1";
azArg[2] = zMasterSchema;
sprintf(zDbNum, "%d", iDb);
azArg[3] = zDbNum;
azArg[4] = 0;
initData.db = db;
initData.pzErrMsg = pzErrMsg;
rc = sqlite3InitCallback(&initData, 4, (char **)azArg, 0);
if( rc!=SQLITE_OK ){
sqlite3SafetyOn(db);
return rc;
}
pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
if( pTab ){
pTab->readOnly = 1;
}
sqlite3SafetyOn(db);
/* Create a cursor to hold the database open
*/
if( db->aDb[iDb].pBt==0 ){
if( !OMIT_TEMPDB && iDb==1 ) DbSetProperty(db, 1, DB_SchemaLoaded);
return SQLITE_OK;
}
rc = sqlite3BtreeCursor(db->aDb[iDb].pBt, MASTER_ROOT, 0, 0, 0, &curMain);
if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){
sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
return rc;
}
/* Get the database meta information.
**
** Meta values are as follows:
** meta[0] Schema cookie. Changes with each schema change.
** meta[1] File format of schema layer.
** meta[2] Size of the page cache.
** meta[3] Use freelist if 0. Autovacuum if greater than zero.
** meta[4] Db text encoding. 1:UTF-8 3:UTF-16 LE 4:UTF-16 BE
** meta[5] The user cookie. Used by the application.
** meta[6]
** meta[7]
** meta[8]
** meta[9]
**
** Note: The hash defined SQLITE_UTF* symbols in sqliteInt.h correspond to
** the possible values of meta[4].
*/
if( rc==SQLITE_OK ){
int i;
for(i=0; rc==SQLITE_OK && i<sizeof(meta)/sizeof(meta[0]); i++){
rc = sqlite3BtreeGetMeta(db->aDb[iDb].pBt, i+1, (u32 *)&meta[i]);
}
if( rc ){
sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
sqlite3BtreeCloseCursor(curMain);
return rc;
}
}else{
memset(meta, 0, sizeof(meta));
}
db->aDb[iDb].schema_cookie = meta[0];
/* If opening a non-empty database, check the text encoding. For the
** main database, set sqlite3.enc to the encoding of the main database.
** For an attached db, it is an error if the encoding is not the same
** as sqlite3.enc.
*/
if( meta[4] ){ /* text encoding */
if( iDb==0 ){
/* If opening the main database, set db->enc. */
db->enc = (u8)meta[4];
db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0);
}else{
/* If opening an attached database, the encoding much match db->enc */
if( meta[4]!=db->enc ){
sqlite3BtreeCloseCursor(curMain);
sqlite3SetString(pzErrMsg, "attached databases must use the same"
" text encoding as main database", (char*)0);
return SQLITE_ERROR;
}
}
}
size = meta[2];
if( size==0 ){ size = MAX_PAGES; }
db->aDb[iDb].cache_size = size;
if( iDb==0 ){
db->file_format = meta[1];
if( db->file_format==0 ){
/* This happens if the database was initially empty */
db->file_format = 1;
}
if( db->file_format==2 || db->file_format==3 ){
/* File format 2 is treated exactly as file format 1. New
** databases are created with file format 1.
*/
db->file_format = 1;
}
}
/*
** file_format==1 Version 3.0.0.
** file_format==2 Version 3.1.3.
** file_format==3 Version 3.1.4.
**
** Version 3.0 can only use files with file_format==1. Version 3.1.3
** can read and write files with file_format==1 or file_format==2.
** Version 3.1.4 can read and write file formats 1, 2 and 3.
*/
if( meta[1]>3 ){
sqlite3BtreeCloseCursor(curMain);
sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0);
return SQLITE_ERROR;
}
sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->aDb[iDb].cache_size);
/* Read the schema information out of the schema tables
*/
assert( db->init.busy );
if( rc==SQLITE_EMPTY ){
/* For an empty database, there is nothing to read */
rc = SQLITE_OK;
}else{
char *zSql;
zSql = sqlite3MPrintf(
"SELECT name, rootpage, sql, '%s' FROM '%q'.%s",
zDbNum, db->aDb[iDb].zName, zMasterName);
sqlite3SafetyOff(db);
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
sqlite3SafetyOn(db);
sqliteFree(zSql);
sqlite3BtreeCloseCursor(curMain);
}
if( sqlite3_malloc_failed ){
sqlite3SetString(pzErrMsg, "out of memory", (char*)0);
rc = SQLITE_NOMEM;
sqlite3ResetInternalSchema(db, 0);
}
if( rc==SQLITE_OK ){
DbSetProperty(db, iDb, DB_SchemaLoaded);
}else{
sqlite3ResetInternalSchema(db, iDb);
}
return rc;
}
/*
** Initialize all database files - the main database file, the file
** used to store temporary tables, and any additional database files
** created using ATTACH statements. Return a success code. If an
** error occurs, write an error message into *pzErrMsg.
**
** After the database is initialized, the SQLITE_Initialized
** bit is set in the flags field of the sqlite structure.
*/
int sqlite3Init(sqlite3 *db, char **pzErrMsg){
int i, rc;
if( db->init.busy ) return SQLITE_OK;
assert( (db->flags & SQLITE_Initialized)==0 );
rc = SQLITE_OK;
db->init.busy = 1;
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
rc = sqlite3InitOne(db, i, pzErrMsg);
if( rc ){
sqlite3ResetInternalSchema(db, i);
}
}
/* Once all the other databases have been initialised, load the schema
** for the TEMP database. This is loaded last, as the TEMP database
** schema may contain references to objects in other databases.
*/
#ifndef SQLITE_OMIT_TEMPDB
if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
rc = sqlite3InitOne(db, 1, pzErrMsg);
if( rc ){
sqlite3ResetInternalSchema(db, 1);
}
}
#endif
db->init.busy = 0;
if( rc==SQLITE_OK ){
db->flags |= SQLITE_Initialized;
sqlite3CommitInternalChanges(db);
}
if( rc!=SQLITE_OK ){
db->flags &= ~SQLITE_Initialized;
}
return rc;
}
/*
** This routine is a no-op if the database schema is already initialised.
** Otherwise, the schema is loaded. An error code is returned.
*/
int sqlite3ReadSchema(Parse *pParse){
int rc = SQLITE_OK;
sqlite3 *db = pParse->db;
if( !db->init.busy ){
if( (db->flags & SQLITE_Initialized)==0 ){
rc = sqlite3Init(db, &pParse->zErrMsg);
}
}
assert( rc!=SQLITE_OK || (db->flags & SQLITE_Initialized)||db->init.busy );
if( rc!=SQLITE_OK ){
pParse->rc = rc;
pParse->nErr++;
}
return rc;
}
/*
** The version of the library
*/
@ -478,6 +131,10 @@ int sqlite3_close(sqlite3 *db){
return SQLITE_MISUSE;
}
#ifdef SQLITE_SSE
sqlite3_finalize(db->pFetch);
#endif
/* If there are any outstanding VMs, return SQLITE_BUSY. */
if( db->pVdbe ){
sqlite3Error(db, SQLITE_BUSY,
@ -531,8 +188,9 @@ int sqlite3_close(sqlite3 *db){
#ifndef SQLITE_OMIT_GLOBALRECOVER
{
sqlite3 *pPrev = pDbList;
sqlite3 *pPrev;
sqlite3OsEnterMutex();
pPrev = pDbList;
while( pPrev && pPrev->pNext!=db ){
pPrev = pPrev->pNext;
}
@ -613,24 +271,25 @@ const char *sqlite3ErrStr(int rc){
** argument.
*/
static int sqliteDefaultBusyCallback(
void *Timeout, /* Maximum amount of time to wait */
void *ptr, /* Database connection */
int count /* Number of times table has been busy */
){
#if SQLITE_MIN_SLEEP_MS==1
static const char delays[] =
{ 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 50, 100};
static const short int totals[] =
{ 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228, 287};
static const u8 delays[] =
{ 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 };
static const u8 totals[] =
{ 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 };
# define NDELAY (sizeof(delays)/sizeof(delays[0]))
ptr timeout = (ptr)Timeout;
ptr delay, prior;
int timeout = ((sqlite3 *)ptr)->busyTimeout;
int delay, prior;
if( count <= NDELAY ){
delay = delays[count-1];
prior = totals[count-1];
assert( count>=0 );
if( count < NDELAY ){
delay = delays[count];
prior = totals[count];
}else{
delay = delays[NDELAY-1];
prior = totals[NDELAY-1] + delay*(count-NDELAY-1);
prior = totals[NDELAY-1] + delay*(count-(NDELAY-1));
}
if( prior + delay > timeout ){
delay = timeout - prior;
@ -698,7 +357,8 @@ void sqlite3_progress_handler(
*/
int sqlite3_busy_timeout(sqlite3 *db, int ms){
if( ms>0 ){
sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)(ptr)ms);
db->busyTimeout = ms;
sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);
}else{
sqlite3_busy_handler(db, 0, 0);
}
@ -1005,161 +665,10 @@ int sqlite3_errcode(sqlite3 *db){
return db->errCode;
}
/*
** Check schema cookies in all databases. If any cookie is out
** of date, return 0. If all schema cookies are current, return 1.
*/
static int schemaIsValid(sqlite3 *db){
int iDb;
int rc;
BtCursor *curTemp;
int cookie;
int allOk = 1;
for(iDb=0; allOk && iDb<db->nDb; iDb++){
Btree *pBt;
pBt = db->aDb[iDb].pBt;
if( pBt==0 ) continue;
rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, 0, &curTemp);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie);
if( rc==SQLITE_OK && cookie!=db->aDb[iDb].schema_cookie ){
allOk = 0;
}
sqlite3BtreeCloseCursor(curTemp);
}
}
return allOk;
}
/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
int sqlite3_prepare(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char** pzTail /* OUT: End of parsed string */
){
Parse sParse;
char *zErrMsg = 0;
int rc = SQLITE_OK;
if( sqlite3_malloc_failed ){
return SQLITE_NOMEM;
}
assert( ppStmt );
*ppStmt = 0;
if( sqlite3SafetyOn(db) ){
return SQLITE_MISUSE;
}
memset(&sParse, 0, sizeof(sParse));
sParse.db = db;
sqlite3RunParser(&sParse, zSql, &zErrMsg);
if( sqlite3_malloc_failed ){
rc = SQLITE_NOMEM;
sqlite3RollbackAll(db);
sqlite3ResetInternalSchema(db, 0);
db->flags &= ~SQLITE_InTrans;
goto prepare_out;
}
if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
if( sParse.rc!=SQLITE_OK && sParse.checkSchema && !schemaIsValid(db) ){
sParse.rc = SQLITE_SCHEMA;
}
if( sParse.rc==SQLITE_SCHEMA ){
sqlite3ResetInternalSchema(db, 0);
}
if( pzTail ) *pzTail = sParse.zTail;
rc = sParse.rc;
#ifndef SQLITE_OMIT_EXPLAIN
if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
sqlite3VdbeSetNumCols(sParse.pVdbe, 5);
sqlite3VdbeSetColName(sParse.pVdbe, 0, "addr", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 1, "opcode", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 2, "p1", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 3, "p2", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 4, "p3", P3_STATIC);
}
#endif
prepare_out:
if( sqlite3SafetyOff(db) ){
rc = SQLITE_MISUSE;
}
if( rc==SQLITE_OK ){
*ppStmt = (sqlite3_stmt*)sParse.pVdbe;
}else if( sParse.pVdbe ){
sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
}
if( zErrMsg ){
sqlite3Error(db, rc, "%s", zErrMsg);
sqliteFree(zErrMsg);
}else{
sqlite3Error(db, rc, 0);
}
return rc;
}
#ifndef SQLITE_OMIT_UTF16
/*
** Compile the UTF-16 encoded SQL statement zSql into a statement handle.
*/
int sqlite3_prepare16(
sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const void **pzTail /* OUT: End of parsed string */
){
/* This function currently works by first transforming the UTF-16
** encoded string to UTF-8, then invoking sqlite3_prepare(). The
** tricky bit is figuring out the pointer to return in *pzTail.
*/
char const *zSql8 = 0;
char const *zTail8 = 0;
int rc;
sqlite3_value *pTmp;
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
pTmp = sqlite3GetTransientValue(db);
sqlite3ValueSetStr(pTmp, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
zSql8 = sqlite3ValueText(pTmp, SQLITE_UTF8);
if( !zSql8 ){
sqlite3Error(db, SQLITE_NOMEM, 0);
return SQLITE_NOMEM;
}
rc = sqlite3_prepare(db, zSql8, -1, ppStmt, &zTail8);
if( zTail8 && pzTail ){
/* If sqlite3_prepare returns a tail pointer, we calculate the
** equivalent pointer into the UTF-16 string by counting the unicode
** characters between zSql8 and zTail8, and then returning a pointer
** the same number of characters into the UTF-16 string.
*/
int chars_parsed = sqlite3utf8CharLen(zSql8, zTail8-zSql8);
*pzTail = (u8 *)zSql + sqlite3utf16ByteLen(zSql, chars_parsed);
}
return rc;
}
#endif /* SQLITE_OMIT_UTF16 */
/*
** This routine does the work of opening a database on behalf of
** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
** is UTF-8 encoded. The fourth argument, "def_enc" is one of the TEXT_*
** macros from sqliteInt.h. If we end up creating a new database file
** (not opening an existing one), the text encoding of the database
** will be set to this value.
** is UTF-8 encoded.
*/
static int openDatabase(
const char *zFilename, /* Database filename UTF-8 encoded */
@ -1480,3 +989,15 @@ recover_out:
return rc;
}
#endif
/*
** Test to see whether or not the database connection is in autocommit
** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on
** by default. Autocommit is disabled by a BEGIN statement and reenabled
** by the next COMMIT or ROLLBACK.
**
******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
*/
int sqlite3_get_autocommit(sqlite3 *db){
return db->autoCommit;
}

Просмотреть файл

@ -9,129 +9,127 @@ const char *const sqlite3OpcodeNames[] = { "?",
/* 5 */ "MoveGt",
/* 6 */ "AggFocus",
/* 7 */ "RowKey",
/* 8 */ "IdxRecno",
/* 9 */ "AggNext",
/* 10 */ "OpenWrite",
/* 11 */ "If",
/* 12 */ "PutStrKey",
/* 13 */ "Pop",
/* 14 */ "SortPut",
/* 15 */ "AggContextPush",
/* 16 */ "CollSeq",
/* 17 */ "OpenRead",
/* 18 */ "Expire",
/* 19 */ "SortReset",
/* 20 */ "AutoCommit",
/* 21 */ "Sort",
/* 22 */ "ListRewind",
/* 23 */ "IntegrityCk",
/* 24 */ "Function",
/* 25 */ "Noop",
/* 26 */ "Return",
/* 27 */ "Variable",
/* 28 */ "String",
/* 29 */ "ParseSchema",
/* 30 */ "PutIntKey",
/* 31 */ "AggFunc",
/* 32 */ "Close",
/* 33 */ "ListWrite",
/* 34 */ "CreateIndex",
/* 35 */ "IsUnique",
/* 36 */ "IdxIsNull",
/* 37 */ "NotFound",
/* 38 */ "MustBeInt",
/* 39 */ "Halt",
/* 40 */ "IdxLT",
/* 41 */ "AddImm",
/* 42 */ "Statement",
/* 43 */ "RowData",
/* 44 */ "MemMax",
/* 45 */ "Push",
/* 46 */ "KeyAsData",
/* 47 */ "NotExists",
/* 48 */ "OpenTemp",
/* 49 */ "MemIncr",
/* 50 */ "Gosub",
/* 51 */ "AggSet",
/* 52 */ "Integer",
/* 53 */ "SortNext",
/* 54 */ "Prev",
/* 55 */ "CreateTable",
/* 56 */ "Last",
/* 57 */ "ResetCount",
/* 58 */ "Callback",
/* 59 */ "ContextPush",
/* 60 */ "DropTrigger",
/* 61 */ "DropIndex",
/* 62 */ "FullKey",
/* 63 */ "IdxGE",
/* 64 */ "Or",
/* 65 */ "And",
/* 66 */ "Not",
/* 67 */ "IdxDelete",
/* 68 */ "Vacuum",
/* 69 */ "MoveLe",
/* 70 */ "IsNull",
/* 71 */ "NotNull",
/* 72 */ "Ne",
/* 73 */ "Eq",
/* 74 */ "Gt",
/* 75 */ "Le",
/* 76 */ "Lt",
/* 77 */ "Ge",
/* 78 */ "IfNot",
/* 79 */ "BitAnd",
/* 80 */ "BitOr",
/* 81 */ "ShiftLeft",
/* 82 */ "ShiftRight",
/* 83 */ "Add",
/* 84 */ "Subtract",
/* 85 */ "Multiply",
/* 86 */ "Divide",
/* 87 */ "Remainder",
/* 88 */ "Concat",
/* 89 */ "Negative",
/* 90 */ "DropTable",
/* 91 */ "BitNot",
/* 92 */ "String8",
/* 93 */ "MakeRecord",
/* 94 */ "Delete",
/* 95 */ "AggContextPop",
/* 96 */ "ListRead",
/* 97 */ "ListReset",
/* 98 */ "Dup",
/* 99 */ "Goto",
/* 100 */ "Clear",
/* 101 */ "IdxGT",
/* 102 */ "MoveLt",
/* 103 */ "VerifyCookie",
/* 104 */ "Pull",
/* 105 */ "SetNumColumns",
/* 106 */ "AbsValue",
/* 107 */ "Transaction",
/* 108 */ "AggGet",
/* 109 */ "ContextPop",
/* 110 */ "Next",
/* 111 */ "AggInit",
/* 112 */ "Distinct",
/* 113 */ "NewRecno",
/* 114 */ "AggReset",
/* 115 */ "Destroy",
/* 116 */ "ReadCookie",
/* 117 */ "ForceInt",
/* 118 */ "Recno",
/* 119 */ "OpenPseudo",
/* 120 */ "Blob",
/* 121 */ "MemStore",
/* 122 */ "Rewind",
/* 123 */ "MoveGe",
/* 124 */ "IdxPut",
/* 125 */ "Found",
/* 126 */ "NullRow",
/* 8 */ "AggNext",
/* 9 */ "OpenWrite",
/* 10 */ "If",
/* 11 */ "Pop",
/* 12 */ "AggContextPush",
/* 13 */ "CollSeq",
/* 14 */ "OpenRead",
/* 15 */ "Expire",
/* 16 */ "SortReset",
/* 17 */ "AutoCommit",
/* 18 */ "Sort",
/* 19 */ "ListRewind",
/* 20 */ "IntegrityCk",
/* 21 */ "SortInsert",
/* 22 */ "Function",
/* 23 */ "Noop",
/* 24 */ "Return",
/* 25 */ "NewRowid",
/* 26 */ "Variable",
/* 27 */ "String",
/* 28 */ "ParseSchema",
/* 29 */ "AggFunc",
/* 30 */ "Close",
/* 31 */ "ListWrite",
/* 32 */ "CreateIndex",
/* 33 */ "IsUnique",
/* 34 */ "IdxIsNull",
/* 35 */ "NotFound",
/* 36 */ "MustBeInt",
/* 37 */ "Halt",
/* 38 */ "Rowid",
/* 39 */ "IdxLT",
/* 40 */ "AddImm",
/* 41 */ "Statement",
/* 42 */ "RowData",
/* 43 */ "MemMax",
/* 44 */ "Push",
/* 45 */ "NotExists",
/* 46 */ "OpenTemp",
/* 47 */ "MemIncr",
/* 48 */ "Gosub",
/* 49 */ "AggSet",
/* 50 */ "Integer",
/* 51 */ "SortNext",
/* 52 */ "Prev",
/* 53 */ "CreateTable",
/* 54 */ "Last",
/* 55 */ "IdxRowid",
/* 56 */ "ResetCount",
/* 57 */ "Callback",
/* 58 */ "ContextPush",
/* 59 */ "DropTrigger",
/* 60 */ "DropIndex",
/* 61 */ "IdxGE",
/* 62 */ "Or",
/* 63 */ "And",
/* 64 */ "Not",
/* 65 */ "IdxDelete",
/* 66 */ "Vacuum",
/* 67 */ "MoveLe",
/* 68 */ "IsNull",
/* 69 */ "NotNull",
/* 70 */ "Ne",
/* 71 */ "Eq",
/* 72 */ "Gt",
/* 73 */ "Le",
/* 74 */ "Lt",
/* 75 */ "Ge",
/* 76 */ "IfNot",
/* 77 */ "BitAnd",
/* 78 */ "BitOr",
/* 79 */ "ShiftLeft",
/* 80 */ "ShiftRight",
/* 81 */ "Add",
/* 82 */ "Subtract",
/* 83 */ "Multiply",
/* 84 */ "Divide",
/* 85 */ "Remainder",
/* 86 */ "Concat",
/* 87 */ "Negative",
/* 88 */ "DropTable",
/* 89 */ "BitNot",
/* 90 */ "String8",
/* 91 */ "MakeRecord",
/* 92 */ "Delete",
/* 93 */ "AggContextPop",
/* 94 */ "ListRead",
/* 95 */ "ListReset",
/* 96 */ "Dup",
/* 97 */ "Goto",
/* 98 */ "Clear",
/* 99 */ "IdxGT",
/* 100 */ "MoveLt",
/* 101 */ "VerifyCookie",
/* 102 */ "Pull",
/* 103 */ "SetNumColumns",
/* 104 */ "AbsValue",
/* 105 */ "Transaction",
/* 106 */ "AggGet",
/* 107 */ "ContextPop",
/* 108 */ "Next",
/* 109 */ "AggInit",
/* 110 */ "IdxInsert",
/* 111 */ "Distinct",
/* 112 */ "AggReset",
/* 113 */ "Insert",
/* 114 */ "Destroy",
/* 115 */ "ReadCookie",
/* 116 */ "ForceInt",
/* 117 */ "OpenPseudo",
/* 118 */ "Null",
/* 119 */ "Blob",
/* 120 */ "MemStore",
/* 121 */ "Rewind",
/* 122 */ "MoveGe",
/* 123 */ "Found",
/* 124 */ "NullRow",
/* 125 */ "NotUsed_125",
/* 126 */ "NotUsed_126",
/* 127 */ "NotUsed_127",
/* 128 */ "NotUsed_128",
/* 129 */ "NotUsed_129",
/* 130 */ "Real",
/* 131 */ "HexBlob",
/* 128 */ "Real",
/* 129 */ "HexBlob",
};
#endif

Просмотреть файл

@ -1,146 +1,144 @@
/* Automatically generated. Do not edit */
/* See the mkopcodeh.awk script for details */
#define OP_MemLoad 1
#define OP_HexBlob 131 /* same as TK_BLOB */
#define OP_HexBlob 129 /* same as TK_BLOB */
#define OP_Column 2
#define OP_SetCookie 3
#define OP_IfMemPos 4
#define OP_Real 130 /* same as TK_FLOAT */
#define OP_Real 128 /* same as TK_FLOAT */
#define OP_MoveGt 5
#define OP_Ge 77 /* same as TK_GE */
#define OP_Ge 75 /* same as TK_GE */
#define OP_AggFocus 6
#define OP_RowKey 7
#define OP_IdxRecno 8
#define OP_AggNext 9
#define OP_Eq 73 /* same as TK_EQ */
#define OP_OpenWrite 10
#define OP_NotNull 71 /* same as TK_NOTNULL */
#define OP_If 11
#define OP_PutStrKey 12
#define OP_String8 92 /* same as TK_STRING */
#define OP_Pop 13
#define OP_SortPut 14
#define OP_AggContextPush 15
#define OP_CollSeq 16
#define OP_OpenRead 17
#define OP_Expire 18
#define OP_SortReset 19
#define OP_AutoCommit 20
#define OP_Gt 74 /* same as TK_GT */
#define OP_Sort 21
#define OP_ListRewind 22
#define OP_IntegrityCk 23
#define OP_Function 24
#define OP_Subtract 84 /* same as TK_MINUS */
#define OP_And 65 /* same as TK_AND */
#define OP_Noop 25
#define OP_Return 26
#define OP_Remainder 87 /* same as TK_REM */
#define OP_Multiply 85 /* same as TK_STAR */
#define OP_Variable 27
#define OP_String 28
#define OP_ParseSchema 29
#define OP_PutIntKey 30
#define OP_AggFunc 31
#define OP_Close 32
#define OP_ListWrite 33
#define OP_CreateIndex 34
#define OP_IsUnique 35
#define OP_IdxIsNull 36
#define OP_NotFound 37
#define OP_MustBeInt 38
#define OP_Halt 39
#define OP_IdxLT 40
#define OP_AddImm 41
#define OP_Statement 42
#define OP_RowData 43
#define OP_MemMax 44
#define OP_Push 45
#define OP_Or 64 /* same as TK_OR */
#define OP_KeyAsData 46
#define OP_NotExists 47
#define OP_OpenTemp 48
#define OP_MemIncr 49
#define OP_Gosub 50
#define OP_Divide 86 /* same as TK_SLASH */
#define OP_AggSet 51
#define OP_Integer 52
#define OP_SortNext 53
#define OP_Prev 54
#define OP_Concat 88 /* same as TK_CONCAT */
#define OP_BitAnd 79 /* same as TK_BITAND */
#define OP_CreateTable 55
#define OP_Last 56
#define OP_IsNull 70 /* same as TK_ISNULL */
#define OP_ShiftRight 82 /* same as TK_RSHIFT */
#define OP_ResetCount 57
#define OP_Callback 58
#define OP_ContextPush 59
#define OP_DropTrigger 60
#define OP_DropIndex 61
#define OP_FullKey 62
#define OP_IdxGE 63
#define OP_IdxDelete 67
#define OP_Vacuum 68
#define OP_MoveLe 69
#define OP_IfNot 78
#define OP_DropTable 90
#define OP_MakeRecord 93
#define OP_Delete 94
#define OP_AggContextPop 95
#define OP_ListRead 96
#define OP_ListReset 97
#define OP_ShiftLeft 81 /* same as TK_LSHIFT */
#define OP_Dup 98
#define OP_Goto 99
#define OP_Clear 100
#define OP_IdxGT 101
#define OP_MoveLt 102
#define OP_Le 75 /* same as TK_LE */
#define OP_VerifyCookie 103
#define OP_Pull 104
#define OP_Not 66 /* same as TK_NOT */
#define OP_SetNumColumns 105
#define OP_AbsValue 106
#define OP_Transaction 107
#define OP_Negative 89 /* same as TK_UMINUS */
#define OP_Ne 72 /* same as TK_NE */
#define OP_AggGet 108
#define OP_ContextPop 109
#define OP_BitOr 80 /* same as TK_BITOR */
#define OP_Next 110
#define OP_AggInit 111
#define OP_Distinct 112
#define OP_NewRecno 113
#define OP_Lt 76 /* same as TK_LT */
#define OP_AggReset 114
#define OP_Destroy 115
#define OP_ReadCookie 116
#define OP_ForceInt 117
#define OP_Recno 118
#define OP_OpenPseudo 119
#define OP_Blob 120
#define OP_Add 83 /* same as TK_PLUS */
#define OP_MemStore 121
#define OP_Rewind 122
#define OP_MoveGe 123
#define OP_IdxPut 124
#define OP_BitNot 91 /* same as TK_BITNOT */
#define OP_Found 125
#define OP_NullRow 126
#define OP_AggNext 8
#define OP_Eq 71 /* same as TK_EQ */
#define OP_OpenWrite 9
#define OP_NotNull 69 /* same as TK_NOTNULL */
#define OP_If 10
#define OP_String8 90 /* same as TK_STRING */
#define OP_Pop 11
#define OP_AggContextPush 12
#define OP_CollSeq 13
#define OP_OpenRead 14
#define OP_Expire 15
#define OP_SortReset 16
#define OP_AutoCommit 17
#define OP_Gt 72 /* same as TK_GT */
#define OP_Sort 18
#define OP_ListRewind 19
#define OP_IntegrityCk 20
#define OP_SortInsert 21
#define OP_Function 22
#define OP_And 63 /* same as TK_AND */
#define OP_Subtract 82 /* same as TK_MINUS */
#define OP_Noop 23
#define OP_Return 24
#define OP_Remainder 85 /* same as TK_REM */
#define OP_NewRowid 25
#define OP_Multiply 83 /* same as TK_STAR */
#define OP_Variable 26
#define OP_String 27
#define OP_ParseSchema 28
#define OP_AggFunc 29
#define OP_Close 30
#define OP_ListWrite 31
#define OP_CreateIndex 32
#define OP_IsUnique 33
#define OP_IdxIsNull 34
#define OP_NotFound 35
#define OP_MustBeInt 36
#define OP_Halt 37
#define OP_Rowid 38
#define OP_IdxLT 39
#define OP_AddImm 40
#define OP_Statement 41
#define OP_RowData 42
#define OP_MemMax 43
#define OP_Push 44
#define OP_Or 62 /* same as TK_OR */
#define OP_NotExists 45
#define OP_OpenTemp 46
#define OP_MemIncr 47
#define OP_Gosub 48
#define OP_Divide 84 /* same as TK_SLASH */
#define OP_AggSet 49
#define OP_Integer 50
#define OP_SortNext 51
#define OP_Prev 52
#define OP_Concat 86 /* same as TK_CONCAT */
#define OP_BitAnd 77 /* same as TK_BITAND */
#define OP_CreateTable 53
#define OP_Last 54
#define OP_IsNull 68 /* same as TK_ISNULL */
#define OP_IdxRowid 55
#define OP_ShiftRight 80 /* same as TK_RSHIFT */
#define OP_ResetCount 56
#define OP_Callback 57
#define OP_ContextPush 58
#define OP_DropTrigger 59
#define OP_DropIndex 60
#define OP_IdxGE 61
#define OP_IdxDelete 65
#define OP_Vacuum 66
#define OP_MoveLe 67
#define OP_IfNot 76
#define OP_DropTable 88
#define OP_MakeRecord 91
#define OP_Delete 92
#define OP_AggContextPop 93
#define OP_ListRead 94
#define OP_ListReset 95
#define OP_ShiftLeft 79 /* same as TK_LSHIFT */
#define OP_Dup 96
#define OP_Goto 97
#define OP_Clear 98
#define OP_IdxGT 99
#define OP_MoveLt 100
#define OP_Le 73 /* same as TK_LE */
#define OP_VerifyCookie 101
#define OP_Pull 102
#define OP_Not 64 /* same as TK_NOT */
#define OP_SetNumColumns 103
#define OP_AbsValue 104
#define OP_Transaction 105
#define OP_Negative 87 /* same as TK_UMINUS */
#define OP_Ne 70 /* same as TK_NE */
#define OP_AggGet 106
#define OP_ContextPop 107
#define OP_BitOr 78 /* same as TK_BITOR */
#define OP_Next 108
#define OP_AggInit 109
#define OP_IdxInsert 110
#define OP_Distinct 111
#define OP_Lt 74 /* same as TK_LT */
#define OP_AggReset 112
#define OP_Insert 113
#define OP_Destroy 114
#define OP_ReadCookie 115
#define OP_ForceInt 116
#define OP_OpenPseudo 117
#define OP_Null 118
#define OP_Blob 119
#define OP_Add 81 /* same as TK_PLUS */
#define OP_MemStore 120
#define OP_Rewind 121
#define OP_MoveGe 122
#define OP_BitNot 89 /* same as TK_BITNOT */
#define OP_Found 123
#define OP_NullRow 124
/* The following opcode values are never used */
#define OP_NotUsed_125 125
#define OP_NotUsed_126 126
#define OP_NotUsed_127 127
#define OP_NotUsed_128 128
#define OP_NotUsed_129 129
#define NOPUSH_MASK_0 65144
#define NOPUSH_MASK_1 59007
#define NOPUSH_MASK_2 63483
#define NOPUSH_MASK_3 48975
#define NOPUSH_MASK_0 65400
#define NOPUSH_MASK_1 61871
#define NOPUSH_MASK_2 64446
#define NOPUSH_MASK_3 65363
#define NOPUSH_MASK_4 65535
#define NOPUSH_MASK_5 52991
#define NOPUSH_MASK_6 60410
#define NOPUSH_MASK_7 32421
#define NOPUSH_MASK_5 46015
#define NOPUSH_MASK_6 64254
#define NOPUSH_MASK_7 7987
#define NOPUSH_MASK_8 0
#define NOPUSH_MASK_9 0

Просмотреть файл

@ -23,7 +23,8 @@
** N.B. MacOS means Mac Classic (or Carbon). Treat Darwin (OS X) as Unix.
** The MacOS build is designed to use CodeWarrior (tested with v8)
*/
#if !defined(OS_UNIX) && !defined(OS_TEST)
#if !defined(OS_UNIX) && !defined(OS_TEST) && !defined(OS_OTHER)
# define OS_OTHER 0
# ifndef OS_WIN
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
# define OS_WIN 1
@ -54,6 +55,14 @@
# include "os_win.h"
#endif
/* os_other.c and os_other.h are not delivered with SQLite. These files
** are place-holders that can be filled in by third-party developers to
** implement backends to their on proprietary operating systems.
*/
#if OS_OTHER
# include "os_other.h"
#endif
/* If the SET_FULLSYNC macro is not defined above, then make it
** a no-op
*/
@ -175,15 +184,19 @@ int sqlite3OsSeek(OsFile*, i64 offset);
int sqlite3OsSync(OsFile*);
int sqlite3OsTruncate(OsFile*, i64 size);
int sqlite3OsFileSize(OsFile*, i64 *pSize);
int sqlite3OsRandomSeed(char*);
int sqlite3OsSleep(int ms);
int sqlite3OsCurrentTime(double*);
int sqlite3OsFileModTime(OsFile*, double*);
void sqlite3OsEnterMutex(void);
void sqlite3OsLeaveMutex(void);
char *sqlite3OsFullPathname(const char*);
int sqlite3OsLock(OsFile*, int);
int sqlite3OsUnlock(OsFile*, int);
int sqlite3OsCheckReservedLock(OsFile *id);
/* The interface for file I/O is above. Other miscellaneous functions
** are below */
int sqlite3OsRandomSeed(char*);
int sqlite3OsSleep(int ms);
int sqlite3OsCurrentTime(double*);
void sqlite3OsEnterMutex(void);
void sqlite3OsLeaveMutex(void);
#endif /* _SQLITE_OS_H_ */

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -20,6 +20,18 @@
#include <time.h>
#include <errno.h>
#include <unistd.h>
/*
** Do not include any of the File I/O interface procedures if the
** SQLITE_OMIT_DISKIO macro is defined (indicating that there database
** will be in-memory only)
*/
#ifndef SQLITE_OMIT_DISKIO
/*
** Define various macros that are missing from some systems.
*/
#ifndef O_LARGEFILE
# define O_LARGEFILE 0
#endif
@ -34,7 +46,6 @@
# define O_BINARY 0
#endif
/*
** The DJGPP compiler environment looks mostly like Unix, but it
** lacks the fcntl() system call. So redefine fcntl() to be something
@ -432,7 +443,8 @@ int sqlite3OsOpenReadWrite(
int rc;
assert( !id->isOpen );
id->dirfd = -1;
id->h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644);
id->h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY,
SQLITE_DEFAULT_FILE_PERMISSIONS);
if( id->h<0 ){
#ifdef EISDIR
if( errno==EISDIR ){
@ -561,7 +573,7 @@ int sqlite3OsOpenDirectory(
return SQLITE_CANTOPEN;
}
assert( id->dirfd<0 );
id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0644);
id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0);
if( id->dirfd<0 ){
return SQLITE_CANTOPEN;
}
@ -784,7 +796,7 @@ int sqlite3OsSyncDirectory(const char *zDirname){
int fd;
int r;
SimulateIOError(SQLITE_IOERR);
fd = open(zDirname, O_RDONLY|O_BINARY, 0644);
fd = open(zDirname, O_RDONLY|O_BINARY, 0);
TRACE3("DIRSYNC %-3d (%s)\n", fd, zDirname);
if( fd<0 ){
return SQLITE_CANTOPEN;
@ -1198,6 +1210,33 @@ int sqlite3OsClose(OsFile *id){
return SQLITE_OK;
}
/*
** Turn a relative pathname into a full pathname. Return a pointer
** to the full pathname stored in space obtained from sqliteMalloc().
** The calling function is responsible for freeing this space once it
** is no longer needed.
*/
char *sqlite3OsFullPathname(const char *zRelative){
char *zFull = 0;
if( zRelative[0]=='/' ){
sqlite3SetString(&zFull, zRelative, (char*)0);
}else{
char zBuf[5000];
zBuf[0] = 0;
sqlite3SetString(&zFull, getcwd(zBuf, sizeof(zBuf)), "/", zRelative,
(char*)0);
}
return zFull;
}
#endif /* SQLITE_OMIT_DISKIO */
/***************************************************************************
** Everything above deals with file I/O. Everything that follows deals
** with other miscellanous aspects of the operating system interface
****************************************************************************/
/*
** Get information to seed the random number generator. The seed
** is written into the buffer zBuf[256]. The calling function must
@ -1278,24 +1317,6 @@ void sqlite3OsLeaveMutex(){
#endif
}
/*
** Turn a relative pathname into a full pathname. Return a pointer
** to the full pathname stored in space obtained from sqliteMalloc().
** The calling function is responsible for freeing this space once it
** is no longer needed.
*/
char *sqlite3OsFullPathname(const char *zRelative){
char *zFull = 0;
if( zRelative[0]=='/' ){
sqlite3SetString(&zFull, zRelative, (char*)0);
}else{
char zBuf[5000];
sqlite3SetString(&zFull, getcwd(zBuf, sizeof(zBuf)), "/", zRelative,
(char*)0);
}
return zFull;
}
/*
** The following variable, if set to a non-zero value, becomes the result
** returned from sqlite3OsCurrentTime(). This is used for testing.
@ -1321,24 +1342,4 @@ int sqlite3OsCurrentTime(double *prNow){
return 0;
}
#if 0 /* NOT USED */
/*
** Find the time that the file was last modified. Write the
** modification time and date as a Julian Day number into *prNow and
** return SQLITE_OK. Return SQLITE_ERROR if the modification
** time cannot be found.
*/
int sqlite3OsFileModTime(OsFile *id, double *prNow){
int rc;
struct stat statbuf;
if( fstat(id->h, &statbuf)==0 ){
*prNow = statbuf.st_mtime/86400.0 + 2440587.5;
rc = SQLITE_OK;
}else{
rc = SQLITE_ERROR;
}
return rc;
}
#endif /* NOT USED */
#endif /* OS_UNIX */

Просмотреть файл

@ -91,5 +91,12 @@ struct OsFile {
# define SQLITE_MIN_SLEEP_MS 1000
#endif
/*
** Default permissions when creating a new file
*/
#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS
# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644
#endif
#endif /* _SQLITE_OS_UNIX_H_ */

Просмотреть файл

@ -34,6 +34,13 @@
*/
#include "os_common.h"
/*
** Do not include any of the File I/O interface procedures if the
** SQLITE_OMIT_DISKIO macro is defined (indicating that there database
** will be in-memory only)
*/
#ifndef SQLITE_OMIT_DISKIO
/*
** Delete the named file
*/
@ -625,6 +632,36 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
return rc;
}
/*
** Turn a relative pathname into a full pathname. Return a pointer
** to the full pathname stored in space obtained from sqliteMalloc().
** The calling function is responsible for freeing this space once it
** is no longer needed.
*/
char *sqlite3OsFullPathname(const char *zRelative){
char *zNotUsed;
char *zFull;
int nByte;
#ifdef __CYGWIN__
nByte = strlen(zRelative) + MAX_PATH + 1001;
zFull = sqliteMalloc( nByte );
if( zFull==0 ) return 0;
if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0;
#else
nByte = GetFullPathNameA(zRelative, 0, 0, &zNotUsed) + 1;
zFull = sqliteMalloc( nByte );
if( zFull==0 ) return 0;
GetFullPathNameA(zRelative, nByte, zFull, &zNotUsed);
#endif
return zFull;
}
#endif /* SQLITE_OMIT_DISKIO */
/***************************************************************************
** Everything above deals with file I/O. Everything that follows deals
** with other miscellanous aspects of the operating system interface
****************************************************************************/
/*
** Get information to seed the random number generator. The seed
** is written into the buffer zBuf[256]. The calling function must
@ -697,30 +734,6 @@ void sqlite3OsLeaveMutex(){
#endif
}
/*
** Turn a relative pathname into a full pathname. Return a pointer
** to the full pathname stored in space obtained from sqliteMalloc().
** The calling function is responsible for freeing this space once it
** is no longer needed.
*/
char *sqlite3OsFullPathname(const char *zRelative){
char *zNotUsed;
char *zFull;
int nByte;
#ifdef __CYGWIN__
nByte = strlen(zRelative) + MAX_PATH + 1001;
zFull = sqliteMalloc( nByte );
if( zFull==0 ) return 0;
if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0;
#else
nByte = GetFullPathNameA(zRelative, 0, 0, &zNotUsed) + 1;
zFull = sqliteMalloc( nByte );
if( zFull==0 ) return 0;
GetFullPathNameA(zRelative, nByte, zFull, &zNotUsed);
#endif
return zFull;
}
/*
** The following variable, if set to a non-zero value, becomes the result
** returned from sqlite3OsCurrentTime(). This is used for testing.
@ -751,27 +764,4 @@ int sqlite3OsCurrentTime(double *prNow){
return 0;
}
/*
** Find the time that the file was last modified. Write the
** modification time and date as a Julian Day number into *prNow and
** return SQLITE_OK. Return SQLITE_ERROR if the modification
** time cannot be found.
*/
int sqlite3OsFileModTime(OsFile *id, double *prMTime){
int rc;
FILETIME ft;
/* FILETIME structure is a 64-bit value representing the number of
** 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
*/
if( GetFileTime(id->h, 0, 0, &ft) ){
double t;
t = ((double)ft.dwHighDateTime) * 4294967296.0;
*prMTime = (t + ft.dwLowDateTime)/864000000000.0 + 2305813.5;
rc = SQLITE_OK;
}else{
rc = SQLITE_ERROR;
}
return rc;
}
#endif /* OS_WIN */

Просмотреть файл

@ -18,8 +18,9 @@
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.201 2005/03/28 18:04:28 drh Exp $
** @(#) $Id: pager.c,v 1.207 2005/06/07 02:12:30 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include "os.h"
#include "pager.h"
@ -171,7 +172,7 @@ struct PgHdr {
#ifdef SQLITE_CHECK_PAGES
u32 pageHash;
#endif
/* pPager->psAligned bytes of page data follow this header */
/* pPager->pageSize bytes of page data follow this header */
/* Pager.nExtra bytes of local data follow the page data */
};
@ -207,9 +208,9 @@ struct PgHistory {
*/
#define PGHDR_TO_DATA(P) ((void*)(&(P)[1]))
#define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1])
#define PGHDR_TO_EXTRA(G,P) ((void*)&((char*)(&(G)[1]))[(P)->psAligned])
#define PGHDR_TO_EXTRA(G,P) ((void*)&((char*)(&(G)[1]))[(P)->pageSize])
#define PGHDR_TO_HIST(P,PGR) \
((PgHistory*)&((char*)(&(P)[1]))[(PGR)->psAligned+(PGR)->nExtra])
((PgHistory*)&((char*)(&(P)[1]))[(PGR)->pageSize+(PGR)->nExtra])
/*
** How big to make the hash table used for locating in-memory pages
@ -233,31 +234,6 @@ struct PgHistory {
** A open page cache is an instance of the following structure.
*/
struct Pager {
char *zFilename; /* Name of the database file */
char *zJournal; /* Name of the journal file */
char *zDirectory; /* Directory hold database and journal files */
OsFile fd, jfd; /* File descriptors for database and journal */
OsFile stfd; /* File descriptor for the statement subjournal*/
int dbSize; /* Number of pages in the file */
int origDbSize; /* dbSize before the current change */
int stmtSize; /* Size of database (in pages) at stmt_begin() */
i64 stmtJSize; /* Size of journal at stmt_begin() */
int nRec; /* Number of pages written to the journal */
u32 cksumInit; /* Quasi-random value added to every checksum */
int stmtNRec; /* Number of records in stmt subjournal */
int nExtra; /* Add this many bytes to each in-memory page */
void (*xDestructor)(void*,int); /* Call this routine when freeing pages */
void (*xReiniter)(void*,int); /* Call this routine when reloading pages */
int pageSize; /* Number of bytes in a page */
int psAligned; /* pageSize rounded up to a multiple of 8 */
int nPage; /* Total number of in-memory pages */
int nMaxPage; /* High water mark of nPage */
int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */
int mxPage; /* Maximum number of pages to hold in cache */
int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */
int nRead,nWrite; /* Database pages read/written */
void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
void *pCodecArg; /* First argument to xCodec() */
u8 journalOpen; /* True if journal file descriptors is valid */
u8 journalStarted; /* True if header of journal is synced */
u8 useJournal; /* Use a rollback journal on this file */
@ -275,9 +251,26 @@ struct Pager {
u8 dirtyCache; /* True if cached pages have changed */
u8 alwaysRollback; /* Disable dont_rollback() for all pages */
u8 memDb; /* True to inhibit all file I/O */
u8 setMaster; /* True if a m-j name has been written to jrnl */
int dbSize; /* Number of pages in the file */
int origDbSize; /* dbSize before the current change */
int stmtSize; /* Size of database (in pages) at stmt_begin() */
int nRec; /* Number of pages written to the journal */
u32 cksumInit; /* Quasi-random value added to every checksum */
int stmtNRec; /* Number of records in stmt subjournal */
int nExtra; /* Add this many bytes to each in-memory page */
int pageSize; /* Number of bytes in a page */
int nPage; /* Total number of in-memory pages */
int nMaxPage; /* High water mark of nPage */
int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */
int mxPage; /* Maximum number of pages to hold in cache */
u8 *aInJournal; /* One bit for each page in the database file */
u8 *aInStmt; /* One bit for each page in the database */
u8 setMaster; /* True if a m-j name has been written to jrnl */
char *zFilename; /* Name of the database file */
char *zJournal; /* Name of the journal file */
char *zDirectory; /* Directory hold database and journal files */
OsFile fd, jfd; /* File descriptors for database and journal */
OsFile stfd; /* File descriptor for the statement subjournal*/
BusyHandler *pBusyHandler; /* Pointer to sqlite.busyHandler */
PgHdr *pFirst, *pLast; /* List of free pages */
PgHdr *pFirstSynced; /* First free page with PgHdr.needSync==0 */
@ -287,10 +280,29 @@ struct Pager {
i64 journalHdr; /* Byte offset to previous journal header */
i64 stmtHdrOff; /* First journal header written this statement */
i64 stmtCksum; /* cksumInit when statement was started */
i64 stmtJSize; /* Size of journal at stmt_begin() */
int sectorSize; /* Assumed sector size during rollback */
#ifdef SQLITE_TEST
int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */
int nRead,nWrite; /* Database pages read/written */
#endif
void (*xDestructor)(void*,int); /* Call this routine when freeing pages */
void (*xReiniter)(void*,int); /* Call this routine when reloading pages */
void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
void *pCodecArg; /* First argument to xCodec() */
PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number to PgHdr */
};
/*
** If SQLITE_TEST is defined then increment the variable given in
** the argument
*/
#ifdef SQLITE_TEST
# define TEST_INCR(x) x++
#else
# define TEST_INCR(x)
#endif
/*
** These are bits that can be set in Pager.errMask.
*/
@ -1483,22 +1495,8 @@ end_stmt_playback:
/*
** Change the maximum number of in-memory pages that are allowed.
**
** The maximum number is the absolute value of the mxPage parameter.
** If mxPage is negative, the noSync flag is also set. noSync bypasses
** calls to sqlite3OsSync(). The pager runs much faster with noSync on,
** but if the operating system crashes or there is an abrupt power
** failure, the database file might be left in an inconsistent and
** unrepairable state.
*/
void sqlite3pager_set_cachesize(Pager *pPager, int mxPage){
if( mxPage>=0 ){
pPager->noSync = pPager->tempFile;
if( pPager->noSync ) pPager->needSync = 0;
}else{
pPager->noSync = 1;
mxPage = -mxPage;
}
if( mxPage>10 ){
pPager->mxPage = mxPage;
}else{
@ -1541,8 +1539,15 @@ void sqlite3pager_set_safety_level(Pager *pPager, int level){
#endif
/*
** Open a temporary file. Write the name of the file into zName
** (zName must be at least SQLITE_TEMPNAME_SIZE bytes long.) Write
** The following global variable is incremented whenever the library
** attempts to open a temporary file. This information is used for
** testing and analysis only.
*/
int sqlite3_opentemp_count = 0;
/*
** Open a temporary file. Write the name of the file into zFile
** (zFile must be at least SQLITE_TEMPNAME_SIZE bytes long.) Write
** the file descriptor into *fd. Return SQLITE_OK on success or some
** other error code if we fail.
**
@ -1552,6 +1557,7 @@ void sqlite3pager_set_safety_level(Pager *pPager, int level){
static int sqlite3pager_opentemp(char *zFile, OsFile *fd){
int cnt = 8;
int rc;
sqlite3_opentemp_count++; /* Used for testing and analysis only */
do{
cnt--;
sqlite3OsTempFileName(zFile);
@ -1659,7 +1665,6 @@ int sqlite3pager_open(
pPager->nRef = 0;
pPager->dbSize = memDb-1;
pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE;
pPager->psAligned = FORCE_ALIGNMENT(pPager->pageSize);
pPager->stmtSize = 0;
pPager->stmtJSize = 0;
pPager->nPage = 0;
@ -1715,14 +1720,16 @@ void sqlite3pager_set_reiniter(Pager *pPager, void (*xReinit)(void*,int)){
}
/*
** Set the page size.
**
** The page size must only be changed when the cache is empty.
** Set the page size. Return the new size. If the suggest new page
** size is inappropriate, then an alternative page size is selected
** and returned.
*/
void sqlite3pager_set_pagesize(Pager *pPager, int pageSize){
int sqlite3pager_set_pagesize(Pager *pPager, int pageSize){
assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE );
pPager->pageSize = pageSize;
pPager->psAligned = FORCE_ALIGNMENT(pageSize);
if( !pPager->memDb ){
pPager->pageSize = pageSize;
}
return pPager->pageSize;
}
/*
@ -2201,7 +2208,7 @@ static int pager_write_pagelist(PgHdr *pList){
TRACE3("STORE %d page %d\n", PAGERID(pPager), pList->pgno);
rc = sqlite3OsWrite(&pPager->fd, PGHDR_TO_DATA(pList), pPager->pageSize);
CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0);
pPager->nWrite++;
TEST_INCR(pPager->nWrite);
}
#ifndef NDEBUG
else{
@ -2372,10 +2379,10 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
if( pPg==0 ){
/* The requested page is not in the page cache. */
int h;
pPager->nMiss++;
TEST_INCR(pPager->nMiss);
if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 || MEMDB ){
/* Create a new page */
pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->psAligned
pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize
+ sizeof(u32) + pPager->nExtra
+ MEMDB*sizeof(PgHistory) );
if( pPg==0 ){
@ -2458,7 +2465,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
/* Unlink the old page from the free list and the hash table
*/
unlinkPage(pPg);
pPager->nOvfl++;
TEST_INCR(pPager->nOvfl);
}
pPg->pgno = pgno;
if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){
@ -2514,7 +2521,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
}
}else{
pPager->nRead++;
TEST_INCR(pPager->nRead);
}
}
#ifdef SQLITE_CHECK_PAGES
@ -2522,7 +2529,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
#endif
}else{
/* The requested page is in the page cache. */
pPager->nHit++;
TEST_INCR(pPager->nHit);
page_ref(pPg);
}
*ppPage = PGHDR_TO_DATA(pPg);
@ -3191,11 +3198,13 @@ int *sqlite3pager_stats(Pager *pPager){
a[3] = pPager->dbSize;
a[4] = pPager->state;
a[5] = pPager->errMask;
#ifdef SQLITE_TEST
a[6] = pPager->nHit;
a[7] = pPager->nMiss;
a[8] = pPager->nOvfl;
a[9] = pPager->nRead;
a[10] = pPager->nWrite;
#endif
return a;
}
@ -3591,3 +3600,5 @@ void sqlite3pager_refdump(Pager *pPager){
}
}
#endif
#endif /* SQLITE_OMIT_DISKIO */

Просмотреть файл

@ -13,7 +13,7 @@
** subsystem. The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback.
**
** @(#) $Id: pager.h,v 1.42 2005/03/21 04:04:03 danielk1977 Exp $
** @(#) $Id: pager.h,v 1.44 2005/05/20 20:01:56 drh Exp $
*/
/*
@ -23,12 +23,15 @@
# define SQLITE_DEFAULT_PAGE_SIZE 1024
#endif
/* Maximum page size. The upper bound on this value is 65536 (a limit
** imposed by the 2-byte size of cell array pointers.) The
** maximum page size determines the amount of stack space allocated
** by many of the routines in pager.c and btree.c On embedded architectures
** or any machine where memory and especially stack memory is limited,
** one may wish to chose a smaller value for the maximum page size.
/* Maximum page size. The upper bound on this value is 32768. This a limit
** imposed by necessity of storing the value in a 2-byte unsigned integer
** and the fact that the page size must be a power of 2.
**
** This value is used to initialize certain arrays on the stack at
** various places in the code. On embedded machines where stack space
** is limited and the flexibility of having large pages is not needed,
** it makes good sense to reduce the maximum page size to something more
** reasonable, like 1024.
*/
#ifndef SQLITE_MAX_PAGE_SIZE
# define SQLITE_MAX_PAGE_SIZE 8192
@ -68,7 +71,7 @@ int sqlite3pager_open(Pager **ppPager, const char *zFilename,
void sqlite3pager_set_busyhandler(Pager*, BusyHandler *pBusyHandler);
void sqlite3pager_set_destructor(Pager*, void(*)(void*,int));
void sqlite3pager_set_reiniter(Pager*, void(*)(void*,int));
void sqlite3pager_set_pagesize(Pager*, int);
int sqlite3pager_set_pagesize(Pager*, int);
void sqlite3pager_read_fileheader(Pager*, int, unsigned char*);
void sqlite3pager_set_cachesize(Pager*, int);
int sqlite3pager_close(Pager *pPager);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -6,42 +6,42 @@
#define TK_FUNCTION 6
#define TK_COLUMN 7
#define TK_AGG_FUNCTION 8
#define TK_SEMI 9
#define TK_EXPLAIN 10
#define TK_BEGIN 11
#define TK_TRANSACTION 12
#define TK_DEFERRED 13
#define TK_IMMEDIATE 14
#define TK_EXCLUSIVE 15
#define TK_COMMIT 16
#define TK_END 17
#define TK_ROLLBACK 18
#define TK_CREATE 19
#define TK_TABLE 20
#define TK_TEMP 21
#define TK_LP 22
#define TK_RP 23
#define TK_AS 24
#define TK_COMMA 25
#define TK_ID 26
#define TK_ABORT 27
#define TK_AFTER 28
#define TK_ASC 29
#define TK_ATTACH 30
#define TK_BEFORE 31
#define TK_CASCADE 32
#define TK_CONFLICT 33
#define TK_DATABASE 34
#define TK_DESC 35
#define TK_DETACH 36
#define TK_EACH 37
#define TK_FAIL 38
#define TK_FOR 39
#define TK_GLOB 40
#define TK_CONST_FUNC 9
#define TK_SEMI 10
#define TK_EXPLAIN 11
#define TK_BEGIN 12
#define TK_TRANSACTION 13
#define TK_DEFERRED 14
#define TK_IMMEDIATE 15
#define TK_EXCLUSIVE 16
#define TK_COMMIT 17
#define TK_END 18
#define TK_ROLLBACK 19
#define TK_CREATE 20
#define TK_TABLE 21
#define TK_TEMP 22
#define TK_LP 23
#define TK_RP 24
#define TK_AS 25
#define TK_COMMA 26
#define TK_ID 27
#define TK_ABORT 28
#define TK_AFTER 29
#define TK_ASC 30
#define TK_ATTACH 31
#define TK_BEFORE 32
#define TK_CASCADE 33
#define TK_CONFLICT 34
#define TK_DATABASE 35
#define TK_DESC 36
#define TK_DETACH 37
#define TK_EACH 38
#define TK_FAIL 39
#define TK_FOR 40
#define TK_IGNORE 41
#define TK_INITIALLY 42
#define TK_INSTEAD 43
#define TK_LIKE 44
#define TK_LIKE_KW 44
#define TK_MATCH 45
#define TK_KEY 46
#define TK_OF 47
@ -57,86 +57,84 @@
#define TK_VIEW 57
#define TK_REINDEX 58
#define TK_RENAME 59
#define TK_CDATE 60
#define TK_CTIME 61
#define TK_CTIMESTAMP 62
#define TK_ALTER 63
#define TK_OR 64
#define TK_AND 65
#define TK_NOT 66
#define TK_IS 67
#define TK_BETWEEN 68
#define TK_IN 69
#define TK_ISNULL 70
#define TK_NOTNULL 71
#define TK_NE 72
#define TK_EQ 73
#define TK_GT 74
#define TK_LE 75
#define TK_LT 76
#define TK_GE 77
#define TK_ESCAPE 78
#define TK_BITAND 79
#define TK_BITOR 80
#define TK_LSHIFT 81
#define TK_RSHIFT 82
#define TK_PLUS 83
#define TK_MINUS 84
#define TK_STAR 85
#define TK_SLASH 86
#define TK_REM 87
#define TK_CONCAT 88
#define TK_UMINUS 89
#define TK_UPLUS 90
#define TK_BITNOT 91
#define TK_STRING 92
#define TK_JOIN_KW 93
#define TK_CONSTRAINT 94
#define TK_DEFAULT 95
#define TK_NULL 96
#define TK_PRIMARY 97
#define TK_UNIQUE 98
#define TK_CHECK 99
#define TK_REFERENCES 100
#define TK_COLLATE 101
#define TK_AUTOINCR 102
#define TK_ON 103
#define TK_DELETE 104
#define TK_UPDATE 105
#define TK_INSERT 106
#define TK_SET 107
#define TK_DEFERRABLE 108
#define TK_FOREIGN 109
#define TK_DROP 110
#define TK_UNION 111
#define TK_ALL 112
#define TK_INTERSECT 113
#define TK_EXCEPT 114
#define TK_SELECT 115
#define TK_DISTINCT 116
#define TK_DOT 117
#define TK_FROM 118
#define TK_JOIN 119
#define TK_USING 120
#define TK_ORDER 121
#define TK_BY 122
#define TK_GROUP 123
#define TK_HAVING 124
#define TK_LIMIT 125
#define TK_WHERE 126
#define TK_INTO 127
#define TK_VALUES 128
#define TK_INTEGER 129
#define TK_FLOAT 130
#define TK_BLOB 131
#define TK_REGISTER 132
#define TK_VARIABLE 133
#define TK_EXISTS 134
#define TK_CASE 135
#define TK_WHEN 136
#define TK_THEN 137
#define TK_ELSE 138
#define TK_INDEX 139
#define TK_TO 140
#define TK_ADD 141
#define TK_COLUMNKW 142
#define TK_CTIME_KW 60
#define TK_ALTER 61
#define TK_OR 62
#define TK_AND 63
#define TK_NOT 64
#define TK_IS 65
#define TK_BETWEEN 66
#define TK_IN 67
#define TK_ISNULL 68
#define TK_NOTNULL 69
#define TK_NE 70
#define TK_EQ 71
#define TK_GT 72
#define TK_LE 73
#define TK_LT 74
#define TK_GE 75
#define TK_ESCAPE 76
#define TK_BITAND 77
#define TK_BITOR 78
#define TK_LSHIFT 79
#define TK_RSHIFT 80
#define TK_PLUS 81
#define TK_MINUS 82
#define TK_STAR 83
#define TK_SLASH 84
#define TK_REM 85
#define TK_CONCAT 86
#define TK_UMINUS 87
#define TK_UPLUS 88
#define TK_BITNOT 89
#define TK_STRING 90
#define TK_JOIN_KW 91
#define TK_CONSTRAINT 92
#define TK_DEFAULT 93
#define TK_NULL 94
#define TK_PRIMARY 95
#define TK_UNIQUE 96
#define TK_CHECK 97
#define TK_REFERENCES 98
#define TK_COLLATE 99
#define TK_AUTOINCR 100
#define TK_ON 101
#define TK_DELETE 102
#define TK_UPDATE 103
#define TK_INSERT 104
#define TK_SET 105
#define TK_DEFERRABLE 106
#define TK_FOREIGN 107
#define TK_DROP 108
#define TK_UNION 109
#define TK_ALL 110
#define TK_INTERSECT 111
#define TK_EXCEPT 112
#define TK_SELECT 113
#define TK_DISTINCT 114
#define TK_DOT 115
#define TK_FROM 116
#define TK_JOIN 117
#define TK_USING 118
#define TK_ORDER 119
#define TK_BY 120
#define TK_GROUP 121
#define TK_HAVING 122
#define TK_LIMIT 123
#define TK_WHERE 124
#define TK_INTO 125
#define TK_VALUES 126
#define TK_INTEGER 127
#define TK_FLOAT 128
#define TK_BLOB 129
#define TK_REGISTER 130
#define TK_VARIABLE 131
#define TK_EXISTS 132
#define TK_CASE 133
#define TK_WHEN 134
#define TK_THEN 135
#define TK_ELSE 136
#define TK_INDEX 137
#define TK_TO 138
#define TK_ADD 139
#define TK_COLUMNKW 140

Просмотреть файл

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.91 2005/03/29 03:10:59 danielk1977 Exp $
** $Id: pragma.c,v 1.95 2005/06/12 21:35:52 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -19,7 +19,7 @@
/* Ignore this whole file if pragmas are disabled
*/
#ifndef SQLITE_OMIT_PRAGMA
#if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER)
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
# include "pager.h"
@ -693,7 +693,7 @@ void sqlite3Pragma(
static const VdbeOpList idxErr[] = {
{ OP_MemIncr, 0, 0, 0},
{ OP_String8, 0, 0, "rowid "},
{ OP_Recno, 1, 0, 0},
{ OP_Rowid, 1, 0, 0},
{ OP_String8, 0, 0, " missing from index "},
{ OP_String8, 0, 0, 0}, /* 4 */
{ OP_Concat, 2, 0, 0},
@ -905,6 +905,17 @@ void sqlite3Pragma(
}else
#endif
#ifdef SQLITE_SSE
/*
** Check to see if the sqlite_statements table exists. Create it
** if it does not.
*/
if( sqlite3StrICmp(zLeft, "create_sqlite_statement_table")==0 ){
extern int sqlite3CreateStatementsTable(Parse*);
sqlite3CreateStatementsTable(pParse);
}else
#endif
{}
if( v ){
@ -919,4 +930,4 @@ pragma_out:
sqliteFree(zRight);
}
#endif /* SQLITE_OMIT_PRAGMA */
#endif /* SQLITE_OMIT_PRAGMA || SQLITE_OMIT_PARSER */

529
db/sqlite3/src/prepare.c Normal file
Просмотреть файл

@ -0,0 +1,529 @@
/*
** 2005 May 25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the implementation of the sqlite3_prepare()
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.1 2005-08-20 01:23:48 vladimir%pobox.com Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
/*
** Fill the InitData structure with an error message that indicates
** that the database is corrupt.
*/
static void corruptSchema(InitData *pData, const char *zExtra){
if( !sqlite3_malloc_failed ){
sqlite3SetString(pData->pzErrMsg, "malformed database schema",
zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);
}
}
/*
** This is the callback routine for the code that initializes the
** database. See sqlite3Init() below for additional information.
** This routine is also called from the OP_ParseSchema opcode of the VDBE.
**
** Each callback contains the following information:
**
** argv[0] = name of thing being created
** argv[1] = root page number for table or index. NULL for trigger or view.
** argv[2] = SQL text for the CREATE statement.
** argv[3] = "1" for temporary files, "0" for main database, "2" or more
** for auxiliary database files.
**
*/
int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){
InitData *pData = (InitData*)pInit;
sqlite3 *db = pData->db;
int iDb;
assert( argc==4 );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[1]==0 || argv[3]==0 ){
corruptSchema(pData, 0);
return 1;
}
iDb = atoi(argv[3]);
assert( iDb>=0 && iDb<db->nDb );
if( argv[2] && argv[2][0] ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
** But because db->init.busy is set to 1, no VDBE code is generated
** or executed. All the parser does is build the internal data
** structures that describe the table, index, or view.
*/
char *zErr;
int rc;
assert( db->init.busy );
db->init.iDb = iDb;
db->init.newTnum = atoi(argv[1]);
rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
db->init.iDb = 0;
if( SQLITE_OK!=rc ){
corruptSchema(pData, zErr);
sqlite3_free(zErr);
return rc;
}
}else{
/* If the SQL column is blank it means this is an index that
** was created to be the PRIMARY KEY or to fulfill a UNIQUE
** constraint for a CREATE TABLE. The index should have already
** been created when we processed the CREATE TABLE. All we have
** to do here is record the root page number for that index.
*/
Index *pIndex;
pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName);
if( pIndex==0 || pIndex->tnum!=0 ){
/* This can occur if there exists an index on a TEMP table which
** has the same name as another index on a permanent index. Since
** the permanent table is hidden by the TEMP table, we can also
** safely ignore the index on the permanent table.
*/
/* Do Nothing */;
}else{
pIndex->tnum = atoi(argv[1]);
}
}
return 0;
}
/*
** Attempt to read the database schema and initialize internal
** data structures for a single database file. The index of the
** database file is given by iDb. iDb==0 is used for the main
** database. iDb==1 should never be used. iDb>=2 is used for
** auxiliary databases. Return one of the SQLITE_ error codes to
** indicate success or failure.
*/
static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
int rc;
BtCursor *curMain;
int size;
Table *pTab;
char const *azArg[5];
char zDbNum[30];
int meta[10];
InitData initData;
char const *zMasterSchema;
char const *zMasterName = SCHEMA_TABLE(iDb);
/*
** The master database table has a structure like this
*/
static const char master_schema[] =
"CREATE TABLE sqlite_master(\n"
" type text,\n"
" name text,\n"
" tbl_name text,\n"
" rootpage integer,\n"
" sql text\n"
")"
;
#ifndef SQLITE_OMIT_TEMPDB
static const char temp_master_schema[] =
"CREATE TEMP TABLE sqlite_temp_master(\n"
" type text,\n"
" name text,\n"
" tbl_name text,\n"
" rootpage integer,\n"
" sql text\n"
")"
;
#else
#define temp_master_schema 0
#endif
assert( iDb>=0 && iDb<db->nDb );
/* zMasterSchema and zInitScript are set to point at the master schema
** and initialisation script appropriate for the database being
** initialised. zMasterName is the name of the master table.
*/
if( !OMIT_TEMPDB && iDb==1 ){
zMasterSchema = temp_master_schema;
}else{
zMasterSchema = master_schema;
}
zMasterName = SCHEMA_TABLE(iDb);
/* Construct the schema tables. */
sqlite3SafetyOff(db);
azArg[0] = zMasterName;
azArg[1] = "1";
azArg[2] = zMasterSchema;
sprintf(zDbNum, "%d", iDb);
azArg[3] = zDbNum;
azArg[4] = 0;
initData.db = db;
initData.pzErrMsg = pzErrMsg;
rc = sqlite3InitCallback(&initData, 4, (char **)azArg, 0);
if( rc!=SQLITE_OK ){
sqlite3SafetyOn(db);
return rc;
}
pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
if( pTab ){
pTab->readOnly = 1;
}
sqlite3SafetyOn(db);
/* Create a cursor to hold the database open
*/
if( db->aDb[iDb].pBt==0 ){
if( !OMIT_TEMPDB && iDb==1 ) DbSetProperty(db, 1, DB_SchemaLoaded);
return SQLITE_OK;
}
rc = sqlite3BtreeCursor(db->aDb[iDb].pBt, MASTER_ROOT, 0, 0, 0, &curMain);
if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){
sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
return rc;
}
/* Get the database meta information.
**
** Meta values are as follows:
** meta[0] Schema cookie. Changes with each schema change.
** meta[1] File format of schema layer.
** meta[2] Size of the page cache.
** meta[3] Use freelist if 0. Autovacuum if greater than zero.
** meta[4] Db text encoding. 1:UTF-8 3:UTF-16 LE 4:UTF-16 BE
** meta[5] The user cookie. Used by the application.
** meta[6]
** meta[7]
** meta[8]
** meta[9]
**
** Note: The hash defined SQLITE_UTF* symbols in sqliteInt.h correspond to
** the possible values of meta[4].
*/
if( rc==SQLITE_OK ){
int i;
for(i=0; rc==SQLITE_OK && i<sizeof(meta)/sizeof(meta[0]); i++){
rc = sqlite3BtreeGetMeta(db->aDb[iDb].pBt, i+1, (u32 *)&meta[i]);
}
if( rc ){
sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
sqlite3BtreeCloseCursor(curMain);
return rc;
}
}else{
memset(meta, 0, sizeof(meta));
}
db->aDb[iDb].schema_cookie = meta[0];
/* If opening a non-empty database, check the text encoding. For the
** main database, set sqlite3.enc to the encoding of the main database.
** For an attached db, it is an error if the encoding is not the same
** as sqlite3.enc.
*/
if( meta[4] ){ /* text encoding */
if( iDb==0 ){
/* If opening the main database, set db->enc. */
db->enc = (u8)meta[4];
db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0);
}else{
/* If opening an attached database, the encoding much match db->enc */
if( meta[4]!=db->enc ){
sqlite3BtreeCloseCursor(curMain);
sqlite3SetString(pzErrMsg, "attached databases must use the same"
" text encoding as main database", (char*)0);
return SQLITE_ERROR;
}
}
}
size = meta[2];
if( size==0 ){ size = MAX_PAGES; }
db->aDb[iDb].cache_size = size;
if( iDb==0 ){
db->file_format = meta[1];
if( db->file_format==0 ){
/* This happens if the database was initially empty */
db->file_format = 1;
}
if( db->file_format==2 || db->file_format==3 ){
/* File format 2 is treated exactly as file format 1. New
** databases are created with file format 1.
*/
db->file_format = 1;
}
}
/*
** file_format==1 Version 3.0.0.
** file_format==2 Version 3.1.3.
** file_format==3 Version 3.1.4.
**
** Version 3.0 can only use files with file_format==1. Version 3.1.3
** can read and write files with file_format==1 or file_format==2.
** Version 3.1.4 can read and write file formats 1, 2 and 3.
*/
if( meta[1]>3 ){
sqlite3BtreeCloseCursor(curMain);
sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0);
return SQLITE_ERROR;
}
sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->aDb[iDb].cache_size);
/* Read the schema information out of the schema tables
*/
assert( db->init.busy );
if( rc==SQLITE_EMPTY ){
/* For an empty database, there is nothing to read */
rc = SQLITE_OK;
}else{
char *zSql;
zSql = sqlite3MPrintf(
"SELECT name, rootpage, sql, '%s' FROM '%q'.%s",
zDbNum, db->aDb[iDb].zName, zMasterName);
sqlite3SafetyOff(db);
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
sqlite3SafetyOn(db);
sqliteFree(zSql);
sqlite3BtreeCloseCursor(curMain);
}
if( sqlite3_malloc_failed ){
sqlite3SetString(pzErrMsg, "out of memory", (char*)0);
rc = SQLITE_NOMEM;
sqlite3ResetInternalSchema(db, 0);
}
if( rc==SQLITE_OK ){
DbSetProperty(db, iDb, DB_SchemaLoaded);
}else{
sqlite3ResetInternalSchema(db, iDb);
}
return rc;
}
/*
** Initialize all database files - the main database file, the file
** used to store temporary tables, and any additional database files
** created using ATTACH statements. Return a success code. If an
** error occurs, write an error message into *pzErrMsg.
**
** After the database is initialized, the SQLITE_Initialized
** bit is set in the flags field of the sqlite structure.
*/
int sqlite3Init(sqlite3 *db, char **pzErrMsg){
int i, rc;
if( db->init.busy ) return SQLITE_OK;
assert( (db->flags & SQLITE_Initialized)==0 );
rc = SQLITE_OK;
db->init.busy = 1;
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
rc = sqlite3InitOne(db, i, pzErrMsg);
if( rc ){
sqlite3ResetInternalSchema(db, i);
}
}
/* Once all the other databases have been initialised, load the schema
** for the TEMP database. This is loaded last, as the TEMP database
** schema may contain references to objects in other databases.
*/
#ifndef SQLITE_OMIT_TEMPDB
if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
rc = sqlite3InitOne(db, 1, pzErrMsg);
if( rc ){
sqlite3ResetInternalSchema(db, 1);
}
}
#endif
db->init.busy = 0;
if( rc==SQLITE_OK ){
db->flags |= SQLITE_Initialized;
sqlite3CommitInternalChanges(db);
}
if( rc!=SQLITE_OK ){
db->flags &= ~SQLITE_Initialized;
}
return rc;
}
/*
** This routine is a no-op if the database schema is already initialised.
** Otherwise, the schema is loaded. An error code is returned.
*/
int sqlite3ReadSchema(Parse *pParse){
int rc = SQLITE_OK;
sqlite3 *db = pParse->db;
if( !db->init.busy ){
if( (db->flags & SQLITE_Initialized)==0 ){
rc = sqlite3Init(db, &pParse->zErrMsg);
}
}
assert( rc!=SQLITE_OK || (db->flags & SQLITE_Initialized)||db->init.busy );
if( rc!=SQLITE_OK ){
pParse->rc = rc;
pParse->nErr++;
}
return rc;
}
/*
** Check schema cookies in all databases. If any cookie is out
** of date, return 0. If all schema cookies are current, return 1.
*/
static int schemaIsValid(sqlite3 *db){
int iDb;
int rc;
BtCursor *curTemp;
int cookie;
int allOk = 1;
for(iDb=0; allOk && iDb<db->nDb; iDb++){
Btree *pBt;
pBt = db->aDb[iDb].pBt;
if( pBt==0 ) continue;
rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, 0, &curTemp);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie);
if( rc==SQLITE_OK && cookie!=db->aDb[iDb].schema_cookie ){
allOk = 0;
}
sqlite3BtreeCloseCursor(curTemp);
}
}
return allOk;
}
/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
int sqlite3_prepare(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char** pzTail /* OUT: End of parsed string */
){
Parse sParse;
char *zErrMsg = 0;
int rc = SQLITE_OK;
if( sqlite3_malloc_failed ){
return SQLITE_NOMEM;
}
assert( ppStmt );
*ppStmt = 0;
if( sqlite3SafetyOn(db) ){
return SQLITE_MISUSE;
}
memset(&sParse, 0, sizeof(sParse));
sParse.db = db;
sqlite3RunParser(&sParse, zSql, &zErrMsg);
if( sqlite3_malloc_failed ){
rc = SQLITE_NOMEM;
sqlite3RollbackAll(db);
sqlite3ResetInternalSchema(db, 0);
db->flags &= ~SQLITE_InTrans;
goto prepare_out;
}
if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
if( sParse.rc!=SQLITE_OK && sParse.checkSchema && !schemaIsValid(db) ){
sParse.rc = SQLITE_SCHEMA;
}
if( sParse.rc==SQLITE_SCHEMA ){
sqlite3ResetInternalSchema(db, 0);
}
if( pzTail ) *pzTail = sParse.zTail;
rc = sParse.rc;
#ifndef SQLITE_OMIT_EXPLAIN
if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
sqlite3VdbeSetNumCols(sParse.pVdbe, 5);
sqlite3VdbeSetColName(sParse.pVdbe, 0, "addr", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 1, "opcode", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 2, "p1", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 3, "p2", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 4, "p3", P3_STATIC);
}
#endif
prepare_out:
if( sqlite3SafetyOff(db) ){
rc = SQLITE_MISUSE;
}
if( rc==SQLITE_OK ){
*ppStmt = (sqlite3_stmt*)sParse.pVdbe;
}else if( sParse.pVdbe ){
sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
}
if( zErrMsg ){
sqlite3Error(db, rc, "%s", zErrMsg);
sqliteFree(zErrMsg);
}else{
sqlite3Error(db, rc, 0);
}
return rc;
}
#ifndef SQLITE_OMIT_UTF16
/*
** Compile the UTF-16 encoded SQL statement zSql into a statement handle.
*/
int sqlite3_prepare16(
sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const void **pzTail /* OUT: End of parsed string */
){
/* This function currently works by first transforming the UTF-16
** encoded string to UTF-8, then invoking sqlite3_prepare(). The
** tricky bit is figuring out the pointer to return in *pzTail.
*/
char const *zSql8 = 0;
char const *zTail8 = 0;
int rc;
sqlite3_value *pTmp;
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
pTmp = sqlite3GetTransientValue(db);
sqlite3ValueSetStr(pTmp, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
zSql8 = sqlite3ValueText(pTmp, SQLITE_UTF8);
if( !zSql8 ){
sqlite3Error(db, SQLITE_NOMEM, 0);
return SQLITE_NOMEM;
}
rc = sqlite3_prepare(db, zSql8, -1, ppStmt, &zTail8);
if( zTail8 && pzTail ){
/* If sqlite3_prepare returns a tail pointer, we calculate the
** equivalent pointer into the UTF-16 string by counting the unicode
** characters between zSql8 and zTail8, and then returning a pointer
** the same number of characters into the UTF-16 string.
*/
int chars_parsed = sqlite3utf8CharLen(zSql8, zTail8-zSql8);
*pzTail = (u8 *)zSql + sqlite3utf16ByteLen(zSql, chars_parsed);
}
return rc;
}
#endif /* SQLITE_OMIT_UTF16 */

Просмотреть файл

@ -15,7 +15,7 @@
** Random numbers are used by some of the database backends in order
** to generate random integer keys for tables or random filenames.
**
** $Id: random.c,v 1.12 2004/05/08 08:23:32 danielk1977 Exp $
** $Id: random.c,v 1.13 2005/06/12 21:35:52 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -26,13 +26,16 @@
** must be held while executing this routine.
**
** Why not just use a library random generator like lrand48() for this?
** Because the OP_NewRecno opcode in the VDBE depends on having a very
** Because the OP_NewRowid opcode in the VDBE depends on having a very
** good source of random numbers. The lrand48() library function may
** well be good enough. But maybe not. Or maybe lrand48() has some
** subtle problems on some systems that could cause problems. It is hard
** to know. To minimize the risk of problems due to bad lrand48()
** implementations, SQLite uses this random number generator based
** on RC4, which we know works very well.
**
** (Later): Actually, OP_NewRowid does not depend on a good source of
** randomness any more. But we will leave this code in all the same.
*/
static int randomByte(){
unsigned char t;
@ -95,6 +98,3 @@ void sqlite3Randomness(int N, void *pBuf){
}
sqlite3OsLeaveMutex();
}

Просмотреть файл

@ -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.243 2005/03/28 03:39:56 drh Exp $
** $Id: select.c,v 1.252 2005/06/12 21:35:52 drh Exp $
*/
#include "sqliteInt.h"
@ -326,7 +326,7 @@ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){
sqlite3ExprCode(pParse, pOrderBy->a[i].pExpr);
}
sqlite3VdbeAddOp(v, OP_MakeRecord, pOrderBy->nExpr, 0);
sqlite3VdbeAddOp(v, OP_SortPut, 0, 0);
sqlite3VdbeAddOp(v, OP_SortInsert, 0, 0);
}
/*
@ -422,8 +422,7 @@ static int selectInnerLoop(
sqlite3VdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0);
sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue);
VdbeComment((v, "# skip indistinct records"));
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
sqlite3VdbeAddOp(v, OP_PutStrKey, distinct, 0);
sqlite3VdbeAddOp(v, OP_IdxInsert, distinct, 0);
if( pOrderBy==0 ){
codeLimiter(v, p, iContinue, iBreak, nColumn);
}
@ -437,8 +436,7 @@ static int selectInnerLoop(
case SRT_Union: {
sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);
sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC);
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
sqlite3VdbeAddOp(v, OP_PutStrKey, iParm, 0);
sqlite3VdbeAddOp(v, OP_IdxInsert, iParm, 0);
break;
}
@ -464,9 +462,9 @@ static int selectInnerLoop(
if( pOrderBy ){
pushOntoSorter(pParse, v, pOrderBy);
}else{
sqlite3VdbeAddOp(v, OP_NewRecno, iParm, 0);
sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
sqlite3VdbeAddOp(v, OP_PutIntKey, iParm, 0);
sqlite3VdbeAddOp(v, OP_Insert, iParm, 0);
}
break;
}
@ -490,8 +488,7 @@ static int selectInnerLoop(
char aff = (iParm>>16)&0xFF;
aff = sqlite3CompareAffinity(pEList->a[0].pExpr, aff);
sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &aff, 1);
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0);
sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);
}
sqlite3VdbeChangeP2(v, addr2, sqlite3VdbeCurrentAddr(v));
break;
@ -603,9 +600,9 @@ static void generateSortTail(
switch( eDest ){
case SRT_Table:
case SRT_TempTable: {
sqlite3VdbeAddOp(v, OP_NewRecno, iParm, 0);
sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
sqlite3VdbeAddOp(v, OP_PutIntKey, iParm, 0);
sqlite3VdbeAddOp(v, OP_Insert, iParm, 0);
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
@ -615,8 +612,7 @@ static void generateSortTail(
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);
sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, "n", P3_STATIC);
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0);
sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);
break;
}
case SRT_Exists:
@ -689,6 +685,20 @@ static const char *columnType(NameContext *pNC, Expr *pExpr){
pNC = pNC->pNext;
}
}
if( pTab==0 ){
/* FIX ME:
** This can occurs if you have something like "SELECT new.x;" inside
** a trigger. In other words, if you reference the special "new"
** table in the result set of a select. We do not have a good way
** to find the actual table type, so call it "TEXT". This is really
** something of a bug, but I do not know how to fix it.
**
** This code does not produce the correct answer - it just prevents
** a segfault. See ticket #1229.
*/
zType = "TEXT";
break;
}
assert( pTab );
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
@ -858,6 +868,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
if( pTab==0 ){
return 0;
}
pTab->nRef = 1;
pTab->zName = zTabName ? sqliteStrDup(zTabName) : 0;
pEList = pSelect->pEList;
pTab->nCol = pEList->nExpr;
@ -915,6 +926,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
/* Get the typename, type affinity, and collating sequence for the
** column.
*/
memset(&sNC, 0, sizeof(sNC));
sNC.pSrcList = pSelect->pSrc;
zType = sqliteStrDup(columnType(&sNC, p));
pCol->zType = zType;
@ -989,6 +1001,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){
pFrom->zAlias =
sqlite3MPrintf("sqlite_subquery_%p_", (void*)pFrom->pSelect);
}
assert( pFrom->pTab==0 );
pFrom->pTab = pTab =
sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect);
if( pTab==0 ){
@ -1002,11 +1015,13 @@ static int prepSelectStmt(Parse *pParse, Select *p){
#endif
}else{
/* An ordinary table or view name in the FROM clause */
assert( pFrom->pTab==0 );
pFrom->pTab = pTab =
sqlite3LocateTable(pParse,pFrom->zName,pFrom->zDatabase);
if( pTab==0 ){
return 1;
}
pTab->nRef++;
#ifndef SQLITE_OMIT_VIEW
if( pTab->pSelect ){
/* We reach here if the named table is a really a view */
@ -1055,6 +1070,10 @@ static int prepSelectStmt(Parse *pParse, Select *p){
*/
struct ExprList_item *a = pEList->a;
ExprList *pNew = 0;
int flags = pParse->db->flags;
int longNames = (flags & SQLITE_FullColNames)!=0 &&
(flags & SQLITE_ShortColNames)==0;
for(k=0; k<pEList->nExpr; k++){
Expr *pE = a[k].pExpr;
if( pE->op!=TK_ALL &&
@ -1107,7 +1126,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){
pRight = sqlite3Expr(TK_ID, 0, 0, 0);
if( pRight==0 ) break;
setToken(&pRight->token, zName);
if( zTabName && pTabList->nSrc>1 ){
if( zTabName && (longNames || pTabList->nSrc>1) ){
pLeft = sqlite3Expr(TK_ID, 0, 0, 0);
pExpr = sqlite3Expr(TK_DOT, pLeft, pRight, 0);
if( pExpr==0 ) break;
@ -1121,7 +1140,11 @@ static int prepSelectStmt(Parse *pParse, Select *p){
pExpr = pRight;
pExpr->span = pExpr->token;
}
pNew = sqlite3ExprListAppend(pNew, pExpr, &pRight->token);
if( longNames ){
pNew = sqlite3ExprListAppend(pNew, pExpr, &pExpr->span);
}else{
pNew = sqlite3ExprListAppend(pNew, pExpr, &pRight->token);
}
}
}
if( !tableSeen ){
@ -1141,40 +1164,6 @@ static int prepSelectStmt(Parse *pParse, Select *p){
return rc;
}
/*
** This routine recursively unlinks the Select.pSrc.a[].pTab pointers
** in a select structure. It just sets the pointers to NULL. This
** routine is recursive in the sense that if the Select.pSrc.a[].pSelect
** pointer is not NULL, this routine is called recursively on that pointer.
**
** This routine is called on the Select structure that defines a
** VIEW in order to undo any bindings to tables. This is necessary
** because those tables might be DROPed by a subsequent SQL command.
** If the bindings are not removed, then the Select.pSrc->a[].pTab field
** will be left pointing to a deallocated Table structure after the
** DROP and a coredump will occur the next time the VIEW is used.
*/
#if 0
void sqlite3SelectUnbind(Select *p){
int i;
SrcList *pSrc = p->pSrc;
struct SrcList_item *pItem;
Table *pTab;
if( p==0 ) return;
for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
if( (pTab = pItem->pTab)!=0 ){
if( pTab->isTransient ){
sqlite3DeleteTable(0, pTab);
}
pItem->pTab = 0;
if( pItem->pSelect ){
sqlite3SelectUnbind(pItem->pSelect);
}
}
}
}
#endif
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** This routine associates entries in an ORDER BY expression list with
@ -1333,11 +1322,9 @@ static void computeLimitRegisters(Parse *pParse, Select *p){
** DISTINCT, UNION, INTERSECT and EXCEPT select statements (but not
** UNION ALL).
**
** Make the new table a KeyAsData table if keyAsData is true.
**
** The value returned is the address of the OP_OpenTemp instruction.
*/
static int openTempIndex(Parse *pParse, Select *p, int iTab, int keyAsData){
static int openTempIndex(Parse *pParse, Select *p, int iTab){
KeyInfo *pKeyInfo;
int nColumn;
sqlite3 *db = pParse->db;
@ -1361,9 +1348,6 @@ static int openTempIndex(Parse *pParse, Select *p, int iTab, int keyAsData){
}
addr = sqlite3VdbeOp3(v, OP_OpenTemp, iTab, 0,
(char*)pKeyInfo, P3_KEYINFO_HANDOFF);
if( keyAsData ){
sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1);
}
return addr;
}
@ -1558,7 +1542,6 @@ static int multiSelect(
if( rc!=SQLITE_OK ){
goto multi_select_end;
}
sqlite3VdbeAddOp(v, OP_KeyAsData, unionTab, 1);
}
assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) );
aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, unionTab, 0);
@ -1650,7 +1633,6 @@ static int multiSelect(
if( rc!=SQLITE_OK ){
goto multi_select_end;
}
sqlite3VdbeAddOp(v, OP_KeyAsData, tab1, 1);
assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) );
aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, tab1, 0);
assert( p->pEList );
@ -1669,7 +1651,6 @@ static int multiSelect(
if( rc!=SQLITE_OK ){
goto multi_select_end;
}
sqlite3VdbeAddOp(v, OP_KeyAsData, tab2, 1);
assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) );
aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, tab2, 0);
p->pPrior = 0;
@ -1697,7 +1678,7 @@ static int multiSelect(
iCont = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp(v, OP_Rewind, tab1, iBreak);
computeLimitRegisters(pParse, p);
iStart = sqlite3VdbeAddOp(v, OP_FullKey, tab1, 0);
iStart = sqlite3VdbeAddOp(v, OP_RowKey, tab1, 0);
sqlite3VdbeAddOp(v, OP_NotFound, tab2, iCont);
rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
p->pOrderBy, -1, eDest, iParm,
@ -2025,11 +2006,8 @@ static int flattenSubquery(
{
int nSubSrc = pSubSrc->nSrc;
int jointype = pSubitem->jointype;
Table *pTab = pSubitem->pTab;
if( pTab && pTab->isTransient ){
sqlite3DeleteTable(0, pSubitem->pTab);
}
sqlite3DeleteTable(0, pSubitem->pTab);
sqliteFree(pSubitem->zDatabase);
sqliteFree(pSubitem->zName);
sqliteFree(pSubitem->zAlias);
@ -2236,12 +2214,12 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
sqlite3VdbeOp3(v, OP_OpenRead, iIdx, pIdx->tnum,
(char*)&pIdx->keyInfo, P3_KEYINFO);
if( seekOp==OP_Rewind ){
sqlite3VdbeAddOp(v, OP_String, 0, 0);
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
sqlite3VdbeAddOp(v, OP_MakeRecord, 1, 0);
seekOp = OP_MoveGt;
}
sqlite3VdbeAddOp(v, seekOp, iIdx, 0);
sqlite3VdbeAddOp(v, OP_IdxRecno, iIdx, 0);
sqlite3VdbeAddOp(v, OP_IdxRowid, iIdx, 0);
sqlite3VdbeAddOp(v, OP_Close, iIdx, 0);
sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
}
@ -2720,7 +2698,14 @@ int sqlite3Select(
for(i=0; i<pParse->nAgg; i++){
FuncDef *pFunc;
if( (pFunc = pParse->aAgg[i].pFunc)!=0 && pFunc->xFinalize!=0 ){
sqlite3VdbeOp3(v, OP_AggInit, 0, i, (char*)pFunc, P3_FUNCDEF);
int nExpr = 0;
#ifdef SQLITE_SSE
Expr *pAggExpr = pParse->aAgg[i].pExpr;
if( pAggExpr && pAggExpr->pList ){
nExpr = pAggExpr->pList->nExpr;
}
#endif
sqlite3VdbeOp3(v, OP_AggInit, nExpr, i, (char*)pFunc, P3_FUNCDEF);
}
}
if( pGroupBy ){
@ -2744,7 +2729,7 @@ int sqlite3Select(
/* Initialize the memory cell to NULL for SRT_Mem or 0 for SRT_Exists
*/
if( eDest==SRT_Mem || eDest==SRT_Exists ){
sqlite3VdbeAddOp(v, eDest==SRT_Mem ? OP_String8 : OP_Integer, 0, 0);
sqlite3VdbeAddOp(v, eDest==SRT_Mem ? OP_Null : OP_Integer, 0, 0);
sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
}
@ -2752,7 +2737,7 @@ int sqlite3Select(
*/
if( isDistinct ){
distinct = pParse->nTab++;
openTempIndex(pParse, p, distinct, 0);
openTempIndex(pParse, p, distinct);
}else{
distinct = -1;
}
@ -2760,7 +2745,7 @@ int sqlite3Select(
/* Begin the database scan
*/
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,
pGroupBy ? 0 : &pOrderBy, p->pFetch);
pGroupBy ? 0 : &pOrderBy);
if( pWInfo==0 ) goto select_end;
/* Use the standard inner loop if we are not dealing with
@ -2821,7 +2806,7 @@ int sqlite3Select(
if( !pColl ) pColl = pParse->db->pDfltColl;
sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ);
}
sqlite3VdbeOp3(v, OP_AggFunc, 0, nExpr, (char*)pDef, P3_POINTER);
sqlite3VdbeOp3(v, OP_AggFunc, 0, nExpr, (char*)pDef, P3_FUNCDEF);
}
}

Просмотреть файл

1281
db/sqlite3/src/sqlite3.h Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.375 2005/03/29 03:10:59 danielk1977 Exp $
** @(#) $Id: sqliteInt.h,v 1.387 2005/06/12 21:35:52 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@ -40,6 +40,7 @@
#endif
#include "config.h"
#include "sqlite3.h"
#include "hash.h"
#include "parse.h"
@ -180,20 +181,6 @@
#ifndef LONGDOUBLE_TYPE
# define LONGDOUBLE_TYPE long double
#endif
#ifndef INTPTR_TYPE
# if SQLITE_PTR_SZ==4
# define INTPTR_TYPE int
# else
# define INTPTR_TYPE sqlite_int64
# endif
#endif
#ifndef UINTPTR_TYPE
# if SQLITE_PTR_SZ==4
# define UINTPTR_TYPE unsigned int
# else
# define UINTPTR_TYPE sqlite_uint64
# endif
#endif
typedef sqlite_int64 i64; /* 8-byte signed integer */
typedef UINT64_TYPE u64; /* 8-byte unsigned integer */
typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
@ -201,8 +188,6 @@ typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
typedef INT16_TYPE i16; /* 2-byte signed integer */
typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
typedef UINT8_TYPE i8; /* 1-byte signed integer */
typedef INTPTR_TYPE ptr; /* Big enough to hold a pointer */
typedef UINTPTR_TYPE uptr; /* Big enough to hold a pointer */
/*
** Macros to determine whether the machine is big or little endian,
@ -317,7 +302,6 @@ extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */
typedef struct Column Column;
typedef struct Table Table;
typedef struct Index Index;
typedef struct Instruction Instruction;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct Parse Parse;
@ -339,7 +323,6 @@ typedef struct KeyClass KeyClass;
typedef struct CollSeq CollSeq;
typedef struct KeyInfo KeyInfo;
typedef struct NameContext NameContext;
typedef struct Fetch Fetch;
/*
** Each database file to be accessed by the system is an instance
@ -418,16 +401,13 @@ struct Db {
struct sqlite3 {
int nDb; /* Number of backends currently in use */
Db *aDb; /* All backends */
Db aDbStatic[2]; /* Static space for the 2 default backends */
int flags; /* Miscellanous flags. See below */
int errCode; /* Most recent error code (SQLITE_*) */
u8 enc; /* Text encoding for this database. */
u8 autoCommit; /* The auto-commit flag. */
u8 file_format; /* What file format version is this database? */
u8 temp_store; /* 1: file 2: memory 0: default */
int nTable; /* Number of tables in the database */
BusyHandler busyHandler; /* Busy callback */
void *pCommitArg; /* Argument to xCommitCallback() */
int (*xCommitCallback)(void*);/* Invoked at every commit. */
Hash aFunc; /* All functions that can be in SQL exprs */
Hash aCollSeq; /* All collating sequences */
CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
i64 lastRowid; /* ROWID of most recent insert (see above) */
i64 priorNewRowid; /* Last randomly generated ROWID */
@ -443,6 +423,15 @@ struct sqlite3 {
int activeVdbeCnt; /* Number of vdbes currently executing */
void (*xTrace)(void*,const char*); /* Trace function */
void *pTraceArg; /* Argument to the trace function */
void *pCommitArg; /* Argument to xCommitCallback() */
int (*xCommitCallback)(void*);/* Invoked at every commit. */
void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
void *pCollNeededArg;
sqlite3_value *pValue; /* Value used for transient conversions */
sqlite3_value *pErr; /* Most recent error message */
char *zErrMsg; /* Most recent error message (UTF-8 encoded) */
char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */
#ifndef SQLITE_OMIT_AUTHORIZATION
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
/* Access authorization function */
@ -453,18 +442,16 @@ struct sqlite3 {
void *pProgressArg; /* Argument to the progress callback */
int nProgressOps; /* Number of opcodes for progress callback */
#endif
int errCode; /* Most recent error code (SQLITE_*) */
u8 enc; /* Text encoding for this database. */
u8 autoCommit; /* The auto-commit flag. */
void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
void *pCollNeededArg;
sqlite3_value *pValue; /* Value used for transient conversions */
sqlite3_value *pErr; /* Most recent error message */
char *zErrMsg; /* Most recent error message (UTF-8 encoded) */
char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */
#ifndef SQLITE_OMIT_GLOBALRECOVER
sqlite3 *pNext; /* Linked list of open db handles. */
#endif
Hash aFunc; /* All functions that can be in SQL exprs */
Hash aCollSeq; /* All collating sequences */
BusyHandler busyHandler; /* Busy callback */
int busyTimeout; /* Busy handler timeout, in msec */
Db aDbStatic[2]; /* Static space for the 2 default backends */
#ifdef SQLITE_SSE
sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */
#endif
};
@ -622,6 +609,7 @@ struct Table {
u8 hasPrimKey; /* True if there exists a primary key */
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
u8 autoInc; /* True if the integer primary key is autoincrement */
int nRef; /* Number of pointers to this Table */
Trigger *pTrigger; /* List of SQL triggers on this table */
FKey *pFKey; /* Linked list of all foreign keys in this table */
char *zColAff; /* String defining the affinity of each column */
@ -717,7 +705,8 @@ struct FKey {
** comparison of the two index keys.
**
** If the KeyInfo.incrKey value is true and the comparison would
** otherwise be equal, then return a result as if the second key larger.
** otherwise be equal, then return a result as if the second key
** were larger.
*/
struct KeyInfo {
u8 enc; /* Text encoding - one of the TEXT_Utf* values */
@ -1049,7 +1038,6 @@ struct Select {
Expr *pOffset; /* OFFSET expression. NULL means not used. */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
IdList **ppOpenTemp; /* OP_OpenTemp addresses used by multi-selects */
Fetch *pFetch; /* If this stmt is part of a FETCH command */
u8 isResolved; /* True once sqlite3SelectResolve() has run. */
u8 isAgg; /* True if this is an aggregate query */
};
@ -1113,15 +1101,15 @@ struct Parse {
u8 nameClash; /* A permanent table name clashes with temp table name */
u8 checkSchema; /* Causes schema cookie check after an error */
u8 nested; /* Number of nested calls to the parser/code generator */
u8 fillAgg; /* If true, ignore the Expr.iAgg field. Normally false */
int nErr; /* Number of errors seen */
int nTab; /* Number of previously allocated VDBE cursors */
int nMem; /* Number of memory cells used so far */
int nSet; /* Number of sets used so far */
u32 cookieMask; /* Bitmask of schema verified databases */
int cookieValue[MAX_ATTACHED+2]; /* Values of cookies to verify */
int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
u32 writeMask; /* Start a write transaction on these databases */
u8 fillAgg; /* If true, ignore the Expr.iAgg field. Normally false */
u32 cookieMask; /* Bitmask of schema verified databases */
int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
int cookieValue[MAX_ATTACHED+2]; /* Values of cookies to verify */
/* Above is constant between recursions. Below is reset before and after
** each recursion */
@ -1155,7 +1143,7 @@ struct AuthContext {
};
/*
** Bitfield flags for P2 value in OP_PutIntKey and OP_Delete
** Bitfield flags for P2 value in OP_Insert and OP_Delete
*/
#define OPFLAG_NCHANGE 1 /* Set to update db->nChange */
#define OPFLAG_LASTROWID 2 /* Set to update db->lastRowid */
@ -1347,13 +1335,15 @@ void sqlite3RealToSortable(double r, char *);
char *sqlite3StrDup(const char*);
char *sqlite3StrNDup(const char*, int);
# define sqlite3CheckMemory(a,b)
# define sqlite3MallocX sqlite3Malloc
#endif
void sqlite3FreeX(void*);
void *sqlite3MallocX(int);
char *sqlite3MPrintf(const char*, ...);
char *sqlite3VMPrintf(const char*, va_list);
void sqlite3DebugPrintf(const char*, ...);
void *sqlite3TextToPtr(const char*);
void sqlite3SetString(char **, const char *, ...);
void sqlite3SetString(char **, ...);
void sqlite3ErrorMsg(Parse*, const char*, ...);
void sqlite3Dequote(char*);
int sqlite3KeywordCode(const char*, int);
@ -1419,7 +1409,7 @@ void sqlite3OpenTableForReading(Vdbe*, int iCur, Table*);
void sqlite3OpenTable(Vdbe*, int iCur, Table*, int);
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, Fetch*);
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**);
void sqlite3WhereEnd(WhereInfo*);
void sqlite3ExprCode(Parse*, Expr*);
void sqlite3ExprCodeAndCache(Parse*, Expr*);
@ -1573,5 +1563,11 @@ int sqlite3SelectResolve(Parse *, Select *, NameContext *);
void sqlite3ColumnDefault(Vdbe *, Table *, int);
void sqlite3AlterFinishAddColumn(Parse *, Token *);
void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
const char *sqlite3TestErrorName(int);
CollSeq *sqlite3GetCollSeq(sqlite3*, CollSeq *, const char *, int);
#ifdef SQLITE_SSE
#include "sseInt.h"
#endif
#endif

Просмотреть файл

@ -11,7 +11,7 @@
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.119 2005/02/26 17:31:27 drh Exp $
** $Id: tclsqlite.c,v 1.125 2005/05/20 09:40:56 danielk1977 Exp $
*/
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
@ -83,6 +83,7 @@ struct SqliteDb {
char *zTrace; /* The trace callback routine */
char *zProgress; /* The progress callback routine */
char *zAuth; /* The authorization callback routine */
char *zNull; /* Text to substitute for an SQL NULL value */
SqlFunc *pFunc; /* List of SQL functions */
SqlCollate *pCollate; /* List of SQL collation functions */
int rc; /* Return code of most recent sqlite3_exec() */
@ -136,6 +137,9 @@ static void DbDeleteCmd(void *db){
if( pDb->zAuth ){
Tcl_Free(pDb->zAuth);
}
if( pDb->zNull ){
Tcl_Free(pDb->zNull);
}
Tcl_Free((char*)pDb);
}
@ -267,12 +271,33 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
Tcl_DStringAppendElement(&cmd, sqlite3_value_text(argv[i]));
}
}
rc = Tcl_Eval(p->interp, Tcl_DStringValue(&cmd));
if( rc ){
rc = Tcl_EvalEx(p->interp, Tcl_DStringValue(&cmd), Tcl_DStringLength(&cmd),
TCL_EVAL_DIRECT);
Tcl_DStringFree(&cmd);
if( rc && rc!=TCL_RETURN ){
sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
}else{
sqlite3_result_text(context, Tcl_GetStringResult(p->interp), -1,
SQLITE_TRANSIENT);
Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
int n;
u8 *data;
char *zType = pVar->typePtr ? pVar->typePtr->name : "";
char c = zType[0];
if( c=='b' && strcmp(zType,"bytearray")==0 ){
data = Tcl_GetByteArrayFromObj(pVar, &n);
sqlite3_result_blob(context, data, n, SQLITE_TRANSIENT);
}else if( (c=='b' && strcmp(zType,"boolean")==0) ||
(c=='i' && strcmp(zType,"int")==0) ){
Tcl_GetIntFromObj(0, pVar, &n);
sqlite3_result_int(context, n);
}else if( c=='d' && strcmp(zType,"double")==0 ){
double r;
Tcl_GetDoubleFromObj(0, pVar, &r);
sqlite3_result_double(context, r);
}else{
data = Tcl_GetStringFromObj(pVar, &n);
sqlite3_result_text(context, data, n, SQLITE_TRANSIENT);
}
}
}
@ -441,9 +466,10 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
"changes", "close", "collate",
"collation_needed", "commit_hook", "complete",
"copy", "errorcode", "eval",
"function", "last_insert_rowid", "onecolumn",
"progress", "rekey", "timeout",
"total_changes", "trace", "version",
"function", "last_insert_rowid", "nullvalue",
"onecolumn", "progress", "rekey",
"timeout", "total_changes", "trace",
"version",
0
};
enum DB_enum {
@ -451,9 +477,10 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
DB_CHANGES, DB_CLOSE, DB_COLLATE,
DB_COLLATION_NEEDED, DB_COMMIT_HOOK, DB_COMPLETE,
DB_COPY, DB_ERRORCODE, DB_EVAL,
DB_FUNCTION, DB_LAST_INSERT_ROWID,DB_ONECOLUMN,
DB_PROGRESS, DB_REKEY, DB_TIMEOUT,
DB_TOTAL_CHANGES, DB_TRACE, DB_VERSION
DB_FUNCTION, DB_LAST_INSERT_ROWID,DB_NULLVALUE,
DB_ONECOLUMN, DB_PROGRESS, DB_REKEY,
DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE,
DB_VERSION
};
/* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
@ -938,11 +965,14 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
*/
if( pArray ){
Tcl_Obj *pColList = Tcl_NewObj();
Tcl_Obj *pStar = Tcl_NewStringObj("*", -1);
Tcl_IncrRefCount(pColList);
for(i=0; i<nCol; i++){
Tcl_ListObjAppendElement(interp, pColList, apColName[i]);
}
Tcl_ObjSetVar2(interp, pArray, Tcl_NewStringObj("*",-1), pColList,0);
Tcl_ObjSetVar2(interp, pArray, pStar, pColList,0);
Tcl_DecrRefCount(pColList);
Tcl_DecrRefCount(pStar);
}
/* Execute the SQL
@ -972,6 +1002,10 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
pVal = Tcl_NewDoubleObj(r);
break;
}
case SQLITE_NULL: {
pVal = dbTextToObj(pDb->zNull);
break;
}
default: {
pVal = dbTextToObj(sqlite3_column_text(pStmt, i));
break;
@ -1243,6 +1277,37 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
break;
}
/*
** $db nullvalue ?STRING?
**
** Change text used when a NULL comes back from the database. If ?STRING?
** is not present, then the current string used for NULL is returned.
** If STRING is present, then STRING is returned.
**
*/
case DB_NULLVALUE: {
if( objc!=2 && objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "NULLVALUE");
return TCL_ERROR;
}
if( objc==3 ){
int len;
char *zNull = Tcl_GetStringFromObj(objv[2], &len);
if( pDb->zNull ){
Tcl_Free(pDb->zNull);
}
if( zNull && len>0 ){
pDb->zNull = Tcl_Alloc( len + 1 );
strncpy(pDb->zNull, zNull, len);
pDb->zNull[len] = '\0';
}else{
pDb->zNull = 0;
}
}
Tcl_SetObjResult(interp, dbTextToObj(pDb->zNull));
break;
}
/*
** $db total_changes
**
@ -1727,12 +1792,17 @@ int TCLSH_MAIN(int argc, char **argv){
extern int Sqlitetest4_Init(Tcl_Interp*);
extern int Sqlitetest5_Init(Tcl_Interp*);
extern int Md5_Init(Tcl_Interp*);
extern int Sqlitetestsse_Init(Tcl_Interp*);
Sqlitetest1_Init(interp);
Sqlitetest2_Init(interp);
Sqlitetest3_Init(interp);
Sqlitetest4_Init(interp);
Sqlitetest5_Init(interp);
Md5_Init(interp);
#ifdef SQLITE_SSE
Sqlitetestsse_Init(interp);
#endif
}
#endif
if( argc>=2 || TCLSH==2 ){

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -15,7 +15,7 @@
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.101 2005/02/26 17:31:27 drh Exp $
** $Id: tokenize.c,v 1.103 2005/06/06 14:45:43 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -341,10 +341,10 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
db->flags &= ~SQLITE_Interrupt;
pParse->rc = SQLITE_OK;
i = 0;
pEngine = sqlite3ParserAlloc((void*(*)(int))malloc);
pEngine = sqlite3ParserAlloc((void*(*)(int))sqlite3MallocX);
if( pEngine==0 ){
sqlite3SetString(pzErrMsg, "out of memory", (char*)0);
return 1;
return SQLITE_NOMEM;
}
assert( pParse->sLastToken.dyn==0 );
assert( pParse->pNewTable==0 );
@ -401,7 +401,7 @@ abort_parse:
}
sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
}
sqlite3ParserFree(pEngine, free);
sqlite3ParserFree(pEngine, sqlite3FreeX);
if( sqlite3_malloc_failed ){
pParse->rc = SQLITE_NOMEM;
}

Просмотреть файл

@ -215,7 +215,7 @@ void sqlite3FinishTrigger(
*/
if( !db->init.busy ){
static const VdbeOpList insertTrig[] = {
{ OP_NewRecno, 0, 0, 0 },
{ OP_NewRowid, 0, 0, 0 },
{ OP_String8, 0, 0, "trigger" },
{ OP_String8, 0, 0, 0 }, /* 2: trigger name */
{ OP_String8, 0, 0, 0 }, /* 3: table name */
@ -224,7 +224,7 @@ void sqlite3FinishTrigger(
{ OP_String8, 0, 0, 0 }, /* 6: SQL */
{ OP_Concat, 0, 0, 0 },
{ OP_MakeRecord, 5, 0, "tttit" },
{ OP_PutIntKey, 0, 0, 0 },
{ OP_Insert, 0, 0, 0 },
};
int addr;
Vdbe *v;

Просмотреть файл

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.105 2005/03/09 12:26:51 danielk1977 Exp $
** $Id: update.c,v 1.108 2005/06/12 21:35:53 drh Exp $
*/
#include "sqliteInt.h"
@ -80,8 +80,8 @@ void sqlite3Update(
int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
** an expression for the i-th column of the table.
** aXRef[i]==-1 if the i-th column is not changed. */
int chngRecno; /* True if the record number is being changed */
Expr *pRecnoExpr = 0; /* Expression defining the new record number */
int chngRowid; /* True if the record number is being changed */
Expr *pRowidExpr = 0; /* Expression defining the new record number */
int openAll = 0; /* True if all indices need to be opened */
AuthContext sContext; /* The authorization context */
NameContext sNC; /* The name-context to resolve expressions in */
@ -160,7 +160,7 @@ void sqlite3Update(
** column to be updated, make sure we have authorization to change
** that column.
*/
chngRecno = 0;
chngRowid = 0;
for(i=0; i<pChanges->nExpr; i++){
if( sqlite3ExprResolveNames(&sNC, pChanges->a[i].pExpr) ){
goto update_cleanup;
@ -168,8 +168,8 @@ void sqlite3Update(
for(j=0; j<pTab->nCol; j++){
if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
if( j==pTab->iPKey ){
chngRecno = 1;
pRecnoExpr = pChanges->a[i].pExpr;
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
}
aXRef[j] = i;
break;
@ -177,8 +177,8 @@ void sqlite3Update(
}
if( j>=pTab->nCol ){
if( sqlite3IsRowid(pChanges->a[i].zName) ){
chngRecno = 1;
pRecnoExpr = pChanges->a[i].pExpr;
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
}else{
sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
goto update_cleanup;
@ -204,7 +204,7 @@ void sqlite3Update(
** number of the original table entry is changing.
*/
for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){
if( chngRecno ){
if( chngRowid ){
i = 0;
}else {
for(i=0; i<pIdx->nColumn; i++){
@ -219,7 +219,7 @@ void sqlite3Update(
aIdxUsed = (char*)&apIdx[nIdx];
}
for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
if( chngRecno ){
if( chngRowid ){
i = 0;
}else{
for(i=0; i<pIdx->nColumn; i++){
@ -267,12 +267,12 @@ void sqlite3Update(
/* Begin the database scan
*/
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
if( pWInfo==0 ) goto update_cleanup;
/* Remember the index of every item to be updated.
*/
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
/* End the database scan loop.
@ -297,33 +297,33 @@ void sqlite3Update(
*/
sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0);
addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
/* Open a cursor and make it point to the record that is
** being updated.
*/
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
if( !isView ){
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
/* Open a cursor and make it point to the record that is
** being updated.
*/
sqlite3OpenTableForReading(v, iCur, pTab);
}
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
/* Generate the OLD table
*/
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
sqlite3VdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
sqlite3VdbeAddOp(v, OP_Insert, oldIdx, 0);
/* Generate the NEW table
*/
if( chngRecno ){
sqlite3ExprCodeAndCache(pParse, pRecnoExpr);
if( chngRowid ){
sqlite3ExprCodeAndCache(pParse, pRowidExpr);
}else{
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
}
for(i=0; i<pTab->nCol; i++){
if( i==pTab->iPKey ){
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
continue;
}
j = aXRef[i];
@ -339,7 +339,7 @@ void sqlite3Update(
sqlite3TableAffinityStr(v, pTab);
}
if( pParse->nErr ) goto update_cleanup;
sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);
if( !isView ){
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
@ -399,8 +399,8 @@ void sqlite3Update(
** will be after the update. (The old record number is currently
** on top of the stack.)
*/
if( chngRecno ){
sqlite3ExprCode(pParse, pRecnoExpr);
if( chngRowid ){
sqlite3ExprCode(pParse, pRowidExpr);
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
}
@ -408,7 +408,7 @@ void sqlite3Update(
*/
for(i=0; i<pTab->nCol; i++){
if( i==pTab->iPKey ){
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
continue;
}
j = aXRef[i];
@ -422,7 +422,7 @@ void sqlite3Update(
/* Do constraint checks
*/
sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRecno, 1,
sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRowid, 1,
onError, addr);
/* Delete the old indices for the current record.
@ -431,13 +431,13 @@ void sqlite3Update(
/* If changing the record number, delete the old record.
*/
if( chngRecno ){
if( chngRowid ){
sqlite3VdbeAddOp(v, OP_Delete, iCur, 0);
}
/* Create the new index entries and the new record.
*/
sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRecno, 1, -1);
sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRowid, 1, -1);
}
/* Increment the row counter

Просмотреть файл

@ -14,7 +14,7 @@
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.132 2005/03/18 14:03:15 drh Exp $
** $Id: util.c,v 1.136 2005/06/06 15:06:39 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
@ -65,9 +65,11 @@ static int memcnt = 0;
#endif
/*
** Number of 32-bit guard words
** Number of 32-bit guard words. This should probably be a multiple of
** 2 since on 64-bit machines we want the value returned by sqliteMalloc()
** to be 8-byte aligned.
*/
#define N_GUARD 1
#define N_GUARD 2
/*
** Allocate new memory and set it to zero. Return NULL if
@ -110,6 +112,13 @@ void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){
return p;
}
/*
** This version of malloc is always a real function, never a macro
*/
void *sqlite3MallocX(int n){
return sqlite3Malloc_(n, 0, __FILE__, __LINE__);
}
/*
** Check to see if the given pointer was obtained from sqliteMalloc()
** and is able to hold at least N bytes. Raise an exception if this
@ -338,15 +347,15 @@ char *sqlite3StrNDup(const char *z, int n){
** point to that string. The 1st argument must either be NULL or
** point to memory obtained from sqliteMalloc().
*/
void sqlite3SetString(char **pz, const char *zFirst, ...){
void sqlite3SetString(char **pz, ...){
va_list ap;
int nByte;
const char *z;
char *zResult;
if( pz==0 ) return;
nByte = strlen(zFirst) + 1;
va_start(ap, zFirst);
nByte = 1;
va_start(ap, pz);
while( (z = va_arg(ap, const char*))!=0 ){
nByte += strlen(z);
}
@ -356,9 +365,8 @@ void sqlite3SetString(char **pz, const char *zFirst, ...){
if( zResult==0 ){
return;
}
strcpy(zResult, zFirst);
zResult += strlen(zResult);
va_start(ap, zFirst);
*zResult = 0;
va_start(ap, pz);
while( (z = va_arg(ap, const char*))!=0 ){
strcpy(zResult, z);
zResult += strlen(zResult);
@ -388,7 +396,7 @@ void sqlite3SetString(char **pz, const char *zFirst, ...){
** zFormat and any string tokens that follow it are assumed to be
** encoded in UTF-8.
**
** To clear the most recent error for slqite handle "db", sqlite3Error
** To clear the most recent error for sqlite handle "db", sqlite3Error
** should be called with err_code set to SQLITE_OK and zFormat set
** to NULL.
*/

Просмотреть файл

@ -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.40 2005/02/16 03:27:05 drh Exp $
** $Id: vacuum.c,v 1.45 2005/06/07 09:21:07 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -100,6 +100,11 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
Btree *pMain; /* The database being vacuumed */
Btree *pTemp;
char *zSql = 0;
int writeschema_flag; /* Saved value of the write-schema flag */
/* Save the current value of the write-schema flag before setting it. */
writeschema_flag = db->flags&SQLITE_WriteSchema;
db->flags |= SQLITE_WriteSchema;
if( !db->autoCommit ){
sqlite3SetString(pzErrMsg, "cannot VACUUM from within a transaction",
@ -276,6 +281,10 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
}
end_of_vacuum:
/* Restore the original value of the write-schema flag. */
db->flags &= ~SQLITE_WriteSchema;
db->flags |= writeschema_flag;
/* Currently there is an SQL level transaction open on the vacuum
** database. No locks are held on any other files (since the main file
** was committed at the btree level). So it safe to end the transaction
@ -296,5 +305,6 @@ end_of_vacuum:
if( zSql ) sqliteFree( zSql );
sqlite3ResetInternalSchema(db, 0);
#endif
return rc;
}

Просмотреть файл

@ -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.463 2005/03/29 13:07:00 danielk1977 Exp $
** $Id: vdbe.c,v 1.469 2005/06/12 21:35:53 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -717,7 +717,8 @@ case OP_String8: { /* same as TK_STRING */
#ifndef SQLITE_OMIT_UTF16
pOp->opcode = OP_String;
if( db->enc!=SQLITE_UTF8 && pOp->p3 ){
assert( pOp->p3!=0 );
if( db->enc!=SQLITE_UTF8 ){
pTos++;
sqlite3VdbeMemSetStr(pTos, pOp->p3, -1, SQLITE_UTF8, SQLITE_STATIC);
if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pTos, db->enc) ) goto no_mem;
@ -743,26 +744,34 @@ case OP_String8: { /* same as TK_STRING */
*/
case OP_String: {
pTos++;
if( pOp->p3 ){
pTos->flags = MEM_Str|MEM_Static|MEM_Term;
pTos->z = pOp->p3;
assert( pOp->p3!=0 );
pTos->flags = MEM_Str|MEM_Static|MEM_Term;
pTos->z = pOp->p3;
#ifndef SQLITE_OMIT_UTF16
if( db->enc==SQLITE_UTF8 ){
pTos->n = strlen(pTos->z);
}else{
pTos->n = sqlite3utf16ByteLen(pTos->z, -1);
}
#else
assert( db->enc==SQLITE_UTF8 );
if( db->enc==SQLITE_UTF8 ){
pTos->n = strlen(pTos->z);
#endif
pTos->enc = db->enc;
}else{
pTos->flags = MEM_Null;
pTos->n = sqlite3utf16ByteLen(pTos->z, -1);
}
#else
assert( db->enc==SQLITE_UTF8 );
pTos->n = strlen(pTos->z);
#endif
pTos->enc = db->enc;
break;
}
/* Opcode: Null * * *
**
** Push a NULL onto the stack.
*/
case OP_Null: {
pTos++;
pTos->flags = MEM_Null;
break;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
/* Opcode: HexBlob * * P3
**
@ -1316,7 +1325,7 @@ case OP_AddImm: { /* no-push */
** greater than its current value if P1==1.
*/
case OP_ForceInt: { /* no-push */
int v;
i64 v;
assert( pTos>=p->aStack );
applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc);
if( (pTos->flags & (MEM_Int|MEM_Real))==0 ){
@ -1373,11 +1382,11 @@ case OP_MustBeInt: { /* no-push */
** Pop the top two elements from the stack. If they are equal, then
** jump to instruction P2. Otherwise, continue to the next instruction.
**
** The least significant byte of P1 may be either 0x00 or 0x01. If either
** operand is NULL (and thus if the result is unknown) then take the jump
** only if the least significant byte of P1 is 0x01.
** If the 0x100 bit of P1 is true and either operand is NULL then take the
** jump. If the 0x100 bit of P1 is false then fall thru if either operand
** is NULL.
**
** The second least significant byte of P1 must be an affinity character -
** The least significant byte of P1 (mask 0xff) must be an affinity character -
** 'n', 't', 'i' or 'o' - or 0x00. An attempt is made to coerce both values
** according to the affinity before the comparison is made. If the byte is
** 0x00, then numeric affinity is used.
@ -1446,7 +1455,7 @@ case OP_Ge: { /* same as TK_GE, no-push */
if( flags&MEM_Null ){
popStack(&pTos, 2);
if( pOp->p2 ){
if( (pOp->p1&0xFF) ) pc = pOp->p2-1;
if( pOp->p1 & 0x100 ) pc = pOp->p2-1;
}else{
pTos++;
pTos->flags = MEM_Null;
@ -1454,7 +1463,7 @@ case OP_Ge: { /* same as TK_GE, no-push */
break;
}
affinity = (pOp->p1>>8)&0xFF;
affinity = pOp->p1 & 0xFF;
if( affinity ){
applyAffinity(pNos, affinity, db->enc);
applyAffinity(pTos, affinity, db->enc);
@ -1639,7 +1648,11 @@ case OP_IfNot: { /* no-push */
if( pTos->flags & MEM_Null ){
c = pOp->p1;
}else{
#ifdef SQLITE_OMIT_FLOATING_POINT
c = sqlite3VdbeIntValue(pTos);
#else
c = sqlite3VdbeRealValue(pTos)!=0.0;
#endif
if( pOp->opcode==OP_IfNot ) c = !c;
}
Release(pTos);
@ -1704,10 +1717,6 @@ case OP_SetNumColumns: { /* no-push */
assert( p->apCsr[pOp->p1]!=0 );
pC = p->apCsr[pOp->p1];
pC->nField = pOp->p2;
if( (!pC->keyAsData && pC->zeroData) || (pC->keyAsData && pC->intKey) ){
rc = SQLITE_CORRUPT;
goto abort_due_to_error;
}
break;
}
@ -1791,7 +1800,7 @@ case OP_Column: {
}else if( pC->cacheValid ){
payloadSize = pC->payloadSize;
zRec = pC->aRow;
}else if( pC->keyAsData ){
}else if( pC->isIndex ){
i64 payloadSize64;
sqlite3BtreeKeySize(pCrsr, &payloadSize64);
payloadSize = payloadSize64;
@ -1846,7 +1855,7 @@ case OP_Column: {
if( zRec ){
zData = zRec;
}else{
if( pC->keyAsData ){
if( pC->isIndex ){
zData = (char*)sqlite3BtreeKeyFetch(pCrsr, &avail);
}else{
zData = (char*)sqlite3BtreeDataFetch(pCrsr, &avail);
@ -1872,7 +1881,7 @@ case OP_Column: {
** acquire the complete header text.
*/
if( !zRec && avail<szHdr ){
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, szHdr, pC->keyAsData, &sMem);
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, szHdr, pC->isIndex, &sMem);
if( rc!=SQLITE_OK ){
goto op_column_out;
}
@ -1936,7 +1945,7 @@ case OP_Column: {
zData = &zRec[aOffset[p2]];
}else{
len = sqlite3VdbeSerialTypeLen(aType[p2]);
rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len,pC->keyAsData,&sMem);
rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex,&sMem);
if( rc!=SQLITE_OK ){
goto op_column_out;
}
@ -2436,11 +2445,12 @@ case OP_OpenWrite: { /* no-push */
rc = sqlite3BtreeCursor(pX, p2, wrFlag,
sqlite3VdbeRecordCompare, pOp->p3,
&pCur->pCursor);
pCur->pKeyInfo = (KeyInfo*)pOp->p3;
if( pCur->pKeyInfo ){
if( pOp->p3type==P3_KEYINFO ){
pCur->pKeyInfo = (KeyInfo*)pOp->p3;
pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
pCur->pKeyInfo->enc = p->db->enc;
}else{
pCur->pKeyInfo = 0;
pCur->pIncrKey = &pCur->bogusIncrKey;
}
switch( rc ){
@ -2452,11 +2462,32 @@ case OP_OpenWrite: { /* no-push */
}
case SQLITE_OK: {
int flags = sqlite3BtreeFlags(pCur->pCursor);
pCur->intKey = (flags & BTREE_INTKEY)!=0;
pCur->zeroData = (flags & BTREE_ZERODATA)!=0;
/* Sanity checking. Only the lower four bits of the flags byte should
** be used. Bit 3 (mask 0x08) is unpreditable. The lower 3 bits
** (mask 0x07) should be either 5 (intkey+leafdata for tables) or
** 2 (zerodata for indices). If these conditions are not met it can
** only mean that we are dealing with a corrupt database file
*/
if( (flags & 0xf0)!=0 || ((flags & 0x07)!=5 && (flags & 0x07)!=2) ){
rc = SQLITE_CORRUPT;
goto abort_due_to_error;
}
pCur->isTable = (flags & BTREE_INTKEY)!=0;
pCur->isIndex = (flags & BTREE_ZERODATA)!=0;
/* If P3==0 it means we are expected to open a table. If P3!=0 then
** we expect to be opening an index. If this is not what happened,
** then the database is corrupt
*/
if( (pCur->isTable && pOp->p3type==P3_KEYINFO)
|| (pCur->isIndex && pOp->p3type!=P3_KEYINFO) ){
rc = SQLITE_CORRUPT;
goto abort_due_to_error;
}
break;
}
case SQLITE_EMPTY: {
pCur->isTable = pOp->p3type!=P3_KEYINFO;
pCur->isIndex = !pCur->isTable;
rc = SQLITE_OK;
break;
}
@ -2514,12 +2545,14 @@ case OP_OpenTemp: { /* no-push */
pCx->pKeyInfo->enc = p->db->enc;
pCx->pIncrKey = &pCx->pKeyInfo->incrKey;
}
pCx->isTable = 0;
}else{
rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, 0, &pCx->pCursor);
pCx->intKey = 1;
pCx->isTable = 1;
pCx->pIncrKey = &pCx->bogusIncrKey;
}
}
pCx->isIndex = !pCx->isTable;
break;
}
@ -2543,6 +2576,8 @@ case OP_OpenPseudo: { /* no-push */
pCx->nullRow = 1;
pCx->pseudoTable = 1;
pCx->pIncrKey = &pCx->bogusIncrKey;
pCx->isTable = 1;
pCx->isIndex = 0;
break;
}
#endif
@ -2617,7 +2652,7 @@ case OP_MoveGt: { /* no-push */
oc = pOp->opcode;
pC->nullRow = 0;
*pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe;
if( pC->intKey ){
if( pC->isTable ){
i64 iKey;
Integerify(pTos);
iKey = intToKey(pTos->i);
@ -2632,15 +2667,15 @@ case OP_MoveGt: { /* no-push */
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
pC->lastRecno = pTos->i;
pC->recnoIsValid = res==0;
pC->lastRowid = pTos->i;
pC->rowidIsValid = res==0;
}else{
Stringify(pTos, db->enc);
rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
pC->recnoIsValid = 0;
pC->rowidIsValid = 0;
}
pC->deferredMoveto = 0;
pC->cacheValid = 0;
@ -2650,7 +2685,7 @@ case OP_MoveGt: { /* no-push */
if( res<0 ){
rc = sqlite3BtreeNext(pC->pCursor, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
pC->recnoIsValid = 0;
pC->rowidIsValid = 0;
}else{
res = 0;
}
@ -2659,7 +2694,7 @@ case OP_MoveGt: { /* no-push */
if( res>=0 ){
rc = sqlite3BtreePrevious(pC->pCursor, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
pC->recnoIsValid = 0;
pC->rowidIsValid = 0;
}else{
/* res might be negative because the table is empty. Check to
** see if this is the case.
@ -2682,31 +2717,46 @@ case OP_MoveGt: { /* no-push */
/* Opcode: Distinct P1 P2 *
**
** Use the top of the stack as a string key. If a record with that key does
** not exist in the table of cursor P1, then jump to P2. If the record
** does already exist, then fall thru. The cursor is left pointing
** at the record if it exists. The key is not popped from the stack.
** Use the top of the stack as a record created using MakeRecord. P1 is a
** cursor on a table that declared as an index. If that table contains an
** entry that matches the top of the stack fall thru. If the top of the stack
** matches no entry in P1 then jump to P2.
**
** This operation is similar to NotFound except that this operation
** The cursor is left pointing at the matching entry if it exists. The
** record on the top of the stack is not popped.
**
** This instruction is similar to NotFound except that this operation
** does not pop the key from the stack.
**
** The instruction is used to implement the DISTINCT operator on SELECT
** statements. The P1 table is not a true index but rather a record of
** all results that have produced so far.
**
** See also: Found, NotFound, MoveTo, IsUnique, NotExists
*/
/* Opcode: Found P1 P2 *
**
** Use the top of the stack as a string key. If a record with that key
** does exist in table of P1, then jump to P2. If the record
** does not exist, then fall thru. The cursor is left pointing
** to the record if it exists. The key is popped from the stack.
** Top of the stack holds a blob constructed by MakeRecord. P1 is an index.
** If an entry that matches the top of the stack exists in P1 then
** jump to P2. If the top of the stack does not match any entry in P1
** then fall thru. The P1 cursor is left pointing at the matching entry
** if it exists. The blob is popped off the top of the stack.
**
** This instruction is used to implement the IN operator where the
** left-hand side is a SELECT statement. P1 is not a true index but
** is instead a temporary index that holds the results of the SELECT
** statement. This instruction just checks to see if the left-hand side
** of the IN operator (stored on the top of the stack) exists in the
** result of the SELECT statement.
**
** See also: Distinct, NotFound, MoveTo, IsUnique, NotExists
*/
/* Opcode: NotFound P1 P2 *
**
** Use the top of the stack as a string key. If a record with that key
** does not exist in table of P1, then jump to P2. If the record
** does exist, then fall thru. The cursor is left pointing to the
** record if it exists. The key is popped from the stack.
** The top of the stack holds a blob constructed by MakeRecord. P1 is
** an index. If no entry exists in P1 that matches the blob then jump
** to P1. If an entry does existing, fall through. The cursor is left
** pointing to the entry that matches. The blob is popped from the stack.
**
** The difference between this operation and Distinct is that
** Distinct does not pop the key from the stack.
@ -2724,7 +2774,7 @@ case OP_Found: { /* no-push */
assert( p->apCsr[i]!=0 );
if( (pC = p->apCsr[i])->pCursor!=0 ){
int res, rx;
assert( pC->intKey==0 );
assert( pC->isTable==0 );
Stringify(pTos, db->enc);
rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
alreadyExists = rx==SQLITE_OK && res==0;
@ -2751,8 +2801,8 @@ case OP_Found: { /* no-push */
** stack but it leaves K unchanged.
**
** P1 is an index. So it has no data and its key consists of a
** record generated by OP_MakeIdxKey. This key contains one or more
** fields followed by a ROWID field.
** record generated by OP_MakeRecord where the last field is the
** rowid of the entry that the index refers to.
**
** This instruction asks if there is an entry in P1 where the
** fields matches K but the rowid is different from R.
@ -2853,8 +2903,9 @@ case OP_IsUnique: { /* no-push */
** record if it exists. The integer key is popped from the stack.
**
** The difference between this operation and NotFound is that this
** operation assumes the key is an integer and NotFound assumes it
** is a string.
** operation assumes the key is an integer and that P1 is a table whereas
** NotFound assumes key is a blob constructed from MakeRecord and
** P1 is an index.
**
** See also: Distinct, Found, MoveTo, NotFound, IsUnique
*/
@ -2869,16 +2920,16 @@ case OP_NotExists: { /* no-push */
int res;
u64 iKey;
assert( pTos->flags & MEM_Int );
assert( p->apCsr[i]->intKey );
assert( p->apCsr[i]->isTable );
iKey = intToKey(pTos->i);
rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res);
pC->lastRecno = pTos->i;
pC->recnoIsValid = res==0;
pC->lastRowid = pTos->i;
pC->rowidIsValid = res==0;
pC->nullRow = 0;
pC->cacheValid = 0;
if( res!=0 ){
pc = pOp->p2 - 1;
pC->recnoIsValid = 0;
pC->rowidIsValid = 0;
}
}
Release(pTos);
@ -2886,9 +2937,9 @@ case OP_NotExists: { /* no-push */
break;
}
/* Opcode: NewRecno P1 P2 *
/* Opcode: NewRowid P1 P2 *
**
** Get a new integer record number used as the key to a table.
** Get a new integer record number (a.k.a "rowid") used as the key to a table.
** The record number is not previously used as a key in the database
** table that cursor P1 points to. The new record number is pushed
** onto the stack.
@ -2900,7 +2951,7 @@ case OP_NotExists: { /* no-push */
** record number. This P2 mechanism is used to help implement the
** AUTOINCREMENT feature.
*/
case OP_NewRecno: {
case OP_NewRowid: {
int i = pOp->p1;
i64 v = 0;
Cursor *pC;
@ -3028,7 +3079,7 @@ case OP_NewRecno: {
goto abort_due_to_error;
}
}
pC->recnoIsValid = 0;
pC->rowidIsValid = 0;
pC->deferredMoveto = 0;
pC->cacheValid = 0;
}
@ -3038,7 +3089,7 @@ case OP_NewRecno: {
break;
}
/* Opcode: PutIntKey P1 P2 *
/* Opcode: Insert P1 P2 *
**
** Write an entry into the table of cursor P1. A new entry is
** created if it doesn't already exist or the data for an existing
@ -3050,19 +3101,11 @@ case OP_NewRecno: {
** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P2 is set,
** then rowid is stored for subsequent return by the
** sqlite3_last_insert_rowid() function (otherwise it's unmodified).
*/
/* Opcode: PutStrKey P1 * *
**
** Write an entry into the table of cursor P1. A new entry is
** created if it doesn't already exist or the data for an existing
** entry is overwritten. The data is the value on the top of the
** stack. The key is the next value down on the stack. The key must
** be a string. The stack is popped twice by this instruction.
**
** P1 may not be a pseudo-table opened using the OpenPseudo opcode.
** This instruction only works on tables. The equivalent instruction
** for indices is OP_IdxInsert.
*/
case OP_PutIntKey: /* no-push */
case OP_PutStrKey: { /* no-push */
case OP_Insert: { /* no-push */
Mem *pNos = &pTos[-1];
int i = pOp->p1;
Cursor *pC;
@ -3070,35 +3113,16 @@ case OP_PutStrKey: { /* no-push */
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( ((pC = p->apCsr[i])->pCursor!=0 || pC->pseudoTable) ){
char *zKey;
i64 nKey;
i64 iKey;
if( pOp->opcode==OP_PutStrKey ){
Stringify(pNos, db->enc);
nKey = pNos->n;
zKey = pNos->z;
}else{
assert( pNos->flags & MEM_Int );
i64 iKey; /* The integer ROWID or key for the record to be inserted */
/* If the table is an INTKEY table, set nKey to the value of
** the integer key, and zKey to NULL. Otherwise, set nKey to
** sizeof(i64) and point zKey at iKey. iKey contains the integer
** key in the on-disk byte order.
*/
iKey = intToKey(pNos->i);
if( pC->intKey ){
nKey = intToKey(pNos->i);
zKey = 0;
}else{
nKey = sizeof(i64);
zKey = (char*)&iKey;
}
assert( pNos->flags & MEM_Int );
assert( pC->isTable );
iKey = intToKey(pNos->i);
if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i;
if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){
pC->nextRowidValid = 0;
}
if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i;
if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){
pC->nextRowidValid = 0;
}
if( pTos->flags & MEM_Null ){
pTos->z = 0;
@ -3108,11 +3132,6 @@ case OP_PutStrKey: { /* no-push */
}
#ifndef SQLITE_OMIT_TRIGGER
if( pC->pseudoTable ){
/* PutStrKey does not work for pseudo-tables.
** The following assert makes sure we are not trying to use
** PutStrKey on a pseudo-table
*/
assert( pOp->opcode==OP_PutIntKey );
sqliteFree(pC->pData);
pC->iKey = iKey;
pC->nData = pTos->n;
@ -3129,12 +3148,12 @@ case OP_PutStrKey: { /* no-push */
pC->nullRow = 0;
}else{
#endif
rc = sqlite3BtreeInsert(pC->pCursor, zKey, nKey, pTos->z, pTos->n);
rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, pTos->z, pTos->n);
#ifndef SQLITE_OMIT_TRIGGER
}
#endif
pC->recnoIsValid = 0;
pC->rowidIsValid = 0;
pC->deferredMoveto = 0;
pC->cacheValid = 0;
}
@ -3188,23 +3207,6 @@ case OP_ResetCount: { /* no-push */
break;
}
/* Opcode: KeyAsData P1 P2 *
**
** Turn the key-as-data mode for cursor P1 either on (if P2==1) or
** off (if P2==0). In key-as-data mode, the OP_Column opcode pulls
** data off of the key rather than the data. This is used for
** processing compound selects.
*/
case OP_KeyAsData: { /* no-push */
int i = pOp->p1;
Cursor *pC;
assert( i>=0 && i<p->nCursor );
pC = p->apCsr[i];
assert( pC!=0 );
pC->keyAsData = pOp->p2;
break;
}
/* Opcode: RowData P1 * *
**
** Push onto the stack the complete row data for cursor P1.
@ -3229,9 +3231,12 @@ case OP_RowData: {
Cursor *pC;
u32 n;
/* Note that RowKey and RowData are really exactly the same instruction */
pTos++;
assert( i>=0 && i<p->nCursor );
pC = p->apCsr[i];
assert( pC->isTable || pOp->opcode==OP_RowKey );
assert( pC->isIndex || pOp->opcode==OP_RowData );
assert( pC!=0 );
if( pC->nullRow ){
pTos->flags = MEM_Null;
@ -3242,9 +3247,9 @@ case OP_RowData: {
if( pC->nullRow ){
pTos->flags = MEM_Null;
break;
}else if( pC->keyAsData || pOp->opcode==OP_RowKey ){
}else if( pC->isIndex ){
i64 n64;
assert( !pC->intKey );
assert( !pC->isTable );
sqlite3BtreeKeySize(pCrsr, &n64);
n = n64;
}else{
@ -3261,7 +3266,7 @@ case OP_RowData: {
pTos->xDel = 0;
pTos->z = z;
}
if( pC->keyAsData || pOp->opcode==OP_RowKey ){
if( pC->isIndex ){
sqlite3BtreeKey(pCrsr, 0, n, pTos->z);
}else{
sqlite3BtreeData(pCrsr, 0, n, pTos->z);
@ -3278,14 +3283,12 @@ case OP_RowData: {
break;
}
/* Opcode: Recno P1 * *
/* Opcode: Rowid P1 * *
**
** Push onto the stack an integer which is the first 4 bytes of the
** the key to the current entry in a sequential scan of the database
** file P1. The sequential scan should have been started using the
** Next opcode.
** Push onto the stack an integer which is the key of the table entry that
** P1 is currently point to.
*/
case OP_Recno: {
case OP_Rowid: {
int i = pOp->p1;
Cursor *pC;
i64 v;
@ -3296,8 +3299,8 @@ case OP_Recno: {
rc = sqlite3VdbeCursorMoveto(pC);
if( rc ) goto abort_due_to_error;
pTos++;
if( pC->recnoIsValid ){
v = pC->lastRecno;
if( pC->rowidIsValid ){
v = pC->lastRowid;
}else if( pC->pseudoTable ){
v = keyToInt(pC->iKey);
}else if( pC->nullRow || pC->pCursor==0 ){
@ -3313,58 +3316,6 @@ case OP_Recno: {
break;
}
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* Opcode: FullKey P1 * *
**
** Extract the complete key from the record that cursor P1 is currently
** pointing to and push the key onto the stack as a string.
**
** Compare this opcode to Recno. The Recno opcode extracts the first
** 4 bytes of the key and pushes those bytes onto the stack as an
** integer. This instruction pushes the entire key as a string.
**
** This opcode may not be used on a pseudo-table.
*/
case OP_FullKey: {
int i = pOp->p1;
BtCursor *pCrsr;
Cursor *pC;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
assert( p->apCsr[i]->keyAsData );
assert( !p->apCsr[i]->pseudoTable );
pTos++;
pTos->flags = MEM_Null;
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
i64 amt;
char *z;
rc = sqlite3VdbeCursorMoveto(pC);
if( rc ) goto abort_due_to_error;
assert( pC->intKey==0 );
sqlite3BtreeKeySize(pCrsr, &amt);
if( amt<=0 ){
rc = SQLITE_CORRUPT;
goto abort_due_to_error;
}
if( amt>NBFS ){
z = sqliteMallocRaw( amt );
if( z==0 ) goto no_mem;
pTos->flags = MEM_Blob | MEM_Dyn;
pTos->xDel = 0;
}else{
z = pTos->zShort;
pTos->flags = MEM_Blob | MEM_Short;
}
sqlite3BtreeKey(pCrsr, 0, amt, z);
pTos->z = z;
pTos->n = amt;
}
break;
}
#endif
/* Opcode: NullRow P1 * *
**
** Move the cursor P1 to a null row. Any OP_Column operations
@ -3379,13 +3330,13 @@ case OP_NullRow: { /* no-push */
pC = p->apCsr[i];
assert( pC!=0 );
pC->nullRow = 1;
pC->recnoIsValid = 0;
pC->rowidIsValid = 0;
break;
}
/* Opcode: Last P1 P2 *
**
** The next use of the Recno or Column or Next instruction for P1
** The next use of the Rowid or Column or Next instruction for P1
** will refer to the last entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
@ -3416,7 +3367,7 @@ case OP_Last: { /* no-push */
/* Opcode: Rewind P1 P2 *
**
** The next use of the Recno or Column or Next instruction for P1
** The next use of the Rowid or Column or Next instruction for P1
** will refer to the first entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
@ -3489,11 +3440,11 @@ case OP_Next: { /* no-push */
}else{
pC->nullRow = 1;
}
pC->recnoIsValid = 0;
pC->rowidIsValid = 0;
break;
}
/* Opcode: IdxPut P1 P2 P3
/* Opcode: IdxInsert P1 P2 P3
**
** The top of the stack holds a SQL index key made using the
** MakeIdxKey instruction. This opcode writes that key into the
@ -3503,8 +3454,11 @@ case OP_Next: { /* no-push */
** the program aborts with a SQLITE_CONSTRAINT error and the database
** is rolled back. If P3 is not null, then it becomes part of the
** error message returned with the SQLITE_CONSTRAINT.
**
** This instruction only works for indices. The equivalent instruction
** for tables is OP_Insert.
*/
case OP_IdxPut: { /* no-push */
case OP_IdxInsert: { /* no-push */
int i = pOp->p1;
Cursor *pC;
BtCursor *pCrsr;
@ -3541,7 +3495,7 @@ case OP_IdxPut: { /* no-push */
}
}
}
assert( pC->intKey==0 );
assert( pC->isTable==0 );
rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0);
assert( pC->deferredMoveto==0 );
pC->cacheValid = 0;
@ -3578,15 +3532,15 @@ case OP_IdxDelete: { /* no-push */
break;
}
/* Opcode: IdxRecno P1 * *
/* Opcode: IdxRowid P1 * *
**
** Push onto the stack an integer which is the varint located at the
** end of the index key pointed to by cursor P1. This integer should be
** the record number of the table entry to which this index entry points.
** Push onto the stack an integer which is the last entry in the record at
** the end of the index key pointed to by cursor P1. This integer should be
** the rowid of the table entry to which this index entry points.
**
** See also: Recno, MakeIdxKey.
** See also: Rowid, MakeIdxKey.
*/
case OP_IdxRecno: {
case OP_IdxRowid: {
int i = pOp->p1;
BtCursor *pCrsr;
Cursor *pC;
@ -3599,7 +3553,7 @@ case OP_IdxRecno: {
i64 rowid;
assert( pC->deferredMoveto==0 );
assert( pC->intKey==0 );
assert( pC->isTable==0 );
if( pC->nullRow ){
pTos->flags = MEM_Null;
}else{
@ -4104,21 +4058,26 @@ case OP_ContextPop: { /* no-push */
}
#endif /* #ifndef SQLITE_OMIT_TRIGGER */
/* Opcode: SortPut * * *
/* Opcode: SortInsert * * *
**
** The TOS is the key and the NOS is the data. Pop both from the stack
** and put them on the sorter. The key and data should have been
** made using the MakeRecord opcode.
*/
case OP_SortPut: { /* no-push */
case OP_SortInsert: { /* no-push */
Mem *pNos = &pTos[-1];
Sorter *pSorter;
assert( pNos>=p->aStack );
if( Dynamicify(pTos, db->enc) ) goto no_mem;
pSorter = sqliteMallocRaw( sizeof(Sorter) );
if( pSorter==0 ) goto no_mem;
pSorter->pNext = p->pSort;
p->pSort = pSorter;
pSorter->pNext = 0;
if( p->pSortTail ){
p->pSortTail->pNext = pSorter;
}else{
p->pSort = pSorter;
}
p->pSortTail = pSorter;
assert( pTos->flags & MEM_Dyn );
pSorter->nKey = pTos->n;
pSorter->zKey = pTos->z;
@ -4332,11 +4291,16 @@ case OP_AggReset: { /* no-push */
break;
}
/* Opcode: AggInit * P2 P3
/* Opcode: AggInit P1 P2 P3
**
** Initialize the function parameters for an aggregate function.
** The aggregate will operate out of aggregate column P2.
** P3 is a pointer to the FuncDef structure for the function.
**
** The P1 argument is not used by this opcode. However if the SSE
** extension is compiled in, P1 is set to the number of arguments that
** will be passed to the aggregate function, if any. This is used
** by SSE to select the correct function when (de)serializing statements.
*/
case OP_AggInit: { /* no-push */
int i = pOp->p2;

Просмотреть файл

@ -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.94 2005/03/23 01:48:48 drh Exp $
** $Id: vdbe.h,v 1.95 2005/05/19 08:43:00 danielk1977 Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
@ -38,7 +38,7 @@ struct VdbeOp {
int p1; /* First operand */
int p2; /* Second parameter (often the jump destination) */
char *p3; /* Third parameter */
int p3type; /* P3_STATIC, P3_DYNAMIC or P3_POINTER */
int p3type; /* One of the P3_xxx constants defined below */
#ifdef VDBE_PROFILE
int cnt; /* Number of times this instruction was executed */
long long cycles; /* Total time spend executing this instruction */
@ -64,7 +64,6 @@ typedef struct VdbeOpList VdbeOpList;
#define P3_NOTUSED 0 /* The P3 parameter is not used */
#define P3_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */
#define P3_STATIC (-2) /* Pointer to a static string */
#define P3_POINTER (-3) /* P3 is a pointer to some structure or object */
#define P3_COLLSEQ (-4) /* P3 is a pointer to a CollSeq structure */
#define P3_FUNCDEF (-5) /* P3 is a pointer to a FuncDef structure */
#define P3_KEYINFO (-6) /* P3 is a pointer to a KeyInfo structure */

Просмотреть файл

@ -60,19 +60,18 @@ typedef unsigned char Bool;
*/
struct Cursor {
BtCursor *pCursor; /* The cursor structure of the backend */
i64 lastRecno; /* Last recno from a Next or NextIdx operation */
i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
i64 nextRowid; /* Next rowid returned by OP_NewRowid */
Bool zeroed; /* True if zeroed out and ready for reuse */
Bool recnoIsValid; /* True if lastRecno is valid */
Bool keyAsData; /* The OP_Column command works on key instead of data */
Bool rowidIsValid; /* True if lastRowid is valid */
Bool atFirst; /* True if pointing to first entry */
Bool useRandomRowid; /* Generate new record numbers semi-randomly */
Bool nullRow; /* True if pointing to a row with no data */
Bool nextRowidValid; /* True if the nextRowid field is valid */
Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */
Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
Bool intKey; /* True if the table requires integer keys */
Bool zeroData; /* True if table contains keys only - no data */
Bool isTable; /* True if a table requiring integer keys */
Bool isIndex; /* True if an index containing keys only - no data */
u8 bogusIncrKey; /* Something for pIncrKey to point to if pKeyInfo==0 */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
Btree *pBt; /* Separate file holding temporary table */
@ -314,6 +313,7 @@ struct Vdbe {
int nCursor; /* Number of slots in apCsr[] */
Cursor **apCsr; /* One element of this array for each open cursor */
Sorter *pSort; /* A linked list of objects to be sorted */
Sorter *pSortTail; /* Last element on the pSort list */
int nVar; /* Number of entries in aVar[] */
Mem *aVar; /* Values for the OP_Variable opcode. */
char **azVar; /* Name of variables */

Просмотреть файл

@ -23,8 +23,6 @@
** that sqlite3_prepare() generates. For example, if new functions or
** collating sequences are registered or if an authorizer function is
** added or changed.
**
***** EXPERIMENTAL ******
*/
int sqlite3_expired(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
@ -383,8 +381,18 @@ int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
/*
** Convert the N-th element of pStmt->pColName[] into a string using
** xFunc() then return that string. If N is out of range, return 0.
** If useType is 1, then use the second set of N elements (the datatype
** names) instead of the first set.
**
** There are up to 5 names for each column. useType determines which
** name is returned. Here are the names:
**
** 0 The column name as it should be displayed for output
** 1 The datatype name for the column
** 2 The name of the database that the column derives from
** 3 The name of the table that the column derives from
** 4 The name of the table column that the result column derives from
**
** If the result is not a simple column reference (if it is an expression
** or a constant) then useTypes 2, 3, and 4 return NULL.
*/
static const void *columnName(
sqlite3_stmt *pStmt,
@ -398,9 +406,7 @@ static const void *columnName(
if( p==0 || N>=n || N<0 ){
return 0;
}
if( useType ){
N += n;
}
N += useType*n;
return xFunc(&p->aColName[N]);
}
@ -412,33 +418,72 @@ static const void *columnName(
const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 0);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 0);
}
#endif
/*
** Return the column declaration type (if applicable) of the 'i'th column
** of the result set of SQL statement pStmt, encoded as UTF-8.
** of the result set of SQL statement pStmt.
*/
const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 1);
}
#ifndef SQLITE_OMIT_UTF16
/*
** Return the name of the 'i'th column of the result set of SQL statement
** pStmt, encoded as UTF-16.
*/
const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 0);
}
/*
** Return the column declaration type (if applicable) of the 'i'th column
** of the result set of SQL statement pStmt, encoded as UTF-16.
*/
const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 1);
}
#endif /* SQLITE_OMIT_UTF16 */
#if !defined(SQLITE_OMIT_ORIGIN_NAMES) && 0
/*
** Return the name of the database from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unabiguous reference to a database column.
*/
const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 2);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 2);
}
#endif /* SQLITE_OMIT_UTF16 */
/*
** Return the name of the table from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unabiguous reference to a database column.
*/
const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 3);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 3);
}
#endif /* SQLITE_OMIT_UTF16 */
/*
** Return the name of the table column from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unabiguous reference to a database column.
*/
const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 4);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, 4);
}
#endif /* SQLITE_OMIT_UTF16 */
#endif /* SQLITE_OMIT_ORIGIN_NAMES */
/******************************* sqlite3_bind_ ***************************
**
** Routines used to attach values to wildcards in a compiled SQL statement.
@ -454,7 +499,7 @@ const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
static int vdbeUnbind(Vdbe *p, int i){
Mem *pVar;
if( p==0 || p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
sqlite3Error(p->db, SQLITE_MISUSE, 0);
if( p ) sqlite3Error(p->db, SQLITE_MISUSE, 0);
return SQLITE_MISUSE;
}
if( i<1 || i>p->nVar ){
@ -624,43 +669,38 @@ int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
}
/*
** Transfer any existing parameter bindings from pOldStmt to pNewStmt.
** They both must have the exact same number of parameters. They must
** both be created against the same database. Neither must be
** currently in a running state.
**/
int sqlite3_transfer_bindings(
sqlite3_stmt *pOldStmt,
sqlite3_stmt *pNewStmt
){
Vdbe *pold = (Vdbe*)pOldStmt;
Vdbe *pnew = (Vdbe*)pNewStmt;
int rc, i;
if( pold->db!=pnew->db ){
sqlite3Error(pold->db, SQLITE_MISUSE, 0);
** 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 sqlite3_transfer_bindings(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) ){
return SQLITE_MISUSE;
}
if( pold==0 || pold->magic!=VDBE_MAGIC_RUN || pold->pc>=0 ){
sqlite3Error(pold->db, SQLITE_MISUSE, 0);
return SQLITE_MISUSE;
if( pFrom->nVar!=pTo->nVar ){
return SQLITE_ERROR;
}
if( pnew==0 || pnew->magic!=VDBE_MAGIC_RUN || pnew->pc>=0 ){
sqlite3Error(pnew->db, SQLITE_MISUSE, 0);
return SQLITE_MISUSE;
for(i=0; rc==SQLITE_OK && i<pFrom->nVar; i++){
rc = sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]);
}
if( pold->nVar != pnew->nVar ){
sqlite3Error(pold->db, SQLITE_MISUSE, 0);
return SQLITE_MISUSE;
}
for(i=0; i < pold->nVar; i++) {
int rv=sqlite3VdbeMemCopy(&(pnew->aVar[i]), &(pold->aVar[i]));
if(rv!=SQLITE_OK)
return rv;
}
return SQLITE_OK;
return rc;
}
/*
** Return the sqlite3* database handle to which the prepared statement given
** in the argument belongs. This is the same database handle that was
** the first argument to the sqlite3_prepare() that was used to create
** the statement in the first place.
*/
sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){
return pStmt ? ((Vdbe*)pStmt)->db : 0;
}
/** experimental **/
/*
** Given a wildcard parameter name, return the set of indexes of the
** variables with that name. If there are no variables with the given

Просмотреть файл

@ -191,7 +191,7 @@ static int opcodeNoPush(u8 op){
** error if someone builds with an awk that uses (for example) 32-bit
** IEEE floats.
*/
static u32 masks[5] = {
static const u32 masks[5] = {
NOPUSH_MASK_0 + (NOPUSH_MASK_1<<16),
NOPUSH_MASK_2 + (NOPUSH_MASK_3<<16),
NOPUSH_MASK_4 + (NOPUSH_MASK_5<<16),
@ -220,6 +220,12 @@ int sqlite3VdbeOpcodeNoPush(u8 op){
**
** The integer *pMaxStack is set to the maximum number of vdbe stack
** entries that static analysis reveals this program might need.
**
** This routine also does the following optimization: It scans for
** Halt instructions where P1==SQLITE_CONSTRAINT or P2==OE_Abort or for
** IdxInsert instructions where P2!=0. If no such instruction is
** found, then every Statement instruction is changed to a Noop. In
** this way, we avoid creating the statement journal file unnecessarily.
*/
static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
int i;
@ -227,6 +233,8 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
int nMaxStack = p->nOp;
Op *pOp;
int *aLabel = p->aLabel;
int doesStatementRollback = 0;
int hasStatementBegin = 0;
for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
u8 opcode = pOp->opcode;
@ -237,6 +245,16 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
if( pOp->p1>nMaxArgs ) nMaxArgs = pOp->p1;
}else if( opcode==OP_AggFunc ){
if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
}else if( opcode==OP_Halt ){
if( pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort ){
doesStatementRollback = 1;
}
}else if( opcode==OP_IdxInsert ){
if( pOp->p2 ){
doesStatementRollback = 1;
}
}else if( opcode==OP_Statement ){
hasStatementBegin = 1;
}
if( opcodeNoPush(opcode) ){
@ -252,6 +270,19 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
*pMaxFuncArgs = nMaxArgs;
*pMaxStack = nMaxStack;
/* If we never rollback a statement transaction, then statement
** transactions are not needed. So change every OP_Statement
** opcode into an OP_Noop. This avoid a call to sqlite3OsOpenExclusive()
** which can be expensive on some platforms.
*/
if( hasStatementBegin && !doesStatementRollback ){
for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
if( pOp->opcode==OP_Statement ){
pOp->opcode = OP_Noop;
}
}
}
}
/*
@ -332,12 +363,17 @@ void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){
** A value of n==0 means copy bytes of zP3 up to and including the
** first null byte. If n>0 then copy n+1 bytes of zP3.
**
** If n==P3_STATIC it means that zP3 is a pointer to a constant static
** string and we can just copy the pointer. n==P3_POINTER means zP3 is
** a pointer to some object other than a string. n==P3_COLLSEQ and
** n==P3_KEYINFO mean that zP3 is a pointer to a CollSeq or KeyInfo
** structure. A copy is made of KeyInfo structures into memory obtained
** from sqliteMalloc.
** If n==P3_KEYINFO it means that zP3 is a pointer to a KeyInfo structure.
** A copy is made of the KeyInfo structure into memory obtained from
** sqliteMalloc, to be freed when the Vdbe is finalized.
** n==P3_KEYINFO_HANDOFF indicates that zP3 points to a KeyInfo structure
** stored in memory that the caller has obtained from sqliteMalloc. The
** caller should not free the allocation, it will be freed when the Vdbe is
** finalized.
**
** Other values of n (P3_STATIC, P3_COLLSEQ etc.) indicate that zP3 points
** to a string or structure that is guaranteed to exist for the lifetime of
** the Vdbe. In these cases we can just copy the pointer.
**
** If addr<0 then change P3 on the most recently inserted instruction.
*/
@ -348,6 +384,9 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
if( n==P3_DYNAMIC || n==P3_KEYINFO_HANDOFF ){
sqliteFree((void*)zP3);
}
if( n==P3_MEM ){
sqlite3ValueFree((sqlite3_value *)zP3);
}
return;
}
if( addr<0 || addr>=p->nOp ){
@ -463,11 +502,6 @@ static char *displayP3(Op *pOp, char *zTemp, int nTemp){
char *zP3;
assert( nTemp>=20 );
switch( pOp->p3type ){
case P3_POINTER: {
sprintf(zTemp, "ptr(%#x)", (int)pOp->p3);
zP3 = zTemp;
break;
}
case P3_KEYINFO: {
int i, j;
KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3;
@ -686,7 +720,9 @@ void sqlite3VdbeMakeReady(
/* No instruction ever pushes more than a single element onto the
** stack. And the stack never grows on successive executions of the
** same loop. So the total number of instructions is an upper bound
** on the maximum stack depth required.
** on the maximum stack depth required. (Added later:) The
** resolveP2Values() call computes a tighter upper bound on the
** stack size.
**
** Allocation all the stack space we will ever need.
*/
@ -779,6 +815,7 @@ void sqlite3VdbeSorterReset(Vdbe *p){
sqlite3VdbeMemRelease(&pSorter->data);
sqliteFree(pSorter);
}
p->pSortTail = 0;
}
/*
@ -1106,6 +1143,7 @@ static int vdbeCommit(sqlite3 *db){
** This requires a master journal file to ensure the transaction is
** committed atomicly.
*/
#ifndef SQLITE_OMIT_DISKIO
else{
char *zMaster = 0; /* File-name for the master journal */
char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt);
@ -1222,6 +1260,7 @@ static int vdbeCommit(sqlite3 *db){
}
}
}
#endif
return rc;
}
@ -1533,8 +1572,8 @@ int sqlite3VdbeCursorMoveto(Cursor *p){
if( p->deferredMoveto ){
int res, rc;
extern int sqlite3_search_count;
assert( p->intKey );
if( p->intKey ){
assert( p->isTable );
if( p->isTable ){
rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, &res);
}else{
rc = sqlite3BtreeMoveto(p->pCursor,(char*)&p->movetoTarget,
@ -1542,8 +1581,8 @@ int sqlite3VdbeCursorMoveto(Cursor *p){
}
if( rc ) return rc;
*p->pIncrKey = 0;
p->lastRecno = keyToInt(p->movetoTarget);
p->recnoIsValid = res==0;
p->lastRowid = keyToInt(p->movetoTarget);
p->rowidIsValid = res==0;
if( res<0 ){
rc = sqlite3BtreeNext(p->pCursor, &res);
if( rc ) return rc;
@ -1604,7 +1643,7 @@ u32 sqlite3VdbeSerialType(Mem *pMem){
}
if( flags&MEM_Int ){
/* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
# define MAX_6BYTE ((((i64)0x00010000)<<32)-1)
# define MAX_6BYTE ((((i64)0x00001000)<<32)-1)
i64 i = pMem->i;
u64 u = i<0 ? -i : i;
if( u<=127 ) return 1;
@ -1687,61 +1726,71 @@ int sqlite3VdbeSerialGet(
u32 serial_type, /* Serial type to deserialize */
Mem *pMem /* Memory cell to write value into */
){
int len;
if( serial_type==0 ){
/* NULL */
pMem->flags = MEM_Null;
return 0;
}
len = sqlite3VdbeSerialTypeLen(serial_type);
if( serial_type<=7 ){
/* Integer and Real */
if( serial_type<=4 ){
/* 32-bit integer type. This is handled by a special case for
** performance reasons. */
int v = buf[0];
int n;
if( v&0x80 ){
v |= -256;
}
for(n=1; n<len; n++){
v = (v<<8) | buf[n];
}
switch( serial_type ){
case 8: /* Reserved for future use */
case 9: /* Reserved for future use */
case 10: /* Reserved for future use */
case 11: /* Reserved for future use */
case 0: { /* NULL */
pMem->flags = MEM_Null;
break;
}
case 1: { /* 1-byte signed integer */
pMem->i = (signed char)buf[0];
pMem->flags = MEM_Int;
pMem->i = v;
return n;
}else{
u64 v = 0;
int n;
if( buf[0]&0x80 ){
v = -1;
}
for(n=0; n<len; n++){
v = (v<<8) | buf[n];
}
if( serial_type==7 ){
pMem->flags = MEM_Real;
pMem->r = *(double*)&v;
}else{
pMem->flags = MEM_Int;
pMem->i = *(i64*)&v;
}
return 1;
}
}else{
/* String or blob */
assert( serial_type>=12 );
pMem->z = (char *)buf;
pMem->n = len;
pMem->xDel = 0;
if( serial_type&0x01 ){
pMem->flags = MEM_Str | MEM_Ephem;
}else{
pMem->flags = MEM_Blob | MEM_Ephem;
case 2: { /* 2-byte signed integer */
pMem->i = (((signed char)buf[0])<<8) | buf[1];
pMem->flags = MEM_Int;
return 2;
}
case 3: { /* 3-byte signed integer */
pMem->i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2];
pMem->flags = MEM_Int;
return 3;
}
case 4: { /* 4-byte signed integer */
pMem->i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
pMem->flags = MEM_Int;
return 4;
}
case 5: { /* 6-byte signed integer */
u64 x = (((signed char)buf[0])<<8) | buf[1];
u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
x = (x<<32) | y;
pMem->i = *(i64*)&x;
pMem->flags = MEM_Int;
return 6;
}
case 6: /* 6-byte signed integer */
case 7: { /* IEEE floating point */
u64 x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
u32 y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
x = (x<<32) | y;
if( serial_type==6 ){
pMem->i = *(i64*)&x;
pMem->flags = MEM_Int;
}else{
pMem->r = *(double*)&x;
pMem->flags = MEM_Real;
}
return 8;
}
default: {
int len = (serial_type-12)/2;
pMem->z = (char *)buf;
pMem->n = len;
pMem->xDel = 0;
if( serial_type&0x01 ){
pMem->flags = MEM_Str | MEM_Ephem;
}else{
pMem->flags = MEM_Blob | MEM_Ephem;
}
return len;
}
}
return len;
return 0;
}
/*
@ -1795,8 +1844,8 @@ int sqlite3VdbeRecordCompare(
d2 += sqlite3VdbeSerialGet(&aKey2[d2], serial_type2, &mem2);
rc = sqlite3MemCompare(&mem1, &mem2, i<nField ? pKeyInfo->aColl[i] : 0);
sqlite3VdbeMemRelease(&mem1);
sqlite3VdbeMemRelease(&mem2);
if( mem1.flags & MEM_Dyn ) sqlite3VdbeMemRelease(&mem1);
if( mem2.flags & MEM_Dyn ) sqlite3VdbeMemRelease(&mem2);
if( rc!=0 ){
break;
}

Просмотреть файл

@ -608,8 +608,13 @@ int sqlite3VdbeMemFromBtree(
zData[amt] = 0;
zData[amt+1] = 0;
if( rc!=SQLITE_OK ){
if( amt>NBFS ){
if( amt>NBFS-2 ){
assert( zData!=pMem->zShort );
assert( pMem->flags & MEM_Dyn );
sqliteFree(zData);
} else {
assert( zData==pMem->zShort );
assert( pMem->flags & MEM_Short );
}
return rc;
}

Просмотреть файл

@ -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.136 2005/03/16 12:15:21 danielk1977 Exp $
** $Id: where.c,v 1.139 2005/06/12 21:35:53 drh Exp $
*/
#include "sqliteInt.h"
@ -497,7 +497,6 @@ static void codeEqualityTerm(
sqlite3CodeSubselect(pParse, pX);
iTab = pX->iTable;
sqlite3VdbeAddOp(v, OP_Rewind, iTab, brk);
sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1);
VdbeComment((v, "# %.*s", pX->span.n, pX->span.z));
pLevel->inP2 = sqlite3VdbeAddOp(v, OP_Column, iTab, 0);
pLevel->inOp = OP_Next;
@ -546,7 +545,7 @@ static void codeEqualityTerm(
**
** The code that sqlite3WhereBegin() generates leaves the cursors named
** in pTabList pointing at their appropriate entries. The [...] code
** can use OP_Column and OP_Recno opcodes on these cursors to extract
** can use OP_Column and OP_Rowid opcodes on these cursors to extract
** data from the various tables of the loop.
**
** If the WHERE clause is empty, the foreach loops must each scan their
@ -599,8 +598,7 @@ WhereInfo *sqlite3WhereBegin(
Parse *pParse, /* The parser context */
SrcList *pTabList, /* A list of all tables to be scanned */
Expr *pWhere, /* The WHERE clause */
ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
Fetch *pFetch /* Initial location of cursors. NULL otherwise */
ExprList **ppOrderBy /* An ORDER BY clause, or NULL */
){
int i; /* Loop counter */
WhereInfo *pWInfo; /* Will become the return value of this function */
@ -794,7 +792,7 @@ WhereInfo *sqlite3WhereBegin(
&& (pTerm->prereqRight & loopMask)==pTerm->prereqRight ){
int iColumn = pX->pLeft->iColumn;
int k;
char idxaff = pIdx->pTable->aCol[iColumn].affinity;
char idxaff = iColumn>=0 ? pIdx->pTable->aCol[iColumn].affinity : 0;
for(k=0; k<pIdx->nColumn; k++){
/* If the collating sequences or affinities don't match,
** ignore this index. */
@ -950,7 +948,6 @@ WhereInfo *sqlite3WhereBegin(
(char*)&pIx->keyInfo, P3_KEYINFO);
}
if( (pLevel->score & 1)!=0 ){
sqlite3VdbeAddOp(v, OP_KeyAsData, iIdxCur, 1);
sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1);
}
sqlite3CodeVerifySchema(pParse, pTab->iDb);
@ -985,7 +982,7 @@ WhereInfo *sqlite3WhereBegin(
if( i>0 && (pTabList->a[i-1].jointype & JT_LEFT)!=0 ){
if( !pParse->nMem ) pParse->nMem++;
pLevel->iLeftJoin = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1);
VdbeComment((v, "# init LEFT JOIN no-match flag"));
}
@ -1062,7 +1059,7 @@ WhereInfo *sqlite3WhereBegin(
sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);
sqlite3VdbeAddOp(v, OP_IdxIsNull, nColumn, cont);
if( !omitTable ){
sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0);
sqlite3VdbeAddOp(v, OP_IdxRowid, iIdxCur, 0);
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
}
pLevel->p1 = iIdxCur;
@ -1121,9 +1118,9 @@ WhereInfo *sqlite3WhereBegin(
pLevel->p1 = iCur;
pLevel->p2 = start;
if( testOp!=OP_Noop ){
sqlite3VdbeAddOp(v, OP_Recno, iCur, 0);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
sqlite3VdbeAddOp(v, testOp, (int)(('n'<<8)&0x0000FF00), brk);
sqlite3VdbeAddOp(v, testOp, 'n', brk);
}
}else if( pIdx==0 ){
/* Case 4: There is no usable index. We must do a complete
@ -1296,7 +1293,7 @@ WhereInfo *sqlite3WhereBegin(
sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);
sqlite3VdbeAddOp(v, OP_IdxIsNull, nEqColumn + ((score&4)!=0), cont);
if( !omitTable ){
sqlite3VdbeAddOp(v, OP_IdxRecno, iIdxCur, 0);
sqlite3VdbeAddOp(v, OP_IdxRowid, iIdxCur, 0);
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
}
@ -1425,9 +1422,9 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
break;
}
}
}else if( pOp->opcode==OP_Recno ){
}else if( pOp->opcode==OP_Rowid ){
pOp->p1 = pLevel->iIdxCur;
pOp->opcode = OP_IdxRecno;
pOp->opcode = OP_IdxRowid;
}else if( pOp->opcode==OP_NullRow ){
pOp->opcode = OP_Noop;
}