Update to SQLite 3.2.2
This commit is contained in:
Родитель
fcf4d7234a
Коммит
9e163a98f6
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче