Upgrade to SQLite 3.2.7, r=darin

This commit is contained in:
vladimir%pobox.com 2005-12-13 19:49:36 +00:00
Родитель e6d06e8485
Коммит 7ec2aabd8f
48 изменённых файлов: 8245 добавлений и 6177 удалений

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

@ -1,5 +1,5 @@
This is sqlite 3.0.8. (SQLITE_3_0_8 tag)
This is sqlite 3.2.7.
See http://www.sqlite.org/ for more info.
@ -12,13 +12,11 @@ PR_BYTES_PER_WORD.
We only imported the bits that we actually need for the build --
basically, the contents of the src directory, plus autogenerated files
(see below). Note that we don't use all the files in the src dir,
but we import *.c *.h *.in for simplicity.
(see below). Note that we don't use all the files in the src dir;
we just bring in *.c *.h (including a full sqlite3.h).
To move to a new version:
Update VERSION in src/Makefile.in
Update opcodes.c, opcodes.h, parse.c, parse.h, all of which are
normally generated as part of the sqlite build. Pull these out of the
sqlite3 windows source .zip, or autoconfiscate and build a tarball and
@ -26,3 +24,4 @@ copy them out. Yes, this sucks, but it's better than having to build
the parser and all that goop as part of our build.
-- Vlad Vukicevic <vladimir@pobox.com> 10/2004

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

@ -52,11 +52,13 @@ EXPORTS = sqlite3.h
CSRCS = \
alter.c \
analyze.c \
attach.c \
auth.c \
btree.c \
build.c \
callback.c \
complete.c \
date.c \
delete.c \
experimental.c \
@ -87,6 +89,7 @@ CSRCS = \
vdbe.c \
vdbeapi.c \
vdbeaux.c \
vdbefifo.c \
vdbemem.c \
where.c \
$(NULL)

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

@ -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.3 2005-08-20 01:23:48 vladimir%pobox.com Exp $
** $Id: alter.c,v 1.4 2005-12-13 19:49:35 vladimir%pobox.com Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -258,6 +258,7 @@ void sqlite3AlterRenameTable(
char *zWhere = 0; /* Where clause to locate temp triggers */
#endif
if( sqlite3_malloc_failed ) goto exit_rename_table;
assert( pSrc->nSrc==1 );
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
@ -500,8 +501,10 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
int i;
int nAlloc;
/* Look up the table being altered. */
assert( !pParse->pNewTable );
assert( pParse->pNewTable==0 );
if( sqlite3_malloc_failed ) goto exit_begin_add_column;
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
if( !pTab ) goto exit_begin_add_column;
@ -520,6 +523,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
pNew = (Table *)sqliteMalloc(sizeof(Table));
if( !pNew ) goto exit_begin_add_column;
pParse->pNewTable = pNew;
pNew->nRef = 1;
pNew->nCol = pTab->nCol;
assert( pNew->nCol>0 );
nAlloc = (((pNew->nCol-1)/8)*8)+8;

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

@ -0,0 +1,386 @@
/*
** 2005 July 8
**
** 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 code associated with the ANALYZE command.
**
** @(#) $Id: analyze.c,v 1.1 2005-12-13 19:49:35 vladimir%pobox.com Exp $
*/
#ifndef SQLITE_OMIT_ANALYZE
#include "sqliteInt.h"
/*
** This routine generates code that opens the sqlite_stat1 table on cursor
** iStatCur.
**
** If the sqlite_stat1 tables does not previously exist, it is created.
** If it does previously exist, all entires associated with table zWhere
** are removed. If zWhere==0 then all entries are removed.
*/
static void openStatTable(
Parse *pParse, /* Parsing context */
int iDb, /* The database we are looking in */
int iStatCur, /* Open the sqlite_stat1 table on this cursor */
const char *zWhere /* Delete entries associated with this table */
){
sqlite3 *db = pParse->db;
Db *pDb;
int iRootPage;
Table *pStat;
Vdbe *v = sqlite3GetVdbe(pParse);
pDb = &db->aDb[iDb];
if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){
/* The sqlite_stat1 tables does not exist. Create it.
** Note that a side-effect of the CREATE TABLE statement is to leave
** the rootpage of the new table on the top of the stack. This is
** important because the OpenWrite opcode below will be needing it. */
sqlite3NestedParse(pParse,
"CREATE TABLE %Q.sqlite_stat1(tbl,idx,stat)",
pDb->zName
);
iRootPage = 0; /* Cause rootpage to be taken from top of stack */
}else if( zWhere ){
/* The sqlite_stat1 table exists. Delete all entries associated with
** the table zWhere. */
sqlite3NestedParse(pParse,
"DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q",
pDb->zName, zWhere
);
iRootPage = pStat->tnum;
}else{
/* The sqlite_stat1 table already exists. Delete all rows. */
iRootPage = pStat->tnum;
sqlite3VdbeAddOp(v, OP_Clear, pStat->tnum, iDb);
}
/* Open the sqlite_stat1 table for writing.
*/
sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
sqlite3VdbeAddOp(v, OP_OpenWrite, iStatCur, iRootPage);
sqlite3VdbeAddOp(v, OP_SetNumColumns, iStatCur, 3);
}
/*
** Generate code to do an analysis of all indices associated with
** a single table.
*/
static void analyzeOneTable(
Parse *pParse, /* Parser context */
Table *pTab, /* Table whose indices are to be analyzed */
int iStatCur, /* Cursor that writes to the sqlite_stat1 table */
int iMem /* Available memory locations begin here */
){
Index *pIdx; /* An index to being analyzed */
int iIdxCur; /* Cursor number for index being analyzed */
int nCol; /* Number of columns in the index */
Vdbe *v; /* The virtual machine being built up */
int i; /* Loop counter */
int topOfLoop; /* The top of the loop */
int endOfLoop; /* The end of the loop */
int addr; /* The address of an instruction */
v = sqlite3GetVdbe(pParse);
if( pTab==0 || pTab->pIndex==0 ){
/* Do no analysis for tables that have no indices */
return;
}
#ifndef SQLITE_OMIT_AUTHORIZATION
if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0,
pParse->db->aDb[pTab->iDb].zName ) ){
return;
}
#endif
iIdxCur = pParse->nTab;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
/* Open a cursor to the index to be analyzed
*/
sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
VdbeComment((v, "# %s", pIdx->zName));
sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum,
(char*)&pIdx->keyInfo, P3_KEYINFO);
nCol = pIdx->nColumn;
if( iMem+nCol*2>=pParse->nMem ){
pParse->nMem = iMem+nCol*2+1;
}
sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, nCol+1);
/* Memory cells are used as follows:
**
** mem[iMem]: The total number of rows in the table.
** mem[iMem+1]: Number of distinct values in column 1
** ...
** mem[iMem+nCol]: Number of distinct values in column N
** mem[iMem+nCol+1] Last observed value of column 1
** ...
** mem[iMem+nCol+nCol]: Last observed value of column N
**
** Cells iMem through iMem+nCol are initialized to 0. The others
** are initialized to NULL.
*/
for(i=0; i<=nCol; i++){
sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem+i);
}
for(i=0; i<nCol; i++){
sqlite3VdbeAddOp(v, OP_MemNull, iMem+nCol+i+1, 0);
}
/* Do the analysis.
*/
endOfLoop = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, endOfLoop);
topOfLoop = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp(v, OP_MemIncr, iMem, 0);
for(i=0; i<nCol; i++){
sqlite3VdbeAddOp(v, OP_Column, iIdxCur, i);
sqlite3VdbeAddOp(v, OP_MemLoad, iMem+nCol+i+1, 0);
sqlite3VdbeAddOp(v, OP_Ne, 0x100, 0);
}
sqlite3VdbeAddOp(v, OP_Goto, 0, endOfLoop);
for(i=0; i<nCol; i++){
addr = sqlite3VdbeAddOp(v, OP_MemIncr, iMem+i+1, 0);
sqlite3VdbeChangeP2(v, topOfLoop + 3*i + 3, addr);
sqlite3VdbeAddOp(v, OP_Column, iIdxCur, i);
sqlite3VdbeAddOp(v, OP_MemStore, iMem+nCol+i+1, 1);
}
sqlite3VdbeResolveLabel(v, endOfLoop);
sqlite3VdbeAddOp(v, OP_Next, iIdxCur, topOfLoop);
sqlite3VdbeAddOp(v, OP_Close, iIdxCur, 0);
/* Store the results.
**
** The result is a single row of the sqlite_stmt1 table. The first
** two columns are the names of the table and index. The third column
** is a string composed of a list of integer statistics about the
** index. The first integer in the list is the total number of entires
** in the index. There is one additional integer in the list for each
** column of the table. This additional integer is a guess of how many
** rows of the table the index will select. If D is the count of distinct
** values and K is the total number of rows, then the integer is computed
** as:
**
** I = (K+D-1)/D
**
** If K==0 then no entry is made into the sqlite_stat1 table.
** If K>0 then it is always the case the D>0 so division by zero
** is never possible.
*/
sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0);
addr = sqlite3VdbeAddOp(v, OP_IfNot, 0, 0);
sqlite3VdbeAddOp(v, OP_NewRowid, iStatCur, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pIdx->zName, 0);
sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, " ", 0);
for(i=0; i<nCol; i++){
sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0);
sqlite3VdbeAddOp(v, OP_MemLoad, iMem+i+1, 0);
sqlite3VdbeAddOp(v, OP_Add, 0, 0);
sqlite3VdbeAddOp(v, OP_AddImm, -1, 0);
sqlite3VdbeAddOp(v, OP_MemLoad, iMem+i+1, 0);
sqlite3VdbeAddOp(v, OP_Divide, 0, 0);
if( i==nCol-1 ){
sqlite3VdbeAddOp(v, OP_Concat, nCol*2-1, 0);
}else{
sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
}
}
sqlite3VdbeOp3(v, OP_MakeRecord, 3, 0, "ttt", 0);
sqlite3VdbeAddOp(v, OP_Insert, iStatCur, 0);
sqlite3VdbeJumpHere(v, addr);
}
}
/*
** Generate code that will cause the most recent index analysis to
** be laoded into internal hash tables where is can be used.
*/
static void loadAnalysis(Parse *pParse, int iDb){
Vdbe *v = sqlite3GetVdbe(pParse);
sqlite3VdbeAddOp(v, OP_LoadAnalysis, iDb, 0);
}
/*
** Generate code that will do an analysis of an entire database
*/
static void analyzeDatabase(Parse *pParse, int iDb){
sqlite3 *db = pParse->db;
HashElem *k;
int iStatCur;
int iMem;
sqlite3BeginWriteOperation(pParse, 0, iDb);
iStatCur = pParse->nTab++;
openStatTable(pParse, iDb, iStatCur, 0);
iMem = pParse->nMem;
for(k=sqliteHashFirst(&db->aDb[iDb].tblHash); k; k=sqliteHashNext(k)){
Table *pTab = (Table*)sqliteHashData(k);
analyzeOneTable(pParse, pTab, iStatCur, iMem);
}
loadAnalysis(pParse, iDb);
}
/*
** Generate code that will do an analysis of a single table in
** a database.
*/
static void analyzeTable(Parse *pParse, Table *pTab){
int iDb;
int iStatCur;
assert( pTab!=0 );
iDb = pTab->iDb;
sqlite3BeginWriteOperation(pParse, 0, iDb);
iStatCur = pParse->nTab++;
openStatTable(pParse, iDb, iStatCur, pTab->zName);
analyzeOneTable(pParse, pTab, iStatCur, pParse->nMem);
loadAnalysis(pParse, iDb);
}
/*
** Generate code for the ANALYZE command. The parser calls this routine
** when it recognizes an ANALYZE command.
**
** ANALYZE -- 1
** ANALYZE <database> -- 2
** ANALYZE ?<database>.?<tablename> -- 3
**
** Form 1 causes all indices in all attached databases to be analyzed.
** Form 2 analyzes all indices the single database named.
** Form 3 analyzes all indices associated with the named table.
*/
void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
sqlite3 *db = pParse->db;
int iDb;
int i;
char *z, *zDb;
Table *pTab;
Token *pTableName;
/* Read the database schema. If an error occurs, leave an error message
** and code in pParse and return NULL. */
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
return;
}
if( pName1==0 ){
/* Form 1: Analyze everything */
for(i=0; i<db->nDb; i++){
if( i==1 ) continue; /* Do not analyze the TEMP database */
analyzeDatabase(pParse, i);
}
}else if( pName2==0 || pName2->n==0 ){
/* Form 2: Analyze the database or table named */
iDb = sqlite3FindDb(db, pName1);
if( iDb>=0 ){
analyzeDatabase(pParse, iDb);
}else{
z = sqlite3NameFromToken(pName1);
pTab = sqlite3LocateTable(pParse, z, 0);
sqliteFree(z);
if( pTab ){
analyzeTable(pParse, pTab);
}
}
}else{
/* Form 3: Analyze the fully qualified table name */
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName);
if( iDb>=0 ){
zDb = db->aDb[iDb].zName;
z = sqlite3NameFromToken(pTableName);
pTab = sqlite3LocateTable(pParse, z, zDb);
sqliteFree(z);
if( pTab ){
analyzeTable(pParse, pTab);
}
}
}
}
/*
** Used to pass information from the analyzer reader through to the
** callback routine.
*/
typedef struct analysisInfo analysisInfo;
struct analysisInfo {
sqlite3 *db;
const char *zDatabase;
};
/*
** This callback is invoked once for each index when reading the
** sqlite_stat1 table.
**
** argv[0] = name of the index
** argv[1] = results of analysis - on integer for each column
*/
static int analysisLoader(void *pData, int argc, char **argv, char **azNotUsed){
analysisInfo *pInfo = (analysisInfo*)pData;
Index *pIndex;
int i, c;
unsigned int v;
const char *z;
assert( argc==2 );
if( argv==0 || argv[0]==0 || argv[1]==0 ){
return 0;
}
pIndex = sqlite3FindIndex(pInfo->db, argv[0], pInfo->zDatabase);
if( pIndex==0 ){
return 0;
}
z = argv[1];
for(i=0; *z && i<=pIndex->nColumn; i++){
v = 0;
while( (c=z[0])>='0' && c<='9' ){
v = v*10 + c - '0';
z++;
}
pIndex->aiRowEst[i] = v;
if( *z==' ' ) z++;
}
return 0;
}
/*
** Load the content of the sqlite_stat1 table into the index hash tables.
*/
void sqlite3AnalysisLoad(sqlite3 *db, int iDb){
analysisInfo sInfo;
HashElem *i;
char *zSql;
/* Clear any prior statistics */
for(i=sqliteHashFirst(&db->aDb[iDb].idxHash); i; i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
sqlite3DefaultRowEst(pIdx);
}
/* Check to make sure the sqlite_stat1 table existss */
sInfo.db = db;
sInfo.zDatabase = db->aDb[iDb].zName;
if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){
return;
}
/* Load new statistics out of the sqlite_stat1 table */
zSql = sqlite3MPrintf("SELECT idx, stat FROM %Q.sqlite_stat1",
sInfo.zDatabase);
sqlite3SafetyOff(db);
sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
sqlite3SafetyOn(db);
sqliteFree(zSql);
}
#endif /* SQLITE_OMIT_ANALYZE */

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

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
** $Id: attach.c,v 1.33 2005/03/16 12:15:21 danielk1977 Exp $
** $Id: attach.c,v 1.34 2005/08/20 03:03:04 drh Exp $
*/
#include "sqliteInt.h"
@ -146,8 +146,8 @@ void sqlite3Attach(
db->aDb[i].pBt = 0;
}
sqlite3ResetInternalSchema(db, 0);
if( 0==pParse->nErr ){
pParse->nErr++;
assert( pParse->nErr>0 ); /* Always set by sqlite3ReadSchema() */
if( pParse->rc==SQLITE_OK ){
pParse->rc = SQLITE_ERROR;
}
}

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

@ -14,7 +14,7 @@
** systems that do not need this facility may omit it by recompiling
** the library with -DSQLITE_OMIT_AUTHORIZATION=1
**
** $Id: auth.c,v 1.21 2005/01/29 08:32:44 danielk1977 Exp $
** $Id: auth.c,v 1.22 2005/07/29 15:36:15 drh Exp $
*/
#include "sqliteInt.h"
@ -114,6 +114,7 @@ void sqlite3AuthRead(
TriggerStack *pStack; /* The stack of current triggers */
if( db->xAuth==0 ) return;
if( pExpr->op==TK_AS ) return;
assert( pExpr->op==TK_COLUMN );
for(iSrc=0; pTabList && iSrc<pTabList->nSrc; iSrc++){
if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;

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

@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.261 2005/05/24 20:19:58 drh Exp $
** $Id: btree.c,v 1.269 2005/09/17 15:20:27 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
@ -234,8 +234,19 @@ typedef struct MemPage MemPage;
/*
** This is a magic string that appears at the beginning of every
** SQLite database in order to identify the file as a real database.
** 123456789 123456 */
static const char zMagicHeader[] = "SQLite format 3";
**
** You can change this value at compile-time by specifying a
** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The
** header must be exactly 16 bytes including the zero-terminator so
** the string itself should be 15 characters long. If you change
** the header, then your custom library will not be able to read
** databases generated by the standard tools and the standard tools
** will not be able to read databases created by your custom library.
*/
#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */
# define SQLITE_FILE_HEADER "SQLite format 3"
#endif
static const char zMagicHeader[] = SQLITE_FILE_HEADER;
/*
** Page type flags. An ORed combination of these flags appear as the
@ -483,7 +494,7 @@ static int ptrmapPut(Btree *pBt, Pgno key, u8 eType, Pgno parent){
assert( pBt->autoVacuum );
if( key==0 ){
return SQLITE_CORRUPT;
return SQLITE_CORRUPT_BKPT;
}
iPtrmap = PTRMAP_PAGENO(pBt->usableSize, key);
rc = sqlite3pager_get(pBt->pPager, iPtrmap, (void **)&pPtrmap);
@ -529,7 +540,7 @@ static int ptrmapGet(Btree *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
sqlite3pager_unref(pPtrmap);
if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT;
if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT;
return SQLITE_OK;
}
@ -1019,7 +1030,7 @@ static int initPage(
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 */
return SQLITE_CORRUPT_BKPT;
}
if( pPage->isInit ) return SQLITE_OK;
if( pPage->pParent==0 && pParent!=0 ){
@ -1037,11 +1048,11 @@ static int initPage(
pPage->nCell = get2byte(&data[hdr+3]);
if( pPage->nCell>MX_CELL(pBt) ){
/* To many cells for a single page. The page must be corrupt */
return SQLITE_CORRUPT; /* bkpt-CORRUPT */
return SQLITE_CORRUPT_BKPT;
}
if( pPage->nCell==0 && pParent!=0 && pParent->pgno!=1 ){
/* All pages must have at least one cell, except for root pages */
return SQLITE_CORRUPT; /* bkpt-CORRUPT */
return SQLITE_CORRUPT_BKPT;
}
/* Compute the total free space on the page */
@ -1051,13 +1062,13 @@ static int initPage(
int next, size;
if( pc>usableSize-4 ){
/* Free block is off the page */
return SQLITE_CORRUPT; /* bkpt-CORRUPT */
return SQLITE_CORRUPT_BKPT;
}
next = get2byte(&data[pc]);
size = get2byte(&data[pc+2]);
if( next>0 && next<=pc+size+3 ){
/* Free blocks must be in accending order */
return SQLITE_CORRUPT; /* bkpt-CORRUPT */
return SQLITE_CORRUPT_BKPT;
}
nFree += size;
pc = next;
@ -1065,7 +1076,7 @@ static int initPage(
pPage->nFree = nFree;
if( nFree>=usableSize ){
/* Free space cannot exceed total page size */
return SQLITE_CORRUPT; /* bkpt-CORRUPT */
return SQLITE_CORRUPT_BKPT;
}
pPage->isInit = 1;
@ -1135,7 +1146,7 @@ static int getAndInitPage(
){
int rc;
if( pgno==0 ){
return SQLITE_CORRUPT; /* bkpt-CORRUPT */
return SQLITE_CORRUPT_BKPT;
}
rc = getPage(pBt, pgno, ppPage);
if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){
@ -1334,6 +1345,15 @@ int sqlite3BtreeSetSafetyLevel(Btree *pBt, int level){
}
#endif
/*
** Return TRUE if the given btree is set to safety level 1. In other
** words, return TRUE if no sync() occurs on the disk files.
*/
int sqlite3BtreeSyncDisabled(Btree *pBt){
assert( pBt && pBt->pPager );
return sqlite3pager_nosync(pBt->pPager);
}
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)
/*
** Change the default pages size and the number of reserved bytes per page.
@ -1595,8 +1615,6 @@ static int newDatabase(Btree *pBt){
*/
int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){
int rc = SQLITE_OK;
int busy = 0;
BusyHandler *pH;
/* If the btree is already in a write-transaction, or it
** is already in a read-transaction and a read-transaction
@ -1630,9 +1648,7 @@ int sqlite3BtreeBeginTrans(Btree *pBt, int wrflag){
unlockBtreeIfUnused(pBt);
}
}while( rc==SQLITE_BUSY && pBt->inTrans==TRANS_NONE &&
(pH = pBt->pBusyHandler)!=0 &&
pH->xFunc && pH->xFunc(pH->pArg, busy++)
);
sqlite3InvokeBusyHandler(pBt->pBusyHandler) );
return rc;
}
@ -1698,7 +1714,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
if( eType==PTRMAP_OVERFLOW2 ){
/* The pointer is always the first 4 bytes of the page in this case. */
if( get4byte(pPage->aData)!=iFrom ){
return SQLITE_CORRUPT;
return SQLITE_CORRUPT_BKPT;
}
put4byte(pPage->aData, iTo);
}else{
@ -1731,7 +1747,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
if( i==nCell ){
if( eType!=PTRMAP_BTREE ||
get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
return SQLITE_CORRUPT;
return SQLITE_CORRUPT_BKPT;
}
put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
}
@ -1844,7 +1860,7 @@ static int autoVacuumCommit(Btree *pBt, Pgno *nTrunc){
assert( pBt->autoVacuum );
if( PTRMAP_ISPAGE(pgsz, sqlite3pager_pagecount(pPager)) ){
return SQLITE_CORRUPT;
return SQLITE_CORRUPT_BKPT;
}
/* Figure out how many free-pages are in the database. If there are no
@ -1859,7 +1875,7 @@ static int autoVacuumCommit(Btree *pBt, Pgno *nTrunc){
origSize = sqlite3pager_pagecount(pPager);
nPtrMap = (nFreeList-origSize+PTRMAP_PAGENO(pgsz, origSize)+pgsz/5)/(pgsz/5);
finSize = origSize - nFreeList - nPtrMap;
if( origSize>PENDING_BYTE_PAGE(pBt) && finSize<=PENDING_BYTE_PAGE(pBt) ){
if( origSize>=PENDING_BYTE_PAGE(pBt) && finSize<=PENDING_BYTE_PAGE(pBt) ){
finSize--;
if( PTRMAP_ISPAGE(pBt->usableSize, finSize) ){
finSize--;
@ -1882,7 +1898,7 @@ static int autoVacuumCommit(Btree *pBt, Pgno *nTrunc){
rc = ptrmapGet(pBt, iDbPage, &eType, &iPtrPage);
if( rc!=SQLITE_OK ) goto autovacuum_out;
if( eType==PTRMAP_ROOTPAGE ){
rc = SQLITE_CORRUPT;
rc = SQLITE_CORRUPT_BKPT;
goto autovacuum_out;
}
@ -2398,7 +2414,7 @@ static int getPayload(
}
if( amt>0 ){
return SQLITE_CORRUPT; /* bkpt-CORRUPT */
return SQLITE_CORRUPT_BKPT;
}
return SQLITE_OK;
}
@ -2416,7 +2432,7 @@ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
assert( pCur->isValid );
assert( pCur->pPage!=0 );
if( pCur->pPage->intKey ){
return SQLITE_CORRUPT;
return SQLITE_CORRUPT_BKPT;
}
assert( pCur->pPage->intKey==0 );
assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
@ -2465,13 +2481,11 @@ static const unsigned char *fetchPayload(
){
unsigned char *aPayload;
MemPage *pPage;
Btree *pBt;
u32 nKey;
int nLocal;
assert( pCur!=0 && pCur->pPage!=0 );
assert( pCur->isValid );
pBt = pCur->pBt;
pPage = pCur->pPage;
pageIntegrity(pPage);
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
@ -2538,7 +2552,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
pCur->idx = 0;
pCur->info.nSize = 0;
if( pNewPage->nCell<1 ){
return SQLITE_CORRUPT; /* bkpt-CORRUPT */
return SQLITE_CORRUPT_BKPT;
}
return SQLITE_OK;
}
@ -2569,7 +2583,6 @@ static int isRootPage(MemPage *pPage){
** the largest cell index.
*/
static void moveToParent(BtCursor *pCur){
Pgno oldPgno;
MemPage *pParent;
MemPage *pPage;
int idxParent;
@ -2584,7 +2597,6 @@ static void moveToParent(BtCursor *pCur){
pageIntegrity(pParent);
idxParent = pPage->idxParent;
sqlite3pager_ref(pParent->aData);
oldPgno = pPage->pgno;
releasePage(pPage);
pCur->pPage = pParent;
pCur->info.nSize = 0;
@ -2749,7 +2761,7 @@ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){
lwr = 0;
upr = pPage->nCell-1;
if( !pPage->intKey && pKey==0 ){
return SQLITE_CORRUPT;
return SQLITE_CORRUPT_BKPT;
}
pageIntegrity(pPage);
while( lwr<=upr ){
@ -3034,7 +3046,7 @@ static int allocatePage(
TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
}else if( k>pBt->usableSize/4 - 8 ){
/* Value of k is out of range. Database corruption */
return SQLITE_CORRUPT; /* bkpt-CORRUPT */
return SQLITE_CORRUPT_BKPT;
#ifndef SQLITE_OMIT_AUTOVACUUM
}else if( searchList && nearby==iTrunk ){
/* The list is being searched and this trunk page is the page
@ -3109,7 +3121,7 @@ static int allocatePage(
*pPgno = iPage;
if( *pPgno>sqlite3pager_pagecount(pBt->pPager) ){
/* Free page off the end of the file */
return SQLITE_CORRUPT; /* bkpt-CORRUPT */
return SQLITE_CORRUPT_BKPT;
}
TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
": %d more free pages\n",
@ -3203,7 +3215,7 @@ static int freePage(MemPage *pPage){
put4byte(&pPage1->aData[32], pPage->pgno);
TRACE(("FREE-PAGE: %d first\n", pPage->pgno));
}else{
/* Other free pages already exist. Retrieve the first trunk page
/* Other free pages already exist. Retrive the first trunk page
** of the freelist and find out how many leaves it has. */
MemPage *pTrunk;
rc = getPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk);
@ -3250,7 +3262,7 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
while( ovflPgno!=0 ){
MemPage *pOvfl;
if( ovflPgno>sqlite3pager_pagecount(pBt->pPager) ){
return SQLITE_CORRUPT;
return SQLITE_CORRUPT_BKPT;
}
rc = getPage(pBt, ovflPgno, &pOvfl);
if( rc ) return rc;
@ -3595,17 +3607,19 @@ static void assemblePage(
data = pPage->aData;
hdr = pPage->hdrOffset;
put2byte(&data[hdr+3], nCell);
cellbody = allocateSpace(pPage, totalSize);
assert( cellbody>0 );
assert( pPage->nFree >= 2*nCell );
pPage->nFree -= 2*nCell;
for(i=0; i<nCell; i++){
put2byte(&data[cellptr], cellbody);
memcpy(&data[cellbody], apCell[i], aSize[i]);
cellptr += 2;
cellbody += aSize[i];
if( nCell ){
cellbody = allocateSpace(pPage, totalSize);
assert( cellbody>0 );
assert( pPage->nFree >= 2*nCell );
pPage->nFree -= 2*nCell;
for(i=0; i<nCell; i++){
put2byte(&data[cellptr], cellbody);
memcpy(&data[cellbody], apCell[i], aSize[i]);
cellptr += 2;
cellbody += aSize[i];
}
assert( cellbody==pPage->pBt->usableSize );
}
assert( cellbody==pPage->pBt->usableSize );
pPage->nCell = nCell;
}
@ -3809,7 +3823,7 @@ static int balance_nonroot(MemPage *pPage){
/*
** A special case: If a new entry has just been inserted into a
** table (that is, a btree with integer keys and all data at the leaves)
** an the new entry is the right-most entry in the tree (it has the
** and the new entry is the right-most entry in the tree (it has the
** largest key) then use the special balance_quick() routine for
** balancing. balance_quick() is much faster and results in a tighter
** packing of data in the common case.
@ -4082,7 +4096,12 @@ static int balance_nonroot(MemPage *pPage){
szNew[i] = szRight;
szNew[i-1] = szLeft;
}
assert( cntNew[0]>0 );
/* Either we found one or more cells (cntnew[0])>0) or we are the
** a virtual root page. A virtual root page is when the real root
** page is page 1 and we are the only child of that page.
*/
assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) );
/*
** Allocate k new pages. Reuse old pages where possible.
@ -4171,7 +4190,7 @@ static int balance_nonroot(MemPage *pPage){
assert( j<nMaxCells );
assert( pNew->pgno==pgnoNew[i] );
assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]);
assert( pNew->nCell>0 );
assert( pNew->nCell>0 || (nNew==1 && cntNew[0]==0) );
assert( pNew->nOverflow==0 );
#ifndef SQLITE_OMIT_AUTOVACUUM
@ -4649,7 +4668,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
rc = sqlite3BtreeNext(&leafCur, &notUsed);
if( rc!=SQLITE_OK ){
if( rc!=SQLITE_NOMEM ){
rc = SQLITE_CORRUPT; /* bkpt-CORRUPT */
rc = SQLITE_CORRUPT_BKPT;
}
}
if( rc==SQLITE_OK ){
@ -4835,7 +4854,7 @@ static int clearDatabasePage(
int i;
if( pgno>sqlite3pager_pagecount(pBt->pPager) ){
return SQLITE_CORRUPT;
return SQLITE_CORRUPT_BKPT;
}
rc = getAndInitPage(pBt, pgno, &pPage, pParent);
@ -5457,7 +5476,7 @@ static int checkTreePage(
u8 *data;
BtCursor cur;
Btree *pBt;
int maxLocal, usableSize;
int usableSize;
char zContext[100];
char *hit;
@ -5474,7 +5493,6 @@ static int checkTreePage(
"unable to get the page. error code=%d", rc);
return 0;
}
maxLocal = pPage->leafData ? pBt->maxLeaf : pBt->maxLocal;
if( (rc = initPage(pPage, pParent))!=0 ){
checkAppendMsg(pCheck, zContext, "initPage() returns error code %d", rc);
releasePage(pPage);
@ -5721,7 +5739,7 @@ const char *sqlite3BtreeGetJournalname(Btree *pBt){
*/
int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
int rc = SQLITE_OK;
Pgno i, nPage, nToPage;
Pgno i, nPage, nToPage, iSkip;
if( pBtTo->inTrans!=TRANS_WRITE || pBtFrom->inTrans!=TRANS_WRITE ){
return SQLITE_ERROR;
@ -5729,8 +5747,10 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
if( pBtTo->pCursor ) return SQLITE_BUSY;
nToPage = sqlite3pager_pagecount(pBtTo->pPager);
nPage = sqlite3pager_pagecount(pBtFrom->pPager);
iSkip = PENDING_BYTE_PAGE(pBtTo);
for(i=1; rc==SQLITE_OK && i<=nPage; i++){
void *pPage;
if( i==iSkip ) continue;
rc = sqlite3pager_get(pBtFrom->pPager, i, &pPage);
if( rc ) break;
rc = sqlite3pager_overwrite(pBtTo->pPager, i, pPage);
@ -5739,6 +5759,7 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
}
for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){
void *pPage;
if( i==iSkip ) continue;
rc = sqlite3pager_get(pBtTo->pPager, i, &pPage);
if( rc ) break;
rc = sqlite3pager_write(pPage);

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

@ -13,7 +13,7 @@
** subsystem. See comments in the source code for a detailed description
** of what each interface routine does.
**
** @(#) $Id: btree.h,v 1.63 2005/03/21 04:04:03 danielk1977 Exp $
** @(#) $Id: btree.h,v 1.64 2005/08/27 16:36:49 drh Exp $
*/
#ifndef _BTREE_H_
#define _BTREE_H_
@ -58,6 +58,7 @@ int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*);
int sqlite3BtreeSetCacheSize(Btree*,int);
int sqlite3BtreeSetSafetyLevel(Btree*,int);
int sqlite3BtreeSyncDisabled(Btree*);
int sqlite3BtreeSetPageSize(Btree*,int,int);
int sqlite3BtreeGetPageSize(Btree*);
int sqlite3BtreeGetReserve(Btree*);

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

@ -22,7 +22,7 @@
** COMMIT
** ROLLBACK
**
** $Id: build.c,v 1.326 2005/06/12 21:35:52 drh Exp $
** $Id: build.c,v 1.351 2005/09/20 17:42:23 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -76,7 +76,7 @@ void sqlite3FinishCoding(Parse *pParse){
if( pParse->cookieGoto>0 ){
u32 mask;
int iDb;
sqlite3VdbeChangeP2(v, pParse->cookieGoto-1, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeJumpHere(v, pParse->cookieGoto-1);
for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
if( (mask & pParse->cookieMask)==0 ) continue;
sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
@ -85,6 +85,7 @@ void sqlite3FinishCoding(Parse *pParse){
sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->cookieGoto);
}
#ifndef SQLITE_OMIT_TRACE
/* Add a No-op that contains the complete text of the compiled SQL
** statement as its P3 argument. This does not change the functionality
** of the program.
@ -92,6 +93,7 @@ void sqlite3FinishCoding(Parse *pParse){
** This is used to implement sqlite3_trace().
*/
sqlite3VdbeOp3(v, OP_Noop, 0, 0, pParse->zSql, pParse->zTail-pParse->zSql);
#endif /* SQLITE_OMIT_TRACE */
}
@ -101,7 +103,7 @@ void sqlite3FinishCoding(Parse *pParse){
FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
sqlite3VdbeTrace(v, trace);
sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3,
pParse->nTab+3, pParse->nMaxDepth+1, pParse->explain);
pParse->nTab+3, pParse->explain);
pParse->rc = SQLITE_DONE;
pParse->colNamesSet = 0;
}else if( pParse->rc==SQLITE_OK ){
@ -130,7 +132,6 @@ void sqlite3FinishCoding(Parse *pParse){
void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
va_list ap;
char *zSql;
int rc;
# define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar))
char saveBuf[SAVE_SZ];
@ -145,7 +146,7 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
pParse->nested++;
memcpy(saveBuf, &pParse->nVar, SAVE_SZ);
memset(&pParse->nVar, 0, SAVE_SZ);
rc = sqlite3RunParser(pParse, zSql, 0);
sqlite3RunParser(pParse, zSql, 0);
sqliteFree(zSql);
memcpy(&pParse->nVar, saveBuf, SAVE_SZ);
pParse->nested--;
@ -200,9 +201,6 @@ Table *sqlite3LocateTable(Parse *pParse, const char *zName, const char *zDbase){
if( p==0 ){
if( zDbase ){
sqlite3ErrorMsg(pParse, "no such table: %s.%s", zDbase, zName);
}else if( sqlite3FindTable(pParse->db, zName, 0)!=0 ){
sqlite3ErrorMsg(pParse, "table \"%s\" is not in database \"%s\"",
zName, zDbase);
}else{
sqlite3ErrorMsg(pParse, "no such table: %s", zName);
}
@ -258,10 +256,7 @@ static void sqliteDeleteIndex(sqlite3 *db, Index *p){
assert( db!=0 && p->zName!=0 );
pOld = sqlite3HashInsert(&db->aDb[p->iDb].idxHash, p->zName,
strlen(p->zName)+1, 0);
if( pOld!=0 && pOld!=p ){
sqlite3HashInsert(&db->aDb[p->iDb].idxHash, pOld->zName,
strlen(pOld->zName)+1, pOld);
}
assert( pOld==0 || pOld==p );
freeIndex(p);
}
@ -535,7 +530,7 @@ void sqlite3OpenMasterTable(Vdbe *v, int iDb){
** index of the named database in db->aDb[], or -1 if the named db
** does not exist.
*/
static int findDb(sqlite3 *db, Token *pName){
int sqlite3FindDb(sqlite3 *db, Token *pName){
int i = -1; /* Database number */
int n; /* Number of characters in the name */
Db *pDb; /* A database whose name space is being searched */
@ -583,7 +578,7 @@ int sqlite3TwoPartName(
if( pName2 && pName2->n>0 ){
assert( !db->init.busy );
*pUnqual = pName2;
iDb = findDb(db, pName1);
iDb = sqlite3FindDb(db, pName1);
if( iDb<0 ){
sqlite3ErrorMsg(pParse, "unknown database %T", pName1);
pParse->nErr++;
@ -640,7 +635,6 @@ void sqlite3StartTable(
int isView /* True if this is a VIEW */
){
Table *pTable;
Index *pIdx;
char *zName = 0; /* The name of the new table */
sqlite3 *db = pParse->db;
Vdbe *v;
@ -719,8 +713,7 @@ void sqlite3StartTable(
sqlite3ErrorMsg(pParse, "table %T already exists", pName);
goto begin_table_error;
}
if( (pIdx = sqlite3FindIndex(db, zName, 0))!=0 &&
( iDb==0 || !db->init.busy) ){
if( sqlite3FindIndex(db, zName, 0)!=0 && (iDb==0 || !db->init.busy) ){
sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);
goto begin_table_error;
}
@ -745,7 +738,7 @@ void sqlite3StartTable(
** so that INSERT can find the table easily.
*/
#ifndef SQLITE_OMIT_AUTOINCREMENT
if( strcmp(zName, "sqlite_sequence")==0 ){
if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){
db->aDb[iDb].pSeqTab = pTable;
}
#endif
@ -902,11 +895,11 @@ void sqlite3AddNotNull(Parse *pParse, int onError){
** If none of the substrings in the above table are found,
** SQLITE_AFF_NUMERIC is returned.
*/
static char sqlite3AffinityType(const char *zType, int nType){
char sqlite3AffinityType(const Token *pType){
u32 h = 0;
char aff = SQLITE_AFF_NUMERIC;
const unsigned char *zIn = zType;
const unsigned char *zEnd = (zIn+nType);
const unsigned char *zIn = pType->z;
const unsigned char *zEnd = &pType->z[pType->n];
while( zIn!=zEnd ){
h = (h<<8) + sqlite3UpperToLower[*zIn];
@ -938,30 +931,18 @@ static char sqlite3AffinityType(const char *zType, int nType){
** that contains the typename of the column and store that string
** in zType.
*/
void sqlite3AddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
void sqlite3AddColumnType(Parse *pParse, Token *pType){
Table *p;
int i, j;
int n;
char *z;
const unsigned char *zIn;
int i;
Column *pCol;
if( (p = pParse->pNewTable)==0 ) return;
i = p->nCol-1;
if( i<0 ) return;
pCol = &p->aCol[i];
zIn = pFirst->z;
n = pLast->n + (pLast->z - zIn);
assert( pCol->zType==0 );
z = pCol->zType = sqliteMallocRaw(n+1);
if( z==0 ) return;
for(i=j=0; i<n; i++){
int c = zIn[i];
if( isspace(c) ) continue;
z[j++] = c;
}
z[j] = 0;
pCol->affinity = sqlite3AffinityType(z, n);
sqliteFree(pCol->zType);
pCol->zType = sqlite3NameFromToken(pType);
pCol->affinity = sqlite3AffinityType(pType);
}
/*
@ -977,14 +958,15 @@ void sqlite3AddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){
Table *p;
Column *pCol;
if( (p = pParse->pNewTable)==0 ) return;
pCol = &(p->aCol[p->nCol-1]);
if( !sqlite3ExprIsConstant(pExpr) ){
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
pCol->zName);
}else{
sqlite3ExprDelete(pCol->pDflt);
pCol->pDflt = sqlite3ExprDup(pExpr);
if( (p = pParse->pNewTable)!=0 ){
pCol = &(p->aCol[p->nCol-1]);
if( !sqlite3ExprIsConstantOrFunction(pExpr) ){
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
pCol->zName);
}else{
sqlite3ExprDelete(pCol->pDflt);
pCol->pDflt = sqlite3ExprDup(pExpr);
}
}
sqlite3ExprDelete(pExpr);
}
@ -1033,7 +1015,9 @@ void sqlite3AddPrimaryKey(
break;
}
}
if( iCol<pTab->nCol ) pTab->aCol[iCol].isPrimKey = 1;
if( iCol<pTab->nCol ){
pTab->aCol[iCol].isPrimKey = 1;
}
}
if( pList->nExpr>1 ) iCol = -1;
}
@ -1317,13 +1301,11 @@ void sqlite3EndTable(
*/
if( p->pSelect==0 ){
/* A regular table */
/* sqlite3VdbeAddOp(v, OP_CreateTable, p->iDb, 0); */
zType = "table";
zType2 = "TABLE";
#ifndef SQLITE_OMIT_VIEW
}else{
/* A view */
/* sqlite3VdbeAddOp(v, OP_Integer, 0, 0); */
zType = "view";
zType2 = "VIEW";
#endif
@ -1535,10 +1517,13 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
** Actually, this error is caught previously and so the following test
** should always fail. But we will leave it in place just to be safe.
*/
#if 0
if( pTable->nCol<0 ){
sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName);
return 1;
}
#endif
assert( pTable->nCol>=0 );
/* If we get this far, it means we need to compute the table names.
** Note that the call to sqlite3ResultSetOfSelect() will expand any
@ -1973,7 +1958,6 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
int addr1; /* Address of top of loop */
int tnum; /* Root page of index */
Vdbe *v; /* Generate code into this virtual machine */
int isUnique; /* True for a unique index */
#ifndef SQLITE_OMIT_AUTHORIZATION
if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
@ -2002,18 +1986,23 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
sqlite3VdbeAddOp(v, OP_Integer, pIndex->iDb, 0);
sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum,
(char*)&pIndex->keyInfo, P3_KEYINFO);
sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqlite3VdbeAddOp(v, OP_OpenRead, iTab, pTab->tnum);
sqlite3VdbeAddOp(v, OP_SetNumColumns, iTab, pTab->nCol);
sqlite3OpenTableForReading(v, iTab, pTab);
addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0);
sqlite3GenerateIndexKey(v, pIndex, iTab);
isUnique = pIndex->onError!=OE_None;
sqlite3VdbeAddOp(v, OP_IdxInsert, iIdx, isUnique);
if( isUnique ){
sqlite3VdbeChangeP3(v, -1, "indexed columns are not unique", P3_STATIC);
if( pIndex->onError!=OE_None ){
int curaddr = sqlite3VdbeCurrentAddr(v);
int addr2 = curaddr+4;
sqlite3VdbeChangeP2(v, curaddr-1, addr2);
sqlite3VdbeAddOp(v, OP_Rowid, iTab, 0);
sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
sqlite3VdbeAddOp(v, OP_IsUnique, iIdx, addr2);
sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, OE_Abort,
"indexed columns are not unique", P3_STATIC);
assert( addr2==sqlite3VdbeCurrentAddr(v) );
}
sqlite3VdbeAddOp(v, OP_IdxInsert, iIdx, 0);
sqlite3VdbeAddOp(v, OP_Next, iTab, addr1+1);
sqlite3VdbeChangeP2(v, addr1, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp(v, OP_Close, iTab, 0);
sqlite3VdbeAddOp(v, OP_Close, iIdx, 0);
}
@ -2079,7 +2068,9 @@ void sqlite3CreateIndex(
if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) &&
sqlite3FixSrcList(&sFix, pTblName)
){
goto exit_create_index;
/* Because the parser constructs pTblName from a single identifier,
** sqlite3FixSrcList can never fail. */
assert(0);
}
pTab = sqlite3LocateTable(pParse, pTblName->a[0].zName,
pTblName->a[0].zDatabase);
@ -2124,14 +2115,12 @@ void sqlite3CreateIndex(
goto exit_create_index;
}
if( !db->init.busy ){
Index *pISameName; /* Another index with the same name */
Table *pTSameName; /* A table with same name as the index */
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index;
if( (pISameName = sqlite3FindIndex(db, zName, db->aDb[iDb].zName))!=0 ){
if( sqlite3FindIndex(db, zName, db->aDb[iDb].zName)!=0 ){
sqlite3ErrorMsg(pParse, "index %s already exists", zName);
goto exit_create_index;
}
if( (pTSameName = sqlite3FindTable(db, zName, 0))!=0 ){
if( sqlite3FindTable(db, zName, 0)!=0 ){
sqlite3ErrorMsg(pParse, "there is already a table named %s", zName);
goto exit_create_index;
}
@ -2177,11 +2166,12 @@ void sqlite3CreateIndex(
/*
** Allocate the index structure.
*/
pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 +
(sizeof(int) + sizeof(CollSeq*))*pList->nExpr );
pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 + sizeof(int) +
(sizeof(int)*2 + sizeof(CollSeq*))*pList->nExpr );
if( sqlite3_malloc_failed ) goto exit_create_index;
pIndex->aiColumn = (int*)&pIndex->keyInfo.aColl[pList->nExpr];
pIndex->zName = (char*)&pIndex->aiColumn[pList->nExpr];
pIndex->aiRowEst = (unsigned*)&pIndex->aiColumn[pList->nExpr];
pIndex->zName = (char*)&pIndex->aiRowEst[pList->nExpr+1];
strcpy(pIndex->zName, zName);
pIndex->pTable = pTab;
pIndex->nColumn = pList->nExpr;
@ -2217,6 +2207,7 @@ void sqlite3CreateIndex(
}
}
pIndex->keyInfo.nField = pList->nExpr;
sqlite3DefaultRowEst(pIndex);
if( pTab==pParse->pNewTable ){
/* This routine has been called to create an automatic index as a
@ -2383,6 +2374,37 @@ exit_create_index:
return;
}
/*
** Fill the Index.aiRowEst[] array with default information - information
** to be used when we have not run the ANALYZE command.
**
** aiRowEst[0] is suppose to contain the number of elements in the index.
** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the
** number of rows in the table that match any particular value of the
** first column of the index. aiRowEst[2] is an estimate of the number
** of rows that match any particular combiniation of the first 2 columns
** of the index. And so forth. It must always be the case that
*
** aiRowEst[N]<=aiRowEst[N-1]
** aiRowEst[N]>=1
**
** Apart from that, we have little to go on besides intuition as to
** how aiRowEst[] should be initialized. The numbers generated here
** are based on typical values found in actual indices.
*/
void sqlite3DefaultRowEst(Index *pIdx){
unsigned *a = pIdx->aiRowEst;
int i;
assert( a!=0 );
a[0] = 1000000;
for(i=pIdx->nColumn; i>=1; i--){
a[i] = 10;
}
if( pIdx->onError!=OE_None ){
a[pIdx->nColumn] = 1;
}
}
/*
** This routine will drop an existing named index. This routine
** implements the DROP INDEX statement.
@ -2444,6 +2466,47 @@ exit_drop_index:
sqlite3SrcListDelete(pName);
}
/*
** ppArray points into a structure where there is an array pointer
** followed by two integers. The first integer is the
** number of elements in the structure array. The second integer
** is the number of allocated slots in the array.
**
** In other words, the structure looks something like this:
**
** struct Example1 {
** struct subElem *aEntry;
** int nEntry;
** int nAlloc;
** }
**
** The pnEntry parameter points to the equivalent of Example1.nEntry.
**
** This routine allocates a new slot in the array, zeros it out,
** and returns its index. If malloc fails a negative number is returned.
**
** szEntry is the sizeof of a single array entry. initSize is the
** number of array entries allocated on the initial allocation.
*/
int sqlite3ArrayAllocate(void **ppArray, int szEntry, int initSize){
char *p;
int *an = (int*)&ppArray[1];
if( an[0]>=an[1] ){
void *pNew;
int newSize;
newSize = an[1]*2 + initSize;
pNew = sqliteRealloc(*ppArray, newSize*szEntry);
if( pNew==0 ){
return -1;
}
an[1] = newSize;
*ppArray = pNew;
}
p = *ppArray;
memset(&p[an[0]*szEntry], 0, szEntry);
return an[0]++;
}
/*
** Append a new element to the given IdList. Create a new IdList if
** need be.
@ -2451,27 +2514,47 @@ exit_drop_index:
** A new IdList is returned, or NULL if malloc() fails.
*/
IdList *sqlite3IdListAppend(IdList *pList, Token *pToken){
int i;
if( pList==0 ){
pList = sqliteMalloc( sizeof(IdList) );
if( pList==0 ) return 0;
pList->nAlloc = 0;
}
if( pList->nId>=pList->nAlloc ){
struct IdList_item *a;
pList->nAlloc = pList->nAlloc*2 + 5;
a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]) );
if( a==0 ){
sqlite3IdListDelete(pList);
return 0;
}
pList->a = a;
i = sqlite3ArrayAllocate((void**)&pList->a, sizeof(pList->a[0]), 5);
if( i<0 ){
sqlite3IdListDelete(pList);
return 0;
}
memset(&pList->a[pList->nId], 0, sizeof(pList->a[0]));
pList->a[pList->nId].zName = sqlite3NameFromToken(pToken);
pList->nId++;
pList->a[i].zName = sqlite3NameFromToken(pToken);
return pList;
}
/*
** Delete an IdList.
*/
void sqlite3IdListDelete(IdList *pList){
int i;
if( pList==0 ) return;
for(i=0; i<pList->nId; i++){
sqliteFree(pList->a[i].zName);
}
sqliteFree(pList->a);
sqliteFree(pList);
}
/*
** Return the index in pList of the identifier named zId. Return -1
** if not found.
*/
int sqlite3IdListIndex(IdList *pList, const char *zName){
int i;
if( pList==0 ) return -1;
for(i=0; i<pList->nId; i++){
if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i;
}
return -1;
}
/*
** Append a new table name to the given SrcList. Create a new SrcList if
** need be. A new entry is created in the SrcList even if pToken is NULL.
@ -2556,32 +2639,6 @@ void sqlite3SrcListAddAlias(SrcList *pList, Token *pToken){
}
}
/*
** Delete an IdList.
*/
void sqlite3IdListDelete(IdList *pList){
int i;
if( pList==0 ) return;
for(i=0; i<pList->nId; i++){
sqliteFree(pList->a[i].zName);
}
sqliteFree(pList->a);
sqliteFree(pList);
}
/*
** Return the index in pList of the identifier named zId. Return -1
** if not found.
*/
int sqlite3IdListIndex(IdList *pList, const char *zName){
int i;
if( pList==0 ) return -1;
for(i=0; i<pList->nId; i++){
if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i;
}
return -1;
}
/*
** Delete an entire SrcList including all its substructure.
*/
@ -2784,7 +2841,7 @@ static int collationMatch(CollSeq *pColl, Index *pIndex){
** If pColl==0 then recompute all indices of pTab.
*/
#ifndef SQLITE_OMIT_REINDEX
void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){
static void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){
Index *pIndex; /* An index associated with pTab */
for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
@ -2802,7 +2859,7 @@ void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){
** all indices everywhere.
*/
#ifndef SQLITE_OMIT_REINDEX
void reindexDatabases(Parse *pParse, CollSeq *pColl){
static void reindexDatabases(Parse *pParse, CollSeq *pColl){
Db *pDb; /* A single database */
int iDb; /* The database index number */
sqlite3 *db = pParse->db; /* The database connection */
@ -2811,7 +2868,7 @@ void reindexDatabases(Parse *pParse, CollSeq *pColl){
for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
if( pDb==0 ) continue;
for(k=sqliteHashFirst(&pDb->tblHash); k; k=sqliteHashNext(k)){
for(k=sqliteHashFirst(&pDb->tblHash); k; k=sqliteHashNext(k)){
pTab = (Table*)sqliteHashData(k);
reindexTable(pParse, pTab, pColl);
}

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

@ -13,7 +13,7 @@
** 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 $
** $Id: callback.c,v 1.2 2005-12-13 19:49:35 vladimir%pobox.com Exp $
*/
#include "sqliteInt.h"
@ -147,7 +147,7 @@ int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
** the collation sequence name. A pointer to this string is stored in
** each collation sequence structure.
*/
static CollSeq * findCollSeqEntry(
static CollSeq *findCollSeqEntry(
sqlite3 *db,
const char *zName,
int nName,
@ -286,10 +286,9 @@ FuncDef *sqlite3FindFunction(
** new entry to the hash table and return it.
*/
if( createFlag && bestmatch<6 &&
(pBest = sqliteMalloc(sizeof(*pBest)+nName+1)) ){
(pBest = sqliteMalloc(sizeof(*pBest)+nName)) ){
pBest->nArg = nArg;
pBest->pNext = pFirst;
pBest->zName = (char*)&pBest[1];
pBest->iPrefEnc = enc;
memcpy(pBest->zName, zName, nName);
pBest->zName[nName] = 0;

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

@ -0,0 +1,263 @@
/*
** 2001 September 15
**
** 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.
**
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that implements the sqlite3_complete() API.
** This code used to be part of the tokenizer.c source file. But by
** separating it out, the code will be automatically omitted from
** static links that do not use it.
**
** $Id: complete.c,v 1.1 2005-12-13 19:49:35 vladimir%pobox.com Exp $
*/
#include "sqliteInt.h"
#ifndef SQLITE_OMIT_COMPLETE
/*
** This is defined in tokenize.c. We just have to import the definition.
*/
extern const char sqlite3IsIdChar[];
#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsIdChar[c-0x20]))
/*
** Token types used by the sqlite3_complete() routine. See the header
** comments on that procedure for additional information.
*/
#define tkSEMI 0
#define tkWS 1
#define tkOTHER 2
#define tkEXPLAIN 3
#define tkCREATE 4
#define tkTEMP 5
#define tkTRIGGER 6
#define tkEND 7
/*
** Return TRUE if the given SQL string ends in a semicolon.
**
** Special handling is require for CREATE TRIGGER statements.
** Whenever the CREATE TRIGGER keywords are seen, the statement
** must end with ";END;".
**
** This implementation uses a state machine with 7 states:
**
** (0) START At the beginning or end of an SQL statement. This routine
** returns 1 if it ends in the START state and 0 if it ends
** in any other state.
**
** (1) NORMAL We are in the middle of statement which ends with a single
** semicolon.
**
** (2) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
** a statement.
**
** (3) CREATE The keyword CREATE has been seen at the beginning of a
** statement, possibly preceeded by EXPLAIN and/or followed by
** TEMP or TEMPORARY
**
** (4) TRIGGER We are in the middle of a trigger definition that must be
** ended by a semicolon, the keyword END, and another semicolon.
**
** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at
** the end of a trigger definition.
**
** (6) END We've seen the ";END" of the ";END;" that occurs at the end
** of a trigger difinition.
**
** Transitions between states above are determined by tokens extracted
** from the input. The following tokens are significant:
**
** (0) tkSEMI A semicolon.
** (1) tkWS Whitespace
** (2) tkOTHER Any other SQL token.
** (3) tkEXPLAIN The "explain" keyword.
** (4) tkCREATE The "create" keyword.
** (5) tkTEMP The "temp" or "temporary" keyword.
** (6) tkTRIGGER The "trigger" keyword.
** (7) tkEND The "end" keyword.
**
** Whitespace never causes a state transition and is always ignored.
**
** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed
** to recognize the end of a trigger can be omitted. All we have to do
** is look for a semicolon that is not part of an string or comment.
*/
int sqlite3_complete(const char *zSql){
u8 state = 0; /* Current state, using numbers defined in header comment */
u8 token; /* Value of the next token */
#ifndef SQLITE_OMIT_TRIGGER
/* A complex statement machine used to detect the end of a CREATE TRIGGER
** statement. This is the normal case.
*/
static const u8 trans[7][8] = {
/* Token: */
/* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */
/* 0 START: */ { 0, 0, 1, 2, 3, 1, 1, 1, },
/* 1 NORMAL: */ { 0, 1, 1, 1, 1, 1, 1, 1, },
/* 2 EXPLAIN: */ { 0, 2, 1, 1, 3, 1, 1, 1, },
/* 3 CREATE: */ { 0, 3, 1, 1, 1, 3, 4, 1, },
/* 4 TRIGGER: */ { 5, 4, 4, 4, 4, 4, 4, 4, },
/* 5 SEMI: */ { 5, 5, 4, 4, 4, 4, 4, 6, },
/* 6 END: */ { 0, 6, 4, 4, 4, 4, 4, 4, },
};
#else
/* If triggers are not suppored by this compile then the statement machine
** used to detect the end of a statement is much simplier
*/
static const u8 trans[2][3] = {
/* Token: */
/* State: ** SEMI WS OTHER */
/* 0 START: */ { 0, 0, 1, },
/* 1 NORMAL: */ { 0, 1, 1, },
};
#endif /* SQLITE_OMIT_TRIGGER */
while( *zSql ){
switch( *zSql ){
case ';': { /* A semicolon */
token = tkSEMI;
break;
}
case ' ':
case '\r':
case '\t':
case '\n':
case '\f': { /* White space is ignored */
token = tkWS;
break;
}
case '/': { /* C-style comments */
if( zSql[1]!='*' ){
token = tkOTHER;
break;
}
zSql += 2;
while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
if( zSql[0]==0 ) return 0;
zSql++;
token = tkWS;
break;
}
case '-': { /* SQL-style comments from "--" to end of line */
if( zSql[1]!='-' ){
token = tkOTHER;
break;
}
while( *zSql && *zSql!='\n' ){ zSql++; }
if( *zSql==0 ) return state==0;
token = tkWS;
break;
}
case '[': { /* Microsoft-style identifiers in [...] */
zSql++;
while( *zSql && *zSql!=']' ){ zSql++; }
if( *zSql==0 ) return 0;
token = tkOTHER;
break;
}
case '`': /* Grave-accent quoted symbols used by MySQL */
case '"': /* single- and double-quoted strings */
case '\'': {
int c = *zSql;
zSql++;
while( *zSql && *zSql!=c ){ zSql++; }
if( *zSql==0 ) return 0;
token = tkOTHER;
break;
}
default: {
int c;
if( IdChar((u8)*zSql) ){
/* Keywords and unquoted identifiers */
int nId;
for(nId=1; IdChar(zSql[nId]); nId++){}
#ifdef SQLITE_OMIT_TRIGGER
token = tkOTHER;
#else
switch( *zSql ){
case 'c': case 'C': {
if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){
token = tkCREATE;
}else{
token = tkOTHER;
}
break;
}
case 't': case 'T': {
if( nId==7 && sqlite3StrNICmp(zSql, "trigger", 7)==0 ){
token = tkTRIGGER;
}else if( nId==4 && sqlite3StrNICmp(zSql, "temp", 4)==0 ){
token = tkTEMP;
}else if( nId==9 && sqlite3StrNICmp(zSql, "temporary", 9)==0 ){
token = tkTEMP;
}else{
token = tkOTHER;
}
break;
}
case 'e': case 'E': {
if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){
token = tkEND;
}else
#ifndef SQLITE_OMIT_EXPLAIN
if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){
token = tkEXPLAIN;
}else
#endif
{
token = tkOTHER;
}
break;
}
default: {
token = tkOTHER;
break;
}
}
#endif /* SQLITE_OMIT_TRIGGER */
zSql += nId-1;
}else{
/* Operators and special symbols */
token = tkOTHER;
}
break;
}
}
state = trans[state][token];
zSql++;
}
return state==0;
}
#ifndef SQLITE_OMIT_UTF16
/*
** This routine is the same as the sqlite3_complete() routine described
** above, except that the parameter is required to be UTF-16 encoded, not
** UTF-8.
*/
int sqlite3_complete16(const void *zSql){
sqlite3_value *pVal;
char const *zSql8;
int rc = 0;
pVal = sqlite3ValueNew();
sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
if( zSql8 ){
rc = sqlite3_complete(zSql8);
}
sqlite3ValueFree(pVal);
return rc;
}
#endif /* SQLITE_OMIT_UTF16 */
#endif /* SQLITE_OMIT_COMPLETE */

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

@ -16,7 +16,7 @@
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: date.c,v 1.44 2005/03/21 00:43:44 drh Exp $
** $Id: date.c,v 1.45 2005/06/25 18:42:14 drh Exp $
**
** NOTES:
**
@ -124,11 +124,7 @@ static int getDigits(const char *zDate, ...){
** Read text from z[] and convert into a floating point number. Return
** the number of digits converted.
*/
static int getValue(const char *z, double *pR){
const char *zEnd;
*pR = sqlite3AtoF(z, &zEnd);
return zEnd - z;
}
#define getValue sqlite3AtoF
/*
** Parse a timezone extension on the end of a date-time.
@ -320,7 +316,7 @@ static int parseDateOrTime(const char *zDate, DateTime *p){
p->validJD = 1;
return 0;
}else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){
p->rJD = sqlite3AtoF(zDate, 0);
getValue(zDate, &p->rJD);
p->validJD = 1;
return 0;
}

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

@ -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.106 2005/06/12 21:35:52 drh Exp $
** $Id: delete.c,v 1.111 2005/09/20 17:42:23 drh Exp $
*/
#include "sqliteInt.h"
@ -65,8 +65,8 @@ void sqlite3OpenTableForReading(
Table *pTab /* The table to be opened */
){
sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
VdbeComment((v, "# %s", pTab->zName));
sqlite3VdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol);
}
@ -178,12 +178,12 @@ void sqlite3DeleteFrom(
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
sqlite3BeginWriteOperation(pParse, triggers_exist, pTab->iDb);
/* If we are trying to delete from a view, construct that view into
** a temporary table.
/* If we are trying to delete from a view, realize that view into
** a ephemeral table.
*/
if( isView ){
Select *pView = sqlite3SelectDup(pTab->pSelect);
sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0, 0);
sqlite3Select(pParse, pView, SRT_VirtualTab, iCur, 0, 0, 0, 0);
sqlite3SelectDelete(pView);
}
@ -240,7 +240,7 @@ void sqlite3DeleteFrom(
/* Remember the rowid of every item to be deleted.
*/
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
if( db->flags & SQLITE_CountRows ){
sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
}
@ -260,14 +260,13 @@ void sqlite3DeleteFrom(
** database scan. We have to delete items after the scan is complete
** because deleting an item can change the scan order.
*/
sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0);
end = sqlite3VdbeMakeLabel(v);
/* This is the beginning of the delete loop when there are
** row triggers.
*/
if( triggers_exist ){
addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
if( !isView ){
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
sqlite3OpenTableForReading(v, iCur, pTab);
@ -288,7 +287,7 @@ void sqlite3DeleteFrom(
if( !isView ){
/* Open cursors for the table we are deleting from and all its
** indices. If there are row triggers, this happens inside the
** OP_ListRead loop because the cursor have to all be closed
** OP_FifoRead loop because the cursor have to all be closed
** before the trigger fires. If there are no row triggers, the
** cursors are opened only once on the outside the loop.
*/
@ -297,7 +296,7 @@ void sqlite3DeleteFrom(
/* This is the beginning of the delete loop when there are no
** row triggers */
if( !triggers_exist ){
addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
}
/* Delete the row */
@ -322,7 +321,6 @@ void sqlite3DeleteFrom(
/* End of the delete loop */
sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
sqlite3VdbeResolveLabel(v, end);
sqlite3VdbeAddOp(v, OP_ListReset, 0, 0);
/* Close the cursors after the loop if there are no row triggers */
if( !triggers_exist ){
@ -382,7 +380,7 @@ void sqlite3GenerateRowDelete(
addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0);
sqlite3GenerateRowIndexDelete(db, v, pTab, iCur, 0);
sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeJumpHere(v, addr);
}
/*
@ -442,6 +440,6 @@ void sqlite3GenerateIndexKey(
sqlite3ColumnDefault(v, pTab, idx);
}
}
sqlite3VdbeAddOp(v, OP_MakeRecord, pIdx->nColumn, (1<<24));
sqlite3VdbeAddOp(v, OP_MakeIdxRec, pIdx->nColumn, 0);
sqlite3IndexAffinityStr(v, pIdx);
}

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

@ -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.206 2005/06/12 21:35:52 drh Exp $
** $Id: expr.c,v 1.230 2005/09/23 21:11:54 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -34,12 +34,18 @@
** SELECT * FROM t1 WHERE (select a from t1);
*/
char sqlite3ExprAffinity(Expr *pExpr){
if( pExpr->op==TK_AS ){
int op = pExpr->op;
if( op==TK_AS ){
return sqlite3ExprAffinity(pExpr->pLeft);
}
if( pExpr->op==TK_SELECT ){
if( op==TK_SELECT ){
return sqlite3ExprAffinity(pExpr->pSelect->pEList->a[0].pExpr);
}
#ifndef SQLITE_OMIT_CAST
if( op==TK_CAST ){
return sqlite3AffinityType(&pExpr->token);
}
#endif
return pExpr->affinity;
}
@ -51,7 +57,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
CollSeq *pColl = 0;
if( pExpr ){
pColl = pExpr->pColl;
if( pExpr->op==TK_AS && !pColl ){
if( (pExpr->op==TK_AS || pExpr->op==TK_CAST) && !pColl ){
return sqlite3ExprCollSeq(pParse, pExpr->pLeft);
}
}
@ -87,6 +93,7 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2){
return SQLITE_AFF_NONE;
}else{
/* One side is a column, the other is not. Use the columns affinity. */
assert( aff1==0 || aff2==0 );
return (aff1 + aff2);
}
}
@ -207,9 +214,8 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){
/*
** When doing a nested parse, you can include terms in an expression
** that look like this: #0 #1 #2 ... These terms refer to elements
** on the stack. "#0" (or just "#") means the top of the stack.
** "#1" means the next down on the stack. And so forth. #-1 means
** memory location 0. #-2 means memory location 1. And so forth.
** on the stack. "#0" means the top of the stack.
** "#1" means the next down on the stack. And so forth.
**
** This routine is called by the parser to deal with on of those terms.
** It immediately generates code to store the value in a memory location.
@ -220,23 +226,19 @@ Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){
Vdbe *v = pParse->pVdbe;
Expr *p;
int depth;
if( v==0 ) return 0;
if( pParse->nested==0 ){
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", pToken);
return 0;
}
if( v==0 ) return 0;
p = sqlite3Expr(TK_REGISTER, 0, 0, pToken);
if( p==0 ){
return 0; /* Malloc failed */
}
depth = atoi(&pToken->z[1]);
if( depth>=0 ){
p->iTable = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_Dup, depth, 0);
sqlite3VdbeAddOp(v, OP_MemStore, p->iTable, 1);
}else{
p->iTable = -1-depth;
}
p->iTable = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_Dup, depth, 0);
sqlite3VdbeAddOp(v, OP_MemStore, p->iTable, 1);
return p;
}
@ -353,7 +355,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
pExpr->iTable = ++pParse->nVar;
if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){
pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10;
pParse->apVarExpr = sqliteRealloc(pParse->apVarExpr,
sqlite3ReallocOrFree((void**)&pParse->apVarExpr,
pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) );
}
if( !sqlite3_malloc_failed ){
@ -378,6 +380,21 @@ void sqlite3ExprDelete(Expr *p){
sqliteFree(p);
}
/*
** The Expr.token field might be a string literal that is quoted.
** If so, remove the quotation marks.
*/
void sqlite3DequoteExpr(Expr *p){
if( ExprHasAnyProperty(p, EP_Dequoted) ){
return;
}
ExprSetProperty(p, EP_Dequoted);
if( p->token.dyn==0 ){
sqlite3TokenCopy(&p->token, &p->token);
}
sqlite3Dequote((char*)p->token.z);
}
/*
** The following group of routines make deep copies of expressions,
@ -529,9 +546,14 @@ Select *sqlite3SelectDup(Select *p){
pNew->pOffset = sqlite3ExprDup(p->pOffset);
pNew->iLimit = -1;
pNew->iOffset = -1;
pNew->ppOpenTemp = 0;
pNew->isResolved = p->isResolved;
pNew->isAgg = p->isAgg;
pNew->usesVirt = 0;
pNew->disallowOrderBy = 0;
pNew->pRightmost = 0;
pNew->addrOpenVirt[0] = -1;
pNew->addrOpenVirt[1] = -1;
pNew->addrOpenVirt[2] = -1;
return pNew;
}
#else
@ -607,6 +629,8 @@ void sqlite3ExprListDelete(ExprList *pList){
**
** The return value from this routine is 1 to abandon the tree walk
** and 0 to continue.
**
** NOTICE: This routine does *not* descend into subqueries.
*/
static int walkExprList(ExprList *, int (*)(void *, Expr*), void *);
static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){
@ -664,17 +688,27 @@ static int walkSelectExpr(Select *p, int (*xFunc)(void *, Expr*), void *pArg){
*/
static int exprNodeIsConstant(void *pArg, Expr *pExpr){
switch( pExpr->op ){
/* Consider functions to be constant if all their arguments are constant
** and *pArg==2 */
case TK_FUNCTION:
if( *((int*)pArg)==2 ) return 0;
/* Fall through */
case TK_ID:
case TK_COLUMN:
case TK_DOT:
case TK_AGG_FUNCTION:
case TK_FUNCTION:
case TK_AGG_COLUMN:
#ifndef SQLITE_OMIT_SUBQUERY
case TK_SELECT:
case TK_EXISTS:
#endif
*((int*)pArg) = 0;
return 2;
case TK_IN:
if( pExpr->pSelect ){
*((int*)pArg) = 0;
return 2;
}
default:
return 0;
}
@ -682,7 +716,7 @@ static int exprNodeIsConstant(void *pArg, Expr *pExpr){
/*
** Walk an expression tree. Return 1 if the expression is constant
** and 0 if it involves variables.
** and 0 if it involves variables or function calls.
**
** For the purposes of this function, a double-quoted string (ex: "abc")
** is considered a variable but a single-quoted string (ex: 'abc') is
@ -694,6 +728,21 @@ int sqlite3ExprIsConstant(Expr *p){
return isConst;
}
/*
** Walk an expression tree. Return 1 if the expression is constant
** or a function call with constant arguments. Return and 0 if there
** are any variables.
**
** For the purposes of this function, a double-quoted string (ex: "abc")
** is considered a variable but a single-quoted string (ex: 'abc') is
** a constant.
*/
int sqlite3ExprIsConstantOrFunction(Expr *p){
int isConst = 2;
walkExprTree(p, exprNodeIsConstant, &isConst);
return isConst!=0;
}
/*
** If the expression p codes a constant integer that is small enough
** to fit in a 32-bit integer, return 1 and put the value of the integer
@ -1184,11 +1233,19 @@ int sqlite3ExprResolveNames(
NameContext *pNC, /* Namespace to resolve expressions in. */
Expr *pExpr /* The expression to be analyzed. */
){
int savedHasAgg;
if( pExpr==0 ) return 0;
savedHasAgg = pNC->hasAgg;
pNC->hasAgg = 0;
walkExprTree(pExpr, nameResolverStep, pNC);
if( pNC->nErr>0 ){
ExprSetProperty(pExpr, EP_Error);
}
if( pNC->hasAgg ){
ExprSetProperty(pExpr, EP_Agg);
}else if( savedHasAgg ){
pNC->hasAgg = 1;
}
return ExprHasProperty(pExpr, EP_Error);
}
@ -1218,37 +1275,38 @@ struct QueryCoder {
*/
#ifndef SQLITE_OMIT_SUBQUERY
void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
int label = 0; /* Address after sub-select code */
int testAddr = 0; /* One-time test address */
Vdbe *v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
/* If this is not a variable (correlated) select, then execute
** it only once. Unless this is part of a trigger program. In
** that case re-execute every time (this could be optimized).
/* This code must be run in its entirety every time it is encountered
** if any of the following is true:
**
** * The right-hand side is a correlated subquery
** * The right-hand side is an expression list containing variables
** * We are inside a trigger
**
** If all of the above are false, then we can run this code just once
** save the results, and reuse the same result on subsequent invocations.
*/
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){
int mem = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0);
label = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp(v, OP_If, 0, label);
sqlite3VdbeAddOp(v, OP_Integer, 1, 0);
sqlite3VdbeAddOp(v, OP_MemStore, mem, 1);
}
if( pExpr->pSelect ){
sqlite3VdbeAddOp(v, OP_AggContextPush, 0, 0);
testAddr = sqlite3VdbeAddOp(v, OP_If, 0, 0);
assert( testAddr>0 || sqlite3_malloc_failed );
sqlite3VdbeAddOp(v, OP_MemInt, 1, mem);
}
switch( pExpr->op ){
case TK_IN: {
char affinity;
KeyInfo keyInfo;
int addr; /* Address of OP_OpenTemp instruction */
int addr; /* Address of OP_OpenVirtual instruction */
affinity = sqlite3ExprAffinity(pExpr->pLeft);
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
** expression it is handled the same way. A temporary table is
** expression it is handled the same way. A virtual table is
** filled with single-field index keys representing the results
** from the SELECT or the <exprlist>.
**
@ -1261,7 +1319,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
** is used.
*/
pExpr->iTable = pParse->nTab++;
addr = sqlite3VdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 0);
addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, pExpr->iTable, 0);
memset(&keyInfo, 0, sizeof(keyInfo));
keyInfo.nField = 1;
sqlite3VdbeAddOp(v, OP_SetNumColumns, pExpr->iTable, 1);
@ -1290,20 +1348,30 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
** a column, use numeric affinity.
*/
int i;
ExprList *pList = pExpr->pList;
struct ExprList_item *pItem;
if( !affinity ){
affinity = SQLITE_AFF_NUMERIC;
}
keyInfo.aColl[0] = pExpr->pLeft->pColl;
/* Loop through each expression in <exprlist>. */
for(i=0; i<pExpr->pList->nExpr; i++){
Expr *pE2 = pExpr->pList->a[i].pExpr;
for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
Expr *pE2 = pItem->pExpr;
/* Check that the expression is constant and valid. */
if( !sqlite3ExprIsConstant(pE2) ){
sqlite3ErrorMsg(pParse,
"right-hand side of IN operator must be constant");
return;
/* If the expression is not constant then we will need to
** disable the test that was generated above that makes sure
** this code only executes once. Because for a non-constant
** expression we need to rerun this code each time.
*/
if( testAddr>0 && !sqlite3ExprIsConstant(pE2) ){
VdbeOp *aOp = sqlite3VdbeGetOp(v, testAddr-1);
int i;
for(i=0; i<3; i++){
aOp[i].opcode = OP_Noop;
}
testAddr = 0;
}
/* Evaluate the expression and insert it into the temp table */
@ -1341,11 +1409,8 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
}
}
if( pExpr->pSelect ){
sqlite3VdbeAddOp(v, OP_AggContextPop, 0, 0);
}
if( label<0 ){
sqlite3VdbeResolveLabel(v, label);
if( testAddr ){
sqlite3VdbeJumpHere(v, testAddr);
}
return;
}
@ -1360,7 +1425,7 @@ static void codeInteger(Vdbe *v, const char *z, int n){
if( sqlite3GetInt32(z, &i) ){
sqlite3VdbeAddOp(v, OP_Integer, i, 0);
}else if( sqlite3FitsIn64Bits(z) ){
sqlite3VdbeOp3(v, OP_Integer, 0, 0, z, n);
sqlite3VdbeOp3(v, OP_Int64, 0, 0, z, n);
}else{
sqlite3VdbeOp3(v, OP_Real, 0, 0, z, n);
}
@ -1386,10 +1451,21 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
}
op = pExpr->op;
switch( op ){
case TK_AGG_COLUMN: {
AggInfo *pAggInfo = pExpr->pAggInfo;
struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
if( !pAggInfo->directMode ){
sqlite3VdbeAddOp(v, OP_MemLoad, pCol->iMem, 0);
break;
}else if( pAggInfo->useSortingIdx ){
sqlite3VdbeAddOp(v, OP_Column, pAggInfo->sortingIdx,
pCol->iSorterColumn);
break;
}
/* Otherwise, fall thru into the TK_COLUMN case */
}
case TK_COLUMN: {
if( !pParse->fillAgg && pExpr->iAgg>=0 ){
sqlite3VdbeAddOp(v, OP_AggGet, pExpr->iAggCtx, pExpr->iAgg);
}else if( pExpr->iColumn>=0 ){
if( pExpr->iColumn>=0 ){
sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn);
sqlite3ColumnDefault(v, pExpr->pTab, pExpr->iColumn);
}else{
@ -1405,8 +1481,8 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
case TK_STRING: {
assert( TK_FLOAT==OP_Real );
assert( TK_STRING==OP_String8 );
sqlite3DequoteExpr(pExpr);
sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z, pExpr->token.n);
sqlite3VdbeDequoteP3(v, -1);
break;
}
case TK_NULL: {
@ -1415,9 +1491,16 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
int n;
const char *z;
assert( TK_BLOB==OP_HexBlob );
sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z+1, pExpr->token.n-1);
sqlite3VdbeDequoteP3(v, -1);
n = pExpr->token.n - 3;
z = pExpr->token.z + 2;
assert( n>=0 );
if( n==0 ){
z = "";
}
sqlite3VdbeOp3(v, op, 0, 0, z, n);
break;
}
#endif
@ -1432,6 +1515,22 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iTable, 0);
break;
}
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
int aff, op;
sqlite3ExprCode(pParse, pExpr->pLeft);
aff = sqlite3AffinityType(&pExpr->token);
switch( aff ){
case SQLITE_AFF_INTEGER: op = OP_ToInt; break;
case SQLITE_AFF_NUMERIC: op = OP_ToNumeric; break;
case SQLITE_AFF_TEXT: op = OP_ToText; break;
case SQLITE_AFF_NONE: op = OP_ToBlob; break;
}
sqlite3VdbeAddOp(v, op, 0, 0);
break;
}
#endif /* SQLITE_OMIT_CAST */
case TK_LT:
case TK_LE:
case TK_GT:
@ -1515,7 +1614,8 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
break;
}
case TK_AGG_FUNCTION: {
sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
AggInfo *pInfo = pExpr->pAggInfo;
sqlite3VdbeAddOp(v, OP_MemLoad, pInfo->aFunc[pExpr->iAgg].iMem, 0);
break;
}
case TK_CONST_FUNC:
@ -1525,7 +1625,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
FuncDef *pDef;
int nId;
const char *zId;
int p2 = 0;
int constMask = 0;
int i;
u8 enc = pParse->db->enc;
CollSeq *pColl = 0;
@ -1536,7 +1636,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
nExpr = sqlite3ExprCodeExprList(pParse, pList);
for(i=0; i<nExpr && i<32; i++){
if( sqlite3ExprIsConstant(pList->a[i].pExpr) ){
p2 |= (1<<i);
constMask |= (1<<i);
}
if( pDef->needCollSeq && !pColl ){
pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
@ -1546,7 +1646,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
if( !pColl ) pColl = pParse->db->pDfltColl;
sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ);
}
sqlite3VdbeOp3(v, OP_Function, nExpr, p2, (char*)pDef, P3_FUNCDEF);
sqlite3VdbeOp3(v, OP_Function, constMask, nExpr, (char*)pDef, P3_FUNCDEF);
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
@ -1610,7 +1710,6 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
case TK_CASE: {
int expr_end_label;
int jumpInst;
int addr;
int nExpr;
int i;
ExprList *pEList;
@ -1638,8 +1737,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
}
sqlite3ExprCode(pParse, aListelem[i+1].pExpr);
sqlite3VdbeAddOp(v, OP_Goto, 0, expr_end_label);
addr = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeChangeP2(v, jumpInst, addr);
sqlite3VdbeJumpHere(v, jumpInst);
}
if( pExpr->pLeft ){
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
@ -1663,9 +1761,9 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
assert( pExpr->iColumn==OE_Rollback ||
pExpr->iColumn == OE_Abort ||
pExpr->iColumn == OE_Fail );
sqlite3DequoteExpr(pExpr);
sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn,
pExpr->token.z, pExpr->token.n);
sqlite3VdbeDequoteP3(v, -1);
} else {
assert( pExpr->iColumn == OE_Ignore );
sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0);
@ -1717,11 +1815,9 @@ int sqlite3ExprCodeExprList(
){
struct ExprList_item *pItem;
int i, n;
Vdbe *v;
if( pList==0 ) return 0;
v = sqlite3GetVdbe(pParse);
n = pList->nExpr;
for(pItem=pList->a, i=0; i<n; i++, pItem++){
for(pItem=pList->a, i=n; i>0; i--, pItem++){
sqlite3ExprCode(pParse, pItem->pExpr);
}
return n;
@ -1808,7 +1904,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
codeCompare(pParse, pLeft, pRight, OP_Le, dest, jumpIfNull);
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeJumpHere(v, addr);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
break;
}
@ -1941,6 +2037,7 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
return 0;
}
if( pA->op!=pB->op ) return 0;
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0;
if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0;
if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0;
if( pA->pList ){
@ -1964,23 +2061,32 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
return 1;
}
/*
** Add a new element to the pParse->aAgg[] array and return its index.
** The new element is initialized to zero. The calling function is
** expected to fill it in.
** Add a new element to the pAggInfo->aCol[] array. Return the index of
** the new element. Return a negative number if malloc fails.
*/
static int appendAggInfo(Parse *pParse){
if( (pParse->nAgg & 0x7)==0 ){
int amt = pParse->nAgg + 8;
AggExpr *aAgg = sqliteRealloc(pParse->aAgg, amt*sizeof(pParse->aAgg[0]));
if( aAgg==0 ){
return -1;
}
pParse->aAgg = aAgg;
static int addAggInfoColumn(AggInfo *pInfo){
int i;
i = sqlite3ArrayAllocate((void**)&pInfo->aCol, sizeof(pInfo->aCol[0]), 3);
if( i<0 ){
return -1;
}
memset(&pParse->aAgg[pParse->nAgg], 0, sizeof(pParse->aAgg[0]));
return pParse->nAgg++;
}
return i;
}
/*
** Add a new element to the pAggInfo->aFunc[] array. Return the index of
** the new element. Return a negative number if malloc fails.
*/
static int addAggInfoFunc(AggInfo *pInfo){
int i;
i = sqlite3ArrayAllocate((void**)&pInfo->aFunc, sizeof(pInfo->aFunc[0]), 2);
if( i<0 ){
return -1;
}
return i;
}
/*
** This is an xFunc for walkExprTree() used to implement
@ -1991,60 +2097,118 @@ static int appendAggInfo(Parse *pParse){
*/
static int analyzeAggregate(void *pArg, Expr *pExpr){
int i;
AggExpr *aAgg;
NameContext *pNC = (NameContext *)pArg;
Parse *pParse = pNC->pParse;
SrcList *pSrcList = pNC->pSrcList;
AggInfo *pAggInfo = pNC->pAggInfo;
switch( pExpr->op ){
case TK_COLUMN: {
for(i=0; pSrcList && i<pSrcList->nSrc; i++){
if( pExpr->iTable==pSrcList->a[i].iCursor ){
aAgg = pParse->aAgg;
for(i=0; i<pParse->nAgg; i++){
if( aAgg[i].isAgg ) continue;
if( aAgg[i].pExpr->iTable==pExpr->iTable
&& aAgg[i].pExpr->iColumn==pExpr->iColumn ){
break;
/* Check to see if the column is in one of the tables in the FROM
** clause of the aggregate query */
if( pSrcList ){
struct SrcList_item *pItem = pSrcList->a;
for(i=0; i<pSrcList->nSrc; i++, pItem++){
struct AggInfo_col *pCol;
if( pExpr->iTable==pItem->iCursor ){
/* If we reach this point, it means that pExpr refers to a table
** that is in the FROM clause of the aggregate query.
**
** Make an entry for the column in pAggInfo->aCol[] if there
** is not an entry there already.
*/
pCol = pAggInfo->aCol;
for(i=0; i<pAggInfo->nColumn; i++, pCol++){
if( pCol->iTable==pExpr->iTable &&
pCol->iColumn==pExpr->iColumn ){
break;
}
}
}
if( i>=pParse->nAgg ){
i = appendAggInfo(pParse);
if( i<0 ) return 1;
pParse->aAgg[i].isAgg = 0;
pParse->aAgg[i].pExpr = pExpr;
}
pExpr->iAgg = i;
pExpr->iAggCtx = pNC->nDepth;
return 1;
}
if( i>=pAggInfo->nColumn && (i = addAggInfoColumn(pAggInfo))>=0 ){
pCol = &pAggInfo->aCol[i];
pCol->iTable = pExpr->iTable;
pCol->iColumn = pExpr->iColumn;
pCol->iMem = pParse->nMem++;
pCol->iSorterColumn = -1;
pCol->pExpr = pExpr;
if( pAggInfo->pGroupBy ){
int j, n;
ExprList *pGB = pAggInfo->pGroupBy;
struct ExprList_item *pTerm = pGB->a;
n = pGB->nExpr;
for(j=0; j<n; j++, pTerm++){
Expr *pE = pTerm->pExpr;
if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable &&
pE->iColumn==pExpr->iColumn ){
pCol->iSorterColumn = j;
break;
}
}
}
if( pCol->iSorterColumn<0 ){
pCol->iSorterColumn = pAggInfo->nSortingColumn++;
}
}
/* There is now an entry for pExpr in pAggInfo->aCol[] (either
** because it was there before or because we just created it).
** Convert the pExpr to be a TK_AGG_COLUMN referring to that
** pAggInfo->aCol[] entry.
*/
pExpr->pAggInfo = pAggInfo;
pExpr->op = TK_AGG_COLUMN;
pExpr->iAgg = i;
break;
} /* endif pExpr->iTable==pItem->iCursor */
} /* end loop over pSrcList */
}
return 1;
}
case TK_AGG_FUNCTION: {
/* The pNC->nDepth==0 test causes aggregate functions in subqueries
** to be ignored */
if( pNC->nDepth==0 ){
aAgg = pParse->aAgg;
for(i=0; i<pParse->nAgg; i++){
if( !aAgg[i].isAgg ) continue;
if( sqlite3ExprCompare(aAgg[i].pExpr, pExpr) ){
/* Check to see if pExpr is a duplicate of another aggregate
** function that is already in the pAggInfo structure
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
if( sqlite3ExprCompare(pItem->pExpr, pExpr) ){
break;
}
}
if( i>=pParse->nAgg ){
if( i>=pAggInfo->nFunc ){
/* pExpr is original. Make a new entry in pAggInfo->aFunc[]
*/
u8 enc = pParse->db->enc;
i = appendAggInfo(pParse);
if( i<0 ) return 1;
pParse->aAgg[i].isAgg = 1;
pParse->aAgg[i].pExpr = pExpr;
pParse->aAgg[i].pFunc = sqlite3FindFunction(pParse->db,
pExpr->token.z, pExpr->token.n,
pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0);
i = addAggInfoFunc(pAggInfo);
if( i>=0 ){
pItem = &pAggInfo->aFunc[i];
pItem->pExpr = pExpr;
pItem->iMem = pParse->nMem++;
pItem->pFunc = sqlite3FindFunction(pParse->db,
pExpr->token.z, pExpr->token.n,
pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0);
if( pExpr->flags & EP_Distinct ){
pItem->iDistinct = pParse->nTab++;
}else{
pItem->iDistinct = -1;
}
}
}
/* Make pExpr point to the appropriate pAggInfo->aFunc[] entry
*/
pExpr->iAgg = i;
pExpr->pAggInfo = pAggInfo;
return 1;
}
}
}
/* Recursively walk subqueries looking for TK_COLUMN nodes that need
** to be changed to TK_AGG_COLUMN. But increment nDepth so that
** TK_AGG_FUNCTION nodes in subqueries will be unchanged.
*/
if( pExpr->pSelect ){
pNC->nDepth++;
walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC);
@ -2069,3 +2233,21 @@ int sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
walkExprTree(pExpr, analyzeAggregate, pNC);
return pNC->pParse->nErr - nErr;
}
/*
** Call sqlite3ExprAnalyzeAggregates() for every expression in an
** expression list. Return the number of errors.
**
** If an error is found, the analysis is cut short.
*/
int sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){
struct ExprList_item *pItem;
int i;
int nErr = 0;
if( pList ){
for(pItem=pList->a, i=0; nErr==0 && i<pList->nExpr; i++, pItem++){
nErr += sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr);
}
}
return nErr;
}

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

@ -16,7 +16,7 @@
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.98 2005/05/24 12:01:02 danielk1977 Exp $
** $Id: func.c,v 1.110 2005/09/08 20:37:43 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -26,6 +26,9 @@
#include "vdbeInt.h"
#include "os.h"
/*
** Return the collating function associated with a function.
*/
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
return context->pColl;
}
@ -78,6 +81,7 @@ static void typeofFunc(
sqlite3_result_text(context, z, -1, SQLITE_STATIC);
}
/*
** Implementation of the length() function
*/
@ -183,7 +187,7 @@ static void substrFunc(
static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
int n = 0;
double r;
char zBuf[100];
char zBuf[500]; /* larger than the %f representation of the largest double */
assert( argc==1 || argc==2 );
if( argc==2 ){
if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return;
@ -193,7 +197,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
}
if( SQLITE_NULL==sqlite3_value_type(argv[0]) ) return;
r = sqlite3_value_double(argv[0]);
sprintf(zBuf,"%.*f",n,r);
sqlite3_snprintf(sizeof(zBuf),zBuf,"%.*f",n,r);
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}
@ -307,8 +311,14 @@ struct compareInfo {
u8 matchSet;
u8 noCase;
};
static const struct compareInfo globInfo = { '*', '?', '[', 0 };
static const struct compareInfo likeInfo = { '%', '_', 0, 1 };
/* The correct SQL-92 behavior is for the LIKE operator to ignore
** case. Thus 'a' LIKE 'A' would be true. */
static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 };
/* If SQLITE_CASE_SENSITIVE_LIKE is defined, then the LIKE operator
** is case sensitive causing 'a' LIKE 'A' to be false */
static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };
/*
** X is a pointer to the first byte of a UTF-8 character. Increment
@ -450,6 +460,15 @@ static int patternCompare(
return *zString==0;
}
/*
** Count the number of times that the LIKE operator (or GLOB which is
** just a variation of LIKE) gets called. This is used for testing
** only.
*/
#ifdef SQLITE_TEST
int sqlite3_like_count = 0;
#endif
/*
** Implementation of the like() SQL function. This function implements
@ -460,8 +479,8 @@ static int patternCompare(
**
** is implemented as like(B,A).
**
** If the pointer retrieved by via a call to sqlite3_user_data() is
** not NULL, then this function uses UTF-16. Otherwise UTF-8.
** This same function (with a different compareInfo structure) computes
** the GLOB operator.
*/
static void likeFunc(
sqlite3_context *context,
@ -484,24 +503,11 @@ static void likeFunc(
escape = sqlite3ReadUtf8(zEsc);
}
if( zA && zB ){
sqlite3_result_int(context, patternCompare(zA, zB, &likeInfo, escape));
}
}
/*
** Implementation of the glob() SQL function. This function implements
** the build-in GLOB operator. The first argument to the function is the
** string and the second argument is the pattern. So, the SQL statements:
**
** A GLOB B
**
** is implemented as glob(B,A).
*/
static void globFunc(sqlite3_context *context, int arg, sqlite3_value **argv){
const unsigned char *zA = sqlite3_value_text(argv[0]);
const unsigned char *zB = sqlite3_value_text(argv[1]);
if( zA && zB ){
sqlite3_result_int(context, patternCompare(zA, zB, &globInfo, 0));
struct compareInfo *pInfo = sqlite3_user_data(context);
#ifdef SQLITE_TEST
sqlite3_like_count++;
#endif
sqlite3_result_int(context, patternCompare(zA, zB, pInfo, escape));
}
}
@ -813,6 +819,7 @@ typedef struct SumCtx SumCtx;
struct SumCtx {
double sum; /* Sum of terms */
int cnt; /* Number of elements summed */
u8 seenFloat; /* True if there has been any floating point value */
};
/*
@ -820,21 +827,32 @@ struct SumCtx {
*/
static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
SumCtx *p;
if( argc<1 ) return;
int type;
assert( argc==1 );
p = sqlite3_aggregate_context(context, sizeof(*p));
if( p && SQLITE_NULL!=sqlite3_value_type(argv[0]) ){
type = sqlite3_value_type(argv[0]);
if( p && type!=SQLITE_NULL ){
p->sum += sqlite3_value_double(argv[0]);
p->cnt++;
if( type==SQLITE_FLOAT ){
p->seenFloat = 1;
}
}
}
static void sumFinalize(sqlite3_context *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, sizeof(*p));
sqlite3_result_double(context, p ? p->sum : 0.0);
p = sqlite3_aggregate_context(context, 0);
if( p && p->cnt>0 ){
if( p->seenFloat ){
sqlite3_result_double(context, p->sum);
}else{
sqlite3_result_int64(context, (i64)p->sum);
}
}
}
static void avgFinalize(sqlite3_context *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, sizeof(*p));
p = sqlite3_aggregate_context(context, 0);
if( p && p->cnt>0 ){
sqlite3_result_double(context, p->sum/(double)p->cnt);
}
@ -872,20 +890,10 @@ static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
}
static void countFinalize(sqlite3_context *context){
CountCtx *p;
p = sqlite3_aggregate_context(context, sizeof(*p));
p = sqlite3_aggregate_context(context, 0);
sqlite3_result_int(context, p ? p->n : 0);
}
/*
** This function tracks state information for the min() and max()
** aggregate functions.
*/
typedef struct MinMaxCtx MinMaxCtx;
struct MinMaxCtx {
char *z; /* The best so far */
char zBuf[28]; /* Space that can be used for storage */
};
/*
** Routines to implement min() and max() aggregate functions.
*/
@ -920,11 +928,13 @@ static void minmaxStep(sqlite3_context *context, int argc, sqlite3_value **argv)
}
static void minMaxFinalize(sqlite3_context *context){
sqlite3_value *pRes;
pRes = (sqlite3_value *)sqlite3_aggregate_context(context, sizeof(Mem));
if( pRes->flags ){
sqlite3_result_value(context, pRes);
pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0);
if( pRes ){
if( pRes->flags ){
sqlite3_result_value(context, pRes);
}
sqlite3VdbeMemRelease(pRes);
}
sqlite3VdbeMemRelease(pRes);
}
@ -962,9 +972,6 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
{ "coalesce", 1, 0, SQLITE_UTF8, 0, 0 },
{ "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc },
{ "random", -1, 0, SQLITE_UTF8, 0, randomFunc },
{ "like", 2, 0, SQLITE_UTF8, 0, likeFunc },
{ "like", 3, 0, SQLITE_UTF8, 0, likeFunc },
{ "glob", 2, 0, SQLITE_UTF8, 0, globFunc },
{ "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc },
{ "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc},
{ "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc },
@ -1036,8 +1043,76 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
}
sqlite3RegisterDateTimeFunctions(db);
#ifdef SQLITE_SSE
{
sqlite3SseFunctions(db);
}
sqlite3SseFunctions(db);
#endif
#ifdef SQLITE_CASE_SENSITIVE_LIKE
sqlite3RegisterLikeFunctions(db, 1);
#else
sqlite3RegisterLikeFunctions(db, 0);
#endif
}
/*
** Set the LIKEOPT flag on the 2-argument function with the given name.
*/
static void setLikeOptFlag(sqlite3 *db, const char *zName, int flagVal){
FuncDef *pDef;
pDef = sqlite3FindFunction(db, zName, strlen(zName), 2, SQLITE_UTF8, 0);
if( pDef ){
pDef->flags = flagVal;
}
}
/*
** Register the built-in LIKE and GLOB functions. The caseSensitive
** parameter determines whether or not the LIKE operator is case
** sensitive. GLOB is always case sensitive.
*/
void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
struct compareInfo *pInfo;
if( caseSensitive ){
pInfo = (struct compareInfo*)&likeInfoAlt;
}else{
pInfo = (struct compareInfo*)&likeInfoNorm;
}
sqlite3_create_function(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0);
sqlite3_create_function(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0);
sqlite3_create_function(db, "glob", 2, SQLITE_UTF8,
(struct compareInfo*)&globInfo, likeFunc, 0,0);
setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE);
setLikeOptFlag(db, "like",
caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE);
}
/*
** pExpr points to an expression which implements a function. If
** it is appropriate to apply the LIKE optimization to that function
** then set aWc[0] through aWc[2] to the wildcard characters and
** return TRUE. If the function is not a LIKE-style function then
** return FALSE.
*/
int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
FuncDef *pDef;
if( pExpr->op!=TK_FUNCTION ){
return 0;
}
if( pExpr->pList->nExpr!=2 ){
return 0;
}
pDef = sqlite3FindFunction(db, pExpr->token.z, pExpr->token.n, 2,
SQLITE_UTF8, 0);
if( pDef==0 || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
return 0;
}
/* The memcpy() statement assumes that the wildcard characters are
** the first three statements in the compareInfo structure. The
** asserts() that follow verify that assumption
*/
memcpy(aWc, pDef->pUserData, 3);
assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll );
assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne );
assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet );
*pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0;
return 1;
}

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

@ -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.139 2005/06/12 21:35:52 drh Exp $
** $Id: insert.c,v 1.143 2005/09/20 17:42:23 drh Exp $
*/
#include "sqliteInt.h"
@ -372,13 +372,13 @@ void sqlite3Insert(
** of the program jumps to it. Create the temporary table, then jump
** back up and execute the SELECT code above.
*/
sqlite3VdbeChangeP2(v, iInitCode, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeAddOp(v, OP_OpenTemp, srcTab, 0);
sqlite3VdbeJumpHere(v, iInitCode);
sqlite3VdbeAddOp(v, OP_OpenVirtual, srcTab, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, srcTab, nColumn);
sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop);
sqlite3VdbeResolveLabel(v, iCleanup);
}else{
sqlite3VdbeChangeP2(v, iInitCode, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeJumpHere(v, iInitCode);
}
}else{
/* This is the case if the data for the INSERT is coming from a VALUES
@ -470,8 +470,7 @@ void sqlite3Insert(
*/
if( db->flags & SQLITE_CountRows ){
iCntMem = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
sqlite3VdbeAddOp(v, OP_MemStore, iCntMem, 1);
sqlite3VdbeAddOp(v, OP_MemInt, 0, iCntMem);
}
/* Open tables and indices if there are no row triggers */
@ -817,7 +816,6 @@ void sqlite3GenerateConstraintChecks(
Index *pIdx;
int seenReplace = 0;
int jumpInst1=0, jumpInst2;
int contAddr;
int hasTwoRowids = (isUpdate && rowidChng);
v = sqlite3GetVdbe(pParse);
@ -867,7 +865,7 @@ void sqlite3GenerateConstraintChecks(
break;
}
}
sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeJumpHere(v, addr);
}
/* Test all CHECK constraints
@ -921,10 +919,9 @@ void sqlite3GenerateConstraintChecks(
break;
}
}
contAddr = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeChangeP2(v, jumpInst2, contAddr);
sqlite3VdbeJumpHere(v, jumpInst2);
if( isUpdate ){
sqlite3VdbeChangeP2(v, jumpInst1, contAddr);
sqlite3VdbeJumpHere(v, jumpInst1);
sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1);
sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
}
@ -949,7 +946,7 @@ void sqlite3GenerateConstraintChecks(
sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1);
}
}
jumpInst1 = sqlite3VdbeAddOp(v, OP_MakeRecord, pIdx->nColumn, (1<<24));
jumpInst1 = sqlite3VdbeAddOp(v, OP_MakeIdxRec, pIdx->nColumn, 0);
sqlite3IndexAffinityStr(v, pIdx);
/* Find out what action to take in case there is an indexing conflict */
@ -1018,12 +1015,10 @@ void sqlite3GenerateConstraintChecks(
break;
}
}
contAddr = sqlite3VdbeCurrentAddr(v);
assert( contAddr<(1<<24) );
#if NULL_DISTINCT_FOR_UNIQUE
sqlite3VdbeChangeP2(v, jumpInst1, contAddr | (1<<24));
sqlite3VdbeJumpHere(v, jumpInst1);
#endif
sqlite3VdbeChangeP2(v, jumpInst2, contAddr);
sqlite3VdbeJumpHere(v, jumpInst2);
}
}
@ -1097,11 +1092,12 @@ void sqlite3OpenTableAndIndices(
Vdbe *v = sqlite3GetVdbe(pParse);
assert( v!=0 );
sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqlite3VdbeAddOp(v, op, base, pTab->tnum);
VdbeComment((v, "# %s", pTab->zName));
sqlite3VdbeAddOp(v, op, base, pTab->tnum);
sqlite3VdbeAddOp(v, OP_SetNumColumns, base, pTab->nCol);
for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
VdbeComment((v, "# %s", pIdx->zName));
sqlite3VdbeOp3(v, op, i+base, pIdx->tnum,
(char*)&pIdx->keyInfo, P3_KEYINFO);
}

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

@ -1,83 +1,84 @@
/* Hash score: 153 */
/* Hash score: 158 */
static int keywordCode(const char *z, int n){
static const char zText[515] =
static const char zText[535] =
"ABORTABLEFTEMPORARYADDATABASELECTHENDEFAULTRANSACTIONATURALTER"
"AISEACHECKEYAFTEREFERENCESCAPELSEXCEPTRIGGEREGEXPLAINITIALLYAND"
"EFERRABLEXCLUSIVEXISTSTATEMENTATTACHAVINGLOBEFOREIGNOREINDEXAUTOINCREMENT"
"BEGINNERENAMEBETWEENOTNULLIKEBYCASCADEFERREDELETECASECOLLATECOLUMN"
"COMMITCONFLICTCONSTRAINTERSECTCREATECROSSCURRENT_DATECURRENT_TIMESTAMP"
"RAGMATCHDESCDETACHDISTINCTDROPRIMARYFAILIMITFROMFULLGROUPDATE"
"IMMEDIATEINSERTINSTEADINTOFFSETISNULLJOINORDEREPLACEOUTERESTRICT"
"RIGHTROLLBACKROWHENUNIONUNIQUEUSINGVACUUMVALUESVIEWHERE";
"AISEACHECKEYAFTEREFERENCESCAPELSEXCEPTRIGGEREGEXPLAINITIALLYANALYZE"
"XCLUSIVEXISTSTATEMENTANDEFERRABLEATTACHAVINGLOBEFOREIGNOREINDEX"
"AUTOINCREMENTBEGINNERENAMEBETWEENOTNULLIKEBYCASCADEFERREDELETE"
"CASECASTCOLLATECOLUMNCOMMITCONFLICTCONSTRAINTERSECTCREATECROSS"
"CURRENT_DATECURRENT_TIMESTAMPLANDESCDETACHDISTINCTDROPRAGMATCH"
"FAILIMITFROMFULLGROUPDATEIMMEDIATEINSERTINSTEADINTOFFSETISNULL"
"JOINORDEREPLACEOUTERESTRICTPRIMARYQUERYRIGHTROLLBACKROWHENUNION"
"UNIQUEUSINGVACUUMVALUESVIEWHERE";
static const unsigned char aHash[127] = {
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, 111, 50, 55, 0, 2, 54, 0, 106,
91, 80, 106, 90, 0, 4, 0, 0, 113, 0, 83, 0, 0,
94, 44, 76, 92, 0, 105, 108, 96, 0, 0, 10, 0, 0,
112, 0, 109, 102, 0, 28, 48, 0, 41, 0, 0, 65, 71,
0, 63, 19, 0, 104, 36, 103, 0, 107, 74, 0, 0, 33,
0, 61, 37, 0, 8, 0, 114, 38, 12, 0, 77, 40, 25,
66, 0, 0, 31, 81, 53, 30, 50, 20, 88, 0, 34, 0,
75, 26, 0, 72, 0, 0, 0, 64, 47, 67, 22, 87, 29,
69, 86, 0, 1, 0, 9, 100, 58, 18, 0, 111, 82, 98,
54, 6, 85, 0, 0, 49, 93, 0, 101, 0, 70, 0, 0,
15, 0, 115, 51, 56, 0, 2, 55, 0, 110,
};
static const unsigned char aNext[111] = {
static const unsigned char aNext[115] = {
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, 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,
0, 11, 0, 0, 0, 0, 5, 13, 0, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0,
0, 0, 16, 0, 23, 52, 0, 0, 0, 0, 45, 0, 59,
0, 0, 0, 0, 0, 0, 0, 0, 73, 42, 0, 24, 60,
21, 0, 79, 0, 0, 68, 0, 0, 84, 46, 0, 0, 0,
0, 0, 0, 0, 39, 95, 97, 0, 0, 99, 0, 32, 0,
14, 27, 78, 0, 57, 89, 0, 35, 0, 62, 0,
};
static const unsigned char aLen[111] = {
static const unsigned char aLen[115] = {
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, 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, 7, 5, 8, 5, 8, 3, 4,
5, 6, 5, 6, 6, 4, 5,
7, 6, 7, 9, 3, 7, 9, 6, 9, 3, 10, 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, 4, 7,
6, 6, 8, 10, 9, 6, 5, 12, 12, 17, 4, 4, 6,
8, 2, 4, 6, 5, 4, 5, 4, 4, 5, 6, 9, 6,
7, 4, 2, 6, 3, 6, 4, 5, 7, 5, 8, 7, 5,
5, 8, 3, 4, 5, 6, 5, 6, 6, 4, 5,
};
static const unsigned short int aOffset[111] = {
static const unsigned short int aOffset[115] = {
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, 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,
99, 105, 108, 113, 118, 122, 128, 136, 141, 150, 152, 162, 167,
172, 175, 177, 177, 181, 185, 187, 192, 194, 196, 205, 208, 212,
218, 224, 224, 227, 230, 234, 236, 237, 241, 248, 254, 258, 262,
269, 275, 281, 289, 296, 305, 311, 316, 328, 328, 344, 348, 352,
358, 359, 366, 369, 373, 378, 381, 386, 390, 394, 397, 403, 412,
418, 425, 428, 428, 431, 434, 440, 444, 448, 455, 459, 467, 474,
479, 484, 492, 494, 498, 503, 509, 514, 520, 526, 529,
};
static const unsigned char aCode[111] = {
static const unsigned char aCode[115] = {
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_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_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_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_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,
TK_ALL, TK_ANALYZE, TK_EXCLUSIVE, TK_EXISTS, TK_STATEMENT,
TK_AND, TK_DEFERRABLE, 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_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_CAST, TK_COLLATE,
TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_CONSTRAINT, TK_INTERSECT,
TK_CREATE, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_CTIME_KW,
TK_PLAN, TK_DESC, TK_DETACH, TK_DISTINCT, TK_IS,
TK_DROP, TK_PRAGMA, TK_MATCH, 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_REPLACE,
TK_JOIN_KW, TK_RESTRICT, TK_PRIMARY, TK_QUERY, 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.293 2005/05/26 16:23:34 drh Exp $
** $Id: main.c,v 1.302 2005/09/17 15:20:27 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -234,7 +234,6 @@ const char *sqlite3ErrStr(int rc){
case SQLITE_DONE:
case SQLITE_OK: z = "not an error"; break;
case SQLITE_ERROR: z = "SQL logic error or missing database"; break;
case SQLITE_INTERNAL: z = "internal SQLite implementation flaw"; break;
case SQLITE_PERM: z = "access permission denied"; break;
case SQLITE_ABORT: z = "callback requested query abort"; break;
case SQLITE_BUSY: z = "database is locked"; break;
@ -244,13 +243,11 @@ const char *sqlite3ErrStr(int rc){
case SQLITE_INTERRUPT: z = "interrupted"; break;
case SQLITE_IOERR: z = "disk I/O error"; break;
case SQLITE_CORRUPT: z = "database disk image is malformed"; break;
case SQLITE_NOTFOUND: z = "table or record not found"; break;
case SQLITE_FULL: z = "database is full"; break;
case SQLITE_FULL: z = "database or disk is full"; break;
case SQLITE_CANTOPEN: z = "unable to open database file"; break;
case SQLITE_PROTOCOL: z = "database locking protocol failure"; break;
case SQLITE_EMPTY: z = "table contains no data"; break;
case SQLITE_SCHEMA: z = "database schema has changed"; break;
case SQLITE_TOOBIG: z = "too much data for one table row"; break;
case SQLITE_CONSTRAINT: z = "constraint failed"; break;
case SQLITE_MISMATCH: z = "datatype mismatch"; break;
case SQLITE_MISUSE: z = "library routine called out of sequence";break;
@ -298,7 +295,7 @@ static int sqliteDefaultBusyCallback(
sqlite3OsSleep(delay);
return 1;
#else
int timeout = (int)Timeout;
int timeout = ((sqlite3 *)ptr)->busyTimeout;
if( (count+1)*1000 > timeout ){
return 0;
}
@ -307,6 +304,25 @@ static int sqliteDefaultBusyCallback(
#endif
}
/*
** Invoke the given busy handler.
**
** This routine is called when an operation failed with a lock.
** If this routine returns non-zero, the lock is retried. If it
** returns 0, the operation aborts with an SQLITE_BUSY error.
*/
int sqlite3InvokeBusyHandler(BusyHandler *p){
int rc;
if( p==0 || p->xFunc==0 || p->nBusy<0 ) return 0;
rc = p->xFunc(p->pArg, p->nBusy);
if( rc==0 ){
p->nBusy = -1;
}else{
p->nBusy++;
}
return rc;
}
/*
** This routine sets the busy callback for an Sqlite database to the
** given callback function with the given argument.
@ -321,6 +337,7 @@ int sqlite3_busy_handler(
}
db->busyHandler.xFunc = xBusy;
db->busyHandler.pArg = pArg;
db->busyHandler.nBusy = 0;
return SQLITE_OK;
}
@ -454,6 +471,7 @@ int sqlite3_create_function(
p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1);
if( p==0 ) return SQLITE_NOMEM;
p->flags = 0;
p->xFunc = xFunc;
p->xStep = xStep;
p->xFinalize = xFinal;
@ -491,13 +509,14 @@ int sqlite3_create_function16(
}
#endif
#ifndef SQLITE_OMIT_TRACE
/*
** Register a trace function. The pArg from the previously registered trace
** is returned.
**
** A NULL trace function means that no tracing is executes. A non-NULL
** trace is a pointer to a function that is invoked at the start of each
** sqlite3_exec().
** SQL statement.
*/
void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){
void *pOld = db->pTraceArg;
@ -505,6 +524,25 @@ void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){
db->pTraceArg = pArg;
return pOld;
}
/*
** Register a profile function. The pArg from the previously registered
** profile function is returned.
**
** A NULL profile function means that no profiling is executes. A non-NULL
** profile is a pointer to a function that is invoked at the conclusion of
** each SQL statement that is run.
*/
void *sqlite3_profile(
sqlite3 *db,
void (*xProfile)(void*,const char*,sqlite_uint64),
void *pArg
){
void *pOld = db->pProfileArg;
db->xProfile = xProfile;
db->pProfileArg = pArg;
return pOld;
}
#endif /* SQLITE_OMIT_TRACE */
/*** EXPERIMENTAL ***
**
@ -530,11 +568,11 @@ void *sqlite3_commit_hook(
** opened and used. If zFilename is the magic name ":memory:" then
** the database is stored in memory (and is thus forgotten as soon as
** the connection is closed.) If zFilename is NULL then the database
** is for temporary use only and is deleted as soon as the connection
** is closed.
** is a "virtual" database for transient use only and is deleted as
** soon as the connection is closed.
**
** A temporary database can be either a disk file (that is automatically
** deleted when the file is closed) or a set of red-black trees held in memory,
** A virtual database can be either a disk file (that is automatically
** deleted when the file is closed) or it an be held entirely in memory,
** depending on the values of the TEMP_STORE compile-time macro and the
** db->temp_store variable, according to the following chart:
**
@ -676,6 +714,7 @@ static int openDatabase(
){
sqlite3 *db;
int rc, i;
CollSeq *pColl;
/* Allocate the sqlite data structure */
db = sqliteMalloc( sizeof(sqlite3) );
@ -712,6 +751,13 @@ static int openDatabase(
/* Also add a UTF-8 case-insensitive collation sequence. */
sqlite3_create_collation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc);
/* Set flags on the built-in collating sequences */
db->pDfltColl->type = SQLITE_COLL_BINARY;
pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "NOCASE", 6, 0);
if( pColl ){
pColl->type = SQLITE_COLL_NOCASE;
}
/* Open the backend database driver */
rc = sqlite3BtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt);
if( rc!=SQLITE_OK ){
@ -829,7 +875,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt){
rc = SQLITE_OK;
}else{
rc = sqlite3VdbeReset((Vdbe*)pStmt);
sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0, 0);
sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0);
}
return rc;
}
@ -883,7 +929,7 @@ int sqlite3_create_collation(
pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1);
if( 0==pColl ){
rc = SQLITE_NOMEM;
rc = SQLITE_NOMEM;
}else{
pColl->xCmp = xCompare;
pColl->pUser = pCtx;
@ -1001,3 +1047,14 @@ recover_out:
int sqlite3_get_autocommit(sqlite3 *db){
return db->autoCommit;
}
#ifdef SQLITE_DEBUG
/*
** The following routine is subtituted for constant SQLITE_CORRUPT in
** debugging builds. This provides a way to set a breakpoint for when
** corruption is first detected.
*/
int sqlite3Corrupt(void){
return SQLITE_CORRUPT;
}
#endif

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

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

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

@ -1,129 +1,129 @@
/* Automatically generated. Do not edit */
/* See the mkopcodeh.awk script for details */
#define OP_MemLoad 1
#define OP_HexBlob 129 /* same as TK_BLOB */
#define OP_HexBlob 134 /* same as TK_BLOB */
#define OP_Column 2
#define OP_SetCookie 3
#define OP_IfMemPos 4
#define OP_Real 128 /* same as TK_FLOAT */
#define OP_MoveGt 5
#define OP_Ge 75 /* same as TK_GE */
#define OP_AggFocus 6
#define OP_Real 133 /* same as TK_FLOAT */
#define OP_Sequence 5
#define OP_MoveGt 6
#define OP_Ge 80 /* same as TK_GE */
#define OP_RowKey 7
#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_Eq 76 /* same as TK_EQ */
#define OP_OpenWrite 8
#define OP_NotNull 74 /* same as TK_NOTNULL */
#define OP_If 9
#define OP_ToInt 10
#define OP_String8 95 /* 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_CollSeq 12
#define OP_OpenRead 13
#define OP_Expire 14
#define OP_AutoCommit 15
#define OP_Gt 77 /* same as TK_GT */
#define OP_IntegrityCk 16
#define OP_Sort 17
#define OP_Function 18
#define OP_And 68 /* same as TK_AND */
#define OP_Subtract 87 /* same as TK_MINUS */
#define OP_Noop 19
#define OP_Return 20
#define OP_Remainder 90 /* same as TK_REM */
#define OP_NewRowid 21
#define OP_Multiply 88 /* same as TK_STAR */
#define OP_Variable 22
#define OP_String 23
#define OP_ParseSchema 24
#define OP_Close 25
#define OP_CreateIndex 26
#define OP_IsUnique 27
#define OP_IdxIsNull 28
#define OP_NotFound 29
#define OP_Int64 30
#define OP_MustBeInt 31
#define OP_Halt 32
#define OP_Rowid 33
#define OP_IdxLT 34
#define OP_AddImm 35
#define OP_Statement 36
#define OP_RowData 37
#define OP_MemMax 38
#define OP_Push 39
#define OP_Or 67 /* same as TK_OR */
#define OP_NotExists 40
#define OP_MemIncr 41
#define OP_Gosub 42
#define OP_Divide 89 /* same as TK_SLASH */
#define OP_Integer 43
#define OP_ToNumeric 44
#define OP_MemInt 45
#define OP_Prev 46
#define OP_Concat 91 /* same as TK_CONCAT */
#define OP_BitAnd 82 /* same as TK_BITAND */
#define OP_CreateTable 47
#define OP_Last 48
#define OP_IsNull 73 /* same as TK_ISNULL */
#define OP_IdxRowid 49
#define OP_MakeIdxRec 50
#define OP_ShiftRight 85 /* same as TK_RSHIFT */
#define OP_ResetCount 51
#define OP_FifoWrite 52
#define OP_Callback 53
#define OP_ContextPush 54
#define OP_DropTrigger 55
#define OP_DropIndex 56
#define OP_IdxGE 57
#define OP_IdxDelete 58
#define OP_Vacuum 59
#define OP_MoveLe 60
#define OP_IfNot 61
#define OP_DropTable 62
#define OP_MakeRecord 63
#define OP_ToBlob 64
#define OP_Delete 65
#define OP_AggFinal 66
#define OP_ShiftLeft 84 /* same as TK_LSHIFT */
#define OP_Dup 70
#define OP_Goto 71
#define OP_FifoRead 72
#define OP_Clear 81
#define OP_IdxGT 93
#define OP_MoveLt 96
#define OP_Le 78 /* same as TK_LE */
#define OP_VerifyCookie 97
#define OP_AggStep 98
#define OP_Pull 99
#define OP_ToText 100
#define OP_Not 69 /* same as TK_NOT */
#define OP_SetNumColumns 101
#define OP_AbsValue 102
#define OP_Transaction 103
#define OP_Negative 92 /* same as TK_UMINUS */
#define OP_Ne 75 /* same as TK_NE */
#define OP_ContextPop 104
#define OP_BitOr 83 /* same as TK_BITOR */
#define OP_Next 105
#define OP_IdxInsert 106
#define OP_Distinct 107
#define OP_Lt 79 /* same as TK_LT */
#define OP_Insert 108
#define OP_Destroy 109
#define OP_ReadCookie 110
#define OP_ForceInt 111
#define OP_LoadAnalysis 112
#define OP_OpenVirtual 113
#define OP_Explain 114
#define OP_OpenPseudo 115
#define OP_Null 116
#define OP_Blob 117
#define OP_Add 86 /* same as TK_PLUS */
#define OP_MemStore 118
#define OP_Rewind 119
#define OP_MoveGe 120
#define OP_BitNot 94 /* same as TK_BITNOT */
#define OP_MemMove 121
#define OP_MemNull 122
#define OP_Found 123
#define OP_NullRow 124
@ -131,14 +131,19 @@
#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 OP_NotUsed_130 130
#define OP_NotUsed_131 131
#define OP_NotUsed_132 132
#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 46015
#define NOPUSH_MASK_6 64254
#define NOPUSH_MASK_7 7987
#define NOPUSH_MASK_0 65368
#define NOPUSH_MASK_1 47898
#define NOPUSH_MASK_2 22493
#define NOPUSH_MASK_3 32761
#define NOPUSH_MASK_4 65215
#define NOPUSH_MASK_5 30719
#define NOPUSH_MASK_6 40895
#define NOPUSH_MASK_7 6603
#define NOPUSH_MASK_8 0
#define NOPUSH_MASK_9 0

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

@ -171,8 +171,13 @@
** 1GB boundary.
**
*/
#ifndef SQLITE_TEST
#define PENDING_BYTE 0x40000000 /* First byte past the 1GB boundary */
/* #define PENDING_BYTE 0x5400 // Page 22 - for testing */
#else
extern unsigned int sqlite3_pending_byte;
#define PENDING_BYTE sqlite3_pending_byte
#endif
#define RESERVED_BYTE (PENDING_BYTE+1)
#define SHARED_FIRST (PENDING_BYTE+2)
#define SHARED_SIZE 510
@ -191,7 +196,7 @@ int sqlite3OsClose(OsFile*);
int sqlite3OsRead(OsFile*, void*, int amt);
int sqlite3OsWrite(OsFile*, const void*, int amt);
int sqlite3OsSeek(OsFile*, i64 offset);
int sqlite3OsSync(OsFile*);
int sqlite3OsSync(OsFile*, int);
int sqlite3OsTruncate(OsFile*, i64 size);
int sqlite3OsFileSize(OsFile*, i64 *pSize);
char *sqlite3OsFullPathname(const char*);

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

@ -28,6 +28,14 @@
#endif
/*
* When testing, this global variable stores the location of the
* pending-byte in the database file.
*/
#ifdef SQLITE_TEST
unsigned int sqlite3_pending_byte = 0x40000000;
#endif
int sqlite3_os_trace = 0;
#ifdef SQLITE_DEBUG
static int last_page = 0;
@ -82,6 +90,7 @@ static unsigned int elapse;
#ifdef SQLITE_TEST
int sqlite3_io_error_pending = 0;
int sqlite3_diskfull_pending = 0;
int sqlite3_diskfull = 0;
#define SimulateIOError(A) \
if( sqlite3_io_error_pending ) \
if( sqlite3_io_error_pending-- == 1 ){ local_ioerr(); return A; }
@ -89,8 +98,15 @@ static void local_ioerr(){
sqlite3_io_error_pending = 0; /* Really just a place to set a breakpoint */
}
#define SimulateDiskfullError \
if( sqlite3_diskfull_pending ) \
if( sqlite3_diskfull_pending-- == 1 ){ local_ioerr(); return SQLITE_FULL; }
if( sqlite3_diskfull_pending ){ \
if( sqlite3_diskfull_pending == 1 ){ \
local_ioerr(); \
sqlite3_diskfull = 1; \
return SQLITE_FULL; \
}else{ \
sqlite3_diskfull_pending--; \
} \
}
#else
#define SimulateIOError(A)
#define SimulateDiskfullError

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

@ -18,6 +18,7 @@
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>
@ -56,25 +57,36 @@
# define fcntl(A,B,C) 0
#endif
/*
** Macros used to determine whether or not to use threads. The
** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for
** Posix threads and SQLITE_W32_THREADS is defined if we are
** synchronizing using Win32 threads.
*/
#if defined(THREADSAFE) && THREADSAFE
# include <pthread.h>
# define SQLITE_UNIX_THREADS 1
#endif
/*
** Include code that is common to all os_*.c files
*/
#include "os_common.h"
#if defined(THREADSAFE) && THREADSAFE && defined(__linux__)
#define getpid pthread_self
/*
** The threadid macro resolves to the thread-id or to 0. Used for
** testing and debugging only.
*/
#ifdef SQLITE_UNIX_THREADS
#define threadid pthread_self()
#else
#define threadid 0
#endif
/*
** Set or check the OsFile.tid field. This field is set when an OsFile
** is first opened. All subsequent uses of the OsFile verify that the
** same thread is operating on the OsFile. Some operating systems do
** not allow locks to be overridden by other threads and that restriction
** means that sqlite3* database handles cannot be moved from one thread
** to another. This logic makes sure a user does not try to do that
** by mistake.
*/
#ifdef SQLITE_UNIX_THREADS
# define SET_THREADID(X) X->tid = pthread_self()
# define CHECK_THREADID(X) (!pthread_equal(X->tid, pthread_self()))
#else
# define SET_THREADID(X)
# define CHECK_THREADID(X) 0
#endif
/*
@ -264,6 +276,65 @@ struct threadTestData {
int result; /* Result of the locking operation */
};
#ifdef SQLITE_LOCK_TRACE
/*
** Print out information about all locking operations.
**
** This routine is used for troubleshooting locks on multithreaded
** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE
** command-line option on the compiler. This code is normally
** turnned off.
*/
static int lockTrace(int fd, int op, struct flock *p){
char *zOpName, *zType;
int s;
int savedErrno;
if( op==F_GETLK ){
zOpName = "GETLK";
}else if( op==F_SETLK ){
zOpName = "SETLK";
}else{
s = fcntl(fd, op, p);
sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
return s;
}
if( p->l_type==F_RDLCK ){
zType = "RDLCK";
}else if( p->l_type==F_WRLCK ){
zType = "WRLCK";
}else if( p->l_type==F_UNLCK ){
zType = "UNLCK";
}else{
assert( 0 );
}
assert( p->l_whence==SEEK_SET );
s = fcntl(fd, op, p);
savedErrno = errno;
sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
(int)p->l_pid, s);
if( s && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
struct flock l2;
l2 = *p;
fcntl(fd, F_GETLK, &l2);
if( l2.l_type==F_RDLCK ){
zType = "RDLCK";
}else if( l2.l_type==F_WRLCK ){
zType = "WRLCK";
}else if( l2.l_type==F_UNLCK ){
zType = "UNLCK";
}else{
assert( 0 );
}
sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid);
}
errno = savedErrno;
return s;
}
#define fcntl lockTrace
#endif /* SQLITE_LOCK_TRACE */
/*
** The testThreadLockingBehavior() routine launches two separate
** threads on this routine. This routine attempts to lock a file
@ -443,6 +514,7 @@ int sqlite3OsOpenReadWrite(
int rc;
assert( !id->isOpen );
id->dirfd = -1;
SET_THREADID(id);
id->h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY,
SQLITE_DEFAULT_FILE_PERMISSIONS);
if( id->h<0 ){
@ -494,9 +566,11 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
if( access(zFilename, 0)==0 ){
return SQLITE_CANTOPEN;
}
SET_THREADID(id);
id->dirfd = -1;
id->h = open(zFilename,
O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600);
O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY,
SQLITE_DEFAULT_FILE_PERMISSIONS);
if( id->h<0 ){
return SQLITE_CANTOPEN;
}
@ -528,6 +602,7 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){
int rc;
assert( !id->isOpen );
SET_THREADID(id);
id->dirfd = -1;
id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
if( id->h<0 ){
@ -572,6 +647,7 @@ int sqlite3OsOpenDirectory(
** open. */
return SQLITE_CANTOPEN;
}
SET_THREADID(id);
assert( id->dirfd<0 );
id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0);
if( id->dirfd<0 ){
@ -696,6 +772,9 @@ int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
int sqlite3OsSeek(OsFile *id, i64 offset){
assert( id->isOpen );
SEEK(offset/1024 + 1);
#ifdef SQLITE_TEST
if( offset ) SimulateDiskfullError
#endif
lseek(id->h, offset, SEEK_SET);
return SQLITE_OK;
}
@ -721,7 +800,7 @@ int sqlite3_fullsync_count = 0;
** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
** or power failure will likely corrupt the database file.
*/
static int full_fsync(int fd, int fullSync){
static int full_fsync(int fd, int fullSync, int dataOnly){
int rc;
/* Record the number of times that we do a normal fsync() and
@ -749,8 +828,15 @@ static int full_fsync(int fd, int fullSync){
/* If the FULLSYNC failed, try to do a normal fsync() */
if( rc ) rc = fsync(fd);
#else
rc = fsync(fd);
#else /* if !defined(F_FULLSYNC) */
#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO>0
if( dataOnly ){
rc = fdatasync(fd);
}else
#endif /* _POSIX_SYNCHRONIZED_IO > 0 */
{
rc = fsync(fd);
}
#endif /* defined(F_FULLFSYNC) */
#endif /* defined(SQLITE_NO_SYNC) */
@ -760,6 +846,10 @@ static int full_fsync(int fd, int fullSync){
/*
** Make sure all writes to a particular file are committed to disk.
**
** If dataOnly==0 then both the file itself and its metadata (file
** size, access time, etc) are synced. If dataOnly!=0 then only the
** file data is synced.
**
** Under Unix, also make sure that the directory entry for the file
** has been created by fsync-ing the directory that contains the file.
** If we do not do this and we encounter a power failure, the directory
@ -768,16 +858,16 @@ static int full_fsync(int fd, int fullSync){
** the directory entry for the journal was never created) and the transaction
** will not roll back - possibly leading to database corruption.
*/
int sqlite3OsSync(OsFile *id){
int sqlite3OsSync(OsFile *id, int dataOnly){
assert( id->isOpen );
SimulateIOError(SQLITE_IOERR);
TRACE2("SYNC %-3d\n", id->h);
if( full_fsync(id->h, id->fullSync) ){
if( full_fsync(id->h, id->fullSync, dataOnly) ){
return SQLITE_IOERR;
}
if( id->dirfd>=0 ){
TRACE2("DIRSYNC %-3d\n", id->dirfd);
full_fsync(id->dirfd, id->fullSync);
full_fsync(id->dirfd, id->fullSync, 0);
close(id->dirfd); /* Only need to sync once, so close the directory */
id->dirfd = -1; /* when we are done. */
}
@ -839,6 +929,7 @@ int sqlite3OsCheckReservedLock(OsFile *id){
int r = 0;
assert( id->isOpen );
if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
sqlite3OsEnterMutex(); /* Needed because id->pLock is shared across threads */
/* Check if a thread in this process holds such a lock */
@ -956,6 +1047,7 @@ int sqlite3OsLock(OsFile *id, int locktype){
TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", id->h, locktypeName(locktype),
locktypeName(id->locktype), locktypeName(pLock->locktype), pLock->cnt
,getpid() );
if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
/* If there is already a lock of this type or more restrictive on the
** OsFile, do nothing. Don't use the end_lock: exit path, as
@ -1002,6 +1094,7 @@ int sqlite3OsLock(OsFile *id, int locktype){
}
lock.l_len = 1L;
lock.l_whence = SEEK_SET;
/* A PENDING lock is needed before acquiring a SHARED lock and before
@ -1037,7 +1130,10 @@ int sqlite3OsLock(OsFile *id, int locktype){
lock.l_start = PENDING_BYTE;
lock.l_len = 1L;
lock.l_type = F_UNLCK;
fcntl(id->h, F_SETLK, &lock);
if( fcntl(id->h, F_SETLK, &lock)!=0 ){
rc = SQLITE_IOERR; /* This should never happen */
goto end_lock;
}
if( s ){
rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
}else{
@ -1107,6 +1203,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
assert( id->isOpen );
TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", id->h, locktype, id->locktype,
id->pLock->locktype, id->pLock->cnt, getpid());
if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
assert( locktype<=SHARED_LOCK );
if( id->locktype<=locktype ){
@ -1131,8 +1228,11 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
lock.l_whence = SEEK_SET;
lock.l_start = PENDING_BYTE;
lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
fcntl(id->h, F_SETLK, &lock);
pLock->locktype = SHARED_LOCK;
if( fcntl(id->h, F_SETLK, &lock)==0 ){
pLock->locktype = SHARED_LOCK;
}else{
rc = SQLITE_IOERR; /* This should never happen */
}
}
if( locktype==NO_LOCK ){
struct openCnt *pOpen;
@ -1146,8 +1246,11 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0L;
fcntl(id->h, F_SETLK, &lock);
pLock->locktype = NO_LOCK;
if( fcntl(id->h, F_SETLK, &lock)==0 ){
pLock->locktype = NO_LOCK;
}else{
rc = SQLITE_IOERR; /* This should never happen */
}
}
/* Decrement the count of locks against this same file. When the
@ -1177,6 +1280,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
*/
int sqlite3OsClose(OsFile *id){
if( !id->isOpen ) return SQLITE_OK;
if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
sqlite3OsUnlock(id, NO_LOCK);
if( id->dirfd>=0 ) close(id->dirfd);
id->dirfd = -1;
@ -1189,13 +1293,13 @@ int sqlite3OsClose(OsFile *id){
*/
int *aNew;
struct openCnt *pOpen = id->pOpen;
pOpen->nPending++;
aNew = sqliteRealloc( pOpen->aPending, pOpen->nPending*sizeof(int) );
aNew = sqliteRealloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
if( aNew==0 ){
/* If a malloc fails, just leak the file descriptor */
}else{
pOpen->aPending = aNew;
pOpen->aPending[pOpen->nPending-1] = id->h;
pOpen->aPending[pOpen->nPending] = id->h;
pOpen->nPending++;
}
}else{
/* There are no outstanding locks so we can close the file immediately */
@ -1221,10 +1325,14 @@ char *sqlite3OsFullPathname(const char *zRelative){
if( zRelative[0]=='/' ){
sqlite3SetString(&zFull, zRelative, (char*)0);
}else{
char zBuf[5000];
char *zBuf = sqliteMalloc(5000);
if( zBuf==0 ){
return 0;
}
zBuf[0] = 0;
sqlite3SetString(&zFull, getcwd(zBuf, sizeof(zBuf)), "/", zRelative,
sqlite3SetString(&zFull, getcwd(zBuf, 5000), "/", zRelative,
(char*)0);
sqliteFree(zBuf);
}
return zFull;
}
@ -1331,9 +1439,16 @@ int sqlite3_current_time = 0;
** return 0. Return 1 if the time and date cannot be found.
*/
int sqlite3OsCurrentTime(double *prNow){
#ifdef NO_GETTOD
time_t t;
time(&t);
*prNow = t/86400.0 + 2440587.5;
#else
struct timeval sNow;
struct timezone sTz; /* Not used */
gettimeofday(&sNow, &sTz);
*prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_usec/86400000000.0;
#endif
#ifdef SQLITE_TEST
if( sqlite3_current_time ){
*prNow = sqlite3_current_time/86400.0 + 2440587.5;

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

@ -1,102 +0,0 @@
/*
** 2004 May 22
**
** 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 header file defined OS-specific features for Unix.
*/
#ifndef _SQLITE_OS_UNIX_H_
#define _SQLITE_OS_UNIX_H_
/*
** Helpful hint: To get this to compile on HP/UX, add -D_INCLUDE_POSIX_SOURCE
** to the compiler command line.
*/
/*
** These #defines should enable >2GB file support on Posix if the
** underlying operating system supports it. If the OS lacks
** large file support, or if the OS is windows, these should be no-ops.
**
** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
** on the compiler command line. This is necessary if you are compiling
** on a recent machine (ex: RedHat 7.2) but you want your code to work
** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2
** without this option, LFS is enable. But LFS does not exist in the kernel
** in RedHat 6.0, so the code won't work. Hence, for maximum binary
** portability you should omit LFS.
**
** Similar is true for MacOS. LFS is only supported on MacOS 9 and later.
*/
#ifndef SQLITE_DISABLE_LFS
# define _LARGE_FILE 1
# ifndef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 64
# endif
# define _LARGEFILE_SOURCE 1
#endif
/*
** standard include files.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/*
** The OsFile structure is a operating-system independing representation
** of an open file handle. It is defined differently for each architecture.
**
** This is the definition for Unix.
**
** OsFile.locktype takes one of the values SHARED_LOCK, RESERVED_LOCK,
** PENDING_LOCK or EXCLUSIVE_LOCK.
*/
typedef struct OsFile OsFile;
struct OsFile {
struct Pager *pPager; /* The pager that owns this OsFile. Might be 0 */
struct openCnt *pOpen; /* Info about all open fd's on this inode */
struct lockInfo *pLock; /* Info about locks on this inode */
int h; /* The file descriptor */
unsigned char locktype; /* The type of lock held on this fd */
unsigned char isOpen; /* True if needs to be closed */
unsigned char fullSync; /* Use F_FULLSYNC if available */
int dirfd; /* File descriptor for the directory */
};
/*
** A macro to set the OsFile.fullSync flag, if it exists.
*/
#define SET_FULLSYNC(x,y) ((x).fullSync = (y))
/*
** Maximum number of characters in a temporary file name
*/
#define SQLITE_TEMPNAME_SIZE 200
/*
** Minimum interval supported by sqlite3OsSleep().
*/
#if defined(HAVE_USLEEP) && HAVE_USLEEP
# define SQLITE_MIN_SLEEP_MS 1
#else
# 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_ */

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

@ -41,11 +41,99 @@
*/
#ifndef SQLITE_OMIT_DISKIO
/*
** The following variable is (normally) set once and never changes
** thereafter. It records whether the operating system is Win95
** or WinNT.
**
** 0: Operating system unknown.
** 1: Operating system is Win95.
** 2: Operating system is WinNT.
**
** In order to facilitate testing on a WinNT system, the test fixture
** can manually set this value to 1 to emulate Win98 behavior.
*/
int sqlite3_os_type = 0;
/*
** Return true (non-zero) if we are running under WinNT, Win2K or WinXP.
** Return false (zero) for Win95, Win98, or WinME.
**
** Here is an interesting observation: Win95, Win98, and WinME lack
** the LockFileEx() API. But we can still statically link against that
** API as long as we don't call it win running Win95/98/ME. A call to
** this routine is used to determine if the host is Win95/98/ME or
** WinNT/2K/XP so that we will know whether or not we can safely call
** the LockFileEx() API.
*/
static int isNT(void){
if( sqlite3_os_type==0 ){
OSVERSIONINFO sInfo;
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
GetVersionEx(&sInfo);
sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
}
return sqlite3_os_type==2;
}
/*
** Convert a UTF-8 string to UTF-32. Space to hold the returned string
** is obtained from sqliteMalloc.
*/
static WCHAR *utf8ToUnicode(const char *zFilename){
int nByte;
WCHAR *zWideFilename;
if( !isNT() ){
return 0;
}
nByte = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0)*sizeof(WCHAR);
zWideFilename = sqliteMalloc( nByte*sizeof(zWideFilename[0]) );
if( zWideFilename==0 ){
return 0;
}
nByte = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nByte);
if( nByte==0 ){
sqliteFree(zWideFilename);
zWideFilename = 0;
}
return zWideFilename;
}
/*
** Convert UTF-32 to UTF-8. Space to hold the returned string is
** obtained from sqliteMalloc().
*/
static char *unicodeToUtf8(const WCHAR *zWideFilename){
int nByte;
char *zFilename;
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
zFilename = sqliteMalloc( nByte );
if( zFilename==0 ){
return 0;
}
nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
0, 0);
if( nByte == 0 ){
sqliteFree(zFilename);
zFilename = 0;
}
return zFilename;
}
/*
** Delete the named file
*/
int sqlite3OsDelete(const char *zFilename){
DeleteFileA(zFilename);
WCHAR *zWide = utf8ToUnicode(zFilename);
if( zWide ){
DeleteFileW(zWide);
sqliteFree(zWide);
}else{
DeleteFileA(zFilename);
}
TRACE2("DELETE \"%s\"\n", zFilename);
return SQLITE_OK;
}
@ -54,7 +142,15 @@ int sqlite3OsDelete(const char *zFilename){
** Return TRUE if the named file exists.
*/
int sqlite3OsFileExists(const char *zFilename){
return GetFileAttributesA(zFilename) != 0xffffffff;
int exists = 0;
WCHAR *zWide = utf8ToUnicode(zFilename);
if( zWide ){
exists = GetFileAttributesW(zWide) != 0xffffffff;
sqliteFree(zWide);
}else{
exists = GetFileAttributesA(zFilename) != 0xffffffff;
}
return exists;
}
/*
@ -76,30 +172,60 @@ int sqlite3OsOpenReadWrite(
int *pReadonly
){
HANDLE h;
WCHAR *zWide = utf8ToUnicode(zFilename);
assert( !id->isOpen );
h = CreateFileA(zFilename,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h==INVALID_HANDLE_VALUE ){
h = CreateFileA(zFilename,
GENERIC_READ,
FILE_SHARE_READ,
if( zWide ){
h = CreateFileW(zWide,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h==INVALID_HANDLE_VALUE ){
return SQLITE_CANTOPEN;
h = CreateFileW(zWide,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h==INVALID_HANDLE_VALUE ){
sqliteFree(zWide);
return SQLITE_CANTOPEN;
}
*pReadonly = 1;
}else{
*pReadonly = 0;
}
*pReadonly = 1;
sqliteFree(zWide);
}else{
*pReadonly = 0;
h = CreateFileA(zFilename,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h==INVALID_HANDLE_VALUE ){
h = CreateFileA(zFilename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h==INVALID_HANDLE_VALUE ){
return SQLITE_CANTOPEN;
}
*pReadonly = 1;
}else{
*pReadonly = 0;
}
}
id->h = h;
id->locktype = NO_LOCK;
@ -128,6 +254,7 @@ int sqlite3OsOpenReadWrite(
int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
HANDLE h;
int fileflags;
WCHAR *zWide = utf8ToUnicode(zFilename);
assert( !id->isOpen );
if( delFlag ){
fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS
@ -135,14 +262,26 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
}else{
fileflags = FILE_FLAG_RANDOM_ACCESS;
}
h = CreateFileA(zFilename,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
fileflags,
NULL
);
if( zWide ){
h = CreateFileW(zWide,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
fileflags,
NULL
);
sqliteFree(zWide);
}else{
h = CreateFileA(zFilename,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
fileflags,
NULL
);
}
if( h==INVALID_HANDLE_VALUE ){
return SQLITE_CANTOPEN;
}
@ -164,15 +303,28 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
*/
int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){
HANDLE h;
WCHAR *zWide = utf8ToUnicode(zFilename);
assert( !id->isOpen );
h = CreateFileA(zFilename,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( zWide ){
h = CreateFileW(zWide,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
sqliteFree(zWide);
}else{
h = CreateFileA(zFilename,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
}
if( h==INVALID_HANDLE_VALUE ){
return SQLITE_CANTOPEN;
}
@ -229,6 +381,16 @@ int sqlite3OsTempFileName(char *zBuf){
if( sqlite3_temp_directory ){
strncpy(zTempPath, sqlite3_temp_directory, SQLITE_TEMPNAME_SIZE-30);
zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
}else if( isNT() ){
char *zMulti;
WCHAR zWidePath[SQLITE_TEMPNAME_SIZE];
GetTempPathW(SQLITE_TEMPNAME_SIZE-30, zWidePath);
zMulti = unicodeToUtf8(zWidePath);
if( zMulti ){
strncpy(zTempPath, zMulti, SQLITE_TEMPNAME_SIZE-30);
zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
sqliteFree(zMulti);
}
}else{
GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zTempPath);
}
@ -303,6 +465,13 @@ int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
return SQLITE_OK;
}
/*
** Some microsoft compilers lack this definition.
*/
#ifndef INVALID_SET_FILE_POINTER
# define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif
/*
** Move the read/write pointer in a file.
*/
@ -311,16 +480,22 @@ int sqlite3OsSeek(OsFile *id, i64 offset){
LONG lowerBits = offset & 0xffffffff;
DWORD rc;
assert( id->isOpen );
#ifdef SQLITE_TEST
if( offset ) SimulateDiskfullError
#endif
SEEK(offset/1024 + 1);
rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN);
TRACE3("SEEK %d %lld\n", id->h, offset);
if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){
return SQLITE_FULL;
}
return SQLITE_OK;
}
/*
** Make sure all writes to a particular file are committed to disk.
*/
int sqlite3OsSync(OsFile *id){
int sqlite3OsSync(OsFile *id, int dataOnly){
assert( id->isOpen );
TRACE3("SYNC %d lock=%d\n", id->h, id->locktype);
if( FlushFileBuffers(id->h) ){
@ -364,28 +539,6 @@ int sqlite3OsFileSize(OsFile *id, i64 *pSize){
return SQLITE_OK;
}
/*
** Return true (non-zero) if we are running under WinNT, Win2K or WinXP.
** Return false (zero) for Win95, Win98, or WinME.
**
** Here is an interesting observation: Win95, Win98, and WinME lack
** the LockFileEx() API. But we can still statically link against that
** API as long as we don't call it win running Win95/98/ME. A call to
** this routine is used to determine if the host is Win95/98/ME or
** WinNT/2K/XP so that we will know whether or not we can safely call
** the LockFileEx() API.
*/
static int isNT(void){
static int osType = 0; /* 0=unknown 1=win95 2=winNT */
if( osType==0 ){
OSVERSIONINFO sInfo;
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
GetVersionEx(&sInfo);
osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
}
return osType==2;
}
/*
** Acquire a reader lock.
** Different API routines are called depending on whether or not this
@ -426,11 +579,18 @@ static int unlockReadLock(OsFile *id){
** Check that a given pathname is a directory and is writable
**
*/
int sqlite3OsIsDirWritable(char *zBuf){
int sqlite3OsIsDirWritable(char *zDirname){
int fileAttr;
if(! zBuf ) return 0;
if(! isNT() && strlen(zBuf) > MAX_PATH ) return 0;
fileAttr = GetFileAttributesA(zBuf);
WCHAR *zWide;
if( zDirname==0 ) return 0;
if( !isNT() && strlen(zDirname)>MAX_PATH ) return 0;
zWide = utf8ToUnicode(zDirname);
if( zWide ){
fileAttr = GetFileAttributesW(zWide);
sqliteFree(zWide);
}else{
fileAttr = GetFileAttributesA(zDirname);
}
if( fileAttr == 0xffffffff ) return 0;
if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){
return 0;
@ -641,6 +801,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
char *sqlite3OsFullPathname(const char *zRelative){
char *zNotUsed;
char *zFull;
WCHAR *zWide;
int nByte;
#ifdef __CYGWIN__
nByte = strlen(zRelative) + MAX_PATH + 1001;
@ -648,10 +809,22 @@ char *sqlite3OsFullPathname(const char *zRelative){
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);
zWide = utf8ToUnicode(zRelative);
if( zWide ){
WCHAR *zTemp, *zNotUsedW;
nByte = GetFullPathNameW(zWide, 0, 0, &zNotUsedW) + 1;
zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) );
if( zTemp==0 ) return 0;
GetFullPathNameW(zWide, nByte, zTemp, &zNotUsedW);
sqliteFree(zWide);
zFull = unicodeToUtf8(zTemp);
sqliteFree(zTemp);
}else{
nByte = GetFullPathNameA(zRelative, 0, 0, &zNotUsed) + 1;
zFull = sqliteMalloc( nByte*sizeof(zFull[0]) );
if( zFull==0 ) return 0;
GetFullPathNameA(zRelative, nByte, zFull, &zNotUsed);
}
#endif
return zFull;
}

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

@ -18,7 +18,7 @@
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.207 2005/06/07 02:12:30 drh Exp $
** @(#) $Id: pager.c,v 1.215 2005/09/17 15:20:27 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
@ -657,8 +657,10 @@ static int writeJournalHdr(Pager *pPager){
** file descriptor to the end of the journal header sector.
*/
if( rc==SQLITE_OK ){
sqlite3OsSeek(&pPager->jfd, pPager->journalOff-1);
rc = sqlite3OsWrite(&pPager->jfd, "\000", 1);
rc = sqlite3OsSeek(&pPager->jfd, pPager->journalOff-1);
if( rc==SQLITE_OK ){
rc = sqlite3OsWrite(&pPager->jfd, "\000", 1);
}
}
return rc;
}
@ -779,7 +781,7 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3OsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic));
pPager->needSync = 1;
pPager->needSync = !pPager->noSync;
return rc;
}
@ -1038,8 +1040,10 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
assert( pPager->state>=PAGER_EXCLUSIVE || pPg!=0 );
TRACE3("PLAYBACK %d page %d\n", PAGERID(pPager), pgno);
if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0) ){
sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize);
rc = sqlite3OsWrite(&pPager->fd, aData, pPager->pageSize);
rc = sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize);
if( rc==SQLITE_OK ){
rc = sqlite3OsWrite(&pPager->fd, aData, pPager->pageSize);
}
if( pPg ) pPg->dirty = 0;
}
if( pPg ){
@ -1168,8 +1172,10 @@ static int pager_reload_cache(Pager *pPager){
char zBuf[SQLITE_MAX_PAGE_SIZE];
if( !pPg->dirty ) continue;
if( (int)pPg->pgno <= pPager->origDbSize ){
sqlite3OsSeek(&pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1));
rc = sqlite3OsRead(&pPager->fd, zBuf, pPager->pageSize);
rc = sqlite3OsSeek(&pPager->fd, pPager->pageSize*(i64)(pPg->pgno-1));
if( rc==SQLITE_OK ){
rc = sqlite3OsRead(&pPager->fd, zBuf, pPager->pageSize);
}
TRACE3("REFETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
if( rc ) break;
CODEC(pPager, zBuf, pPg->pgno, 2);
@ -1485,7 +1491,7 @@ static int pager_stmt_playback(Pager *pPager){
end_stmt_playback:
if( rc!=SQLITE_OK ){
pPager->errMask |= PAGER_ERR_CORRUPT;
rc = SQLITE_CORRUPT; /* bkpt-CORRUPT */
rc = SQLITE_CORRUPT;
}else{
pPager->journalOff = szJ;
/* pager_reload_cache(pPager); */
@ -1746,25 +1752,35 @@ void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){
/*
** Return the total number of pages in the disk file associated with
** pPager.
** pPager.
**
** If the PENDING_BYTE lies on the page directly after the end of the
** file, then consider this page part of the file too. For example, if
** PENDING_BYTE is byte 4096 (the first byte of page 5) and the size of the
** file is 4096 bytes, 5 is returned instead of 4.
*/
int sqlite3pager_pagecount(Pager *pPager){
i64 n;
assert( pPager!=0 );
if( pPager->dbSize>=0 ){
return pPager->dbSize;
n = pPager->dbSize;
} else {
if( sqlite3OsFileSize(&pPager->fd, &n)!=SQLITE_OK ){
pPager->errMask |= PAGER_ERR_DISK;
return 0;
}
if( n>0 && n<pPager->pageSize ){
n = 1;
}else{
n /= pPager->pageSize;
}
if( pPager->state!=PAGER_UNLOCK ){
pPager->dbSize = n;
}
}
if( sqlite3OsFileSize(&pPager->fd, &n)!=SQLITE_OK ){
pPager->errMask |= PAGER_ERR_DISK;
return 0;
}
n /= pPager->pageSize;
if( !MEMDB && n==PENDING_BYTE/pPager->pageSize ){
if( n==(PENDING_BYTE/pPager->pageSize) ){
n++;
}
if( pPager->state!=PAGER_UNLOCK ){
pPager->dbSize = n;
}
return n;
}
@ -1866,7 +1882,7 @@ static void memoryTruncate(Pager *pPager){
/*
** Try to obtain a lock on a file. Invoke the busy callback if the lock
** is currently not available. Repeate until the busy callback returns
** is currently not available. Repeat until the busy callback returns
** false or until the lock succeeds.
**
** Return SQLITE_OK on success and an error code if we cannot obtain
@ -1880,14 +1896,9 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
if( pPager->state>=locktype ){
rc = SQLITE_OK;
}else{
int busy = 1;
BusyHandler *pH;
do {
rc = sqlite3OsLock(&pPager->fd, locktype);
}while( rc==SQLITE_BUSY &&
(pH = pPager->pBusyHandler)!=0 &&
pH->xFunc && pH->xFunc(pH->pArg, busy++)
);
}while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) );
if( rc==SQLITE_OK ){
pPager->state = locktype;
}
@ -2122,17 +2133,20 @@ static int syncJournal(Pager *pPager){
*/
if( pPager->fullSync ){
TRACE2("SYNC journal of %d\n", PAGERID(pPager));
rc = sqlite3OsSync(&pPager->jfd);
rc = sqlite3OsSync(&pPager->jfd, 0);
if( rc!=0 ) return rc;
}
sqlite3OsSeek(&pPager->jfd, pPager->journalHdr + sizeof(aJournalMagic));
rc = sqlite3OsSeek(&pPager->jfd,
pPager->journalHdr + sizeof(aJournalMagic));
if( rc ) return rc;
rc = write32bits(&pPager->jfd, pPager->nRec);
if( rc ) return rc;
sqlite3OsSeek(&pPager->jfd, pPager->journalOff);
rc = sqlite3OsSeek(&pPager->jfd, pPager->journalOff);
if( rc ) return rc;
}
TRACE2("SYNC journal of %d\n", PAGERID(pPager));
rc = sqlite3OsSync(&pPager->jfd);
rc = sqlite3OsSync(&pPager->jfd, pPager->fullSync);
if( rc!=0 ) return rc;
pPager->journalStarted = 1;
}
@ -2197,7 +2211,8 @@ static int pager_write_pagelist(PgHdr *pList){
while( pList ){
assert( pList->dirty );
sqlite3OsSeek(&pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize);
rc = sqlite3OsSeek(&pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize);
if( rc ) return rc;
/* If there are dirty pages in the page cache with page numbers greater
** than Pager.dbSize, this means sqlite3pager_truncate() was called to
** make the file smaller (presumably by auto-vacuum code). Do not write
@ -2292,8 +2307,8 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
/* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
** number greater than this, or zero, is requested.
*/
if( pgno>PAGER_MAX_PGNO || pgno==0 ){
return SQLITE_CORRUPT;
if( pgno>PAGER_MAX_PGNO || pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
return SQLITE_CORRUPT_BKPT;
}
/* Make sure we have not hit any critical errors.
@ -2507,8 +2522,10 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
}else{
int rc;
assert( MEMDB==0 );
sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize);
rc = sqlite3OsRead(&pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize);
rc = sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize);
if( rc==SQLITE_OK ){
rc = sqlite3OsRead(&pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize);
}
TRACE3("FETCH %d page %d\n", PAGERID(pPager), pPg->pgno);
CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
if( rc!=SQLITE_OK ){
@ -2816,6 +2833,10 @@ int sqlite3pager_write(void *pData){
}
}else{
u32 cksum;
/* We should never write to the journal file the page that
** contains the database locks. The following assert verifies
** that we do not. */
assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
CODEC(pPager, pData, pPg->pgno, 7);
cksum = pager_cksum(pPager, pPg->pgno, pData);
saved = *(u32*)PGHDR_TO_EXTRA(pPg, pPager);
@ -3172,7 +3193,7 @@ int sqlite3pager_rollback(Pager *pPager){
rc = pager_playback(pPager);
}
if( rc!=SQLITE_OK ){
rc = SQLITE_CORRUPT; /* bkpt-CORRUPT */
rc = SQLITE_CORRUPT_BKPT;
pPager->errMask |= PAGER_ERR_CORRUPT;
}
pPager->dbSize = -1;
@ -3346,6 +3367,14 @@ const char *sqlite3pager_journalname(Pager *pPager){
return pPager->zJournal;
}
/*
** Return true if fsync() calls are disabled for this pager. Return FALSE
** if fsync()s are executed normally.
*/
int sqlite3pager_nosync(Pager *pPager){
return pPager->noSync;
}
/*
** Set the codec for this pager
*/
@ -3434,8 +3463,9 @@ int sqlite3pager_sync(Pager *pPager, const char *zMaster, Pgno nTrunc){
*/
Pgno i;
void *pPage;
int iSkip = PAGER_MJ_PGNO(pPager);
for( i=nTrunc+1; i<=pPager->origDbSize; i++ ){
if( !(pPager->aInJournal[i/8] & (1<<(i&7))) ){
if( !(pPager->aInJournal[i/8] & (1<<(i&7))) && i!=iSkip ){
rc = sqlite3pager_get(pPager, i, &pPage);
if( rc!=SQLITE_OK ) goto sync_exit;
rc = sqlite3pager_write(pPage);
@ -3465,7 +3495,7 @@ int sqlite3pager_sync(Pager *pPager, const char *zMaster, Pgno nTrunc){
/* Sync the database file. */
if( !pPager->noSync ){
rc = sqlite3OsSync(&pPager->fd);
rc = sqlite3OsSync(&pPager->fd, 0);
}
pPager->state = PAGER_SYNCED;

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

@ -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.44 2005/05/20 20:01:56 drh Exp $
** @(#) $Id: pager.h,v 1.46 2005/09/19 19:05:21 drh Exp $
*/
/*
@ -34,7 +34,7 @@
** reasonable, like 1024.
*/
#ifndef SQLITE_MAX_PAGE_SIZE
# define SQLITE_MAX_PAGE_SIZE 8192
# define SQLITE_MAX_PAGE_SIZE 32768
#endif
/*
@ -100,6 +100,7 @@ void sqlite3pager_set_safety_level(Pager*,int);
const char *sqlite3pager_filename(Pager*);
const char *sqlite3pager_dirname(Pager*);
const char *sqlite3pager_journalname(Pager*);
int sqlite3pager_nosync(Pager*);
int sqlite3pager_rename(Pager*, const char *zNewName);
void sqlite3pager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*);
int sqlite3pager_movepage(Pager*,void*,Pgno);

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

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

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

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

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.95 2005/06/12 21:35:52 drh Exp $
** $Id: pragma.c,v 1.100 2005/09/20 17:42:23 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -583,12 +583,13 @@ void sqlite3Pragma(
while(pFK){
int j;
for(j=0; j<pFK->nCol; j++){
char *zCol = pFK->aCol[j].zCol;
sqlite3VdbeAddOp(v, OP_Integer, i, 0);
sqlite3VdbeAddOp(v, OP_Integer, j, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pFK->zTo, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0,
pTab->aCol[pFK->aCol[j].iFrom].zName, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pFK->aCol[j].zCol, 0);
sqlite3VdbeOp3(v, zCol ? OP_String8 : OP_Null, 0, 0, zCol, 0);
sqlite3VdbeAddOp(v, OP_Callback, 5, 0);
}
++i;
@ -602,26 +603,29 @@ void sqlite3Pragma(
#ifndef NDEBUG
if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
extern void sqlite3ParserTrace(FILE*, char *);
if( getBoolean(zRight) ){
sqlite3ParserTrace(stdout, "parser: ");
}else{
sqlite3ParserTrace(0, 0);
if( zRight ){
if( getBoolean(zRight) ){
sqlite3ParserTrace(stderr, "parser: ");
}else{
sqlite3ParserTrace(0, 0);
}
}
}else
#endif
/* Reinstall the LIKE and GLOB functions. The variant of LIKE
** used will be case sensitive or not depending on the RHS.
*/
if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){
if( zRight ){
sqlite3RegisterLikeFunctions(db, getBoolean(zRight));
}
}else
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){
int i, j, addr;
/* Code that initializes the integrity check program. Set the
** error count 0
*/
static const VdbeOpList initCode[] = {
{ OP_Integer, 0, 0, 0},
{ OP_MemStore, 0, 1, 0},
};
/* Code that appears at the end of the integrity check. If no error
** messages have been generated, output OK. Otherwise output the
** error message
@ -638,7 +642,7 @@ void sqlite3Pragma(
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, "integrity_check", P3_STATIC);
sqlite3VdbeAddOpList(v, ArraySize(initCode), initCode);
sqlite3VdbeAddOp(v, OP_MemInt, 0, 0); /* Initialize error count to 0 */
/* Do an integrity check on each database file */
for(i=0; i<db->nDb; i++){
@ -684,8 +688,7 @@ void sqlite3Pragma(
if( pTab->pIndex==0 ) continue;
sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead);
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
sqlite3VdbeAddOp(v, OP_MemStore, 1, 1);
sqlite3VdbeAddOp(v, OP_MemInt, 0, 1);
loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0);
sqlite3VdbeAddOp(v, OP_MemIncr, 1, 0);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
@ -703,39 +706,38 @@ void sqlite3Pragma(
jmp2 = sqlite3VdbeAddOp(v, OP_Found, j+2, 0);
addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
sqlite3VdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC);
sqlite3VdbeChangeP2(v, jmp2, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeJumpHere(v, jmp2);
}
sqlite3VdbeAddOp(v, OP_Next, 1, loopTop+1);
sqlite3VdbeChangeP2(v, loopTop, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeJumpHere(v, loopTop);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
static const VdbeOpList cntIdx[] = {
{ OP_Integer, 0, 0, 0},
{ OP_MemStore, 2, 1, 0},
{ OP_Rewind, 0, 0, 0}, /* 2 */
{ OP_MemInt, 0, 2, 0},
{ OP_Rewind, 0, 0, 0}, /* 1 */
{ OP_MemIncr, 2, 0, 0},
{ OP_Next, 0, 0, 0}, /* 4 */
{ OP_Next, 0, 0, 0}, /* 3 */
{ OP_MemLoad, 1, 0, 0},
{ OP_MemLoad, 2, 0, 0},
{ OP_Eq, 0, 0, 0}, /* 7 */
{ OP_Eq, 0, 0, 0}, /* 6 */
{ OP_MemIncr, 0, 0, 0},
{ OP_String8, 0, 0, "wrong # of entries in index "},
{ OP_String8, 0, 0, 0}, /* 10 */
{ OP_String8, 0, 0, 0}, /* 9 */
{ OP_Concat, 0, 0, 0},
{ OP_Callback, 1, 0, 0},
};
if( pIdx->tnum==0 ) continue;
addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
sqlite3VdbeChangeP1(v, addr+2, j+2);
sqlite3VdbeChangeP2(v, addr+2, addr+5);
sqlite3VdbeChangeP1(v, addr+4, j+2);
sqlite3VdbeChangeP2(v, addr+4, addr+3);
sqlite3VdbeChangeP2(v, addr+7, addr+ArraySize(cntIdx));
sqlite3VdbeChangeP3(v, addr+10, pIdx->zName, P3_STATIC);
sqlite3VdbeChangeP1(v, addr+1, j+2);
sqlite3VdbeChangeP2(v, addr+1, addr+4);
sqlite3VdbeChangeP1(v, addr+3, j+2);
sqlite3VdbeChangeP2(v, addr+3, addr+2);
sqlite3VdbeJumpHere(v, addr+6);
sqlite3VdbeChangeP3(v, addr+9, pIdx->zName, P3_STATIC);
}
}
}
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
sqlite3VdbeChangeP2(v, addr+2, addr+ArraySize(endCode));
sqlite3VdbeJumpHere(v, addr+2);
}else
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
@ -891,13 +893,13 @@ void sqlite3Pragma(
Btree *pBt;
Pager *pPager;
if( db->aDb[i].zName==0 ) continue;
sqlite3VdbeOp3(v, OP_String, 0, 0, db->aDb[i].zName, P3_STATIC);
sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, P3_STATIC);
pBt = db->aDb[i].pBt;
if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){
sqlite3VdbeOp3(v, OP_String, 0, 0, "closed", P3_STATIC);
sqlite3VdbeOp3(v, OP_String8, 0, 0, "closed", P3_STATIC);
}else{
int j = sqlite3pager_lockstate(pPager);
sqlite3VdbeOp3(v, OP_String, 0, 0,
sqlite3VdbeOp3(v, OP_String8, 0, 0,
(j>=0 && j<=4) ? azLockName[j] : "unknown", P3_STATIC);
}
sqlite3VdbeAddOp(v, OP_Callback, 2, 0);

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

@ -13,7 +13,7 @@
** 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 $
** $Id: prepare.c,v 1.2 2005-12-13 19:49:35 vladimir%pobox.com Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -294,6 +294,11 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
sqlite3SafetyOn(db);
sqliteFree(zSql);
#ifndef SQLITE_OMIT_ANALYZE
if( rc==SQLITE_OK ){
sqlite3AnalysisLoad(db, iDb);
}
#endif
sqlite3BtreeCloseCursor(curMain);
}
if( sqlite3_malloc_failed ){
@ -370,7 +375,7 @@ int sqlite3ReadSchema(Parse *pParse){
rc = sqlite3Init(db, &pParse->zErrMsg);
}
}
assert( rc!=SQLITE_OK || (db->flags & SQLITE_Initialized)||db->init.busy );
assert( rc!=SQLITE_OK || (db->flags & SQLITE_Initialized) || db->init.busy );
if( rc!=SQLITE_OK ){
pParse->rc = rc;
pParse->nErr++;
@ -453,12 +458,19 @@ int sqlite3_prepare(
#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);
if( sParse.explain==2 ){
sqlite3VdbeSetNumCols(sParse.pVdbe, 3);
sqlite3VdbeSetColName(sParse.pVdbe, 0, "order", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 1, "from", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 2, "detail", P3_STATIC);
}else{
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
@ -526,4 +538,3 @@ int sqlite3_prepare16(
return rc;
}
#endif /* SQLITE_OMIT_UTF16 */

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

@ -111,6 +111,7 @@ static const char aPrefix[] = "-x0\000X0";
static const et_info fmtinfo[] = {
{ 'd', 10, 1, etRADIX, 0, 0 },
{ 's', 0, 4, etSTRING, 0, 0 },
{ 'g', 0, 1, etGENERIC, 30, 0 },
{ 'z', 0, 6, etDYNSTRING, 0, 0 },
{ 'q', 0, 4, etSQLESCAPE, 0, 0 },
{ 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
@ -122,7 +123,6 @@ static const et_info fmtinfo[] = {
{ 'f', 0, 1, etFLOAT, 0, 0 },
{ 'e', 0, 1, etEXP, 30, 0 },
{ 'E', 0, 1, etEXP, 14, 0 },
{ 'g', 0, 1, etGENERIC, 30, 0 },
{ 'G', 0, 1, etGENERIC, 14, 0 },
{ 'i', 10, 1, etRADIX, 0, 0 },
{ 'n', 0, 0, etSIZE, 0, 0 },
@ -163,7 +163,15 @@ static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
}
#endif
#define etBUFSIZE 1000 /* Size of the output buffer */
/*
** On machines with a small stack size, you can redefine the
** SQLITE_PRINT_BUF_SIZE to be less than 350. But beware - for
** smaller values some %f conversions may go into an infinite loop.
*/
#ifndef SQLITE_PRINT_BUF_SIZE
# define SQLITE_PRINT_BUF_SIZE 350
#endif
#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
/*
** The root program. All variations call this core.
@ -210,9 +218,11 @@ static int vxprintf(
etByte flag_plussign; /* True if "+" flag is present */
etByte flag_blanksign; /* True if " " flag is present */
etByte flag_alternateform; /* True if "#" flag is present */
etByte flag_altform2; /* True if "!" flag is present */
etByte flag_zeropad; /* True if field width constant starts with zero */
etByte flag_long; /* True if "l" flag is present */
etByte flag_longlong; /* True if the "ll" flag is present */
etByte done; /* Loop termination flag */
UINT64_TYPE longvalue; /* Value for integer types */
LONGDOUBLE_TYPE realvalue; /* Value for real types */
const et_info *infop; /* Pointer to the appropriate info structure */
@ -225,7 +235,7 @@ static int vxprintf(
" ";
#define etSPACESIZE (sizeof(spaces)-1)
#ifndef etNOFLOATINGPOINT
int exp; /* exponent of real numbers */
int exp, e2; /* exponent of real numbers */
double rounder; /* Used for rounding floating point values */
etByte flag_dp; /* True if decimal point should be shown */
etByte flag_rtz; /* True if trailing zeros should be removed */
@ -254,17 +264,19 @@ static int vxprintf(
}
/* Find out what flags are present */
flag_leftjustify = flag_plussign = flag_blanksign =
flag_alternateform = flag_zeropad = 0;
flag_alternateform = flag_altform2 = flag_zeropad = 0;
done = 0;
do{
switch( c ){
case '-': flag_leftjustify = 1; c = 0; break;
case '+': flag_plussign = 1; c = 0; break;
case ' ': flag_blanksign = 1; c = 0; break;
case '#': flag_alternateform = 1; c = 0; break;
case '0': flag_zeropad = 1; c = 0; break;
default: break;
case '-': flag_leftjustify = 1; break;
case '+': flag_plussign = 1; break;
case ' ': flag_blanksign = 1; break;
case '#': flag_alternateform = 1; break;
case '!': flag_altform2 = 1; break;
case '0': flag_zeropad = 1; break;
default: done = 1; break;
}
}while( c==0 && (c=(*++fmt))!=0 );
}while( !done && (c=(*++fmt))!=0 );
/* Get the field width */
width = 0;
if( c=='*' ){
@ -336,6 +348,7 @@ static int vxprintf(
** At this point, variables are initialized as follows:
**
** flag_alternateform TRUE if a '#' is present.
** flag_altform2 TRUE if a '!' is present.
** flag_plussign TRUE if a '+' is present.
** flag_leftjustify TRUE if a '-' is present or if the
** field width was negative.
@ -414,7 +427,7 @@ static int vxprintf(
realvalue = va_arg(ap,double);
#ifndef etNOFLOATINGPOINT
if( precision<0 ) precision = 6; /* Set default precision */
if( precision>etBUFSIZE-10 ) precision = etBUFSIZE-10;
if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10;
if( realvalue<0.0 ){
realvalue = -realvalue;
prefix = '-';
@ -423,8 +436,7 @@ static int vxprintf(
else if( flag_blanksign ) prefix = ' ';
else prefix = 0;
}
if( infop->type==etGENERIC && precision>0 ) precision--;
rounder = 0.0;
if( xtype==etGENERIC && precision>0 ) precision--;
#if 0
/* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
@ -432,10 +444,11 @@ static int vxprintf(
/* It makes more sense to use 0.5 */
for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1);
#endif
if( infop->type==etFLOAT ) realvalue += rounder;
if( xtype==etFLOAT ) realvalue += rounder;
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
exp = 0;
if( realvalue>0.0 ){
while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; }
@ -467,51 +480,67 @@ static int vxprintf(
}else{
flag_rtz = 0;
}
/*
** The "exp+precision" test causes output to be of type etEXP if
** the precision is too large to fit in buf[].
*/
if( xtype==etEXP ){
e2 = 0;
}else{
e2 = exp;
}
nsd = 0;
if( xtype==etFLOAT && exp+precision<etBUFSIZE-30 ){
flag_dp = (precision>0 || flag_alternateform);
if( prefix ) *(bufpt++) = prefix; /* Sign */
if( exp<0 ) *(bufpt++) = '0'; /* Digits before "." */
else for(; exp>=0; exp--) *(bufpt++) = et_getdigit(&realvalue,&nsd);
if( flag_dp ) *(bufpt++) = '.'; /* The decimal point */
for(exp++; exp<0 && precision>0; precision--, exp++){
*(bufpt++) = '0';
}
while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd);
*(bufpt--) = 0; /* Null terminate */
if( flag_rtz && flag_dp ){ /* Remove trailing zeros and "." */
while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
}
bufpt++; /* point to next free slot */
}else{ /* etEXP or etGENERIC */
flag_dp = (precision>0 || flag_alternateform);
if( prefix ) *(bufpt++) = prefix; /* Sign */
*(bufpt++) = et_getdigit(&realvalue,&nsd); /* First digit */
if( flag_dp ) *(bufpt++) = '.'; /* Decimal point */
while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd);
bufpt--; /* point to last digit */
if( flag_rtz && flag_dp ){ /* Remove tail zeros */
while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
}
bufpt++; /* point to next free slot */
if( exp || flag_exp ){
*(bufpt++) = aDigits[infop->charset];
if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */
else { *(bufpt++) = '+'; }
if( exp>=100 ){
*(bufpt++) = (exp/100)+'0'; /* 100's digit */
exp %= 100;
}
*(bufpt++) = exp/10+'0'; /* 10's digit */
*(bufpt++) = exp%10+'0'; /* 1's digit */
flag_dp = (precision>0) | flag_alternateform | flag_altform2;
/* The sign in front of the number */
if( prefix ){
*(bufpt++) = prefix;
}
/* Digits prior to the decimal point */
if( e2<0 ){
*(bufpt++) = '0';
}else{
for(; e2>=0; e2--){
*(bufpt++) = et_getdigit(&realvalue,&nsd);
}
}
/* The decimal point */
if( flag_dp ){
*(bufpt++) = '.';
}
/* "0" digits after the decimal point but before the first
** significant digit of the number */
for(e2++; e2<0 && precision>0; precision--, e2++){
*(bufpt++) = '0';
}
/* Significant digits after the decimal point */
while( (precision--)>0 ){
*(bufpt++) = et_getdigit(&realvalue,&nsd);
}
/* Remove trailing zeros and the "." if no digits follow the "." */
if( flag_rtz && flag_dp ){
while( bufpt[-1]=='0' ) *(--bufpt) = 0;
assert( bufpt>buf );
if( bufpt[-1]=='.' ){
if( flag_altform2 ){
*(bufpt++) = '0';
}else{
*(--bufpt) = 0;
}
}
}
/* Add the "eNNN" suffix */
if( flag_exp || (xtype==etEXP && exp) ){
*(bufpt++) = aDigits[infop->charset];
if( exp<0 ){
*(bufpt++) = '-'; exp = -exp;
}else{
*(bufpt++) = '+';
}
if( exp>=100 ){
*(bufpt++) = (exp/100)+'0'; /* 100's digit */
exp %= 100;
}
*(bufpt++) = exp/10+'0'; /* 10's digit */
*(bufpt++) = exp%10+'0'; /* 1's digit */
}
*bufpt = 0;
/* The converted number is in buf[] and zero terminated. Output it.
** Note that the number is in the usual order, not reversed as with
** integer conversions. */
@ -564,36 +593,35 @@ static int vxprintf(
if( precision>=0 && precision<length ) length = precision;
break;
case etSQLESCAPE:
case etSQLESCAPE2:
{
int i, j, n, c, isnull;
int needQuote;
char *arg = va_arg(ap,char*);
isnull = arg==0;
if( isnull ) arg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
for(i=n=0; (c=arg[i])!=0; i++){
if( c=='\'' ) n++;
}
needQuote = !isnull && xtype==etSQLESCAPE2;
n += i + 1 + needQuote*2;
if( n>etBUFSIZE ){
bufpt = zExtra = sqliteMalloc( n );
if( bufpt==0 ) return -1;
}else{
bufpt = buf;
}
j = 0;
if( needQuote ) bufpt[j++] = '\'';
for(i=0; (c=arg[i])!=0; i++){
bufpt[j++] = c;
if( c=='\'' ) bufpt[j++] = c;
}
if( needQuote ) bufpt[j++] = '\'';
bufpt[j] = 0;
length = j;
if( precision>=0 && precision<length ) length = precision;
case etSQLESCAPE2: {
int i, j, n, c, isnull;
int needQuote;
char *arg = va_arg(ap,char*);
isnull = arg==0;
if( isnull ) arg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
for(i=n=0; (c=arg[i])!=0; i++){
if( c=='\'' ) n++;
}
needQuote = !isnull && xtype==etSQLESCAPE2;
n += i + 1 + needQuote*2;
if( n>etBUFSIZE ){
bufpt = zExtra = sqliteMalloc( n );
if( bufpt==0 ) return -1;
}else{
bufpt = buf;
}
j = 0;
if( needQuote ) bufpt[j++] = '\'';
for(i=0; (c=arg[i])!=0; i++){
bufpt[j++] = c;
if( c=='\'' ) bufpt[j++] = c;
}
if( needQuote ) bufpt[j++] = '\'';
bufpt[j] = 0;
length = j;
if( precision>=0 && precision<length ) length = precision;
break;
}
case etTOKEN: {
Token *pToken = va_arg(ap, Token*);
if( pToken && pToken->z ){
@ -698,7 +726,11 @@ static void mout(void *arg, const char *zNewText, int nNewChar){
memcpy(pM->zText, pM->zBase, pM->nChar);
}
}else{
pM->zText = pM->xRealloc(pM->zText, pM->nAlloc);
char *zNew;
zNew = pM->xRealloc(pM->zText, pM->nAlloc);
if( zNew ){
pM->zText = zNew;
}
}
}
}
@ -736,7 +768,10 @@ static char *base_vprintf(
memcpy(sM.zText, sM.zBase, sM.nChar+1);
}
}else if( sM.nAlloc>sM.nChar+10 ){
sM.zText = xRealloc(sM.zText, sM.nChar+1);
char *zNew = xRealloc(sM.zText, sM.nChar+1);
if( zNew ){
sM.zText = zNew;
}
}
}
return sM.zText;
@ -754,7 +789,7 @@ static void *printf_realloc(void *old, int size){
** %-conversion extensions.
*/
char *sqlite3VMPrintf(const char *zFormat, va_list ap){
char zBase[1000];
char zBase[SQLITE_PRINT_BUF_SIZE];
return base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
}
@ -765,7 +800,7 @@ char *sqlite3VMPrintf(const char *zFormat, va_list ap){
char *sqlite3MPrintf(const char *zFormat, ...){
va_list ap;
char *z;
char zBase[1000];
char zBase[SQLITE_PRINT_BUF_SIZE];
va_start(ap, zFormat);
z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
va_end(ap);

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

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

@ -12,7 +12,7 @@
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
** $Id: shell.c,v 1.122 2005/02/23 12:35:41 drh Exp $
** $Id: shell.c,v 1.128 2005/09/11 02:03:04 drh Exp $
*/
#include <stdlib.h>
#include <string.h>
@ -313,7 +313,7 @@ static void output_c_string(FILE *out, const char *z){
fputc('\\', out);
fputc('r', out);
}else if( !isprint(c) ){
fprintf(out, "\\%03o", c);
fprintf(out, "\\%03o", c&0xff);
}else{
fputc(c, out);
}
@ -656,10 +656,14 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
zType = azArg[1];
zSql = azArg[2];
if( strcmp(zTable,"sqlite_sequence")!=0 ){
fprintf(p->out, "%s;\n", zSql);
}else{
if( strcmp(zTable, "sqlite_sequence")==0 ){
fprintf(p->out, "DELETE FROM sqlite_sequence;\n");
}else if( strcmp(zTable, "sqlite_stat1")==0 ){
fprintf(p->out, "ANALYZE sqlite_master;\n");
}else if( strncmp(zTable, "sqlite_", 7)==0 ){
return 0;
}else{
fprintf(p->out, "%s;\n", zSql);
}
if( strcmp(zType, "table")==0 ){
@ -984,10 +988,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
p->showHeader = 1;
memset(p->colWidth,0,ArraySize(p->colWidth));
p->colWidth[0] = 4;
p->colWidth[1] = 12;
p->colWidth[1] = 14;
p->colWidth[2] = 10;
p->colWidth[3] = 10;
p->colWidth[4] = 35;
p->colWidth[4] = 33;
}else if (p->explainPrev.valid) {
p->explainPrev.valid = 0;
p->mode = p->explainPrev.mode;
@ -1093,6 +1097,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}
}
}
*z = 0;
if( i+1!=nCol ){
fprintf(stderr,"%s line %d: expected %d columns of data but found %d\n",
zFile, lineno, nCol, i+1);
@ -1289,7 +1294,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
"SELECT sql FROM "
" (SELECT * FROM sqlite_master UNION ALL"
" SELECT * FROM sqlite_temp_master) "
"WHERE type!='meta' AND sql NOTNULL "
"WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'"
"ORDER BY substr(type,2,1), name",
callback, &data, &zErrMsg
);
@ -1333,7 +1338,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
if( nArg==1 ){
rc = sqlite3_get_table(p->db,
"SELECT name FROM sqlite_master "
"WHERE type IN ('table','view') "
"WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'"
"UNION ALL "
"SELECT name FROM sqlite_temp_master "
"WHERE type IN ('table','view') "
@ -1697,6 +1702,13 @@ int main(int argc, char **argv){
}
data.out = stdout;
#ifdef SQLITE_OMIT_MEMORYDB
if( data.zDbFilename==0 ){
fprintf(stderr,"%s: no database filename specified\n", argv[0]);
exit(1);
}
#endif
/* Go ahead and open the database file if it already exists. If the
** file does not exist, delay opening it. This prevents empty database
** files from being created if a user mistypes the database name argument

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

@ -12,7 +12,7 @@
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.136 2005/06/12 22:12:39 drh Exp $
** @(#) $Id: sqlite.h.in,v 1.141 2005/09/08 10:58:52 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
@ -31,7 +31,7 @@ extern "C" {
#ifdef SQLITE_VERSION
# undef SQLITE_VERSION
#endif
#define SQLITE_VERSION "3.2.2"
#define SQLITE_VERSION "3.2.7"
/*
** The format of the version string is "X.Y.Z<trailing string>", where
@ -48,7 +48,7 @@ extern "C" {
#ifdef SQLITE_VERSION_NUMBER
# undef SQLITE_VERSION_NUMBER
#endif
#define SQLITE_VERSION_NUMBER 3002002
#define SQLITE_VERSION_NUMBER 3002007
/*
** The version string is also compiled into the library so that a program
@ -158,7 +158,7 @@ int sqlite3_exec(
*/
#define SQLITE_OK 0 /* Successful result */
#define SQLITE_ERROR 1 /* SQL error or missing database */
#define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */
#define SQLITE_INTERNAL 2 /* NOT USED. Internal logic error in SQLite */
#define SQLITE_PERM 3 /* Access permission denied */
#define SQLITE_ABORT 4 /* Callback routine requested an abort */
#define SQLITE_BUSY 5 /* The database file is locked */
@ -168,13 +168,13 @@ int sqlite3_exec(
#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/
#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
#define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */
#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */
#define SQLITE_FULL 13 /* Insertion failed because database is full */
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
#define SQLITE_EMPTY 16 /* Database is empty */
#define SQLITE_SCHEMA 17 /* The database schema changed */
#define SQLITE_TOOBIG 18 /* Too much data for one row of a table */
#define SQLITE_TOOBIG 18 /* NOT USED. Too much data for one row */
#define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */
#define SQLITE_MISMATCH 20 /* Data type mismatch */
#define SQLITE_MISUSE 21 /* Library used incorrectly */
@ -373,8 +373,9 @@ void sqlite3_free_table(char **result);
**
** We can use this text in an SQL statement as follows:
**
** sqlite3_exec_printf(db, "INSERT INTO table VALUES('%q')",
** callback1, 0, 0, zText);
** char *z = sqlite3_mprintf("INSERT INTO TABLES('%q')", zText);
** sqlite3_exec(db, z, callback1, 0, 0);
** sqlite3_free(z);
**
** Because the %q format string is used, the '\'' character in zText
** is escaped and the SQL generated is as follows:
@ -452,6 +453,7 @@ int sqlite3_set_authorizer(
#define SQLITE_DETACH 25 /* Database Name NULL */
#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */
#define SQLITE_REINDEX 27 /* Index Name NULL */
#define SQLITE_ANALYZE 28 /* Table Name NULL */
/*
@ -463,11 +465,18 @@ int sqlite3_set_authorizer(
#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
/*
** Register a function that is called at every invocation of sqlite3_exec()
** or sqlite3_prepare(). This function can be used (for example) to generate
** a log file of all SQL executed against a database.
** Register a function for tracing SQL command evaluation. The function
** registered by sqlite3_trace() is invoked at the first sqlite3_step()
** for the evaluation of an SQL statement. The function registered by
** sqlite3_profile() runs at the end of each SQL statement and includes
** information on how long that statement ran.
**
** The sqlite3_profile() API is currently considered experimental and
** is subject to change.
*/
void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
void *sqlite3_profile(sqlite3*,
void(*xProfile)(void*,const char*,sqlite_uint64), void*);
/*
** This routine configures a callback function - the progress callback - that
@ -1002,10 +1011,9 @@ int sqlite3_value_type(sqlite3_value*);
void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
/*
** The pUserData parameter to the sqlite3_create_function() and
** sqlite3_create_aggregate() routines used to register user functions
** is available to the implementation of the function using this
** call.
** The pUserData parameter to the sqlite3_create_function()
** routine used to register user functions is available to
** the implementation of the function using this call.
*/
void *sqlite3_user_data(sqlite3_context*);

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

@ -11,11 +11,22 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.387 2005/06/12 21:35:52 drh Exp $
** @(#) $Id: sqliteInt.h,v 1.421 2005/09/19 21:05:49 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
/*
** Many people are failing to set -DNDEBUG=1 when compiling SQLite.
** Setting NDEBUG makes the code smaller and run faster. So the following
** lines are added to automatically set NDEBUG unless the -DSQLITE_DEBUG=1
** option is set. Thus NDEBUG becomes an opt-in rather than an opt-out
** feature.
*/
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif
/*
** These #defines should enable >2GB file support on Posix if the
** underlying operating system supports it. If the OS lacks
@ -210,6 +221,7 @@ typedef struct BusyHandler BusyHandler;
struct BusyHandler {
int (*xFunc)(void *,int); /* The busy callback */
void *pArg; /* First arg to busy callback */
int nBusy; /* Incremented with each busy call */
};
/*
@ -299,30 +311,30 @@ extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */
/*
** Forward references to structures
*/
typedef struct AggInfo AggInfo;
typedef struct AuthContext AuthContext;
typedef struct CollSeq CollSeq;
typedef struct Column Column;
typedef struct Table Table;
typedef struct Index Index;
typedef struct Db Db;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct Parse Parse;
typedef struct Token Token;
typedef struct IdList IdList;
typedef struct SrcList SrcList;
typedef struct WhereInfo WhereInfo;
typedef struct WhereLevel WhereLevel;
typedef struct Select Select;
typedef struct AggExpr AggExpr;
typedef struct FuncDef FuncDef;
typedef struct Trigger Trigger;
typedef struct TriggerStep TriggerStep;
typedef struct TriggerStack TriggerStack;
typedef struct FKey FKey;
typedef struct Db Db;
typedef struct AuthContext AuthContext;
typedef struct FuncDef FuncDef;
typedef struct IdList IdList;
typedef struct Index Index;
typedef struct KeyClass KeyClass;
typedef struct CollSeq CollSeq;
typedef struct KeyInfo KeyInfo;
typedef struct NameContext NameContext;
typedef struct Parse Parse;
typedef struct Select Select;
typedef struct SrcList SrcList;
typedef struct Table Table;
typedef struct Token Token;
typedef struct TriggerStack TriggerStack;
typedef struct TriggerStep TriggerStep;
typedef struct Trigger Trigger;
typedef struct WhereInfo WhereInfo;
typedef struct WhereLevel WhereLevel;
/*
** Each database file to be accessed by the system is an instance
@ -421,8 +433,10 @@ struct sqlite3 {
} init;
struct Vdbe *pVdbe; /* List of active virtual machines */
int activeVdbeCnt; /* Number of vdbes currently executing */
void (*xTrace)(void*,const char*); /* Trace function */
void *pTraceArg; /* Argument to the trace function */
void (*xTrace)(void*,const char*); /* Trace function */
void *pTraceArg; /* Argument to the trace function */
void (*xProfile)(void*,const char*,u64); /* Profiling function */
void *pProfileArg; /* Argument to profile function */
void *pCommitArg; /* Argument to xCommitCallback() */
int (*xCommitCallback)(void*);/* Invoked at every commit. */
void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
@ -497,17 +511,24 @@ struct sqlite3 {
** points to a linked list of these structures.
*/
struct FuncDef {
char *zName; /* SQL name of the function */
int nArg; /* Number of arguments. -1 means unlimited */
i16 nArg; /* Number of arguments. -1 means unlimited */
u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */
u8 needCollSeq; /* True if sqlite3GetFuncCollSeq() might be called */
u8 flags; /* Some combination of SQLITE_FUNC_* */
void *pUserData; /* User data parameter */
FuncDef *pNext; /* Next function with same name */
void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */
void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */
void (*xFinalize)(sqlite3_context*); /* Aggregate finializer */
u8 needCollSeq; /* True if sqlite3GetFuncCollSeq() might be called */
char zName[1]; /* SQL name of the function. MUST BE LAST */
};
/*
** Possible values for FuncDef.flags
*/
#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
/*
** information about each column of an SQL table is held in an instance
** of this structure.
@ -546,10 +567,19 @@ struct Column {
struct CollSeq {
char *zName; /* Name of the collating sequence, UTF-8 encoded */
u8 enc; /* Text encoding handled by xCmp() */
u8 type; /* One of the SQLITE_COLL_... values below */
void *pUser; /* First argument to xCmp() */
int (*xCmp)(void*,int, const void*, int, const void*);
};
/*
** Allowed values of CollSeq flags:
*/
#define SQLITE_COLL_BINARY 1 /* The default memcmp() collating sequence */
#define SQLITE_COLL_NOCASE 2 /* The built-in NOCASE collating sequence */
#define SQLITE_COLL_REVERSE 3 /* The built-in REVERSE collating sequence */
#define SQLITE_COLL_USER 0 /* Any other user-defined collating sequence */
/*
** A sort order can be either ASC or DESC.
*/
@ -746,6 +776,7 @@ struct Index {
char *zName; /* Name of this index */
int nColumn; /* Number of columns in the table used by this index */
int *aiColumn; /* Which columns are used by this index. 1st is 0 */
unsigned *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
Table *pTable; /* The SQL table being indexed */
int tnum; /* Page containing root of this index in database file */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
@ -770,6 +801,49 @@ struct Token {
unsigned n : 31; /* Number of characters in this token */
};
/*
** An instance of this structure contains information needed to generate
** code for a SELECT that contains aggregate functions.
**
** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a
** pointer to this structure. The Expr.iColumn field is the index in
** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate
** code for that node.
**
** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the
** original Select structure that describes the SELECT statement. These
** fields do not need to be freed when deallocating the AggInfo structure.
*/
struct AggInfo {
u8 directMode; /* Direct rendering mode means take data directly
** from source tables rather than from accumulators */
u8 useSortingIdx; /* In direct mode, reference the sorting index rather
** than the source table */
int sortingIdx; /* Cursor number of the sorting index */
ExprList *pGroupBy; /* The group by clause */
int nSortingColumn; /* Number of columns in the sorting index */
struct AggInfo_col { /* For each column used in source tables */
int iTable; /* Cursor number of the source table */
int iColumn; /* Column number within the source table */
int iSorterColumn; /* Column number in the sorting index */
int iMem; /* Memory location that acts as accumulator */
Expr *pExpr; /* The original expression */
} *aCol;
int nColumn; /* Number of used entries in aCol[] */
int nColumnAlloc; /* Number of slots allocated for aCol[] */
int nAccumulator; /* Number of columns that show through to the output.
** Additional columns are used only as parameters to
** aggregate functions */
struct AggInfo_func { /* For each aggregate function */
Expr *pExpr; /* Expression encoding the function */
FuncDef *pFunc; /* The aggregate function implementation */
int iMem; /* Memory location that acts as accumulator */
int iDistinct; /* Virtual table used to enforce DISTINCT */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
int nFuncAlloc; /* Number of slots allocated for aFunc[] */
};
/*
** Each node of an expression in the parse tree is an instance
** of this structure.
@ -829,9 +903,9 @@ struct Expr {
Token span; /* Complete text of the expression */
int iTable, iColumn; /* When op==TK_COLUMN, then this expr node means the
** iColumn-th field of the iTable-th table. */
int iAgg; /* When op==TK_COLUMN and pParse->fillAgg==FALSE, pull
** result from the iAgg-th element of the aggregator */
int iAggCtx; /* The value to pass as P1 of OP_AggGet. */
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
int iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
int iRightJoinTable; /* If EP_FromJoin, the right table of the join */
Select *pSelect; /* When the expression is a sub-select. Also the
** right side of "<expr> IN (<select>)" */
Table *pTab; /* Table for OP_Column expressions. */
@ -840,12 +914,13 @@ struct Expr {
/*
** The following are the meanings of bits in the Expr.flags field.
*/
#define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */
#define EP_Agg 0x0002 /* Contains one or more aggregate functions */
#define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */
#define EP_Error 0x0008 /* Expression contains one or more errors */
#define EP_Not 0x0010 /* Operator preceeded by NOT */
#define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */
#define EP_FromJoin 0x01 /* Originated in ON or USING clause of a join */
#define EP_Agg 0x02 /* Contains one or more aggregate functions */
#define EP_Resolved 0x04 /* IDs have been resolved to COLUMNs */
#define EP_Error 0x08 /* Expression contains one or more errors */
#define EP_Distinct 0x10 /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect 0x20 /* pSelect is correlated, not constant */
#define EP_Dequoted 0x40 /* True if the string has been dequoted */
/*
** These macros can be used to test, set, or clear bits in the
@ -867,6 +942,7 @@ struct Expr {
struct ExprList {
int nExpr; /* Number of expressions on the list */
int nAlloc; /* Number of entries allocated below */
int iECursor; /* VDBE Cursor associated with this ExprList */
struct ExprList_item {
Expr *pExpr; /* The list of expressions */
char *zName; /* Token associated with this expression */
@ -892,12 +968,12 @@ struct ExprList {
** If "a" is the k-th column of table "t", then IdList.a[0].idx==k.
*/
struct IdList {
int nId; /* Number of identifiers on the list */
int nAlloc; /* Number of entries allocated for a[] below */
struct IdList_item {
char *zName; /* Name of the identifier */
int idx; /* Index in some Table.aCol[] of a column named zName */
} *a;
int nId; /* Number of identifiers on the list */
int nAlloc; /* Number of entries allocated for a[] below */
};
/*
@ -925,8 +1001,8 @@ struct SrcList {
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
Table *pTab; /* An SQL table corresponding to zName */
Select *pSelect; /* A SELECT statement used in place of a table name */
int jointype; /* Type of join between this table and the next */
int iCursor; /* The VDBE cursor number used to access this table */
u8 jointype; /* Type of join between this table and the next */
i16 iCursor; /* The VDBE cursor number used to access this table */
Expr *pOn; /* The ON clause of a join */
IdList *pUsing; /* The USING clause of a join */
Bitmask colUsed; /* Bit N (1<<N) set if column N or pTab is used */
@ -937,11 +1013,12 @@ struct SrcList {
** Permitted values of the SrcList.a.jointype field
*/
#define JT_INNER 0x0001 /* Any kind of inner or cross join */
#define JT_NATURAL 0x0002 /* True for a "natural" join */
#define JT_LEFT 0x0004 /* Left outer join */
#define JT_RIGHT 0x0008 /* Right outer join */
#define JT_OUTER 0x0010 /* The "OUTER" keyword is present */
#define JT_ERROR 0x0020 /* unknown or unsupported join type */
#define JT_CROSS 0x0002 /* Explicit use of the CROSS keyword */
#define JT_NATURAL 0x0004 /* True for a "natural" join */
#define JT_LEFT 0x0008 /* Left outer join */
#define JT_RIGHT 0x0010 /* Right outer join */
#define JT_OUTER 0x0020 /* The "OUTER" keyword is present */
#define JT_ERROR 0x0040 /* unknown or unsupported join type */
/*
** For each nested loop in a WHERE clause implementation, the WhereInfo
@ -950,18 +1027,20 @@ struct SrcList {
** access or modified by other modules.
*/
struct WhereLevel {
int iMem; /* Memory cell used by this level */
Index *pIdx; /* Index used. NULL if no index */
int iTabCur; /* The VDBE cursor used to access the table */
int iIdxCur; /* The VDBE cursor used to acesss pIdx */
int score; /* How well this index scored */
int brk; /* Jump here to break out of the loop */
int cont; /* Jump here to continue with the next loop cycle */
int op, p1, p2; /* Opcode used to terminate the loop */
int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */
int top; /* First instruction of interior of the loop */
int inOp, inP1, inP2;/* Opcode used to implement an IN operator */
int bRev; /* Do the scan in the reverse direction */
int iFrom; /* Which entry in the FROM clause */
int flags; /* Flags associated with this level */
int iMem; /* First memory cell used by this level */
int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */
Index *pIdx; /* Index used. NULL if no index */
int iTabCur; /* The VDBE cursor used to access the table */
int iIdxCur; /* The VDBE cursor used to acesss pIdx */
int brk; /* Jump here to break out of the loop */
int cont; /* Jump here to continue with the next loop cycle */
int top; /* First instruction of interior of the loop */
int op, p1, p2; /* Opcode used to terminate the loop */
int nEq; /* Number of == or IN constraints on this loop */
int nIn; /* Number of IN operators constraining this loop */
int *aInLoop; /* Loop terminators for IN operators */
};
/*
@ -1009,8 +1088,9 @@ struct NameContext {
int nRef; /* Number of names resolved by this context */
int nErr; /* Number of errors encountered while resolving names */
u8 allowAgg; /* Aggregate functions allowed here */
u8 hasAgg;
u8 hasAgg; /* True if aggregates are seen */
int nDepth; /* Depth of subquery recursion. 1 for no recursion */
AggInfo *pAggInfo; /* Information about aggregates at this level */
NameContext *pNext; /* Next outer name context. NULL for outermost */
};
@ -1023,64 +1103,55 @@ struct NameContext {
** limit and nOffset to the value of the offset (or 0 if there is not
** offset). But later on, nLimit and nOffset become the memory locations
** in the VDBE that record the limit and offset counters.
**
** addrOpenVirt[] entries contain the address of OP_OpenVirtual opcodes.
** These addresses must be stored so that we can go back and fill in
** the P3_KEYINFO and P2 parameters later. Neither the KeyInfo nor
** the number of columns in P2 can be computed at the same time
** as the OP_OpenVirtual instruction is coded because not
** enough information about the compound query is known at that point.
** The KeyInfo for addrOpenVirt[0] and [1] contains collating sequences
** for the result set. The KeyInfo for addrOpenVirt[2] contains collating
** sequences for the ORDER BY clause.
*/
struct Select {
ExprList *pEList; /* The fields of the result */
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
u8 isDistinct; /* True if the DISTINCT keyword is present */
u8 isResolved; /* True once sqlite3SelectResolve() has run. */
u8 isAgg; /* True if this is an aggregate query */
u8 usesVirt; /* True if uses an OpenVirtual opcode */
u8 disallowOrderBy; /* Do not allow an ORDER BY to be attached if TRUE */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
ExprList *pGroupBy; /* The GROUP BY clause */
Expr *pHaving; /* The HAVING clause */
ExprList *pOrderBy; /* The ORDER BY clause */
Select *pPrior; /* Prior select in a compound select statement */
Select *pRightmost; /* Right-most select in a compound select statement */
Expr *pLimit; /* LIMIT expression. NULL means not used. */
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 */
u8 isResolved; /* True once sqlite3SelectResolve() has run. */
u8 isAgg; /* True if this is an aggregate query */
int addrOpenVirt[3]; /* OP_OpenVirtual opcodes related to this select */
};
/*
** The results of a select can be distributed in several ways.
*/
#define SRT_Callback 1 /* Invoke a callback with each row of result */
#define SRT_Mem 2 /* Store result in a memory cell */
#define SRT_Set 3 /* Store result as unique keys in a table */
#define SRT_Union 5 /* Store result as keys in a table */
#define SRT_Except 6 /* Remove result from a UNION table */
#define SRT_Table 7 /* Store result as data with a unique key */
#define SRT_TempTable 8 /* Store result in a trasient table */
#define SRT_Discard 9 /* Do not save the results anywhere */
#define SRT_Sorter 10 /* Store results in the sorter */
#define SRT_Subroutine 11 /* Call a subroutine to handle results */
#define SRT_Exists 12 /* Put 0 or 1 in a memory cell */
#define SRT_Union 1 /* Store result as keys in an index */
#define SRT_Except 2 /* Remove result from a UNION index */
#define SRT_Discard 3 /* Do not save the results anywhere */
/*
** When a SELECT uses aggregate functions (like "count(*)" or "avg(f1)")
** we have to do some additional analysis of expressions. An instance
** of the following structure holds information about a single subexpression
** somewhere in the SELECT statement. An array of these structures holds
** all the information we need to generate code for aggregate
** expressions.
**
** Note that when analyzing a SELECT containing aggregates, both
** non-aggregate field variables and aggregate functions are stored
** in the AggExpr array of the Parser structure.
**
** The pExpr field points to an expression that is part of either the
** field list, the GROUP BY clause, the HAVING clause or the ORDER BY
** clause. The expression will be freed when those clauses are cleaned
** up. Do not try to delete the expression attached to AggExpr.pExpr.
**
** If AggExpr.pExpr==0, that means the expression is "count(*)".
*/
struct AggExpr {
int isAgg; /* if TRUE contains an aggregate function */
Expr *pExpr; /* The expression */
FuncDef *pFunc; /* Information about the aggregate function */
};
/* The ORDER BY clause is ignored for all of the above */
#define IgnorableOrderby(X) (X<=SRT_Discard)
#define SRT_Callback 4 /* Invoke a callback with each row of result */
#define SRT_Mem 5 /* Store result in a memory cell */
#define SRT_Set 6 /* Store non-null results as keys in an index */
#define SRT_Table 7 /* Store result as data with an automatic rowid */
#define SRT_VirtualTab 8 /* Create virtual table and store like SRT_Table */
#define SRT_Subroutine 9 /* Call a subroutine to handle results */
#define SRT_Exists 10 /* Put 0 or 1 in a memory cell */
/*
** An SQL parser context. A copy of this structure is passed through
@ -1101,7 +1172,6 @@ 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 */
@ -1128,9 +1198,6 @@ struct Parse {
Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
TriggerStack *trigStack; /* Trigger actions being coded */
const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
int nAgg; /* Number of aggregate expressions */
AggExpr *aAgg; /* An array of aggregate expressions */
int nMaxDepth; /* Maximum depth of subquery recursion */
};
/*
@ -1310,6 +1377,19 @@ typedef struct {
*/
extern int sqlite3_always_code_trigger_setup;
/*
** The SQLITE_CORRUPT_BKPT macro can be either a constant (for production
** builds) or a function call (for debugging). If it is a function call,
** it allows the operator to set a breakpoint at the spot where database
** corruption is first detected.
*/
#ifdef SQLITE_DEBUG
extern int sqlite3Corrupt(void);
# define SQLITE_CORRUPT_BKPT sqlite3Corrupt()
#else
# define SQLITE_CORRUPT_BKPT SQLITE_CORRUPT
#endif
/*
** Internal function prototypes
*/
@ -1337,6 +1417,7 @@ void sqlite3RealToSortable(double r, char *);
# define sqlite3CheckMemory(a,b)
# define sqlite3MallocX sqlite3Malloc
#endif
void sqlite3ReallocOrFree(void**,int);
void sqlite3FreeX(void*);
void *sqlite3MallocX(int);
char *sqlite3MPrintf(const char*, ...);
@ -1346,6 +1427,7 @@ void *sqlite3TextToPtr(const char*);
void sqlite3SetString(char **, ...);
void sqlite3ErrorMsg(Parse*, const char*, ...);
void sqlite3Dequote(char*);
void sqlite3DequoteExpr(Expr*);
int sqlite3KeywordCode(const char*, int);
int sqlite3RunParser(Parse*, const char*, char **);
void sqlite3FinishCoding(Parse*);
@ -1371,7 +1453,7 @@ void sqlite3StartTable(Parse*,Token*,Token*,Token*,int,int);
void sqlite3AddColumn(Parse*,Token*);
void sqlite3AddNotNull(Parse*, int);
void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int);
void sqlite3AddColumnType(Parse*,Token*,Token*);
void sqlite3AddColumnType(Parse*,Token*);
void sqlite3AddDefaultValue(Parse*,Expr*);
void sqlite3AddCollateType(Parse*, const char*, int);
void sqlite3EndTable(Parse*,Token*,Token*,Select*);
@ -1386,6 +1468,7 @@ void sqlite3EndTable(Parse*,Token*,Token*,Select*);
void sqlite3DropTable(Parse*, SrcList*, int);
void sqlite3DeleteTable(sqlite3*, Table*);
void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
int sqlite3ArrayAllocate(void**,int,int);
IdList *sqlite3IdListAppend(IdList*, Token*);
int sqlite3IdListIndex(IdList*,const char*);
SrcList *sqlite3SrcListAppend(SrcList*, Token*, Token*);
@ -1430,6 +1513,7 @@ int sqlite3ExprCompare(Expr*, Expr*);
int sqliteFuncId(Token*);
int sqlite3ExprResolveNames(NameContext *, Expr *);
int sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
int sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
Vdbe *sqlite3GetVdbe(Parse*);
void sqlite3Randomness(int, void*);
void sqlite3RollbackAll(sqlite3*);
@ -1438,6 +1522,7 @@ void sqlite3BeginTransaction(Parse*, int);
void sqlite3CommitTransaction(Parse*);
void sqlite3RollbackTransaction(Parse*);
int sqlite3ExprIsConstant(Expr*);
int sqlite3ExprIsConstantOrFunction(Expr*);
int sqlite3ExprIsInteger(Expr*, int*);
int sqlite3IsRowid(const char*);
void sqlite3GenerateRowDelete(sqlite3*, Vdbe*, Table*, int, int);
@ -1510,7 +1595,7 @@ int sqlite3FixSelect(DbFixer*, Select*);
int sqlite3FixExpr(DbFixer*, Expr*);
int sqlite3FixExprList(DbFixer*, ExprList*);
int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
double sqlite3AtoF(const char *z, const char **);
int sqlite3AtoF(const char *z, double*);
char *sqlite3_snprintf(int,char*,const char*,...);
int sqlite3GetInt32(const char *, int*);
int sqlite3FitsIn64Bits(const char *);
@ -1546,7 +1631,7 @@ const void *sqlite3ValueText(sqlite3_value*, u8);
int sqlite3ValueBytes(sqlite3_value*, u8);
void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*));
void sqlite3ValueFree(sqlite3_value*);
sqlite3_value *sqlite3ValueNew();
sqlite3_value *sqlite3ValueNew(void);
sqlite3_value *sqlite3GetTransientValue(sqlite3*db);
int sqlite3ValueFromExpr(Expr *, u8, u8, sqlite3_value **);
void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
@ -1565,6 +1650,14 @@ void sqlite3AlterFinishAddColumn(Parse *, Token *);
void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
const char *sqlite3TestErrorName(int);
CollSeq *sqlite3GetCollSeq(sqlite3*, CollSeq *, const char *, int);
char sqlite3AffinityType(const Token*);
void sqlite3Analyze(Parse*, Token*, Token*);
int sqlite3InvokeBusyHandler(BusyHandler*);
int sqlite3FindDb(sqlite3*, Token*);
void sqlite3AnalysisLoad(sqlite3*,int iDB);
void sqlite3DefaultRowEst(Index*);
void sqlite3RegisterLikeFunctions(sqlite3*, int);
int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
#ifdef SQLITE_SSE
#include "sseInt.h"

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

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

@ -15,7 +15,7 @@
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.103 2005/06/06 14:45:43 drh Exp $
** $Id: tokenize.c,v 1.107 2005/08/23 11:31:26 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -38,9 +38,9 @@
/*
** If X is a character that can be used in an identifier and
** X&0x80==0 then isIdChar[X] will be 1. If X&0x80==0x80 then
** X&0x80==0 then sqlite3IsIdChar[X] will be 1. If X&0x80==0x80 then
** X is always an identifier character. (Hence all UTF-8
** characters can be part of an identifier). isIdChar[X] will
** characters can be part of an identifier). sqlite3IsIdChar[X] will
** be 0 for every character in the lower 128 ASCII characters
** that cannot be used as part of an identifier.
**
@ -55,7 +55,7 @@
** SQLite will allow '$' in identifiers for compatibility.
** But the feature is undocumented.
*/
static const char isIdChar[] = {
const char sqlite3IsIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
@ -65,7 +65,7 @@ static const char isIdChar[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
};
#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && isIdChar[c-0x20]))
#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsIdChar[c-0x20]))
/*
** Return the length of the token that begins at z[0].
@ -183,12 +183,9 @@ static int getToken(const unsigned char *z, int *tokenType){
*tokenType = TK_BITNOT;
return 1;
}
case '#': {
for(i=1; isdigit(z[i]) || (i==1 && z[1]=='-'); i++){}
*tokenType = TK_REGISTER;
return i;
}
case '\'': case '"': {
case '`':
case '\'':
case '"': {
int delim = z[0];
for(i=1; (c=z[i])!=0; i++){
if( c==delim ){
@ -204,16 +201,23 @@ static int getToken(const unsigned char *z, int *tokenType){
return i;
}
case '.': {
*tokenType = TK_DOT;
return 1;
#ifndef SQLITE_OMIT_FLOATING_POINT
if( !isdigit(z[1]) )
#endif
{
*tokenType = TK_DOT;
return 1;
}
/* If the next character is a digit, this is a floating point
** number that begins with ".". Fall thru into the next case */
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
*tokenType = TK_INTEGER;
for(i=1; isdigit(z[i]); i++){}
for(i=0; isdigit(z[i]); i++){}
#ifndef SQLITE_OMIT_FLOATING_POINT
if( z[i]=='.' && isdigit(z[i+1]) ){
i += 2;
if( z[i]=='.' ){
i++;
while( isdigit(z[i]) ){ i++; }
*tokenType = TK_FLOAT;
}
@ -239,50 +243,47 @@ static int getToken(const unsigned char *z, int *tokenType){
for(i=1; isdigit(z[i]); i++){}
return i;
}
case ':': {
for(i=1; IdChar(z[i]); i++){}
*tokenType = i>1 ? TK_VARIABLE : TK_ILLEGAL;
return i;
case '#': {
for(i=1; isdigit(z[i]); i++){}
if( i>1 ){
/* Parameters of the form #NNN (where NNN is a number) are used
** internally by sqlite3NestedParse. */
*tokenType = TK_REGISTER;
return i;
}
/* Fall through into the next case if the '#' is not followed by
** a digit. Try to match #AAAA where AAAA is a parameter name. */
}
#ifndef SQLITE_OMIT_TCL_VARIABLE
case '$': {
case '$':
#endif
case ':': {
int n = 0;
*tokenType = TK_VARIABLE;
if( z[1]=='{' ){
int nBrace = 1;
for(i=2; (c=z[i])!=0 && nBrace; i++){
if( c=='{' ){
nBrace++;
}else if( c=='}' ){
nBrace--;
}
}
if( c==0 ) *tokenType = TK_ILLEGAL;
}else{
int n = 0;
for(i=1; (c=z[i])!=0; i++){
if( isalnum(c) || c=='_' ){
n++;
}else if( c=='(' && n>0 ){
do{
i++;
}while( (c=z[i])!=0 && !isspace(c) && c!=')' );
if( c==')' ){
i++;
}else{
*tokenType = TK_ILLEGAL;
}
break;
}else if( c==':' && z[i+1]==':' ){
for(i=1; (c=z[i])!=0; i++){
if( IdChar(c) ){
n++;
#ifndef SQLITE_OMIT_TCL_VARIABLE
}else if( c=='(' && n>0 ){
do{
i++;
}while( (c=z[i])!=0 && !isspace(c) && c!=')' );
if( c==')' ){
i++;
}else{
break;
*tokenType = TK_ILLEGAL;
}
break;
}else if( c==':' && z[i+1]==':' ){
i++;
#endif
}else{
break;
}
if( n==0 ) *tokenType = TK_ILLEGAL;
}
if( n==0 ) *tokenType = TK_ILLEGAL;
return i;
}
#endif
#ifndef SQLITE_OMIT_BLOB_LITERAL
case 'x': case 'X': {
if( (c=z[1])=='\'' || c=='"' ){
@ -430,241 +431,3 @@ abort_parse:
}
return nErr;
}
/* The sqlite3_complete() API may be omitted (to save code space) by
** defining the following symbol.
*/
#ifndef SQLITE_OMIT_COMPLETE
/*
** Token types used by the sqlite3_complete() routine. See the header
** comments on that procedure for additional information.
*/
#define tkSEMI 0
#define tkWS 1
#define tkOTHER 2
#define tkEXPLAIN 3
#define tkCREATE 4
#define tkTEMP 5
#define tkTRIGGER 6
#define tkEND 7
/*
** Return TRUE if the given SQL string ends in a semicolon.
**
** Special handling is require for CREATE TRIGGER statements.
** Whenever the CREATE TRIGGER keywords are seen, the statement
** must end with ";END;".
**
** This implementation uses a state machine with 7 states:
**
** (0) START At the beginning or end of an SQL statement. This routine
** returns 1 if it ends in the START state and 0 if it ends
** in any other state.
**
** (1) NORMAL We are in the middle of statement which ends with a single
** semicolon.
**
** (2) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
** a statement.
**
** (3) CREATE The keyword CREATE has been seen at the beginning of a
** statement, possibly preceeded by EXPLAIN and/or followed by
** TEMP or TEMPORARY
**
** (4) TRIGGER We are in the middle of a trigger definition that must be
** ended by a semicolon, the keyword END, and another semicolon.
**
** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at
** the end of a trigger definition.
**
** (6) END We've seen the ";END" of the ";END;" that occurs at the end
** of a trigger difinition.
**
** Transitions between states above are determined by tokens extracted
** from the input. The following tokens are significant:
**
** (0) tkSEMI A semicolon.
** (1) tkWS Whitespace
** (2) tkOTHER Any other SQL token.
** (3) tkEXPLAIN The "explain" keyword.
** (4) tkCREATE The "create" keyword.
** (5) tkTEMP The "temp" or "temporary" keyword.
** (6) tkTRIGGER The "trigger" keyword.
** (7) tkEND The "end" keyword.
**
** Whitespace never causes a state transition and is always ignored.
**
** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed
** to recognize the end of a trigger can be omitted. All we have to do
** is look for a semicolon that is not part of an string or comment.
*/
int sqlite3_complete(const char *zSql){
u8 state = 0; /* Current state, using numbers defined in header comment */
u8 token; /* Value of the next token */
#ifndef SQLITE_OMIT_TRIGGER
/* A complex statement machine used to detect the end of a CREATE TRIGGER
** statement. This is the normal case.
*/
static const u8 trans[7][8] = {
/* Token: */
/* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */
/* 0 START: */ { 0, 0, 1, 2, 3, 1, 1, 1, },
/* 1 NORMAL: */ { 0, 1, 1, 1, 1, 1, 1, 1, },
/* 2 EXPLAIN: */ { 0, 2, 1, 1, 3, 1, 1, 1, },
/* 3 CREATE: */ { 0, 3, 1, 1, 1, 3, 4, 1, },
/* 4 TRIGGER: */ { 5, 4, 4, 4, 4, 4, 4, 4, },
/* 5 SEMI: */ { 5, 5, 4, 4, 4, 4, 4, 6, },
/* 6 END: */ { 0, 6, 4, 4, 4, 4, 4, 4, },
};
#else
/* If triggers are not suppored by this compile then the statement machine
** used to detect the end of a statement is much simplier
*/
static const u8 trans[2][3] = {
/* Token: */
/* State: ** SEMI WS OTHER */
/* 0 START: */ { 0, 0, 1, },
/* 1 NORMAL: */ { 0, 1, 1, },
};
#endif /* SQLITE_OMIT_TRIGGER */
while( *zSql ){
switch( *zSql ){
case ';': { /* A semicolon */
token = tkSEMI;
break;
}
case ' ':
case '\r':
case '\t':
case '\n':
case '\f': { /* White space is ignored */
token = tkWS;
break;
}
case '/': { /* C-style comments */
if( zSql[1]!='*' ){
token = tkOTHER;
break;
}
zSql += 2;
while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
if( zSql[0]==0 ) return 0;
zSql++;
token = tkWS;
break;
}
case '-': { /* SQL-style comments from "--" to end of line */
if( zSql[1]!='-' ){
token = tkOTHER;
break;
}
while( *zSql && *zSql!='\n' ){ zSql++; }
if( *zSql==0 ) return state==0;
token = tkWS;
break;
}
case '[': { /* Microsoft-style identifiers in [...] */
zSql++;
while( *zSql && *zSql!=']' ){ zSql++; }
if( *zSql==0 ) return 0;
token = tkOTHER;
break;
}
case '"': /* single- and double-quoted strings */
case '\'': {
int c = *zSql;
zSql++;
while( *zSql && *zSql!=c ){ zSql++; }
if( *zSql==0 ) return 0;
token = tkOTHER;
break;
}
default: {
int c;
if( IdChar((u8)*zSql) ){
/* Keywords and unquoted identifiers */
int nId;
for(nId=1; IdChar(zSql[nId]); nId++){}
#ifdef SQLITE_OMIT_TRIGGER
token = tkOTHER;
#else
switch( *zSql ){
case 'c': case 'C': {
if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){
token = tkCREATE;
}else{
token = tkOTHER;
}
break;
}
case 't': case 'T': {
if( nId==7 && sqlite3StrNICmp(zSql, "trigger", 7)==0 ){
token = tkTRIGGER;
}else if( nId==4 && sqlite3StrNICmp(zSql, "temp", 4)==0 ){
token = tkTEMP;
}else if( nId==9 && sqlite3StrNICmp(zSql, "temporary", 9)==0 ){
token = tkTEMP;
}else{
token = tkOTHER;
}
break;
}
case 'e': case 'E': {
if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){
token = tkEND;
}else
#ifndef SQLITE_OMIT_EXPLAIN
if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){
token = tkEXPLAIN;
}else
#endif
{
token = tkOTHER;
}
break;
}
default: {
token = tkOTHER;
break;
}
}
#endif /* SQLITE_OMIT_TRIGGER */
zSql += nId-1;
}else{
/* Operators and special symbols */
token = tkOTHER;
}
break;
}
}
state = trans[state][token];
zSql++;
}
return state==0;
}
#ifndef SQLITE_OMIT_UTF16
/*
** This routine is the same as the sqlite3_complete() routine described
** above, except that the parameter is required to be UTF-16 encoded, not
** UTF-8.
*/
int sqlite3_complete16(const void *zSql){
sqlite3_value *pVal;
char const *zSql8;
int rc = 0;
pVal = sqlite3ValueNew();
sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
if( zSql8 ){
rc = sqlite3_complete(zSql8);
}
sqlite3ValueFree(pVal);
return rc;
}
#endif /* SQLITE_OMIT_UTF16 */
#endif /* SQLITE_OMIT_COMPLETE */

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

@ -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.108 2005/06/12 21:35:53 drh Exp $
** $Id: update.c,v 1.112 2005/09/20 17:42:23 drh Exp $
*/
#include "sqliteInt.h"
@ -47,7 +47,11 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){
u8 enc = sqlite3VdbeDb(v)->enc;
Column *pCol = &pTab->aCol[i];
sqlite3ValueFromExpr(pCol->pDflt, enc, pCol->affinity, &pValue);
sqlite3VdbeChangeP3(v, -1, (const char *)pValue, P3_MEM);
if( pValue ){
sqlite3VdbeChangeP3(v, -1, (const char *)pValue, P3_MEM);
}else{
VdbeComment((v, "# %s.%s", pTab->zName, pCol->zName));
}
}
}
@ -255,13 +259,13 @@ void sqlite3Update(
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
sqlite3BeginWriteOperation(pParse, 1, pTab->iDb);
/* If we are trying to update a view, construct that view into
** a temporary table.
/* If we are trying to update a view, realize that view into
** a ephemeral table.
*/
if( isView ){
Select *pView;
pView = sqlite3SelectDup(pTab->pSelect);
sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0, 0);
sqlite3Select(pParse, pView, SRT_VirtualTab, iCur, 0, 0, 0, 0);
sqlite3SelectDelete(pView);
}
@ -273,7 +277,7 @@ void sqlite3Update(
/* Remember the index of every item to be updated.
*/
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
/* End the database scan loop.
*/
@ -295,8 +299,7 @@ void sqlite3Update(
/* The top of the update loop for when there are triggers.
*/
sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0);
addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0);
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
if( !isView ){
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
@ -389,8 +392,7 @@ void sqlite3Update(
** So make the cursor point at the old record.
*/
if( !triggers_exist ){
sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0);
addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0);
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
}
sqlite3VdbeAddOp(v, OP_NotExists, iCur, addr);
@ -467,8 +469,7 @@ void sqlite3Update(
** all record selected by the WHERE clause have been updated.
*/
sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeAddOp(v, OP_ListReset, 0, 0);
sqlite3VdbeJumpHere(v, addr);
/* Close all tables if there were no FOR EACH ROW triggers */
if( !triggers_exist ){

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

@ -14,7 +14,7 @@
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.136 2005/06/06 15:06:39 drh Exp $
** $Id: util.c,v 1.146 2005/09/17 18:34:11 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
@ -58,6 +58,8 @@ int sqlite3_malloc_failed = 0;
*/
int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */
int sqlite3_nFree; /* Number of sqliteFree() calls */
int sqlite3_memUsed; /* Total memory obtained from malloc */
int sqlite3_memMax; /* Mem usage high-water mark */
int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */
int sqlite3_iMallocReset = -1; /* When iMallocFail reaches 0, set to this */
#if SQLITE_MEMDEBUG>1
@ -72,13 +74,10 @@ static int memcnt = 0;
#define N_GUARD 2
/*
** Allocate new memory and set it to zero. Return NULL if
** no memory is available.
** Check for a simulated memory allocation failure. Return true if
** the failure should be simulated. Return false to proceed as normal.
*/
void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){
void *p;
int *pi;
int i, k;
static int simulatedMallocFailure(int n, char *zFile, int line){
if( sqlite3_iMallocFail>=0 ){
sqlite3_iMallocFail--;
if( sqlite3_iMallocFail==0 ){
@ -88,10 +87,28 @@ void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){
n, zFile,line);
#endif
sqlite3_iMallocFail = sqlite3_iMallocReset;
return 0;
return 1;
}
}
if( n==0 ) return 0;
return 0;
}
/*
** Allocate new memory and set it to zero. Return NULL if
** no memory is available.
*/
void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){
void *p;
int *pi;
int i, k;
if( n==0 ){
return 0;
}
if( simulatedMallocFailure(n, zFile, line) ){
return 0;
}
sqlite3_memUsed += n;
if( sqlite3_memMax<sqlite3_memUsed ) sqlite3_memMax = sqlite3_memUsed;
k = (n+sizeof(int)-1)/sizeof(int);
pi = malloc( (N_GUARD*2+1+k)*sizeof(int));
if( pi==0 ){
@ -157,6 +174,7 @@ void sqlite3Free_(void *p, char *zFile, int line){
}
}
n = pi[N_GUARD];
sqlite3_memUsed -= n;
k = (n+sizeof(int)-1)/sizeof(int);
for(i=0; i<N_GUARD; i++){
if( pi[k+N_GUARD+1+i]!=0xdead3344 ){
@ -188,6 +206,9 @@ void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){
sqlite3Free_(oldP,zFile,line);
return 0;
}
if( simulatedMallocFailure(n, zFile, line) ){
return 0;
}
oldPi = oldP;
oldPi -= N_GUARD+1;
if( oldPi[0]!=0xdead1122 ){
@ -195,6 +216,7 @@ void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){
return 0;
}
oldN = oldPi[N_GUARD];
sqlite3_memUsed -= oldN;
oldK = (oldN+sizeof(int)-1)/sizeof(int);
for(i=0; i<N_GUARD; i++){
if( oldPi[oldK+N_GUARD+1+i]!=0xdead3344 ){
@ -211,6 +233,8 @@ void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){
}
for(i=0; i<N_GUARD; i++) pi[i] = 0xdead1122;
pi[N_GUARD] = n;
sqlite3_memUsed += n;
if( sqlite3_memMax<sqlite3_memUsed ) sqlite3_memMax = sqlite3_memUsed;
for(i=0; i<N_GUARD; i++) pi[k+N_GUARD+1+i] = 0xdead3344;
p = &pi[N_GUARD+1];
memcpy(p, oldP, n>oldN ? oldN : n);
@ -268,6 +292,7 @@ void sqlite3FreeX(void *p){
*/
void *sqlite3Malloc(int n){
void *p;
if( n==0 ) return 0;
if( (p = malloc(n))==0 ){
if( n>0 ) sqlite3_malloc_failed++;
}else{
@ -282,6 +307,7 @@ void *sqlite3Malloc(int n){
*/
void *sqlite3MallocRaw(int n){
void *p;
if( n==0 ) return 0;
if( (p = malloc(n))==0 ){
if( n>0 ) sqlite3_malloc_failed++;
}
@ -340,6 +366,19 @@ char *sqlite3StrNDup(const char *z, int n){
}
#endif /* !defined(SQLITE_MEMDEBUG) */
/*
** Reallocate a buffer to a different size. This is similar to
** sqliteRealloc() except that if the allocation fails the buffer
** is freed.
*/
void sqlite3ReallocOrFree(void **ppBuf, int newSize){
void *pNew = sqliteRealloc(*ppBuf, newSize);
if( pNew==0 ){
sqliteFree(*ppBuf);
}
*ppBuf = pNew;
}
/*
** Create a string from the 2nd and subsequent arguments (up to the
** first NULL argument), store the string in memory obtained from
@ -372,8 +411,8 @@ void sqlite3SetString(char **pz, ...){
zResult += strlen(zResult);
}
va_end(ap);
#ifdef SQLITE_DEBUG
#if SQLITE_DEBUG>1
#ifdef SQLITE_MEMDEBUG
#if SQLITE_MEMDEBUG>1
fprintf(stderr,"string at 0x%x is %s\n", (int)*pz, *pz);
#endif
#endif
@ -460,7 +499,8 @@ void sqlite3Dequote(char *z){
switch( quote ){
case '\'': break;
case '"': break;
case '[': quote = ']'; break;
case '`': break; /* For MySQL compatibility */
case '[': quote = ']'; break; /* For MS SqlServer compatibility */
default: return;
}
for(i=1, j=0; z[i]; i++){
@ -565,8 +605,9 @@ int sqlite3IsNumber(const char *z, int *realnum, u8 enc){
** of "." depending on how locale is set. But that would cause problems
** for SQL. So this routine always uses "." regardless of locale.
*/
double sqlite3AtoF(const char *z, const char **pzEnd){
int sqlite3AtoF(const char *z, double *pResult){
int sign = 1;
const char *zBegin = z;
LONGDOUBLE_TYPE v1 = 0.0;
if( *z=='-' ){
sign = -1;
@ -613,8 +654,8 @@ double sqlite3AtoF(const char *z, const char **pzEnd){
v1 *= scale;
}
}
if( pzEnd ) *pzEnd = z;
return sign<0 ? -v1 : v1;
*pResult = sign<0 ? -v1 : v1;
return z - zBegin;
}
/*
@ -720,7 +761,7 @@ int sqlite3SafetyOn(sqlite3 *db){
if( db->magic==SQLITE_MAGIC_OPEN ){
db->magic = SQLITE_MAGIC_BUSY;
return 0;
}else if( db->magic==SQLITE_MAGIC_BUSY || db->magic==SQLITE_MAGIC_ERROR ){
}else if( db->magic==SQLITE_MAGIC_BUSY ){
db->magic = SQLITE_MAGIC_ERROR;
db->flags |= SQLITE_Interrupt;
}
@ -736,7 +777,7 @@ int sqlite3SafetyOff(sqlite3 *db){
if( db->magic==SQLITE_MAGIC_BUSY ){
db->magic = SQLITE_MAGIC_OPEN;
return 0;
}else if( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ERROR ){
}else if( db->magic==SQLITE_MAGIC_OPEN ){
db->magic = SQLITE_MAGIC_ERROR;
db->flags |= SQLITE_Interrupt;
}

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

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

@ -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.95 2005/05/19 08:43:00 danielk1977 Exp $
** $Id: vdbe.h,v 1.99 2005/09/20 17:42:23 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
@ -104,13 +104,12 @@ int sqlite3VdbeOp3(Vdbe*,int,int,int,const char *zP3,int);
int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
void sqlite3VdbeJumpHere(Vdbe*, int addr);
void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N);
void sqlite3VdbeDequoteP3(Vdbe*, int addr);
int sqlite3VdbeFindOp(Vdbe*, int, int, int);
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
int sqlite3VdbeMakeLabel(Vdbe*);
void sqlite3VdbeDelete(Vdbe*);
void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int);
void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int);
int sqlite3VdbeFinalize(Vdbe*);
void sqlite3VdbeResolveLabel(Vdbe*, int);
int sqlite3VdbeCurrentAddr(Vdbe*);

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

@ -81,6 +81,7 @@ struct Cursor {
u8 *pIncrKey; /* Pointer to pKeyInfo->incrKey */
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
int nField; /* Number of fields in the header */
i64 seqCount; /* Sequence counter */
/* Cached information about the header for the data record that the
** cursor is currently pointing to. Only valid if cacheValid is true.
@ -113,35 +114,18 @@ typedef struct Cursor Cursor;
** SQLITE_BLOB.
*/
struct Mem {
i64 i; /* Integer value */
i64 i; /* Integer value. Or FuncDef* when flags==MEM_Agg */
double r; /* Real value */
char *z; /* String or BLOB value */
int n; /* Number of characters in string value, including '\0' */
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
u8 type; /* One of MEM_Null, MEM_Str, etc. */
u8 enc; /* TEXT_Utf8, TEXT_Utf16le, or TEXT_Utf16be */
double r; /* Real value */
char *z; /* String or BLOB value */
void (*xDel)(void *); /* If not null, call this function to delete Mem.z */
char zShort[NBFS]; /* Space for short strings */
};
typedef struct Mem Mem;
/*
** A sorter builds a list of elements to be sorted. Each element of
** the list is an instance of the following structure.
*/
typedef struct Sorter Sorter;
struct Sorter {
int nKey; /* Number of bytes in the key */
char *zKey; /* The key by which we will sort */
Mem data;
Sorter *pNext; /* Next in the list */
};
/*
** Number of buckets used for merge-sort.
*/
#define NSORT 30
/* One or more of the following flags are set to indicate the validOK
** representations of the value stored in the Mem struct.
**
@ -173,12 +157,7 @@ struct Sorter {
#define MEM_Static 0x0080 /* Mem.z points to a static string */
#define MEM_Ephem 0x0100 /* Mem.z points to an ephemeral string */
#define MEM_Short 0x0200 /* Mem.z points to Mem.zShort */
/* The following MEM_ value appears only in AggElem.aMem.s.flag fields.
** It indicates that the corresponding AggElem.aMem.z points to a
** aggregate function context that needs to be finalized.
*/
#define MEM_AggCtx 0x0400 /* Mem.z points to an agg function context */
#define MEM_Agg 0x0400 /* Mem.z points to an agg function context */
/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
@ -210,41 +189,16 @@ typedef struct VdbeFunc VdbeFunc;
** But this file is the only place where the internal details of this
** structure are known.
**
** This structure is defined inside of vdbe.c because it uses substructures
** This structure is defined inside of vdbeInt.h because it uses substructures
** (Mem) which are only defined there.
*/
struct sqlite3_context {
FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */
Mem s; /* The return value is stored here */
void *pAgg; /* Aggregate context */
u8 isError; /* Set to true for an error */
int cnt; /* Number of times that the step function has been called */
CollSeq *pColl;
};
/*
** An Agg structure describes an Aggregator. Each Agg consists of
** zero or more Aggregator elements (AggElem). Each AggElem contains
** a key and one or more values. The values are used in processing
** aggregate functions in a SELECT. The key is used to implement
** the GROUP BY clause of a select.
*/
typedef struct Agg Agg;
typedef struct AggElem AggElem;
struct Agg {
int nMem; /* Number of values stored in each AggElem */
AggElem *pCurrent; /* The AggElem currently in focus */
FuncDef **apFunc; /* Information about aggregate functions */
Btree *pBtree; /* The tmp. btree used to group elements, if required. */
BtCursor *pCsr; /* Read/write cursor to the table in pBtree */
int nTab; /* Root page of the table in pBtree */
u8 searching; /* True between the first AggNext and AggReset */
};
struct AggElem {
char *zKey; /* The key to this AggElem */
int nKey; /* Number of bytes in the key, including '\0' at end */
Mem aMem[1]; /* The values for this AggElem */
Mem s; /* The return value is stored here */
Mem *pMem; /* Memory cell used to store aggregate context */
u8 isError; /* Set to true for an error */
CollSeq *pColl; /* Collating sequence */
};
/*
@ -260,17 +214,29 @@ struct Set {
};
/*
** A Keylist is a bunch of keys into a table. The keylist can
** grow without bound. The keylist stores the ROWIDs of database
** records that need to be deleted or updated.
** A FifoPage structure holds a single page of valves. Pages are arranged
** in a list.
*/
typedef struct Keylist Keylist;
struct Keylist {
int nKey; /* Number of slots in aKey[] */
int nUsed; /* Next unwritten slot in aKey[] */
int nRead; /* Next unread slot in aKey[] */
Keylist *pNext; /* Next block of keys */
i64 aKey[1]; /* One or more keys. Extra space allocated as needed */
typedef struct FifoPage FifoPage;
struct FifoPage {
int nSlot; /* Number of entries aSlot[] */
int iWrite; /* Push the next value into this entry in aSlot[] */
int iRead; /* Read the next value from this entry in aSlot[] */
FifoPage *pNext; /* Next page in the fifo */
i64 aSlot[1]; /* One or more slots for rowid values */
};
/*
** The Fifo structure is typedef-ed in vdbeInt.h. But the implementation
** of that structure is private to this file.
**
** The Fifo structure describes the entire fifo.
*/
typedef struct Fifo Fifo;
struct Fifo {
int nEntry; /* Total number of entries */
FifoPage *pFirst; /* First page on the list */
FifoPage *pLast; /* Last page on the list */
};
/*
@ -286,7 +252,7 @@ typedef struct Context Context;
struct Context {
int lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
int nChange; /* Statement changes (Vdbe.nChanges) */
Keylist *pList; /* Records that will participate in a DELETE or UPDATE */
Fifo sFifo; /* Records that will participate in a DELETE or UPDATE */
};
/*
@ -312,8 +278,6 @@ struct Vdbe {
Mem *aColName; /* Column names to return */
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 */
@ -321,11 +285,8 @@ struct Vdbe {
int magic; /* Magic number for sanity checking */
int nMem; /* Number of memory locations currently allocated */
Mem *aMem; /* The memory locations */
int nAgg; /* Number of elements in apAgg */
Agg *apAgg; /* Array of aggregate contexts */
Agg *pAgg; /* Current aggregate context */
int nCallback; /* Number of callbacks invoked so far */
Keylist *pList; /* A list of ROWIDs */
Fifo sFifo; /* A list of ROWIDs */
int contextStackTop; /* Index of top element in the context stack */
int contextStackDepth; /* The size of the "context" stack */
Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/
@ -346,6 +307,7 @@ struct Vdbe {
u8 aborted; /* True if ROLLBACK in another VM causes an abort */
u8 expired; /* True if the VM needs to be recompiled */
int nChange; /* Number of db changes made since last reset */
i64 startTime; /* Time when query started - used for profiling */
};
/*
@ -360,9 +322,6 @@ struct Vdbe {
** Function prototypes
*/
void sqlite3VdbeFreeCursor(Cursor*);
void sqlite3VdbeSorterReset(Vdbe*);
int sqlite3VdbeAggReset(sqlite3*, Agg *, KeyInfo *);
void sqlite3VdbeKeylistFree(Keylist*);
void sqliteVdbePopStack(Vdbe*,int);
int sqlite3VdbeCursorMoveto(Cursor*);
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
@ -404,6 +363,7 @@ double sqlite3VdbeRealValue(Mem*);
int sqlite3VdbeMemRealify(Mem*);
int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
void sqlite3VdbeMemRelease(Mem *p);
void sqlite3VdbeMemFinalize(Mem*, FuncDef*);
#ifndef NDEBUG
void sqlite3VdbeMemSanity(Mem*, u8);
int sqlite3VdbeOpcodeNoPush(u8);
@ -411,3 +371,7 @@ int sqlite3VdbeOpcodeNoPush(u8);
int sqlite3VdbeMemTranslate(Mem*, u8);
void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf);
int sqlite3VdbeMemHandleBom(Mem *pMem);
void sqlite3VdbeFifoInit(Fifo*);
int sqlite3VdbeFifoPush(Fifo*, i64);
int sqlite3VdbeFifoPop(Fifo*, i64*);
void sqlite3VdbeFifoClear(Fifo*);

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

@ -15,6 +15,7 @@
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
#include "os.h"
/*
** Return TRUE (non-zero) of the statement supplied as an argument needs
@ -84,7 +85,7 @@ void sqlite3_result_blob(
int n,
void (*xDel)(void *)
){
assert( n>0 );
assert( n>=0 );
sqlite3VdbeMemSetStr(&pCtx->s, z, n, 0, xDel);
}
void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
@ -173,9 +174,10 @@ int sqlite3_step(sqlite3_stmt *pStmt){
return SQLITE_MISUSE;
}
if( p->pc<0 ){
#ifndef SQLITE_OMIT_TRACE
/* Invoke the trace callback if there is one
*/
if( (db = p->db)->xTrace && !db->init.busy ){
if( db->xTrace && !db->init.busy ){
assert( p->nOp>0 );
assert( p->aOp[p->nOp-1].opcode==OP_Noop );
assert( p->aOp[p->nOp-1].p3!=0 );
@ -187,6 +189,12 @@ int sqlite3_step(sqlite3_stmt *pStmt){
return SQLITE_MISUSE;
}
}
if( db->xProfile && !db->init.busy ){
double rNow;
sqlite3OsCurrentTime(&rNow);
p->startTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0;
}
#endif
/* Print a copy of SQL as it is executed if the SQL_TRACE pragma is turned
** on in debugging mode.
@ -213,7 +221,24 @@ int sqlite3_step(sqlite3_stmt *pStmt){
rc = SQLITE_MISUSE;
}
sqlite3Error(p->db, rc, p->zErrMsg);
#ifndef SQLITE_OMIT_TRACE
/* Invoke the profile callback if there is one
*/
if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy ){
double rNow;
u64 elapseTime;
sqlite3OsCurrentTime(&rNow);
elapseTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0 - p->startTime;
assert( p->nOp>0 );
assert( p->aOp[p->nOp-1].opcode==OP_Noop );
assert( p->aOp[p->nOp-1].p3!=0 );
assert( p->aOp[p->nOp-1].p3type==P3_DYNAMIC );
db->xProfile(db->pProfileArg, p->aOp[p->nOp-1].p3, elapseTime);
}
#endif
sqlite3Error(p->db, rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
return rc;
}
@ -230,22 +255,27 @@ void *sqlite3_user_data(sqlite3_context *p){
** Allocate or return the aggregate context for a user function. A new
** context is allocated on the first call. Subsequent calls return the
** same context that was returned on prior calls.
**
** This routine is defined here in vdbe.c because it depends on knowing
** the internals of the sqlite3_context structure which is only defined in
** this source file.
*/
void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
Mem *pMem = p->pMem;
assert( p && p->pFunc && p->pFunc->xStep );
if( p->pAgg==0 ){
if( nByte<=NBFS ){
p->pAgg = (void*)p->s.z;
memset(p->pAgg, 0, nByte);
if( (pMem->flags & MEM_Agg)==0 ){
if( nByte==0 ){
assert( pMem->flags==MEM_Null );
pMem->z = 0;
}else{
p->pAgg = sqliteMalloc( nByte );
pMem->flags = MEM_Agg;
pMem->xDel = sqlite3FreeX;
*(FuncDef**)&pMem->i = p->pFunc;
if( nByte<=NBFS ){
pMem->z = pMem->zShort;
memset(pMem->z, 0, nByte);
}else{
pMem->z = sqliteMalloc( nByte );
}
}
}
return p->pAgg;
return (void*)pMem->z;
}
/*
@ -278,8 +308,9 @@ void sqlite3_set_auxdata(
pVdbeFunc = pCtx->pVdbeFunc;
if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){
int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg;
pCtx->pVdbeFunc = pVdbeFunc = sqliteRealloc(pVdbeFunc, nMalloc);
pVdbeFunc = sqliteRealloc(pVdbeFunc, nMalloc);
if( !pVdbeFunc ) return;
pCtx->pVdbeFunc = pVdbeFunc;
memset(&pVdbeFunc->apAux[pVdbeFunc->nAux], 0,
sizeof(struct AuxData)*(iArg+1-pVdbeFunc->nAux));
pVdbeFunc->nAux = iArg+1;
@ -304,7 +335,7 @@ void sqlite3_set_auxdata(
*/
int sqlite3_aggregate_count(sqlite3_context *p){
assert( p && p->pFunc && p->pFunc->xStep );
return p->cnt;
return p->pMem->n;
}
/*
@ -369,6 +400,11 @@ sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){
const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){
return sqlite3_value_text( columnMem(pStmt,i) );
}
#if 0
sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){
return columnMem(pStmt, i);
}
#endif
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
return sqlite3_value_text16( columnMem(pStmt,i) );

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

@ -25,7 +25,7 @@
** set the sqlite3_vdbe_addop_trace to 1 and all opcodes will be printed
** as they are added to the instruction stream.
*/
#ifndef NDEBUG
#ifdef SQLITE_DEBUG
int sqlite3_vdbe_addop_trace = 0;
#endif
@ -62,16 +62,18 @@ void sqlite3VdbeTrace(Vdbe *p, FILE *trace){
** elements.
*/
static void resizeOpArray(Vdbe *p, int N){
if( p->magic==VDBE_MAGIC_RUN ){
assert( N==p->nOp );
p->nOpAlloc = N;
p->aOp = sqliteRealloc(p->aOp, N*sizeof(Op));
}else if( p->nOpAlloc<N ){
int runMode = p->magic==VDBE_MAGIC_RUN;
if( runMode || p->nOpAlloc<N ){
VdbeOp *pNew;
int nNew = N + 100*(!runMode);
int oldSize = p->nOpAlloc;
p->nOpAlloc = N+100;
p->aOp = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op));
if( p->aOp ){
memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op));
pNew = sqliteRealloc(p->aOp, nNew*sizeof(Op));
if( pNew ){
p->nOpAlloc = nNew;
p->aOp = pNew;
if( nNew>oldSize ){
memset(&p->aOp[oldSize], 0, (nNew-oldSize)*sizeof(Op));
}
}
}
}
@ -100,7 +102,7 @@ int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){
p->nOp++;
assert( p->magic==VDBE_MAGIC_INIT );
resizeOpArray(p, i+1);
if( p->aOp==0 ){
if( sqlite3_malloc_failed ){
return 0;
}
pOp = &p->aOp[i];
@ -109,6 +111,7 @@ int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){
pOp->p2 = p2;
pOp->p3 = 0;
pOp->p3type = P3_NOTUSED;
p->expired = 0;
#ifdef SQLITE_DEBUG
if( sqlite3_vdbe_addop_trace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
#endif
@ -144,7 +147,8 @@ int sqlite3VdbeMakeLabel(Vdbe *p){
assert( p->magic==VDBE_MAGIC_INIT );
if( i>=p->nLabelAlloc ){
p->nLabelAlloc = p->nLabelAlloc*2 + 10;
p->aLabel = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0]));
sqlite3ReallocOrFree((void**)&p->aLabel,
p->nLabelAlloc*sizeof(p->aLabel[0]));
}
if( p->aLabel ){
p->aLabel[i] = -1;
@ -214,8 +218,8 @@ int sqlite3VdbeOpcodeNoPush(u8 op){
**
** This routine is called once after all opcodes have been inserted.
**
** Variable *pMaxFuncArgs is set to the maximum value of any P1 argument
** to an OP_Function or P2 to an OP_AggFunc opcode. This is used by
** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument
** to an OP_Function or OP_AggStep opcode. This is used by
** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array.
**
** The integer *pMaxStack is set to the maximum number of vdbe stack
@ -238,12 +242,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
u8 opcode = pOp->opcode;
/* Todo: Maybe OP_AggFunc should change to use P1 in the same
* way as OP_Function.
*/
if( opcode==OP_Function ){
if( pOp->p1>nMaxArgs ) nMaxArgs = pOp->p1;
}else if( opcode==OP_AggFunc ){
if( opcode==OP_Function || opcode==OP_AggStep ){
if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
}else if( opcode==OP_Halt ){
if( pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort ){
@ -301,7 +300,7 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
int addr;
assert( p->magic==VDBE_MAGIC_INIT );
resizeOpArray(p, p->nOp + nOp);
if( p->aOp==0 ){
if( sqlite3_malloc_failed ){
return 0;
}
addr = p->nOp;
@ -352,6 +351,41 @@ void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){
}
}
/*
** Change teh P2 operand of instruction addr so that it points to
** the address of the next instruction to be coded.
*/
void sqlite3VdbeJumpHere(Vdbe *p, int addr){
sqlite3VdbeChangeP2(p, addr, p->nOp);
}
/*
** Delete a P3 value if necessary.
*/
static void freeP3(int p3type, void *p3){
if( p3 ){
switch( p3type ){
case P3_DYNAMIC:
case P3_KEYINFO:
case P3_KEYINFO_HANDOFF: {
sqliteFree(p3);
break;
}
case P3_VDBEFUNC: {
VdbeFunc *pVdbeFunc = (VdbeFunc *)p3;
sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
sqliteFree(pVdbeFunc);
break;
}
case P3_MEM: {
sqlite3ValueFree((sqlite3_value*)p3);
break;
}
}
}
}
/*
** Change the value of the P3 operand for a specific instruction.
** This routine is useful when a large program is loaded from a
@ -381,12 +415,7 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
Op *pOp;
assert( p->magic==VDBE_MAGIC_INIT );
if( p==0 || p->aOp==0 ){
if( n==P3_DYNAMIC || n==P3_KEYINFO_HANDOFF ){
sqliteFree((void*)zP3);
}
if( n==P3_MEM ){
sqlite3ValueFree((sqlite3_value *)zP3);
}
freeP3(n, (void*)*(char**)&zP3);
return;
}
if( addr<0 || addr>=p->nOp ){
@ -394,16 +423,19 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
if( addr<0 ) return;
}
pOp = &p->aOp[addr];
if( pOp->p3 && pOp->p3type==P3_DYNAMIC ){
sqliteFree(pOp->p3);
pOp->p3 = 0;
}
freeP3(pOp->p3type, pOp->p3);
pOp->p3 = 0;
if( zP3==0 ){
pOp->p3 = 0;
pOp->p3type = P3_NOTUSED;
}else if( n==P3_KEYINFO ){
KeyInfo *pKeyInfo;
int nField, nByte;
/* KeyInfo structures that include an KeyInfo.aSortOrder are always
** sent in using P3_KEYINFO_HANDOFF. The KeyInfo.aSortOrder array
** is not duplicated when P3_KEYINFO is used. */
/* assert( pKeyInfo->aSortOrder==0 ); */
nField = ((KeyInfo*)zP3)->nField;
nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]);
pKeyInfo = sqliteMallocRaw( nByte );
@ -442,47 +474,6 @@ void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
}
#endif
/*
** If the P3 operand to the specified instruction appears
** to be a quoted string token, then this procedure removes
** the quotes.
**
** The quoting operator can be either a grave ascent (ASCII 0x27)
** or a double quote character (ASCII 0x22). Two quotes in a row
** resolve to be a single actual quote character within the string.
*/
void sqlite3VdbeDequoteP3(Vdbe *p, int addr){
Op *pOp;
assert( p->magic==VDBE_MAGIC_INIT );
if( p->aOp==0 ) return;
if( addr<0 || addr>=p->nOp ){
addr = p->nOp - 1;
if( addr<0 ) return;
}
pOp = &p->aOp[addr];
if( pOp->p3==0 || pOp->p3[0]==0 ) return;
if( pOp->p3type==P3_STATIC ){
pOp->p3 = sqliteStrDup(pOp->p3);
pOp->p3type = P3_DYNAMIC;
}
assert( pOp->p3type==P3_DYNAMIC );
sqlite3Dequote(pOp->p3);
}
/*
** Search the current program starting at instruction addr for the given
** opcode and P2 value. Return the address plus 1 if found and 0 if not
** found.
*/
int sqlite3VdbeFindOp(Vdbe *p, int addr, int op, int p2){
int i;
assert( p->magic==VDBE_MAGIC_INIT );
for(i=addr; i<p->nOp; i++){
if( p->aOp[i].opcode==op && p->aOp[i].p2==p2 ) return i+1;
}
return 0;
}
/*
** Return the opcode for a given address.
*/
@ -617,8 +608,9 @@ int sqlite3VdbeList(
}
p->resOnStack = 0;
i = p->pc++;
do{
i = p->pc++;
}while( i<p->nOp && p->explain==2 && p->aOp[i].opcode!=OP_Explain );
if( i>=p->nOp ){
p->rc = SQLITE_OK;
rc = SQLITE_DONE;
@ -657,7 +649,7 @@ int sqlite3VdbeList(
pMem->type = SQLITE_TEXT;
pMem->enc = SQLITE_UTF8;
p->nResColumn = 5;
p->nResColumn = 5 - 2*(p->explain-1);
p->pTos = pMem;
p->rc = SQLITE_OK;
p->resOnStack = 1;
@ -698,7 +690,6 @@ void sqlite3VdbeMakeReady(
int nVar, /* Number of '?' see in the SQL statement */
int nMem, /* Number of memory cells to allocate */
int nCursor, /* Number of cursors to allocate */
int nAgg, /* Number of aggregate contexts required */
int isExplain /* True if the EXPLAIN keywords is present */
){
int n;
@ -741,7 +732,6 @@ void sqlite3VdbeMakeReady(
+ nVar*sizeof(char*) /* azVar */
+ nMem*sizeof(Mem) /* aMem */
+ nCursor*sizeof(Cursor*) /* apCsr */
+ nAgg*sizeof(Agg) /* Aggregate contexts */
);
if( !sqlite3_malloc_failed ){
p->aMem = &p->aStack[nStack];
@ -752,17 +742,12 @@ void sqlite3VdbeMakeReady(
p->apArg = (Mem**)&p->aVar[nVar];
p->azVar = (char**)&p->apArg[nArg];
p->apCsr = (Cursor**)&p->azVar[nVar];
if( nAgg>0 ){
p->nAgg = nAgg;
p->apAgg = (Agg*)&p->apCsr[nCursor];
}
p->nCursor = nCursor;
for(n=0; n<nVar; n++){
p->aVar[n].flags = MEM_Null;
}
}
}
p->pAgg = p->apAgg;
for(n=0; n<p->nMem; n++){
p->aMem[n].flags = MEM_Null;
}
@ -803,167 +788,6 @@ void sqlite3VdbeMakeReady(
#endif
}
/*
** Remove any elements that remain on the sorter for the VDBE given.
*/
void sqlite3VdbeSorterReset(Vdbe *p){
while( p->pSort ){
Sorter *pSorter = p->pSort;
p->pSort = pSorter->pNext;
sqliteFree(pSorter->zKey);
sqlite3VdbeMemRelease(&pSorter->data);
sqliteFree(pSorter);
}
p->pSortTail = 0;
}
/*
** Free all resources allociated with AggElem pElem, an element of
** aggregate pAgg.
*/
static void freeAggElem(AggElem *pElem, Agg *pAgg){
int i;
for(i=0; i<pAgg->nMem; i++){
Mem *pMem = &pElem->aMem[i];
if( pAgg->apFunc && pAgg->apFunc[i] && (pMem->flags & MEM_AggCtx)!=0 ){
sqlite3_context ctx;
ctx.pFunc = pAgg->apFunc[i];
ctx.s.flags = MEM_Null;
ctx.pAgg = pMem->z;
ctx.cnt = pMem->i;
ctx.isError = 0;
(*ctx.pFunc->xFinalize)(&ctx);
pMem->z = ctx.pAgg;
if( pMem->z!=0 && pMem->z!=pMem->zShort ){
sqliteFree(pMem->z);
}
sqlite3VdbeMemRelease(&ctx.s);
}else{
sqlite3VdbeMemRelease(pMem);
}
}
sqliteFree(pElem);
}
/*
** Reset an Agg structure. Delete all its contents.
**
** For installable aggregate functions, if the step function has been
** called, make sure the finalizer function has also been called. The
** finalizer might need to free memory that was allocated as part of its
** private context. If the finalizer has not been called yet, call it
** now.
**
** If db is NULL, then this is being called from sqliteVdbeReset(). In
** this case clean up all references to the temp-table used for
** aggregates (if it was ever opened).
**
** If db is not NULL, then this is being called from with an OP_AggReset
** opcode. Open the temp-table, if it has not already been opened and
** delete the contents of the table used for aggregate information, ready
** for the next round of aggregate processing.
*/
int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){
int rc = 0;
BtCursor *pCsr;
if( !pAgg ) return SQLITE_OK;
pCsr = pAgg->pCsr;
assert( (pCsr && pAgg->nTab>0) || (!pCsr && pAgg->nTab==0)
|| sqlite3_malloc_failed );
/* If pCsr is not NULL, then the table used for aggregate information
** is open. Loop through it and free the AggElem* structure pointed at
** by each entry. If the finalizer has not been called for an AggElem,
** do that too. Finally, clear the btree table itself.
*/
if( pCsr ){
int res;
assert( pAgg->pBtree );
assert( pAgg->nTab>0 );
rc=sqlite3BtreeFirst(pCsr, &res);
while( res==0 && rc==SQLITE_OK ){
AggElem *pElem;
rc = sqlite3BtreeData(pCsr, 0, sizeof(AggElem*), (char *)&pElem);
if( rc!=SQLITE_OK ){
return rc;
}
assert( pAgg->apFunc!=0 );
freeAggElem(pElem, pAgg);
rc=sqlite3BtreeNext(pCsr, &res);
}
if( rc!=SQLITE_OK ){
return rc;
}
sqlite3BtreeCloseCursor(pCsr);
sqlite3BtreeClearTable(pAgg->pBtree, pAgg->nTab);
}else{
/* The cursor may not be open because the aggregator was never used,
** or it could be that it was used but there was no GROUP BY clause.
*/
if( pAgg->pCurrent ){
freeAggElem(pAgg->pCurrent, pAgg);
}
}
/* If db is not NULL and we have not yet and we have not yet opened
** the temporary btree then do so and create the table to store aggregate
** information.
**
** If db is NULL, then close the temporary btree if it is open.
*/
if( db ){
if( !pAgg->pBtree ){
assert( pAgg->nTab==0 );
#ifndef SQLITE_OMIT_MEMORYDB
rc = sqlite3BtreeFactory(db, ":memory:", 0, TEMP_PAGES, &pAgg->pBtree);
#else
rc = sqlite3BtreeFactory(db, 0, 0, TEMP_PAGES, &pAgg->pBtree);
#endif
if( rc!=SQLITE_OK ) return rc;
sqlite3BtreeBeginTrans(pAgg->pBtree, 1);
rc = sqlite3BtreeCreateTable(pAgg->pBtree, &pAgg->nTab, 0);
if( rc!=SQLITE_OK ) return rc;
}
assert( pAgg->nTab!=0 );
rc = sqlite3BtreeCursor(pAgg->pBtree, pAgg->nTab, 1,
sqlite3VdbeRecordCompare, pKeyInfo, &pAgg->pCsr);
if( rc!=SQLITE_OK ) return rc;
}else{
if( pAgg->pBtree ){
sqlite3BtreeClose(pAgg->pBtree);
pAgg->pBtree = 0;
pAgg->nTab = 0;
}
pAgg->pCsr = 0;
}
if( pAgg->apFunc ){
sqliteFree(pAgg->apFunc);
pAgg->apFunc = 0;
}
pAgg->pCurrent = 0;
pAgg->nMem = 0;
pAgg->searching = 0;
return SQLITE_OK;
}
/*
** Delete a keylist
*/
void sqlite3VdbeKeylistFree(Keylist *p){
while( p ){
Keylist *pNext = p->pNext;
sqliteFree(p);
p = pNext;
}
}
/*
** Close a cursor and release all the resources that cursor happens
** to hold.
@ -1010,20 +834,13 @@ static void Cleanup(Vdbe *p){
}
closeAllCursors(p);
releaseMemArray(p->aMem, p->nMem);
if( p->pList ){
sqlite3VdbeKeylistFree(p->pList);
p->pList = 0;
}
sqlite3VdbeFifoClear(&p->sFifo);
if( p->contextStack ){
for(i=0; i<p->contextStackTop; i++){
sqlite3VdbeKeylistFree(p->contextStack[i].pList);
sqlite3VdbeFifoClear(&p->contextStack[i].sFifo);
}
sqliteFree(p->contextStack);
}
sqlite3VdbeSorterReset(p);
for(i=0; i<p->nAgg; i++){
sqlite3VdbeAggReset(0, &p->apAgg[i], 0);
}
p->contextStack = 0;
p->contextStackDepth = 0;
p->contextStackTop = 0;
@ -1145,6 +962,7 @@ static int vdbeCommit(sqlite3 *db){
*/
#ifndef SQLITE_OMIT_DISKIO
else{
int needSync = 0;
char *zMaster = 0; /* File-name for the master journal */
char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt);
OsFile master;
@ -1180,6 +998,9 @@ static int vdbeCommit(sqlite3 *db){
if( pBt && sqlite3BtreeIsInTrans(pBt) ){
char const *zFile = sqlite3BtreeGetJournalname(pBt);
if( zFile[0]==0 ) continue; /* Ignore :memory: databases */
if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){
needSync = 1;
}
rc = sqlite3OsWrite(&master, zFile, strlen(zFile)+1);
if( rc!=SQLITE_OK ){
sqlite3OsClose(&master);
@ -1196,7 +1017,8 @@ static int vdbeCommit(sqlite3 *db){
*/
zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt);
rc = sqlite3OsOpenDirectory(zMainFile, &master);
if( rc!=SQLITE_OK || (rc = sqlite3OsSync(&master))!=SQLITE_OK ){
if( rc!=SQLITE_OK ||
(needSync && (rc=sqlite3OsSync(&master,0))!=SQLITE_OK) ){
sqlite3OsClose(&master);
sqlite3OsDelete(zMaster);
sqliteFree(zMaster);
@ -1540,17 +1362,7 @@ void sqlite3VdbeDelete(Vdbe *p){
if( p->aOp ){
for(i=0; i<p->nOp; i++){
Op *pOp = &p->aOp[i];
if( pOp->p3type==P3_DYNAMIC || pOp->p3type==P3_KEYINFO ){
sqliteFree(pOp->p3);
}
if( pOp->p3type==P3_VDBEFUNC ){
VdbeFunc *pVdbeFunc = (VdbeFunc *)pOp->p3;
sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
sqliteFree(pVdbeFunc);
}
if( pOp->p3type==P3_MEM ){
sqlite3ValueFree((sqlite3_value*)pOp->p3);
}
freeP3(pOp->p3type, pOp->p3);
}
sqliteFree(p->aOp);
}
@ -1763,10 +1575,20 @@ int sqlite3VdbeSerialGet(
pMem->flags = MEM_Int;
return 6;
}
case 6: /* 6-byte signed integer */
case 6: /* 8-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];
u64 x;
u32 y;
#ifndef NDEBUG
/* Verify that integers and floating point values use the same
** byte order. The byte order differs on some (broken) architectures.
*/
static const u64 t1 = ((u64)0x3ff00000)<<32;
assert( 1.0==*(double*)&t1 );
#endif
x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
x = (x<<32) | y;
if( serial_type==6 ){
pMem->i = *(i64*)&x;
@ -1904,7 +1726,7 @@ int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){
sqlite3BtreeKeySize(pCur, &nCellKey);
if( nCellKey<=0 ){
return SQLITE_CORRUPT;
return SQLITE_CORRUPT_BKPT;
}
rc = sqlite3VdbeMemFromBtree(pCur, 0, nCellKey, 1, &m);
if( rc ){

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

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

@ -174,7 +174,7 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){
** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
*/
if( fg & MEM_Real ){
sqlite3_snprintf(NBFS, z, "%.15g", pMem->r);
sqlite3_snprintf(NBFS, z, "%!.15g", pMem->r);
}else{
assert( fg & MEM_Int );
sqlite3_snprintf(NBFS, z, "%lld", pMem->i);
@ -187,15 +187,45 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){
return rc;
}
/*
** Memory cell pMem contains the context of an aggregate function.
** This routine calls the finalize method for that function. The
** result of the aggregate is stored back into pMem.
*/
void sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
if( pFunc && pFunc->xFinalize ){
sqlite3_context ctx;
assert( (pMem->flags & MEM_Null)!=0 || pFunc==*(FuncDef**)&pMem->i );
ctx.s.flags = MEM_Null;
ctx.s.z = pMem->zShort;
ctx.pMem = pMem;
ctx.pFunc = pFunc;
pFunc->xFinalize(&ctx);
if( pMem->z && pMem->z!=pMem->zShort ){
sqliteFree( pMem->z );
}
*pMem = ctx.s;
if( pMem->flags & MEM_Short ){
pMem->z = pMem->zShort;
}
}
}
/*
** Release any memory held by the Mem. This may leave the Mem in an
** inconsistent state, for example with (Mem.z==0) and
** (Mem.type==SQLITE_TEXT).
*/
void sqlite3VdbeMemRelease(Mem *p){
if( p->flags & MEM_Dyn ){
if( p->flags & (MEM_Dyn|MEM_Agg) ){
if( p->xDel ){
p->xDel((void *)p->z);
if( p->flags & MEM_Agg ){
sqlite3VdbeMemFinalize(p, *(FuncDef**)&p->i);
assert( (p->flags & MEM_Agg)==0 );
sqlite3VdbeMemRelease(p);
}else{
p->xDel((void *)p->z);
}
}else{
sqliteFree(p->z);
}
@ -256,12 +286,14 @@ double sqlite3VdbeRealValue(Mem *pMem){
}else if( pMem->flags & MEM_Int ){
return (double)pMem->i;
}else if( pMem->flags & (MEM_Str|MEM_Blob) ){
double val = 0.0;
if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8)
|| sqlite3VdbeMemNulTerminate(pMem) ){
return SQLITE_NOMEM;
}
assert( pMem->z );
return sqlite3AtoF(pMem->z, 0);
sqlite3AtoF(pMem->z, &val);
return val;
}else{
return 0.0;
}
@ -285,6 +317,7 @@ void sqlite3VdbeMemSetNull(Mem *pMem){
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Null;
pMem->type = SQLITE_NULL;
pMem->n = 0;
}
/*
@ -406,6 +439,7 @@ int sqlite3VdbeMemSetStr(
switch( enc ){
case 0:
pMem->flags |= MEM_Blob;
pMem->enc = SQLITE_UTF8;
break;
case SQLITE_UTF8:
@ -666,9 +700,9 @@ void sqlite3VdbeMemSanity(Mem *pMem, u8 db_enc){
/* MEM_Null excludes all other types */
assert( (pMem->flags&(MEM_Str|MEM_Int|MEM_Real|MEM_Blob))==0
|| (pMem->flags&MEM_Null)==0 );
if( (pMem->flags & (MEM_Int|MEM_Real))==(MEM_Int|MEM_Real) ){
assert( pMem->r==pMem->i );
}
/* If the MEM is both real and integer, the values are equal */
assert( (pMem->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real)
|| pMem->r==pMem->i );
}
#endif
@ -696,7 +730,7 @@ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
/*
** Create a new sqlite3_value object.
*/
sqlite3_value* sqlite3ValueNew(){
sqlite3_value* sqlite3ValueNew(void){
Mem *p = sqliteMalloc(sizeof(*p));
if( p ){
p->flags = MEM_Null;

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