Upgrade libsqlite 3 inside PDO sqlite to version 3.3.15

This commit is contained in:
Ilia Alshanetsky 2007-04-09 16:35:11 +00:00
parent 857f992cd3
commit eb8d30f912
51 changed files with 5351 additions and 3624 deletions

View file

@ -211,7 +211,7 @@ static void analyzeOneTable(
}
}
sqlite3VdbeOp3(v, OP_MakeRecord, 3, 0, "aaa", 0);
sqlite3VdbeAddOp(v, OP_Insert, iStatCur, 0);
sqlite3VdbeAddOp(v, OP_Insert, iStatCur, OPFLAG_APPEND);
sqlite3VdbeJumpHere(v, addr);
}
}

View file

@ -15,6 +15,7 @@
*/
#include "sqliteInt.h"
#ifndef SQLITE_OMIT_ATTACH
/*
** Resolve an expression that was part of an ATTACH or DETACH statement. This
** is slightly different from resolving a normal SQL expression, because simple
@ -133,13 +134,14 @@ static void attachFunc(
"attached databases must use the same text encoding as main database");
goto attach_error;
}
sqlite3PagerLockingMode(sqlite3BtreePager(aNew->pBt), db->dfltLockMode);
}
aNew->zName = sqliteStrDup(zName);
aNew->safety_level = 3;
#if SQLITE_HAS_CODEC
{
extern int sqlite3CodecAttach(sqlite3*, int, void*, int);
extern int sqlite3CodecAttach(sqlite3*, int, const void*, int);
extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
int nKey;
char *zKey;
@ -188,7 +190,7 @@ static void attachFunc(
sqlite3ResetInternalSchema(db, 0);
db->nDb = iDb;
if( rc==SQLITE_NOMEM ){
if( !sqlite3MallocFailed() ) sqlite3FailedMalloc();
sqlite3FailedMalloc();
sqlite3_snprintf(sizeof(zErr),zErr, "out of memory");
}else{
sqlite3_snprintf(sizeof(zErr),zErr, "unable to open database: %s", zFile);
@ -350,14 +352,17 @@ void sqlite3Detach(Parse *pParse, Expr *pDbname){
void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
codeAttach(pParse, SQLITE_ATTACH, "sqlite_attach", 3, p, p, pDbname, pKey);
}
#endif /* SQLITE_OMIT_ATTACH */
/*
** Register the functions sqlite_attach and sqlite_detach.
*/
void sqlite3AttachFunctions(sqlite3 *db){
#ifndef SQLITE_OMIT_ATTACH
static const int enc = SQLITE_UTF8;
sqlite3CreateFunc(db, "sqlite_attach", 3, enc, db, attachFunc, 0, 0);
sqlite3CreateFunc(db, "sqlite_detach", 1, enc, db, detachFunc, 0, 0);
#endif
}
/*

File diff suppressed because it is too large Load diff

View file

@ -67,6 +67,8 @@ int sqlite3BtreeGetReserve(Btree*);
int sqlite3BtreeSetAutoVacuum(Btree *, int);
int sqlite3BtreeGetAutoVacuum(Btree *);
int sqlite3BtreeBeginTrans(Btree*,int);
int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
int sqlite3BtreeCommitPhaseTwo(Btree*);
int sqlite3BtreeCommit(Btree*);
int sqlite3BtreeRollback(Btree*);
int sqlite3BtreeBeginStmt(Btree*);
@ -76,7 +78,6 @@ int sqlite3BtreeCreateTable(Btree*, int*, int flags);
int sqlite3BtreeIsInTrans(Btree*);
int sqlite3BtreeIsInStmt(Btree*);
int sqlite3BtreeIsInReadTrans(Btree*);
int sqlite3BtreeSync(Btree*, const char *zMaster);
void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
int sqlite3BtreeSchemaLocked(Btree *);
int sqlite3BtreeLockTable(Btree *, int, u8);
@ -114,10 +115,10 @@ void sqlite3BtreeSetCompare(
);
int sqlite3BtreeCloseCursor(BtCursor*);
int sqlite3BtreeMoveto(BtCursor*, const void *pKey, i64 nKey, int *pRes);
int sqlite3BtreeMoveto(BtCursor*,const void *pKey,i64 nKey,int bias,int *pRes);
int sqlite3BtreeDelete(BtCursor*);
int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
const void *pData, int nData);
const void *pData, int nData, int bias);
int sqlite3BtreeFirst(BtCursor*, int *pRes);
int sqlite3BtreeLast(BtCursor*, int *pRes);
int sqlite3BtreeNext(BtCursor*, int *pRes);

View file

@ -82,7 +82,7 @@ void sqlite3TableLock(
}
nBytes = sizeof(TableLock) * (pParse->nTableLock+1);
sqliteReallocOrFree((void **)&pParse->aTableLock, nBytes);
pParse->aTableLock = sqliteReallocOrFree(pParse->aTableLock, nBytes);
if( pParse->aTableLock ){
p = &pParse->aTableLock[pParse->nTableLock++];
p->iDb = iDb;
@ -442,17 +442,6 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
}
}
/*
** This routine is called whenever a rollback occurs. If there were
** schema changes during the transaction, then we have to reset the
** internal hash tables and reload them from disk.
*/
void sqlite3RollbackInternalChanges(sqlite3 *db){
if( db->flags & SQLITE_InternChanges ){
sqlite3ResetInternalSchema(db, 0);
}
}
/*
** This routine is called when a commit occurs.
*/
@ -887,7 +876,7 @@ void sqlite3StartTable(
sqlite3VdbeAddOp(v, OP_NewRowid, 0, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
sqlite3VdbeAddOp(v, OP_Insert, 0, 0);
sqlite3VdbeAddOp(v, OP_Insert, 0, OPFLAG_APPEND);
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
}
@ -2357,17 +2346,17 @@ void sqlite3CreateIndex(
}
if( !db->init.busy ){
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index;
if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){
if( !ifNotExist ){
sqlite3ErrorMsg(pParse, "index %s already exists", zName);
}
goto exit_create_index;
}
if( sqlite3FindTable(db, zName, 0)!=0 ){
sqlite3ErrorMsg(pParse, "there is already a table named %s", zName);
goto exit_create_index;
}
}
if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){
if( !ifNotExist ){
sqlite3ErrorMsg(pParse, "index %s already exists", zName);
}
goto exit_create_index;
}
}else{
char zBuf[30];
int n;
@ -2783,44 +2772,46 @@ exit_drop_index:
}
/*
** 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.
** pArray is a pointer to an array of objects. Each object in the
** array is szEntry bytes in size. This routine allocates a new
** object on the end of the array.
**
** In other words, the structure looks something like this:
** *pnEntry is the number of entries already in use. *pnAlloc is
** the previously allocated size of the array. initSize is the
** suggested initial array size allocation.
**
** struct Example1 {
** struct subElem *aEntry;
** int nEntry;
** int nAlloc;
** }
** The index of the new entry is returned in *pIdx.
**
** 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.
** This routine returns a pointer to the array of objects. This
** might be the same as the pArray parameter or it might be a different
** pointer if the array was resized.
*/
int sqlite3ArrayAllocate(void **ppArray, int szEntry, int initSize){
char *p;
int *an = (int*)&ppArray[1];
if( an[0]>=an[1] ){
void *sqlite3ArrayAllocate(
void *pArray, /* Array of objects. Might be reallocated */
int szEntry, /* Size of each object in the array */
int initSize, /* Suggested initial allocation, in elements */
int *pnEntry, /* Number of objects currently in use */
int *pnAlloc, /* Current size of the allocation, in elements */
int *pIdx /* Write the index of a new slot here */
){
char *z;
if( *pnEntry >= *pnAlloc ){
void *pNew;
int newSize;
newSize = an[1]*2 + initSize;
pNew = sqliteRealloc(*ppArray, newSize*szEntry);
newSize = (*pnAlloc)*2 + initSize;
pNew = sqliteRealloc(pArray, newSize*szEntry);
if( pNew==0 ){
return -1;
*pIdx = -1;
return pArray;
}
an[1] = newSize;
*ppArray = pNew;
*pnAlloc = newSize;
pArray = pNew;
}
p = *ppArray;
memset(&p[an[0]*szEntry], 0, szEntry);
return an[0]++;
z = (char*)pArray;
memset(&z[*pnEntry * szEntry], 0, szEntry);
*pIdx = *pnEntry;
++*pnEntry;
return pArray;
}
/*
@ -2836,7 +2827,14 @@ IdList *sqlite3IdListAppend(IdList *pList, Token *pToken){
if( pList==0 ) return 0;
pList->nAlloc = 0;
}
i = sqlite3ArrayAllocate((void**)&pList->a, sizeof(pList->a[0]), 5);
pList->a = sqlite3ArrayAllocate(
pList->a,
sizeof(pList->a[0]),
5,
&pList->nId,
&pList->nAlloc,
&i
);
if( i<0 ){
sqlite3IdListDelete(pList);
return 0;

View file

@ -565,7 +565,7 @@ static int parseModifier(const char *zMod, DateTime *p){
case '8':
case '9': {
n = getValue(z, &r);
if( n<=0 ) break;
assert( n>=1 );
if( z[n]==':' ){
/* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
** specified number of hours, minutes, seconds, and fractional seconds
@ -815,7 +815,7 @@ static void strftimeFunc(
case 'f': {
double s = x.s;
if( s>59.999 ) s = 59.999;
sqlite3_snprintf(7, &z[j],"%02.3f", s);
sqlite3_snprintf(7, &z[j],"%06.3f", s);
j += strlen(&z[j]);
break;
}

View file

@ -131,7 +131,7 @@ static char comparisonAffinity(Expr *pExpr){
aff = sqlite3CompareAffinity(pExpr->pSelect->pEList->a[0].pExpr, aff);
}
else if( !aff ){
aff = SQLITE_AFF_NUMERIC;
aff = SQLITE_AFF_NONE;
}
return aff;
}
@ -404,7 +404,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
pExpr->iTable = ++pParse->nVar;
if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){
pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10;
sqliteReallocOrFree((void**)&pParse->apVarExpr,
pParse->apVarExpr = sqliteReallocOrFree(pParse->apVarExpr,
pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) );
}
if( !sqlite3MallocFailed() ){
@ -1518,6 +1518,31 @@ static void codeInteger(Vdbe *v, const char *z, int n){
}
}
/*
** Generate code that will extract the iColumn-th column from
** table pTab and push that column value on the stack. There
** is an open cursor to pTab in iTable. If iColumn<0 then
** code is generated that extracts the rowid.
*/
void sqlite3ExprCodeGetColumn(Vdbe *v, Table *pTab, int iColumn, int iTable){
if( iColumn<0 ){
int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid;
sqlite3VdbeAddOp(v, op, iTable, 0);
}else if( pTab==0 ){
sqlite3VdbeAddOp(v, OP_Column, iTable, iColumn);
}else{
int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
sqlite3VdbeAddOp(v, op, iTable, iColumn);
sqlite3ColumnDefault(v, pTab, iColumn);
#ifndef SQLITE_OMIT_FLOATING_POINT
if( pTab->aCol[iColumn].affinity==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp(v, OP_RealAffinity, 0, 0);
}
#endif
}
}
/*
** Generate code into the current Vdbe to evaluate the given
** expression and leave the result on the top of stack.
@ -1558,21 +1583,8 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
/* This only happens when coding check constraints */
assert( pParse->ckOffset>0 );
sqlite3VdbeAddOp(v, OP_Dup, pParse->ckOffset-pExpr->iColumn-1, 1);
}else if( pExpr->iColumn>=0 ){
Table *pTab = pExpr->pTab;
int iCol = pExpr->iColumn;
int op = (pTab && IsVirtual(pTab)) ? OP_VColumn : OP_Column;
sqlite3VdbeAddOp(v, op, pExpr->iTable, iCol);
sqlite3ColumnDefault(v, pTab, iCol);
#ifndef SQLITE_OMIT_FLOATING_POINT
if( pTab && pTab->aCol[iCol].affinity==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp(v, OP_RealAffinity, 0, 0);
}
#endif
}else{
Table *pTab = pExpr->pTab;
int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid;
sqlite3VdbeAddOp(v, op, pExpr->iTable, 0);
sqlite3ExprCodeGetColumn(v, pExpr->pTab, pExpr->iColumn, pExpr->iTable);
}
break;
}
@ -2175,6 +2187,16 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
/*
** Do a deep comparison of two expression trees. Return TRUE (non-zero)
** if they are identical and return FALSE if they differ in any way.
**
** Sometimes this routine will return FALSE even if the two expressions
** really are equivalent. If we cannot prove that the expressions are
** identical, we return FALSE just to be safe. So if this routine
** returns false, then you do not really know for certain if the two
** expressions are the same. But if you get a TRUE return, then you
** can be sure the expressions are the same. In the places where
** this routine is used, it does not hurt to get an extra FALSE - that
** just might result in some slightly slower code. But returning
** an incorrect TRUE could lead to a malfunction.
*/
int sqlite3ExprCompare(Expr *pA, Expr *pB){
int i;
@ -2198,7 +2220,7 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
}
if( pA->pSelect || pB->pSelect ) return 0;
if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0;
if( pA->token.z ){
if( pA->op!=TK_COLUMN && pA->token.z ){
if( pB->token.z==0 ) return 0;
if( pB->token.n!=pA->token.n ) return 0;
if( sqlite3StrNICmp((char*)pA->token.z,(char*)pB->token.z,pB->token.n)!=0 ){
@ -2215,10 +2237,14 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
*/
static int addAggInfoColumn(AggInfo *pInfo){
int i;
i = sqlite3ArrayAllocate((void**)&pInfo->aCol, sizeof(pInfo->aCol[0]), 3);
if( i<0 ){
return -1;
}
pInfo->aCol = sqlite3ArrayAllocate(
pInfo->aCol,
sizeof(pInfo->aCol[0]),
3,
&pInfo->nColumn,
&pInfo->nColumnAlloc,
&i
);
return i;
}
@ -2228,10 +2254,14 @@ static int addAggInfoColumn(AggInfo *pInfo){
*/
static int addAggInfoFunc(AggInfo *pInfo){
int i;
i = sqlite3ArrayAllocate((void**)&pInfo->aFunc, sizeof(pInfo->aFunc[0]), 2);
if( i<0 ){
return -1;
}
pInfo->aFunc = sqlite3ArrayAllocate(
pInfo->aFunc,
sizeof(pInfo->aFunc[0]),
3,
&pInfo->nFunc,
&pInfo->nFuncAlloc,
&i
);
return i;
}
@ -2266,15 +2296,17 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
** Make an entry for the column in pAggInfo->aCol[] if there
** is not an entry there already.
*/
int k;
pCol = pAggInfo->aCol;
for(i=0; i<pAggInfo->nColumn; i++, pCol++){
for(k=0; k<pAggInfo->nColumn; k++, pCol++){
if( pCol->iTable==pExpr->iTable &&
pCol->iColumn==pExpr->iColumn ){
break;
}
}
if( i>=pAggInfo->nColumn && (i = addAggInfoColumn(pAggInfo))>=0 ){
pCol = &pAggInfo->aCol[i];
if( k>=pAggInfo->nColumn && (k = addAggInfoColumn(pAggInfo))>=0 ){
pCol = &pAggInfo->aCol[k];
pCol->pTab = pExpr->pTab;
pCol->iTable = pExpr->iTable;
pCol->iColumn = pExpr->iColumn;
pCol->iMem = pParse->nMem++;
@ -2305,7 +2337,7 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
*/
pExpr->pAggInfo = pAggInfo;
pExpr->op = TK_AGG_COLUMN;
pExpr->iAgg = i;
pExpr->iAgg = k;
break;
} /* endif pExpr->iTable==pItem->iCursor */
} /* end loop over pSrcList */

View file

@ -668,6 +668,114 @@ static void hexFunc(
sqlite3_result_text(context, zHex, n*2, sqlite3_free);
}
/*
** The replace() function. Three arguments are all strings: call
** them A, B, and C. The result is also a string which is derived
** from A by replacing every occurance of B with C. The match
** must be exact. Collating sequences are not used.
*/
static void replaceFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const unsigned char *zStr; /* The input string A */
const unsigned char *zPattern; /* The pattern string B */
const unsigned char *zRep; /* The replacement string C */
unsigned char *zOut; /* The output */
int nStr; /* Size of zStr */
int nPattern; /* Size of zPattern */
int nRep; /* Size of zRep */
int nOut; /* Maximum size of zOut */
int loopLimit; /* Last zStr[] that might match zPattern[] */
int i, j; /* Loop counters */
assert( argc==3 );
if( sqlite3_value_type(argv[0])==SQLITE_NULL ||
sqlite3_value_type(argv[1])==SQLITE_NULL ||
sqlite3_value_type(argv[2])==SQLITE_NULL ){
return;
}
zStr = sqlite3_value_text(argv[0]);
nStr = sqlite3_value_bytes(argv[0]);
zPattern = sqlite3_value_text(argv[1]);
nPattern = sqlite3_value_bytes(argv[1]);
zRep = sqlite3_value_text(argv[2]);
nRep = sqlite3_value_bytes(argv[2]);
if( nPattern>=nRep ){
nOut = nStr;
}else{
nOut = (nStr/nPattern + 1)*nRep;
}
zOut = sqlite3_malloc(nOut+1);
if( zOut==0 ) return;
loopLimit = nStr - nPattern;
for(i=j=0; i<=loopLimit; i++){
if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){
zOut[j++] = zStr[i];
}else{
memcpy(&zOut[j], zRep, nRep);
j += nRep;
i += nPattern-1;
}
}
memcpy(&zOut[j], &zStr[i], nStr-i);
j += nStr - i;
assert( j<=nOut );
zOut[j] = 0;
sqlite3_result_text(context, (char*)zOut, j, sqlite3_free);
}
/*
** Implementation of the TRIM(), LTRIM(), and RTRIM() functions.
** The userdata is 0x1 for left trim, 0x2 for right trim, 0x3 for both.
*/
static void trimFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const unsigned char *zIn; /* Input string */
const unsigned char *zCharSet; /* Set of characters to trim */
int nIn; /* Number of bytes in input */
int flags;
int i;
unsigned char cFirst, cNext;
if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
return;
}
zIn = sqlite3_value_text(argv[0]);
nIn = sqlite3_value_bytes(argv[0]);
if( argc==1 ){
static const unsigned char zSpace[] = " ";
zCharSet = zSpace;
}else if( sqlite3_value_type(argv[1])==SQLITE_NULL ){
return;
}else{
zCharSet = sqlite3_value_text(argv[1]);
}
cFirst = zCharSet[0];
if( cFirst ){
flags = (int)sqlite3_user_data(context);
if( flags & 1 ){
for(; nIn>0; nIn--, zIn++){
if( cFirst==zIn[0] ) continue;
for(i=1; zCharSet[i] && zCharSet[i]!=zIn[0]; i++){}
if( zCharSet[i]==0 ) break;
}
}
if( flags & 2 ){
for(; nIn>0; nIn--){
cNext = zIn[nIn-1];
if( cFirst==cNext ) continue;
for(i=1; zCharSet[i] && zCharSet[i]!=cNext; i++){}
if( zCharSet[i]==0 ) break;
}
}
}
sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT);
}
#ifdef SQLITE_SOUNDEX
/*
** Compute the soundex encoding of a word.
@ -1019,7 +1127,7 @@ static void minmaxStep(sqlite3_context *context, int argc, sqlite3_value **argv)
** Therefore the next statement sets variable 'max' to 1 for the max()
** aggregate, or 0 for min().
*/
max = ((sqlite3_user_data(context)==(void *)-1)?1:0);
max = sqlite3_user_data(context)!=0;
cmp = sqlite3MemCompare(pBest, pArg, pColl);
if( (max && cmp<0) || (!max && cmp>0) ){
sqlite3VdbeMemCopy(pBest, pArg);
@ -1049,15 +1157,15 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
static const struct {
char *zName;
signed char nArg;
u8 argType; /* 0: none. 1: db 2: (-1) */
u8 argType; /* ff: db 1: 0, 2: 1, 3: 2,... N: N-1. */
u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */
u8 needCollSeq;
void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
} aFuncs[] = {
{ "min", -1, 0, SQLITE_UTF8, 1, minmaxFunc },
{ "min", 0, 0, SQLITE_UTF8, 1, 0 },
{ "max", -1, 2, SQLITE_UTF8, 1, minmaxFunc },
{ "max", 0, 2, SQLITE_UTF8, 1, 0 },
{ "max", -1, 1, SQLITE_UTF8, 1, minmaxFunc },
{ "max", 0, 1, SQLITE_UTF8, 1, 0 },
{ "typeof", 1, 0, SQLITE_UTF8, 0, typeofFunc },
{ "length", 1, 0, SQLITE_UTF8, 0, lengthFunc },
{ "substr", 3, 0, SQLITE_UTF8, 0, substrFunc },
@ -1079,22 +1187,29 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
{ "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc },
{ "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc},
{ "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc },
{ "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid },
{ "changes", 0, 1, SQLITE_UTF8, 0, changes },
{ "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes },
{ "last_insert_rowid", 0, 0xff, SQLITE_UTF8, 0, last_insert_rowid },
{ "changes", 0, 0xff, SQLITE_UTF8, 0, changes },
{ "total_changes", 0, 0xff, SQLITE_UTF8, 0, total_changes },
{ "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc },
{ "ltrim", 1, 1, SQLITE_UTF8, 0, trimFunc },
{ "ltrim", 2, 1, SQLITE_UTF8, 0, trimFunc },
{ "rtrim", 1, 2, SQLITE_UTF8, 0, trimFunc },
{ "rtrim", 2, 2, SQLITE_UTF8, 0, trimFunc },
{ "trim", 1, 3, SQLITE_UTF8, 0, trimFunc },
{ "trim", 2, 3, SQLITE_UTF8, 0, trimFunc },
#ifdef SQLITE_SOUNDEX
{ "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc},
{ "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc},
#endif
#ifndef SQLITE_OMIT_LOAD_EXTENSION
{ "load_extension", 1, 1, SQLITE_UTF8, 0, loadExt },
{ "load_extension", 2, 1, SQLITE_UTF8, 0, loadExt },
{ "load_extension", 1, 0xff, SQLITE_UTF8, 0, loadExt },
{ "load_extension", 2, 0xff, SQLITE_UTF8, 0, loadExt },
#endif
#ifdef SQLITE_TEST
{ "randstr", 2, 0, SQLITE_UTF8, 0, randStr },
{ "test_destructor", 1, 1, SQLITE_UTF8, 0, test_destructor},
{ "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count},
{ "test_auxdata", -1, 0, SQLITE_UTF8, 0, test_auxdata},
{ "test_error", 1, 0, SQLITE_UTF8, 0, test_error},
{ "randstr", 2, 0, SQLITE_UTF8, 0, randStr },
{ "test_destructor", 1, 0xff, SQLITE_UTF8, 0, test_destructor},
{ "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count},
{ "test_auxdata", -1, 0, SQLITE_UTF8, 0, test_auxdata},
{ "test_error", 1, 0, SQLITE_UTF8, 0, test_error},
#endif
};
static const struct {
@ -1106,7 +1221,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
void (*xFinalize)(sqlite3_context*);
} aAggs[] = {
{ "min", 1, 0, 1, minmaxStep, minMaxFinalize },
{ "max", 1, 2, 1, minmaxStep, minMaxFinalize },
{ "max", 1, 1, 1, minmaxStep, minMaxFinalize },
{ "sum", 1, 0, 0, sumStep, sumFinalize },
{ "total", 1, 0, 0, sumStep, totalFinalize },
{ "avg", 1, 0, 0, sumStep, avgFinalize },
@ -1116,10 +1231,12 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
int i;
for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
void *pArg = 0;
switch( aFuncs[i].argType ){
case 1: pArg = db; break;
case 2: pArg = (void *)(-1); break;
void *pArg;
u8 argType = aFuncs[i].argType;
if( argType==0xff ){
pArg = db;
}else{
pArg = (void*)(int)argType;
}
sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0);
@ -1138,11 +1255,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
sqlite3AttachFunctions(db);
#endif
for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
void *pArg = 0;
switch( aAggs[i].argType ){
case 1: pArg = db; break;
case 2: pArg = (void *)(-1); break;
}
void *pArg = (void*)(int)aAggs[i].argType;
sqlite3CreateFunc(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8,
pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize);
if( aAggs[i].needCollSeq ){

View file

@ -291,7 +291,7 @@ static void removeElementGivenHash(
if( pEntry->count<=0 ){
pEntry->chain = 0;
}
if( pH->copyKey && elem->pKey ){
if( pH->copyKey ){
pH->xFree(elem->pKey);
}
pH->xFree( elem );
@ -378,6 +378,9 @@ void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){
rehash(pH,8);
if( pH->htsize==0 ){
pH->count = 0;
if( pH->copyKey ){
pH->xFree(new_elem->pKey);
}
pH->xFree(new_elem);
return data;
}

View file

@ -118,6 +118,117 @@ static int selectReadsTable(Select *p, Schema *pSchema, int iTab){
return 0;
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
/*
** Write out code to initialize the autoincrement logic. This code
** looks up the current autoincrement value in the sqlite_sequence
** table and stores that value in a memory cell. Code generated by
** autoIncStep() will keep that memory cell holding the largest
** rowid value. Code generated by autoIncEnd() will write the new
** largest value of the counter back into the sqlite_sequence table.
**
** This routine returns the index of the mem[] cell that contains
** the maximum rowid counter.
**
** Two memory cells are allocated. The next memory cell after the
** one returned holds the rowid in sqlite_sequence where we will
** write back the revised maximum rowid.
*/
static int autoIncBegin(
Parse *pParse, /* Parsing context */
int iDb, /* Index of the database holding pTab */
Table *pTab /* The table we are writing to */
){
int memId = 0;
if( pTab->autoInc ){
Vdbe *v = pParse->pVdbe;
Db *pDb = &pParse->db->aDb[iDb];
int iCur = pParse->nTab;
int addr;
assert( v );
addr = sqlite3VdbeCurrentAddr(v);
memId = pParse->nMem+1;
pParse->nMem += 2;
sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
sqlite3VdbeAddOp(v, OP_Rewind, iCur, addr+13);
sqlite3VdbeAddOp(v, OP_Column, iCur, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
sqlite3VdbeAddOp(v, OP_Ne, 0x100, addr+12);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_MemStore, memId-1, 1);
sqlite3VdbeAddOp(v, OP_Column, iCur, 1);
sqlite3VdbeAddOp(v, OP_MemStore, memId, 1);
sqlite3VdbeAddOp(v, OP_Goto, 0, addr+13);
sqlite3VdbeAddOp(v, OP_Next, iCur, addr+4);
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
return memId;
}
/*
** Update the maximum rowid for an autoincrement calculation.
**
** This routine should be called when the top of the stack holds a
** new rowid that is about to be inserted. If that new rowid is
** larger than the maximum rowid in the memId memory cell, then the
** memory cell is updated. The stack is unchanged.
*/
static void autoIncStep(Parse *pParse, int memId){
if( memId>0 ){
sqlite3VdbeAddOp(pParse->pVdbe, OP_MemMax, memId, 0);
}
}
/*
** After doing one or more inserts, the maximum rowid is stored
** in mem[memId]. Generate code to write this value back into the
** the sqlite_sequence table.
*/
static void autoIncEnd(
Parse *pParse, /* The parsing context */
int iDb, /* Index of the database holding pTab */
Table *pTab, /* Table we are inserting into */
int memId /* Memory cell holding the maximum rowid */
){
if( pTab->autoInc ){
int iCur = pParse->nTab;
Vdbe *v = pParse->pVdbe;
Db *pDb = &pParse->db->aDb[iDb];
int addr;
assert( v );
addr = sqlite3VdbeCurrentAddr(v);
sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
sqlite3VdbeAddOp(v, OP_MemLoad, memId-1, 0);
sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+7);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp(v, OP_NewRowid, iCur, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
sqlite3VdbeAddOp(v, OP_MemLoad, memId, 0);
sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0);
sqlite3VdbeAddOp(v, OP_Insert, iCur, OPFLAG_APPEND);
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
}
#else
/*
** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines
** above are all no-ops
*/
# define autoIncBegin(A,B,C) (0)
# define autoIncStep(A,B)
# define autoIncEnd(A,B,C,D)
#endif /* SQLITE_OMIT_AUTOINCREMENT */
/* Forward declaration */
static int xferOptimization(
Parse *pParse, /* Parser context */
Table *pDest, /* The table we are inserting into */
Select *pSelect, /* A SELECT statement to use as the data source */
int onError, /* How to handle constraint errors */
int iDbDest /* The database of pDest */
);
/*
** This routine is call to handle SQL of the following forms:
**
@ -133,7 +244,7 @@ static int selectReadsTable(Select *p, Schema *pSchema, int iTab){
** NULL and pSelect is a pointer to the select statement used to generate
** data for the insert.
**
** The code generated follows one of three templates. For a simple
** The code generated follows one of four templates. For a simple
** select with data coming from a VALUES clause, the code executes
** once straight down through. The template looks like this:
**
@ -142,16 +253,37 @@ static int selectReadsTable(Select *p, Schema *pSchema, int iTab){
** write the resulting record into <table>
** cleanup
**
** If the statement is of the form
** The three remaining templates assume the statement is of the form
**
** INSERT INTO <table> SELECT ...
**
** And the SELECT clause does not read from <table> at any time, then
** the generated code follows this template:
** If the SELECT clause is of the restricted form "SELECT * FROM <table2>" -
** in other words if the SELECT pulls all columns from a single table
** and there is no WHERE or LIMIT or GROUP BY or ORDER BY clauses, and
** if <table2> and <table1> are distinct tables but have identical
** schemas, including all the same indices, then a special optimization
** is invoked that copies raw records from <table2> over to <table1>.
** See the xferOptimization() function for the implementation of this
** template. This is the second template.
**
** open a write cursor to <table>
** open read cursor on <table2>
** transfer all records in <table2> over to <table>
** close cursors
** foreach index on <table>
** open a write cursor on the <table> index
** open a read cursor on the corresponding <table2> index
** transfer all records from the read to the write cursors
** close cursors
** end foreach
**
** The third template is for when the second template does not apply
** and the SELECT clause does not read from <table> at any time.
** The generated code follows this template:
**
** goto B
** A: setup for the SELECT
** loop over the tables in the SELECT
** loop over the rows in the SELECT
** gosub C
** end loop
** cleanup after the SELECT
@ -162,7 +294,7 @@ static int selectReadsTable(Select *p, Schema *pSchema, int iTab){
** return
** D: cleanup
**
** The third template is used if the insert statement takes its
** The fourth template is used if the insert statement takes its
** values from a SELECT but the data is being inserted into a table
** that is also read as part of the SELECT. In the third form,
** we have to use a intermediate table to store the results of
@ -214,6 +346,7 @@ void sqlite3Insert(
int newIdx = -1; /* Cursor for the NEW table */
Db *pDb; /* The database containing table being inserted into */
int counterMem = 0; /* Memory cell holding AUTOINCREMENT counter */
int appendFlag = 0; /* True if the insert is likely to be an append */
int iDb;
#ifndef SQLITE_OMIT_TRIGGER
@ -221,10 +354,6 @@ void sqlite3Insert(
int triggers_exist = 0; /* True if there are FOR EACH ROW triggers */
#endif
#ifndef SQLITE_OMIT_AUTOINCREMENT
int counterRowid = 0; /* Memory cell holding rowid of autoinc counter */
#endif
if( pParse->nErr || sqlite3MallocFailed() ){
goto insert_cleanup;
}
@ -291,31 +420,27 @@ void sqlite3Insert(
newIdx = pParse->nTab++;
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
#ifndef SQLITE_OMIT_XFER_OPT
/* If the statement is of the form
**
** INSERT INTO <table1> SELECT * FROM <table2>;
**
** Then special optimizations can be applied that make the transfer
** very fast and which reduce fragmentation of indices.
*/
if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){
assert( !triggers_exist );
assert( pList==0 );
goto insert_cleanup;
}
#endif /* SQLITE_OMIT_XFER_OPT */
/* If this is an AUTOINCREMENT table, look up the sequence number in the
** sqlite_sequence table and store it in memory cell counterMem. Also
** remember the rowid of the sqlite_sequence table entry in memory cell
** counterRowid.
*/
if( pTab->autoInc ){
int iCur = pParse->nTab;
int addr = sqlite3VdbeCurrentAddr(v);
counterRowid = pParse->nMem++;
counterMem = pParse->nMem++;
sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
sqlite3VdbeAddOp(v, OP_Rewind, iCur, addr+13);
sqlite3VdbeAddOp(v, OP_Column, iCur, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
sqlite3VdbeAddOp(v, OP_Ne, 0x100, addr+12);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_MemStore, counterRowid, 1);
sqlite3VdbeAddOp(v, OP_Column, iCur, 1);
sqlite3VdbeAddOp(v, OP_MemStore, counterMem, 1);
sqlite3VdbeAddOp(v, OP_Goto, 0, addr+13);
sqlite3VdbeAddOp(v, OP_Next, iCur, addr+4);
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
#endif /* SQLITE_OMIT_AUTOINCREMENT */
counterMem = autoIncBegin(pParse, iDb, pTab);
/* Figure out how many columns of data are supplied. If the data
** is coming from a SELECT statement, then this step also generates
@ -365,7 +490,7 @@ void sqlite3Insert(
sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
sqlite3VdbeAddOp(v, OP_NewRowid, srcTab, 0);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
sqlite3VdbeAddOp(v, OP_Insert, srcTab, 0);
sqlite3VdbeAddOp(v, OP_Insert, srcTab, OPFLAG_APPEND);
sqlite3VdbeAddOp(v, OP_Return, 0, 0);
/* The following code runs first because the GOTO at the very top
@ -577,25 +702,32 @@ void sqlite3Insert(
}else if( pSelect ){
sqlite3VdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);
}else{
VdbeOp *pOp;
sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr);
pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1);
if( pOp->opcode==OP_Null ){
appendFlag = 1;
pOp->opcode = OP_NewRowid;
pOp->p1 = base;
pOp->p2 = counterMem;
}
}
/* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
** to generate a unique primary key value.
*/
sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
if( !appendFlag ){
sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
}
}else if( IsVirtual(pTab) ){
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
}else{
sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);
appendFlag = 1;
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
if( pTab->autoInc ){
sqlite3VdbeAddOp(v, OP_MemMax, counterMem, 0);
}
#endif /* SQLITE_OMIT_AUTOINCREMENT */
autoIncStep(pParse, counterMem);
/* Push onto the stack, data for all columns of the new entry, beginning
** with the first column.
@ -641,7 +773,8 @@ void sqlite3Insert(
sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
0, onError, endOfLoop);
sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,
(triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1);
(triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1,
appendFlag);
}
}
@ -688,26 +821,11 @@ void sqlite3Insert(
}
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Update the sqlite_sequence table by storing the content of the
** counter value in memory counterMem back into the sqlite_sequence
** table.
*/
if( pTab->autoInc ){
int iCur = pParse->nTab;
int addr = sqlite3VdbeCurrentAddr(v);
sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
sqlite3VdbeAddOp(v, OP_MemLoad, counterRowid, 0);
sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+7);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp(v, OP_NewRowid, iCur, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
sqlite3VdbeAddOp(v, OP_MemLoad, counterMem, 0);
sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0);
sqlite3VdbeAddOp(v, OP_Insert, iCur, 0);
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
#endif
autoIncEnd(pParse, iDb, pTab, counterMem);
/*
** Return the number of rows inserted. If this routine is
@ -1067,7 +1185,8 @@ void sqlite3CompleteInsertion(
char *aIdxUsed, /* Which indices are used. NULL means all are used */
int rowidChng, /* True if the record number will change */
int isUpdate, /* True for UPDATE, False for INSERT */
int newIdx /* Index of NEW table for triggers. -1 if none */
int newIdx, /* Index of NEW table for triggers. -1 if none */
int appendBias /* True if this is likely to be an append */
){
int i;
Vdbe *v;
@ -1098,6 +1217,9 @@ void sqlite3CompleteInsertion(
pik_flags = OPFLAG_NCHANGE;
pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID);
}
if( appendBias ){
pik_flags |= OPFLAG_APPEND;
}
sqlite3VdbeAddOp(v, OP_Insert, base, pik_flags);
if( !pParse->nested ){
sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
@ -1140,3 +1262,327 @@ void sqlite3OpenTableAndIndices(
pParse->nTab = base+i;
}
}
#ifdef SQLITE_TEST
/*
** The following global variable is incremented whenever the
** transfer optimization is used. This is used for testing
** purposes only - to make sure the transfer optimization really
** is happening when it is suppose to.
*/
int sqlite3_xferopt_count;
#endif /* SQLITE_TEST */
#ifndef SQLITE_OMIT_XFER_OPT
/*
** Check to collation names to see if they are compatible.
*/
static int xferCompatibleCollation(const char *z1, const char *z2){
if( z1==0 ){
return z2==0;
}
if( z2==0 ){
return 0;
}
return sqlite3StrICmp(z1, z2)==0;
}
/*
** Check to see if index pSrc is compatible as a source of data
** for index pDest in an insert transfer optimization. The rules
** for a compatible index:
**
** * The index is over the same set of columns
** * The same DESC and ASC markings occurs on all columns
** * The same onError processing (OE_Abort, OE_Ignore, etc)
** * The same collating sequence on each column
*/
static int xferCompatibleIndex(Index *pDest, Index *pSrc){
int i;
assert( pDest && pSrc );
assert( pDest->pTable!=pSrc->pTable );
if( pDest->nColumn!=pSrc->nColumn ){
return 0; /* Different number of columns */
}
if( pDest->onError!=pSrc->onError ){
return 0; /* Different conflict resolution strategies */
}
for(i=0; i<pSrc->nColumn; i++){
if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){
return 0; /* Different columns indexed */
}
if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){
return 0; /* Different sort orders */
}
if( pSrc->azColl[i]!=pDest->azColl[i] ){
return 0; /* Different sort orders */
}
}
/* If no test above fails then the indices must be compatible */
return 1;
}
/*
** Attempt the transfer optimization on INSERTs of the form
**
** INSERT INTO tab1 SELECT * FROM tab2;
**
** This optimization is only attempted if
**
** (1) tab1 and tab2 have identical schemas including all the
** same indices and constraints
**
** (2) tab1 and tab2 are different tables
**
** (3) There must be no triggers on tab1
**
** (4) The result set of the SELECT statement is "*"
**
** (5) The SELECT statement has no WHERE, HAVING, ORDER BY, GROUP BY,
** or LIMIT clause.
**
** (6) The SELECT statement is a simple (not a compound) select that
** contains only tab2 in its FROM clause
**
** This method for implementing the INSERT transfers raw records from
** tab2 over to tab1. The columns are not decoded. Raw records from
** the indices of tab2 are transfered to tab1 as well. In so doing,
** the resulting tab1 has much less fragmentation.
**
** This routine returns TRUE if the optimization is attempted. If any
** of the conditions above fail so that the optimization should not
** be attempted, then this routine returns FALSE.
*/
static int xferOptimization(
Parse *pParse, /* Parser context */
Table *pDest, /* The table we are inserting into */
Select *pSelect, /* A SELECT statement to use as the data source */
int onError, /* How to handle constraint errors */
int iDbDest /* The database of pDest */
){
ExprList *pEList; /* The result set of the SELECT */
Table *pSrc; /* The table in the FROM clause of SELECT */
Index *pSrcIdx, *pDestIdx; /* Source and destination indices */
struct SrcList_item *pItem; /* An element of pSelect->pSrc */
int i; /* Loop counter */
int iDbSrc; /* The database of pSrc */
int iSrc, iDest; /* Cursors from source and destination */
int addr1, addr2; /* Loop addresses */
int emptyDestTest; /* Address of test for empty pDest */
int emptySrcTest; /* Address of test for empty pSrc */
int memRowid = 0; /* A memcell containing a rowid from pSrc */
Vdbe *v; /* The VDBE we are building */
KeyInfo *pKey; /* Key information for an index */
int counterMem; /* Memory register used by AUTOINC */
if( pSelect==0 ){
return 0; /* Must be of the form INSERT INTO ... SELECT ... */
}
if( pDest->pTrigger ){
return 0; /* tab1 must not have triggers */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pDest->isVirtual ){
return 0; /* tab1 must not be a virtual table */
}
#endif
if( onError==OE_Default ){
onError = OE_Abort;
}
if( onError!=OE_Abort && onError!=OE_Rollback ){
return 0; /* Cannot do OR REPLACE or OR IGNORE or OR FAIL */
}
if( pSelect->pSrc==0 ){
return 0; /* SELECT must have a FROM clause */
}
if( pSelect->pSrc->nSrc!=1 ){
return 0; /* FROM clause must have exactly one term */
}
if( pSelect->pSrc->a[0].pSelect ){
return 0; /* FROM clause cannot contain a subquery */
}
if( pSelect->pWhere ){
return 0; /* SELECT may not have a WHERE clause */
}
if( pSelect->pOrderBy ){
return 0; /* SELECT may not have an ORDER BY clause */
}
/* Do not need to test for a HAVING clause. If HAVING is present but
** there is no ORDER BY, we will get an error. */
if( pSelect->pGroupBy ){
return 0; /* SELECT may not have a GROUP BY clause */
}
if( pSelect->pLimit ){
return 0; /* SELECT may not have a LIMIT clause */
}
assert( pSelect->pOffset==0 ); /* Must be so if pLimit==0 */
if( pSelect->pPrior ){
return 0; /* SELECT may not be a compound query */
}
if( pSelect->isDistinct ){
return 0; /* SELECT may not be DISTINCT */
}
pEList = pSelect->pEList;
assert( pEList!=0 );
if( pEList->nExpr!=1 ){
return 0; /* The result set must have exactly one column */
}
assert( pEList->a[0].pExpr );
if( pEList->a[0].pExpr->op!=TK_ALL ){
return 0; /* The result set must be the special operator "*" */
}
/* At this point we have established that the statement is of the
** correct syntactic form to participate in this optimization. Now
** we have to check the semantics.
*/
pItem = pSelect->pSrc->a;
pSrc = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase);
if( pSrc==0 ){
return 0; /* FROM clause does not contain a real table */
}
if( pSrc==pDest ){
return 0; /* tab1 and tab2 may not be the same table */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pSrc->isVirtual ){
return 0; /* tab2 must not be a virtual table */
}
#endif
if( pSrc->pSelect ){
return 0; /* tab2 may not be a view */
}
if( pDest->nCol!=pSrc->nCol ){
return 0; /* Number of columns must be the same in tab1 and tab2 */
}
if( pDest->iPKey!=pSrc->iPKey ){
return 0; /* Both tables must have the same INTEGER PRIMARY KEY */
}
for(i=0; i<pDest->nCol; i++){
if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){
return 0; /* Affinity must be the same on all columns */
}
if( !xferCompatibleCollation(pDest->aCol[i].zColl, pSrc->aCol[i].zColl) ){
return 0; /* Collating sequence must be the same on all columns */
}
if( pDest->aCol[i].notNull && !pSrc->aCol[i].notNull ){
return 0; /* tab2 must be NOT NULL if tab1 is */
}
}
for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
}
if( pSrcIdx==0 ){
return 0; /* pDestIdx has no corresponding index in pSrc */
}
}
#ifndef SQLITE_OMIT_CHECK
if( pDest->pCheck && !sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
}
#endif
/* If we get this far, it means either:
**
** * We can always do the transfer if the table contains an
** an integer primary key
**
** * We can conditionally do the transfer if the destination
** table is empty.
*/
#ifdef SQLITE_TEST
sqlite3_xferopt_count++;
#endif
iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema);
v = sqlite3GetVdbe(pParse);
iSrc = pParse->nTab++;
iDest = pParse->nTab++;
counterMem = autoIncBegin(pParse, iDbDest, pDest);
sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
if( pDest->iPKey<0 && pDest->pIndex!=0 ){
/* If tables do not have an INTEGER PRIMARY KEY and there
** are indices to be copied and the destination is not empty,
** we have to disallow the transfer optimization because the
** the rowids might change which will mess up indexing.
*/
addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iDest, 0);
emptyDestTest = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
sqlite3VdbeJumpHere(v, addr1);
}else{
emptyDestTest = 0;
}
sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
emptySrcTest = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0);
if( pDest->pIndex!=0 ){
sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0);
memRowid = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemStore, memRowid, pDest->iPKey>=0);
}
if( pDest->iPKey>=0 ){
addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
addr2 = sqlite3VdbeAddOp(v, OP_NotExists, iDest, 0);
sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError,
"PRIMARY KEY must be unique", P3_STATIC);
sqlite3VdbeJumpHere(v, addr2);
autoIncStep(pParse, counterMem);
}else if( pDest->pIndex==0 ){
addr1 = sqlite3VdbeAddOp(v, OP_NewRowid, iDest, 0);
}else{
addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0);
assert( pDest->autoInc==0 );
}
sqlite3VdbeAddOp(v, OP_RowData, iSrc, 0);
sqlite3VdbeOp3(v, OP_Insert, iDest,
OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND,
pDest->zName, 0);
sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1);
autoIncEnd(pParse, iDbDest, pDest, counterMem);
for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
}
assert( pSrcIdx );
sqlite3VdbeAddOp(v, OP_Close, iSrc, 0);
sqlite3VdbeAddOp(v, OP_Close, iDest, 0);
sqlite3VdbeAddOp(v, OP_Integer, iDbSrc, 0);
pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx);
VdbeComment((v, "# %s", pSrcIdx->zName));
sqlite3VdbeOp3(v, OP_OpenRead, iSrc, pSrcIdx->tnum,
(char*)pKey, P3_KEYINFO_HANDOFF);
sqlite3VdbeAddOp(v, OP_Integer, iDbDest, 0);
pKey = sqlite3IndexKeyinfo(pParse, pDestIdx);
VdbeComment((v, "# %s", pDestIdx->zName));
sqlite3VdbeOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum,
(char*)pKey, P3_KEYINFO_HANDOFF);
addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0);
sqlite3VdbeAddOp(v, OP_RowKey, iSrc, 0);
if( pDestIdx->onError!=OE_None ){
sqlite3VdbeAddOp(v, OP_MemLoad, memRowid, 0);
addr2 = sqlite3VdbeAddOp(v, OP_IsUnique, iDest, 0);
sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError,
"UNIQUE constraint failed", P3_STATIC);
sqlite3VdbeJumpHere(v, addr2);
}
sqlite3VdbeAddOp(v, OP_IdxInsert, iDest, 1);
sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1+1);
sqlite3VdbeJumpHere(v, addr1);
}
sqlite3VdbeJumpHere(v, emptySrcTest);
sqlite3VdbeAddOp(v, OP_Close, iSrc, 0);
sqlite3VdbeAddOp(v, OP_Close, iDest, 0);
if( emptyDestTest ){
sqlite3VdbeAddOp(v, OP_Halt, SQLITE_OK, 0);
sqlite3VdbeJumpHere(v, emptyDestTest);
sqlite3VdbeAddOp(v, OP_Close, iDest, 0);
return 0;
}else{
return 1;
}
}
#endif /* SQLITE_OMIT_XFER_OPT */

View file

@ -1,85 +1,98 @@
/* Hash score: 167 */
/***** This file contains automatically generated code ******
**
** The code in this file has been automatically generated by
**
** $Header$
**
** The code in this file implements a function that determines whether
** or not a given identifier is really an SQL keyword. The same thing
** might be implemented more directly using a hand-written hash table.
** But by using this automatically generated code, the size of the code
** is substantially reduced. This is important for embedded applications
** on platforms with limited memory.
*/
/* Hash score: 165 */
static int keywordCode(const char *z, int n){
static const char zText[544] =
static const char zText[536] =
"ABORTABLEFTEMPORARYADDATABASELECTHENDEFAULTRANSACTIONATURALTER"
"AISEACHECKEYAFTEREFERENCESCAPELSEXCEPTRIGGEREGEXPLAINITIALLYANALYZE"
"XCLUSIVEXISTSTATEMENTANDEFERRABLEATTACHAVINGLOBEFOREIGNOREINDEX"
"AUTOINCREMENTBEGINNERENAMEBETWEENOTNULLIKEBYCASCADEFERREDELETE"
"CASECASTCOLLATECOLUMNCOMMITCONFLICTCONSTRAINTERSECTCREATECROSS"
"CURRENT_DATECURRENT_TIMESTAMPLANDESCDETACHDISTINCTDROPRAGMATCH"
"FAILIMITFROMFULLGROUPDATEIFIMMEDIATEINSERTINSTEADINTOFFSETISNULL"
"JOINORDEREPLACEOUTERESTRICTPRIMARYQUERYRIGHTROLLBACKROWHENUNION"
"UNIQUEUSINGVACUUMVALUESVIEWHEREVIRTUAL";
"XCLUSIVEXISTSANDEFERRABLEATTACHAVINGLOBEFOREIGNOREINDEXAUTOINCREMENT"
"BEGINNERENAMEBETWEENOTNULLIKEBYCASCADEFERREDELETECASECASTCOLLATE"
"COLUMNCOMMITCONFLICTCONSTRAINTERSECTCREATECROSSCURRENT_DATECURRENT_TIMESTAMP"
"LANDESCDETACHDISTINCTDROPRAGMATCHFAILIMITFROMFULLGROUPDATEIFIMMEDIATE"
"INSERTINSTEADINTOFFSETISNULLJOINORDEREPLACEOUTERESTRICTPRIMARY"
"QUERYRIGHTROLLBACKROWHENUNIONUNIQUEUSINGVACUUMVALUESVIEWHEREVIRTUAL"
;
static const unsigned char aHash[127] = {
92, 80, 107, 91, 0, 4, 0, 0, 114, 0, 83, 0, 0,
95, 44, 76, 93, 0, 106, 109, 97, 90, 0, 10, 0, 0,
113, 0, 117, 103, 0, 28, 48, 0, 41, 0, 0, 65, 71,
0, 63, 19, 0, 105, 36, 104, 0, 108, 74, 0, 0, 33,
0, 61, 37, 0, 8, 0, 115, 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, 101, 58, 18, 0, 112, 82, 99,
54, 6, 85, 0, 0, 49, 94, 0, 102, 0, 70, 0, 0,
15, 0, 116, 51, 56, 0, 2, 55, 0, 111,
91, 79, 106, 90, 0, 4, 0, 0, 113, 0, 82, 0, 0,
94, 43, 75, 92, 0, 105, 108, 96, 89, 0, 10, 0, 0,
112, 0, 116, 102, 0, 28, 47, 0, 40, 0, 0, 64, 70,
0, 62, 19, 0, 104, 35, 103, 0, 107, 73, 0, 0, 33,
0, 60, 36, 0, 8, 0, 114, 37, 12, 0, 76, 39, 25,
65, 0, 0, 31, 80, 52, 30, 49, 20, 87, 0, 34, 0,
74, 26, 0, 71, 0, 0, 0, 63, 46, 66, 22, 86, 29,
68, 85, 0, 1, 0, 9, 100, 57, 18, 0, 111, 81, 98,
53, 6, 84, 0, 0, 48, 93, 0, 101, 0, 69, 0, 0,
15, 0, 115, 50, 55, 0, 2, 54, 0, 110,
};
static const unsigned char aNext[117] = {
static const unsigned char aNext[116] = {
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, 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, 0, 39, 96, 98, 0, 0, 100, 0, 32,
0, 14, 27, 78, 0, 57, 89, 0, 35, 0, 62, 0, 110,
0, 11, 0, 0, 0, 0, 5, 13, 7, 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, 0, 58, 0,
0, 0, 0, 0, 0, 0, 0, 72, 41, 0, 24, 59, 21,
0, 78, 0, 0, 67, 0, 0, 83, 45, 0, 0, 0, 0,
0, 0, 0, 0, 38, 95, 97, 0, 0, 99, 0, 32, 0,
14, 27, 77, 0, 56, 88, 0, 0, 0, 61, 0, 109,
};
static const unsigned char aLen[117] = {
static const unsigned char aLen[116] = {
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, 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, 2, 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, 7,
7, 6, 7, 9, 3, 7, 9, 6, 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, 2, 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, 7,
};
static const unsigned short int aOffset[117] = {
static const unsigned short int aOffset[116] = {
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, 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, 405,
414, 420, 427, 430, 430, 433, 436, 442, 446, 450, 457, 461, 469,
476, 481, 486, 494, 496, 500, 505, 511, 516, 522, 528, 531, 536,
99, 105, 108, 113, 118, 122, 128, 136, 142, 144, 154, 159, 164,
167, 169, 169, 173, 177, 179, 184, 186, 188, 197, 200, 204, 210,
216, 216, 219, 222, 226, 228, 229, 233, 240, 246, 250, 254, 261,
267, 273, 281, 288, 297, 303, 308, 320, 320, 336, 340, 344, 350,
351, 358, 361, 365, 370, 373, 378, 382, 386, 389, 395, 397, 406,
412, 419, 422, 422, 425, 428, 434, 438, 442, 449, 453, 461, 468,
473, 478, 486, 488, 492, 497, 503, 508, 514, 520, 523, 528,
};
static const unsigned char aCode[117] = {
static const unsigned char aCode[116] = {
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_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_IF,
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, TK_VIRTUAL,
TK_ALL, TK_ANALYZE, TK_EXCLUSIVE, TK_EXISTS, 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_IF, 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,
TK_VIRTUAL,
};
int h, i;
if( n<2 ) return TK_ID;

View file

@ -229,6 +229,13 @@ const sqlite3_api_routines sqlite3_apis = {
*************************************************************************
*/
sqlite3_overload_function,
/*
** Added after 3.3.13
*/
sqlite3_prepare_v2,
sqlite3_prepare16_v2,
sqlite3_clear_bindings,
};
/*

View file

@ -20,12 +20,6 @@
#include "os.h"
#include <ctype.h>
/*
** The following constant value is used by the SQLITE_BIGENDIAN and
** SQLITE_LITTLEENDIAN macros.
*/
const int sqlite3one = 1;
/*
** The version of the library
*/
@ -33,6 +27,24 @@ const char sqlite3_version[] = SQLITE_VERSION;
const char *sqlite3_libversion(void){ return sqlite3_version; }
int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; }
/*
** If the following function pointer is not NULL and if
** SQLITE_ENABLE_IOTRACE is enabled, then messages describing
** I/O active are written using this function. These messages
** are intended for debugging activity only.
*/
void (*sqlite3_io_trace)(const char*, ...) = 0;
/*
** If the following global variable points to a string which is the
** name of a directory, then that directory will be used to store
** temporary files.
**
** See also the "PRAGMA temp_store_directory" SQL command.
*/
char *sqlite3_temp_directory = 0;
/*
** This is the default collating function named "BINARY" which is always
** available.
@ -128,6 +140,9 @@ int sqlite3_close(sqlite3 *db){
** cannot be opened for some reason. So this routine needs to run in
** that case. But maybe there should be an extra magic value for the
** "failed to open" state.
**
** TODO: Coverage tests do not test the case where this condition is
** true. It's hard to see how to cause it without messing with threads.
*/
if( db->magic!=SQLITE_MAGIC_CLOSED && sqlite3SafetyOn(db) ){
/* printf("DID NOT CLOSE\n"); fflush(stdout); */
@ -239,7 +254,6 @@ const char *sqlite3ErrStr(int rc){
case SQLITE_CORRUPT: z = "database disk image is malformed"; 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_CONSTRAINT: z = "constraint failed"; break;
@ -722,7 +736,8 @@ int sqlite3BtreeFactory(
*/
const char *sqlite3_errmsg(sqlite3 *db){
const char *z;
if( !db || sqlite3MallocFailed() ){
assert( !sqlite3MallocFailed() );
if( !db ){
return sqlite3ErrStr(SQLITE_NOMEM);
}
if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){
@ -761,7 +776,8 @@ const void *sqlite3_errmsg16(sqlite3 *db){
};
const void *z;
if( sqlite3MallocFailed() ){
assert( !sqlite3MallocFailed() );
if( !db ){
return (void *)(&outOfMemBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]);
}
if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){
@ -876,6 +892,9 @@ static int openDatabase(
db->flags |= SQLITE_ShortColNames
#if SQLITE_DEFAULT_FILE_FORMAT<4
| SQLITE_LegacyFileFmt
#endif
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
| SQLITE_LoadExtension
#endif
;
sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0);
@ -958,6 +977,16 @@ static int openDatabase(
}
#endif
/* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking
** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking
** mode. Doing nothing at all also makes NORMAL the default.
*/
#ifdef SQLITE_DEFAULT_LOCKING_MODE
db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE;
sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt),
SQLITE_DEFAULT_LOCKING_MODE);
#endif
opendb_out:
if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){
sqlite3_close(db);

View file

@ -61,31 +61,31 @@ const char *const sqlite3OpcodeNames[] = { "?",
/* 57 */ "Function",
/* 58 */ "NewRowid",
/* 59 */ "Blob",
/* 60 */ "Next",
/* 61 */ "Or",
/* 62 */ "And",
/* 60 */ "Or",
/* 61 */ "And",
/* 62 */ "Next",
/* 63 */ "ForceInt",
/* 64 */ "ReadCookie",
/* 65 */ "Halt",
/* 66 */ "IsNull",
/* 67 */ "NotNull",
/* 68 */ "Ne",
/* 69 */ "Eq",
/* 70 */ "Gt",
/* 71 */ "Le",
/* 72 */ "Lt",
/* 73 */ "Ge",
/* 74 */ "Expire",
/* 75 */ "BitAnd",
/* 76 */ "BitOr",
/* 77 */ "ShiftLeft",
/* 78 */ "ShiftRight",
/* 79 */ "Add",
/* 80 */ "Subtract",
/* 81 */ "Multiply",
/* 82 */ "Divide",
/* 83 */ "Remainder",
/* 84 */ "Concat",
/* 65 */ "IsNull",
/* 66 */ "NotNull",
/* 67 */ "Ne",
/* 68 */ "Eq",
/* 69 */ "Gt",
/* 70 */ "Le",
/* 71 */ "Lt",
/* 72 */ "Ge",
/* 73 */ "Halt",
/* 74 */ "BitAnd",
/* 75 */ "BitOr",
/* 76 */ "ShiftLeft",
/* 77 */ "ShiftRight",
/* 78 */ "Add",
/* 79 */ "Subtract",
/* 80 */ "Multiply",
/* 81 */ "Divide",
/* 82 */ "Remainder",
/* 83 */ "Concat",
/* 84 */ "Expire",
/* 85 */ "Negative",
/* 86 */ "DropIndex",
/* 87 */ "BitNot",
@ -126,9 +126,9 @@ const char *const sqlite3OpcodeNames[] = { "?",
/* 122 */ "MakeRecord",
/* 123 */ "Variable",
/* 124 */ "CreateTable",
/* 125 */ "Insert",
/* 126 */ "Real",
/* 127 */ "HexBlob",
/* 125 */ "Real",
/* 126 */ "HexBlob",
/* 127 */ "Insert",
/* 128 */ "IdxGE",
/* 129 */ "OpenRead",
/* 130 */ "IdxRowid",
@ -139,11 +139,10 @@ const char *const sqlite3OpcodeNames[] = { "?",
/* 135 */ "NotUsed_135",
/* 136 */ "NotUsed_136",
/* 137 */ "NotUsed_137",
/* 138 */ "NotUsed_138",
/* 139 */ "ToText",
/* 140 */ "ToBlob",
/* 141 */ "ToNumeric",
/* 142 */ "ToInt",
/* 143 */ "ToReal",
/* 138 */ "ToText",
/* 139 */ "ToBlob",
/* 140 */ "ToNumeric",
/* 141 */ "ToInt",
/* 142 */ "ToReal",
};
#endif

View file

@ -3,9 +3,9 @@
#define OP_NotExists 1
#define OP_Dup 2
#define OP_MoveLt 3
#define OP_Multiply 81 /* same as TK_STAR */
#define OP_Multiply 80 /* same as TK_STAR */
#define OP_VCreate 4
#define OP_BitAnd 75 /* same as TK_BITAND */
#define OP_BitAnd 74 /* same as TK_BITAND */
#define OP_DropTrigger 5
#define OP_OpenPseudo 6
#define OP_MemInt 7
@ -14,9 +14,9 @@
#define OP_LoadAnalysis 10
#define OP_IdxGT 11
#define OP_Last 12
#define OP_Subtract 80 /* same as TK_MINUS */
#define OP_Subtract 79 /* same as TK_MINUS */
#define OP_MemLoad 13
#define OP_Remainder 83 /* same as TK_REM */
#define OP_Remainder 82 /* same as TK_REM */
#define OP_SetCookie 14
#define OP_Sequence 15
#define OP_Pull 17
@ -25,36 +25,36 @@
#define OP_DropTable 20
#define OP_MemStore 21
#define OP_ContextPush 22
#define OP_NotNull 67 /* same as TK_NOTNULL */
#define OP_NotNull 66 /* same as TK_NOTNULL */
#define OP_Rowid 23
#define OP_Real 126 /* same as TK_FLOAT */
#define OP_String8 89 /* same as TK_STRING */
#define OP_And 62 /* same as TK_AND */
#define OP_BitNot 88 /* same as TK_BITNOT */
#define OP_Real 125 /* same as TK_FLOAT */
#define OP_String8 88 /* same as TK_STRING */
#define OP_And 61 /* same as TK_AND */
#define OP_BitNot 87 /* same as TK_BITNOT */
#define OP_VFilter 24
#define OP_NullRow 25
#define OP_Noop 26
#define OP_VRowid 27
#define OP_Ge 73 /* same as TK_GE */
#define OP_HexBlob 127 /* same as TK_BLOB */
#define OP_Ge 72 /* same as TK_GE */
#define OP_HexBlob 126 /* same as TK_BLOB */
#define OP_ParseSchema 28
#define OP_Statement 29
#define OP_CollSeq 30
#define OP_ContextPop 31
#define OP_ToText 139 /* same as TK_TO_TEXT */
#define OP_ToText 138 /* same as TK_TO_TEXT */
#define OP_MemIncr 32
#define OP_MoveGe 33
#define OP_Eq 69 /* same as TK_EQ */
#define OP_ToNumeric 141 /* same as TK_TO_NUMERIC*/
#define OP_Eq 68 /* same as TK_EQ */
#define OP_ToNumeric 140 /* same as TK_TO_NUMERIC*/
#define OP_If 34
#define OP_IfNot 35
#define OP_ShiftRight 78 /* same as TK_RSHIFT */
#define OP_ShiftRight 77 /* same as TK_RSHIFT */
#define OP_Destroy 36
#define OP_Distinct 37
#define OP_CreateIndex 38
#define OP_SetNumColumns 39
#define OP_Not 16 /* same as TK_NOT */
#define OP_Gt 70 /* same as TK_GT */
#define OP_Gt 69 /* same as TK_GT */
#define OP_ResetCount 40
#define OP_MakeIdxRec 41
#define OP_Goto 42
@ -69,40 +69,40 @@
#define OP_AutoCommit 51
#define OP_String 52
#define OP_FifoWrite 53
#define OP_ToInt 142 /* same as TK_TO_INT */
#define OP_ToInt 141 /* same as TK_TO_INT */
#define OP_Return 54
#define OP_Callback 55
#define OP_AddImm 56
#define OP_Function 57
#define OP_Concat 84 /* same as TK_CONCAT */
#define OP_Concat 83 /* same as TK_CONCAT */
#define OP_NewRowid 58
#define OP_Blob 59
#define OP_IsNull 66 /* same as TK_ISNULL */
#define OP_Next 60
#define OP_IsNull 65 /* same as TK_ISNULL */
#define OP_Next 62
#define OP_ForceInt 63
#define OP_ReadCookie 64
#define OP_Halt 65
#define OP_Expire 74
#define OP_Or 61 /* same as TK_OR */
#define OP_DropIndex 85
#define OP_IdxInsert 87
#define OP_ShiftLeft 77 /* same as TK_LSHIFT */
#define OP_Halt 73
#define OP_Expire 84
#define OP_Or 60 /* same as TK_OR */
#define OP_DropIndex 86
#define OP_IdxInsert 89
#define OP_ShiftLeft 76 /* same as TK_LSHIFT */
#define OP_FifoRead 90
#define OP_Column 91
#define OP_Int64 92
#define OP_Gosub 93
#define OP_IfMemNeg 94
#define OP_RowData 95
#define OP_BitOr 76 /* same as TK_BITOR */
#define OP_BitOr 75 /* same as TK_BITOR */
#define OP_MemMax 96
#define OP_Close 97
#define OP_ToReal 143 /* same as TK_TO_REAL */
#define OP_ToReal 142 /* same as TK_TO_REAL */
#define OP_VerifyCookie 98
#define OP_IfMemPos 99
#define OP_Null 100
#define OP_Integer 101
#define OP_Transaction 102
#define OP_Divide 82 /* same as TK_SLASH */
#define OP_Divide 81 /* same as TK_SLASH */
#define OP_IdxLT 103
#define OP_Delete 104
#define OP_Rewind 105
@ -117,34 +117,33 @@
#define OP_VOpen 114
#define OP_AggFinal 115
#define OP_OpenWrite 116
#define OP_Negative 86 /* same as TK_UMINUS */
#define OP_Le 71 /* same as TK_LE */
#define OP_Negative 85 /* same as TK_UMINUS */
#define OP_Le 70 /* same as TK_LE */
#define OP_VNext 117
#define OP_AbsValue 118
#define OP_Sort 119
#define OP_NotFound 120
#define OP_MoveLe 121
#define OP_MakeRecord 122
#define OP_Add 79 /* same as TK_PLUS */
#define OP_Ne 68 /* same as TK_NE */
#define OP_Add 78 /* same as TK_PLUS */
#define OP_Ne 67 /* same as TK_NE */
#define OP_Variable 123
#define OP_CreateTable 124
#define OP_Insert 125
#define OP_Insert 127
#define OP_IdxGE 128
#define OP_OpenRead 129
#define OP_IdxRowid 130
#define OP_ToBlob 140 /* same as TK_TO_BLOB */
#define OP_ToBlob 139 /* same as TK_TO_BLOB */
#define OP_VBegin 131
#define OP_TableLock 132
#define OP_OpenEphemeral 133
#define OP_Lt 72 /* same as TK_LT */
#define OP_Lt 71 /* same as TK_LT */
#define OP_Pop 134
/* The following opcode values are never used */
#define OP_NotUsed_135 135
#define OP_NotUsed_136 136
#define OP_NotUsed_137 137
#define OP_NotUsed_138 138
/* Opcodes that are guaranteed to never push a value onto the stack
** contain a 1 their corresponding position of the following mask
@ -154,8 +153,8 @@
#define NOPUSH_MASK_2 0xedaf
#define NOPUSH_MASK_3 0xf1eb
#define NOPUSH_MASK_4 0xfffe
#define NOPUSH_MASK_5 0x61ef
#define NOPUSH_MASK_5 0x62f7
#define NOPUSH_MASK_6 0xbfcf
#define NOPUSH_MASK_7 0x23bf
#define NOPUSH_MASK_8 0xf87b
#define NOPUSH_MASK_7 0x83bf
#define NOPUSH_MASK_8 0x7c7b
#define NOPUSH_MASK_9 0x0000

View file

@ -16,6 +16,7 @@
#define _SQLITE_OS_C_ 1
#include "sqliteInt.h"
#include "os.h"
#undef _SQLITE_OS_C_
/*
** The following routines are convenience wrappers around methods
@ -75,6 +76,10 @@ int sqlite3OsLockState(OsFile *id){
int sqlite3OsCheckReservedLock(OsFile *id){
return id->pMethod->xCheckReservedLock(id);
}
int sqlite3OsSectorSize(OsFile *id){
int (*xSectorSize)(OsFile*) = id->pMethod->xSectorSize;
return xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE;
}
#ifdef SQLITE_ENABLE_REDEF_IO
/*

View file

@ -21,6 +21,18 @@
** Figure out if we are dealing with Unix, Windows, or some other
** operating system.
*/
#if defined(OS_OTHER)
# if OS_OTHER==1
# undef OS_UNIX
# define OS_UNIX 0
# undef OS_WIN
# define OS_WIN 0
# undef OS_OS2
# define OS_OS2 0
# else
# undef OS_OTHER
# endif
#endif
#if !defined(OS_UNIX) && !defined(OS_OTHER)
# define OS_OTHER 0
# ifndef OS_WIN
@ -73,6 +85,13 @@
# define SET_FULLSYNC(x,y)
#endif
/*
** The default size of a disk sector
*/
#ifndef SQLITE_DEFAULT_SECTOR_SIZE
# define SQLITE_DEFAULT_SECTOR_SIZE 512
#endif
/*
** Temporary files are named starting with this prefix followed by 16 random
** alphanumeric characters, and no file extension. They are stored in the
@ -216,6 +235,7 @@ struct IoMethod {
int (*xUnlock)(OsFile*, int);
int (*xLockState)(OsFile *id);
int (*xCheckReservedLock)(OsFile *id);
int (*xSectorSize)(OsFile *id);
};
/*
@ -346,6 +366,7 @@ int sqlite3OsFileExists(const char*);
char *sqlite3OsFullPathname(const char*);
int sqlite3OsIsDirWritable(char*);
int sqlite3OsSyncDirectory(const char*);
int sqlite3OsSectorSize(OsFile *id);
int sqlite3OsTempFileName(char*);
int sqlite3OsRandomSeed(char*);
int sqlite3OsSleep(int ms);
@ -426,9 +447,12 @@ struct sqlite3OsVtbl {
#endif
#ifdef _SQLITE_OS_C_
#if defined(_SQLITE_OS_C_) || defined(SQLITE_AMALGAMATION)
/*
** The os.c file implements the global virtual function table.
** We have to put this file here because the initializers
** (ex: sqlite3OsRandomSeed) are macros that are about to be
** redefined.
*/
struct sqlite3OsVtbl sqlite3Os = {
IF_DISKIO( sqlite3OsOpenReadWrite ),

View file

@ -38,25 +38,23 @@ unsigned int sqlite3_pending_byte = 0x40000000;
int sqlite3_os_trace = 0;
#ifdef SQLITE_DEBUG
static int last_page = 0;
#define SEEK(X) last_page=(X)
#define TRACE1(X) if( sqlite3_os_trace ) sqlite3DebugPrintf(X)
#define TRACE2(X,Y) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y)
#define TRACE3(X,Y,Z) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z)
#define TRACE4(X,Y,Z,A) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A)
#define TRACE5(X,Y,Z,A,B) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A,B)
#define TRACE6(X,Y,Z,A,B,C) if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C)
#define TRACE7(X,Y,Z,A,B,C,D) \
#define OSTRACE1(X) if( sqlite3_os_trace ) sqlite3DebugPrintf(X)
#define OSTRACE2(X,Y) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y)
#define OSTRACE3(X,Y,Z) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z)
#define OSTRACE4(X,Y,Z,A) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A)
#define OSTRACE5(X,Y,Z,A,B) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A,B)
#define OSTRACE6(X,Y,Z,A,B,C) \
if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C)
#define OSTRACE7(X,Y,Z,A,B,C,D) \
if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D)
#else
#define SEEK(X)
#define TRACE1(X)
#define TRACE2(X,Y)
#define TRACE3(X,Y,Z)
#define TRACE4(X,Y,Z,A)
#define TRACE5(X,Y,Z,A,B)
#define TRACE6(X,Y,Z,A,B,C)
#define TRACE7(X,Y,Z,A,B,C,D)
#define OSTRACE1(X)
#define OSTRACE2(X,Y)
#define OSTRACE3(X,Y,Z)
#define OSTRACE4(X,Y,Z,A)
#define OSTRACE5(X,Y,Z,A,B)
#define OSTRACE6(X,Y,Z,A,B,C)
#define OSTRACE7(X,Y,Z,A,B,C,D)
#endif
/*
@ -90,19 +88,23 @@ static unsigned int elapse;
#ifdef SQLITE_TEST
int sqlite3_io_error_hit = 0;
int sqlite3_io_error_pending = 0;
int sqlite3_io_error_persist = 0;
int sqlite3_diskfull_pending = 0;
int sqlite3_diskfull = 0;
#define SimulateIOError(CODE) \
if( sqlite3_io_error_pending ) \
if( sqlite3_io_error_pending-- == 1 ){ local_ioerr(); CODE; }
if( sqlite3_io_error_pending || sqlite3_io_error_hit ) \
if( sqlite3_io_error_pending-- == 1 \
|| (sqlite3_io_error_persist && sqlite3_io_error_hit) ) \
{ local_ioerr(); CODE; }
static void local_ioerr(){
sqlite3_io_error_hit = 1; /* Really just a place to set a breakpoint */
sqlite3_io_error_hit = 1;
}
#define SimulateDiskfullError(CODE) \
if( sqlite3_diskfull_pending ){ \
if( sqlite3_diskfull_pending == 1 ){ \
local_ioerr(); \
sqlite3_diskfull = 1; \
sqlite3_io_error_hit = 1; \
CODE; \
}else{ \
sqlite3_diskfull_pending--; \
@ -186,3 +188,10 @@ void sqlite3GenericFree(void *p){
/* Never actually used, but needed for the linker */
int sqlite3GenericAllocationSize(void *p){ return 0; }
#endif
/*
** The default size of a disk sector
*/
#ifndef PAGER_SECTOR_SIZE
# define PAGER_SECTOR_SIZE 512
#endif

View file

@ -59,7 +59,10 @@
** If we are to be thread-safe, include the pthreads header and define
** the SQLITE_UNIX_THREADS macro.
*/
#if defined(THREADSAFE) && THREADSAFE
#ifndef THREADSAFE
# define THREADSAFE 1
#endif
#if THREADSAFE
# include <pthread.h>
# define SQLITE_UNIX_THREADS 1
#endif
@ -457,7 +460,7 @@ static int lockTrace(int fd, int op, struct flock *p){
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) ){
if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
struct flock l2;
l2 = *p;
fcntl(fd, F_GETLK, &l2);
@ -753,19 +756,20 @@ static int transferOwnership(unixFile *pFile){
hSelf = pthread_self();
if( pthread_equal(pFile->tid, hSelf) ){
/* We are still in the same thread */
TRACE1("No-transfer, same thread\n");
OSTRACE1("No-transfer, same thread\n");
return SQLITE_OK;
}
if( pFile->locktype!=NO_LOCK ){
/* We cannot change ownership while we are holding a lock! */
return SQLITE_MISUSE;
}
TRACE4("Transfer ownership of %d from %d to %d\n", pFile->h,pFile->tid,hSelf);
OSTRACE4("Transfer ownership of %d from %d to %d\n",
pFile->h, pFile->tid, hSelf);
pFile->tid = hSelf;
if (pFile->pLock != NULL) {
releaseLockInfo(pFile->pLock);
rc = findLockInfo(pFile->h, &pFile->pLock, 0);
TRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h,
OSTRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h,
locktypeName(pFile->locktype),
locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);
return rc;
@ -782,6 +786,7 @@ static int transferOwnership(unixFile *pFile){
** Delete the named file
*/
int sqlite3UnixDelete(const char *zFilename){
SimulateIOError(return SQLITE_IOERR_DELETE);
unlink(zFilename);
return SQLITE_OK;
}
@ -864,7 +869,7 @@ int sqlite3UnixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
assert( 0==*pId );
h = open(zFilename,
O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY,
SQLITE_DEFAULT_FILE_PERMISSIONS);
delFlag ? 0600 : SQLITE_DEFAULT_FILE_PERMISSIONS);
if( h<0 ){
return SQLITE_CANTOPEN;
}
@ -914,30 +919,17 @@ static int unixOpenDirectory(
const char *zDirname
){
unixFile *pFile = (unixFile*)id;
if( pFile==0 ){
/* Do not open the directory if the corresponding file is not already
** open. */
return SQLITE_CANTOPEN;
}
assert( pFile!=0 );
SET_THREADID(pFile);
assert( pFile->dirfd<0 );
pFile->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0);
if( pFile->dirfd<0 ){
return SQLITE_CANTOPEN;
}
TRACE3("OPENDIR %-3d %s\n", pFile->dirfd, zDirname);
OSTRACE3("OPENDIR %-3d %s\n", pFile->dirfd, zDirname);
return SQLITE_OK;
}
/*
** If the following global variable points to a string which is the
** name of a directory, then that directory will be used to store
** temporary files.
**
** See also the "PRAGMA temp_store_directory" SQL command.
*/
char *sqlite3_temp_directory = 0;
/*
** Create a temporary file name in zBuf. zBuf must be big enough to
** hold at least SQLITE_TEMPNAME_SIZE characters.
@ -1001,15 +993,23 @@ int sqlite3UnixIsDirWritable(char *zBuf){
static int seekAndRead(unixFile *id, void *pBuf, int cnt){
int got;
i64 newOffset;
#ifdef USE_PREAD
TIMER_START;
#if defined(USE_PREAD)
got = pread(id->h, pBuf, cnt, id->offset);
SimulateIOError( got = -1 );
#elif defined(USE_PREAD64)
got = pread64(id->h, pBuf, cnt, id->offset);
SimulateIOError( got = -1 );
#else
newOffset = lseek(id->h, id->offset, SEEK_SET);
SimulateIOError( newOffset-- );
if( newOffset!=id->offset ){
return -1;
}
got = read(id->h, pBuf, cnt);
#endif
TIMER_END;
OSTRACE5("READ %-3d %5d %7lld %d\n", id->h, got, id->offset, TIMER_ELAPSED);
if( got>0 ){
id->offset += got;
}
@ -1024,13 +1024,7 @@ static int seekAndRead(unixFile *id, void *pBuf, int cnt){
static int unixRead(OsFile *id, void *pBuf, int amt){
int got;
assert( id );
TIMER_START;
got = seekAndRead((unixFile*)id, pBuf, amt);
TIMER_END;
TRACE5("READ %-3d %5d %7d %d\n", ((unixFile*)id)->h, got,
last_page, TIMER_ELAPSED);
SEEK(0);
SimulateIOError( got = -1 );
if( got==amt ){
return SQLITE_OK;
}else if( got<0 ){
@ -1048,8 +1042,11 @@ static int unixRead(OsFile *id, void *pBuf, int amt){
static int seekAndWrite(unixFile *id, const void *pBuf, int cnt){
int got;
i64 newOffset;
#ifdef USE_PREAD
TIMER_START;
#if defined(USE_PREAD)
got = pwrite(id->h, pBuf, cnt, id->offset);
#elif defined(USE_PREAD64)
got = pwrite64(id->h, pBuf, cnt, id->offset);
#else
newOffset = lseek(id->h, id->offset, SEEK_SET);
if( newOffset!=id->offset ){
@ -1057,6 +1054,8 @@ static int seekAndWrite(unixFile *id, const void *pBuf, int cnt){
}
got = write(id->h, pBuf, cnt);
#endif
TIMER_END;
OSTRACE5("WRITE %-3d %5d %7lld %d\n", id->h, got, id->offset, TIMER_ELAPSED);
if( got>0 ){
id->offset += got;
}
@ -1072,15 +1071,10 @@ static int unixWrite(OsFile *id, const void *pBuf, int amt){
int wrote = 0;
assert( id );
assert( amt>0 );
TIMER_START;
while( amt>0 && (wrote = seekAndWrite((unixFile*)id, pBuf, amt))>0 ){
amt -= wrote;
pBuf = &((char*)pBuf)[wrote];
}
TIMER_END;
TRACE5("WRITE %-3d %5d %7d %d\n", ((unixFile*)id)->h, wrote,
last_page, TIMER_ELAPSED);
SEEK(0);
SimulateIOError(( wrote=(-1), amt=1 ));
SimulateDiskfullError(( wrote=0, amt=1 ));
if( amt>0 ){
@ -1098,7 +1092,6 @@ static int unixWrite(OsFile *id, const void *pBuf, int amt){
*/
static int unixSeek(OsFile *id, i64 offset){
assert( id );
SEEK(offset/1024 + 1);
#ifdef SQLITE_TEST
if( offset ) SimulateDiskfullError(return SQLITE_FULL);
#endif
@ -1212,14 +1205,14 @@ static int unixSync(OsFile *id, int dataOnly){
int rc;
unixFile *pFile = (unixFile*)id;
assert( pFile );
TRACE2("SYNC %-3d\n", pFile->h);
OSTRACE2("SYNC %-3d\n", pFile->h);
rc = full_fsync(pFile->h, pFile->fullSync, dataOnly);
SimulateIOError( rc=1 );
if( rc ){
return SQLITE_IOERR_FSYNC;
}
if( pFile->dirfd>=0 ){
TRACE4("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd,
OSTRACE4("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd,
HAVE_FULLFSYNC, pFile->fullSync);
#ifndef SQLITE_DISABLE_DIRSYNC
/* The directory sync is only attempted if full_fsync is
@ -1257,7 +1250,7 @@ int sqlite3UnixSyncDirectory(const char *zDirname){
int fd;
int r;
fd = open(zDirname, O_RDONLY|O_BINARY, 0);
TRACE3("DIRSYNC %-3d (%s)\n", fd, zDirname);
OSTRACE3("DIRSYNC %-3d (%s)\n", fd, zDirname);
if( fd<0 ){
return SQLITE_CANTOPEN;
}
@ -1336,7 +1329,7 @@ static int unixCheckReservedLock(OsFile *id){
}
sqlite3OsLeaveMutex();
TRACE3("TEST WR-LOCK %d %d\n", pFile->h, r);
OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r);
return r;
}
@ -1411,7 +1404,7 @@ static int unixLock(OsFile *id, int locktype){
int s;
assert( pFile );
TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h,
OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h,
locktypeName(locktype), locktypeName(pFile->locktype),
locktypeName(pLock->locktype), pLock->cnt , getpid());
@ -1420,7 +1413,7 @@ static int unixLock(OsFile *id, int locktype){
** sqlite3OsEnterMutex() hasn't been called yet.
*/
if( pFile->locktype>=locktype ){
TRACE3("LOCK %d %s ok (already held)\n", pFile->h,
OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h,
locktypeName(locktype));
return SQLITE_OK;
}
@ -1483,7 +1476,7 @@ static int unixLock(OsFile *id, int locktype){
lock.l_type = (locktype==SHARED_LOCK?F_RDLCK:F_WRLCK);
lock.l_start = PENDING_BYTE;
s = fcntl(pFile->h, F_SETLK, &lock);
if( s ){
if( s==(-1) ){
rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
goto end_lock;
}
@ -1510,7 +1503,7 @@ static int unixLock(OsFile *id, int locktype){
rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
goto end_lock;
}
if( s ){
if( s==(-1) ){
rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
}else{
pFile->locktype = SHARED_LOCK;
@ -1540,7 +1533,7 @@ static int unixLock(OsFile *id, int locktype){
assert(0);
}
s = fcntl(pFile->h, F_SETLK, &lock);
if( s ){
if( s==(-1) ){
rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
}
}
@ -1555,7 +1548,7 @@ static int unixLock(OsFile *id, int locktype){
end_lock:
sqlite3OsLeaveMutex();
TRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
rc==SQLITE_OK ? "ok" : "failed");
return rc;
}
@ -1574,7 +1567,7 @@ static int unixUnlock(OsFile *id, int locktype){
unixFile *pFile = (unixFile*)id;
assert( pFile );
TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype,
OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype,
pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid());
assert( locktype<=SHARED_LOCK );
@ -1594,7 +1587,7 @@ static int unixUnlock(OsFile *id, int locktype){
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){
if( fcntl(pFile->h, F_SETLK, &lock)==(-1) ){
/* This should never happen */
rc = SQLITE_IOERR_RDLOCK;
}
@ -1603,7 +1596,7 @@ static int unixUnlock(OsFile *id, int locktype){
lock.l_whence = SEEK_SET;
lock.l_start = PENDING_BYTE;
lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
if( fcntl(pFile->h, F_SETLK, &lock)==0 ){
if( fcntl(pFile->h, F_SETLK, &lock)!=(-1) ){
pLock->locktype = SHARED_LOCK;
}else{
rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
@ -1621,7 +1614,7 @@ static int unixUnlock(OsFile *id, int locktype){
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0L;
if( fcntl(pFile->h, F_SETLK, &lock)==0 ){
if( fcntl(pFile->h, F_SETLK, &lock)!=(-1) ){
pLock->locktype = NO_LOCK;
}else{
rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
@ -1687,7 +1680,7 @@ static int unixClose(OsFile **pId){
sqlite3OsLeaveMutex();
id->isOpen = 0;
TRACE2("CLOSE %-3d\n", id->h);
OSTRACE2("CLOSE %-3d\n", id->h);
OpenCounter(-1);
sqlite3ThreadSafeFree(id);
*pId = 0;
@ -1734,11 +1727,11 @@ static int _AFPFSSetLock(const char *path, int fd, unsigned long long offset,
pb.offset = offset;
pb.length = length;
pb.fd = fd;
TRACE5("AFPLOCK setting lock %s for %d in range %llx:%llx\n",
OSTRACE5("AFPLOCK setting lock %s for %d in range %llx:%llx\n",
(setLockFlag?"ON":"OFF"), fd, offset, length);
err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
if ( err==-1 ) {
TRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, errno,
OSTRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, errno,
strerror(errno));
return 1; // error
} else {
@ -1778,7 +1771,7 @@ static int afpUnixCheckReservedLock(OsFile *id){
_AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0);
}
}
TRACE3("TEST WR-LOCK %d %d\n", pFile->h, r);
OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r);
return r;
}
@ -1793,14 +1786,14 @@ static int afpUnixLock(OsFile *id, int locktype)
int gotPendingLock = 0;
assert( pFile );
TRACE5("LOCK %d %s was %s pid=%d\n", pFile->h,
OSTRACE5("LOCK %d %s was %s pid=%d\n", pFile->h,
locktypeName(locktype), locktypeName(pFile->locktype), getpid());
/* If there is already a lock of this type or more restrictive on the
** OsFile, do nothing. Don't use the afp_end_lock: exit path, as
** sqlite3OsEnterMutex() hasn't been called yet.
*/
if( pFile->locktype>=locktype ){
TRACE3("LOCK %d %s ok (already held)\n", pFile->h,
OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h,
locktypeName(locktype));
return SQLITE_OK;
}
@ -1907,7 +1900,7 @@ static int afpUnixLock(OsFile *id, int locktype)
afp_end_lock:
sqlite3OsLeaveMutex();
TRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
rc==SQLITE_OK ? "ok" : "failed");
return rc;
}
@ -1926,7 +1919,7 @@ static int afpUnixUnlock(OsFile *id, int locktype) {
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
assert( pFile );
TRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
pFile->locktype, getpid());
assert( locktype<=SHARED_LOCK );
@ -2003,7 +1996,7 @@ static int afpUnixClose(OsFile **pId) {
id->dirfd = -1;
close(id->h);
id->isOpen = 0;
TRACE2("CLOSE %-3d\n", id->h);
OSTRACE2("CLOSE %-3d\n", id->h);
OpenCounter(-1);
sqlite3ThreadSafeFree(id);
*pId = 0;
@ -2099,7 +2092,7 @@ static int flockUnixClose(OsFile **pId) {
close(id->h);
sqlite3OsLeaveMutex();
id->isOpen = 0;
TRACE2("CLOSE %-3d\n", id->h);
OSTRACE2("CLOSE %-3d\n", id->h);
OpenCounter(-1);
sqlite3ThreadSafeFree(id);
*pId = 0;
@ -2218,7 +2211,7 @@ static int dotlockUnixClose(OsFile **pId) {
sqlite3OsLeaveMutex();
id->isOpen = 0;
TRACE2("CLOSE %-3d\n", id->h);
OSTRACE2("CLOSE %-3d\n", id->h);
OpenCounter(-1);
sqlite3ThreadSafeFree(id);
*pId = 0;
@ -2260,7 +2253,7 @@ static int nolockUnixClose(OsFile **pId) {
sqlite3OsLeaveMutex();
id->isOpen = 0;
TRACE2("CLOSE %-3d\n", id->h);
OSTRACE2("CLOSE %-3d\n", id->h);
OpenCounter(-1);
sqlite3ThreadSafeFree(id);
*pId = 0;
@ -2341,6 +2334,20 @@ static int unixLockState(OsFile *id){
return ((unixFile*)id)->locktype;
}
/*
** Return the sector size in bytes of the underlying block device for
** the specified file. This is almost always 512 bytes, but may be
** larger for some devices.
**
** SQLite code assumes this function cannot fail. It also assumes that
** if two files are created in the same file-system directory (i.e.
** a database and it's journal file) that the sector size will be the
** same for both.
*/
static int unixSectorSize(OsFile *id){
return SQLITE_DEFAULT_SECTOR_SIZE;
}
/*
** This vector defines all the methods that can operate on an OsFile
** for unix.
@ -2360,6 +2367,7 @@ static const IoMethod sqlite3UnixIoMethod = {
unixUnlock,
unixLockState,
unixCheckReservedLock,
unixSectorSize,
};
#ifdef SQLITE_ENABLE_LOCKING_STYLE
@ -2382,6 +2390,7 @@ static const IoMethod sqlite3AFPLockingUnixIoMethod = {
afpUnixUnlock,
unixLockState,
afpUnixCheckReservedLock,
unixSectorSize,
};
/*
@ -2403,6 +2412,7 @@ static const IoMethod sqlite3FlockLockingUnixIoMethod = {
flockUnixUnlock,
unixLockState,
flockUnixCheckReservedLock,
unixSectorSize,
};
/*
@ -2424,6 +2434,7 @@ static const IoMethod sqlite3DotlockLockingUnixIoMethod = {
dotlockUnixUnlock,
unixLockState,
dotlockUnixCheckReservedLock,
unixSectorSize,
};
/*
@ -2445,6 +2456,7 @@ static const IoMethod sqlite3NolockLockingUnixIoMethod = {
nolockUnixUnlock,
unixLockState,
nolockUnixCheckReservedLock,
unixSectorSize,
};
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
@ -2472,6 +2484,7 @@ static int allocateUnixFile(
unixFile f;
int rc;
memset(&f, 0, sizeof(f));
lockingStyle = sqlite3DetectLockingStyle(zFilename, h);
if ( lockingStyle == posixLockingStyle ) {
sqlite3OsEnterMutex();
@ -2491,9 +2504,6 @@ static int allocateUnixFile(
unlink(zFilename);
}
f.dirfd = -1;
f.fullSync = 0;
f.locktype = 0;
f.offset = 0;
f.h = h;
SET_THREADID(&f);
pNew = sqlite3ThreadSafeMalloc( sizeof(unixFile) );
@ -2560,6 +2570,7 @@ static int allocateUnixFile(
unixFile f;
int rc;
memset(&f, 0, sizeof(f));
sqlite3OsEnterMutex();
rc = findLockInfo(h, &f.pLock, &f.pOpen);
sqlite3OsLeaveMutex();
@ -2570,11 +2581,8 @@ static int allocateUnixFile(
close(h);
return SQLITE_NOMEM;
}
TRACE3("OPEN %-3d %s\n", h, zFilename);
OSTRACE3("OPEN %-3d %s\n", h, zFilename);
f.dirfd = -1;
f.fullSync = 0;
f.locktype = 0;
f.offset = 0;
f.h = h;
SET_THREADID(&f);
pNew = sqlite3ThreadSafeMalloc( sizeof(unixFile) );
@ -2899,8 +2907,7 @@ int sqlite3UnixCurrentTime(double *prNow){
*prNow = t/86400.0 + 2440587.5;
#else
struct timeval sNow;
struct timezone sTz; /* Not used */
gettimeofday(&sNow, &sTz);
gettimeofday(&sNow, 0);
*prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_usec/86400000000.0;
#endif
#ifdef SQLITE_TEST

View file

@ -596,6 +596,7 @@ int sqlite3WinDelete(const char *zFilename){
if( zConverted==0 ){
return SQLITE_NOMEM;
}
SimulateIOError(return SQLITE_IOERR_DELETE);
if( isNT() ){
do{
rc = DeleteFileW(zConverted);
@ -612,7 +613,7 @@ int sqlite3WinDelete(const char *zFilename){
#endif
}
sqliteFree(zConverted);
TRACE2("DELETE \"%s\"\n", zFilename);
OSTRACE2("DELETE \"%s\"\n", zFilename);
return rc!=0 ? SQLITE_OK : SQLITE_IOERR;
}
@ -738,7 +739,7 @@ int sqlite3WinOpenReadWrite(
#if OS_WINCE
f.zDeleteOnClose = 0;
#endif
TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename);
OSTRACE3("OPEN R/W %d \"%s\"\n", h, zFilename);
return allocateWinFile(&f, pId);
}
@ -819,7 +820,7 @@ int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
return SQLITE_CANTOPEN;
}
f.h = h;
TRACE3("OPEN EX %d \"%s\"\n", h, zFilename);
OSTRACE3("OPEN EX %d \"%s\"\n", h, zFilename);
return allocateWinFile(&f, pId);
}
@ -870,7 +871,7 @@ int sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){
f.zDeleteOnClose = 0;
f.hMutex = NULL;
#endif
TRACE3("OPEN RO %d \"%s\"\n", h, zFilename);
OSTRACE3("OPEN RO %d \"%s\"\n", h, zFilename);
return allocateWinFile(&f, pId);
}
@ -897,13 +898,6 @@ static int winOpenDirectory(
return SQLITE_OK;
}
/*
** If the following global variable points to a string which is the
** name of a directory, then that directory will be used to store
** temporary files.
*/
char *sqlite3_temp_directory = 0;
/*
** Create a temporary file name in zBuf. zBuf must be big enough to
** hold at least SQLITE_TEMPNAME_SIZE characters.
@ -955,7 +949,7 @@ int sqlite3WinTempFileName(char *zBuf){
zBuf[j] = 0;
if( !sqlite3OsFileExists(zBuf) ) break;
}
TRACE2("TEMP FILENAME: %s\n", zBuf);
OSTRACE2("TEMP FILENAME: %s\n", zBuf);
return SQLITE_OK;
}
@ -975,7 +969,7 @@ static int winClose(OsFile **pId){
int rc = 1;
if( pId && (pFile = (winFile*)*pId)!=0 ){
int rc, cnt = 0;
TRACE2("CLOSE %d\n", pFile->h);
OSTRACE2("CLOSE %d\n", pFile->h);
do{
rc = CloseHandle(pFile->h);
}while( rc==0 && cnt++ < MX_CLOSE_ATTEMPT && (Sleep(100), 1) );
@ -1002,7 +996,7 @@ static int winRead(OsFile *id, void *pBuf, int amt){
DWORD got;
assert( id!=0 );
SimulateIOError(return SQLITE_IOERR_READ);
TRACE3("READ %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
OSTRACE3("READ %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
if( !ReadFile(((winFile*)id)->h, pBuf, amt, &got, 0) ){
return SQLITE_IOERR_READ;
}
@ -1024,7 +1018,7 @@ static int winWrite(OsFile *id, const void *pBuf, int amt){
assert( id!=0 );
SimulateIOError(return SQLITE_IOERR_READ);
SimulateDiskfullError(return SQLITE_FULL);
TRACE3("WRITE %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
OSTRACE3("WRITE %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
assert( amt>0 );
while( amt>0 && (rc = WriteFile(((winFile*)id)->h, pBuf, amt, &wrote, 0))!=0
&& wrote>0 ){
@ -1055,9 +1049,8 @@ static int winSeek(OsFile *id, i64 offset){
#ifdef SQLITE_TEST
if( offset ) SimulateDiskfullError(return SQLITE_FULL);
#endif
SEEK(offset/1024 + 1);
rc = SetFilePointer(((winFile*)id)->h, lowerBits, &upperBits, FILE_BEGIN);
TRACE3("SEEK %d %lld\n", ((winFile*)id)->h, offset);
OSTRACE3("SEEK %d %lld\n", ((winFile*)id)->h, offset);
if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){
return SQLITE_FULL;
}
@ -1069,7 +1062,7 @@ static int winSeek(OsFile *id, i64 offset){
*/
static int winSync(OsFile *id, int dataOnly){
assert( id!=0 );
TRACE3("SYNC %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
OSTRACE3("SYNC %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
if( FlushFileBuffers(((winFile*)id)->h) ){
return SQLITE_OK;
}else{
@ -1092,7 +1085,7 @@ int sqlite3WinSyncDirectory(const char *zDirname){
static int winTruncate(OsFile *id, i64 nByte){
LONG upperBits = nByte>>32;
assert( id!=0 );
TRACE3("TRUNCATE %d %lld\n", ((winFile*)id)->h, nByte);
OSTRACE3("TRUNCATE %d %lld\n", ((winFile*)id)->h, nByte);
SimulateIOError(return SQLITE_IOERR_TRUNCATE);
SetFilePointer(((winFile*)id)->h, nByte, &upperBits, FILE_BEGIN);
SetEndOfFile(((winFile*)id)->h);
@ -1220,7 +1213,7 @@ static int winLock(OsFile *id, int locktype){
winFile *pFile = (winFile*)id;
assert( pFile!=0 );
TRACE5("LOCK %d %d was %d(%d)\n",
OSTRACE5("LOCK %d %d was %d(%d)\n",
pFile->h, locktype, pFile->locktype, pFile->sharedLockByte);
/* If there is already a lock of this type or more restrictive on the
@ -1250,7 +1243,7 @@ static int winLock(OsFile *id, int locktype){
/* Try 3 times to get the pending lock. The pending lock might be
** held by another reader process who will release it momentarily.
*/
TRACE2("could not get a PENDING lock. cnt=%d\n", cnt);
OSTRACE2("could not get a PENDING lock. cnt=%d\n", cnt);
Sleep(1);
}
gotPendingLock = res;
@ -1288,12 +1281,12 @@ static int winLock(OsFile *id, int locktype){
if( locktype==EXCLUSIVE_LOCK && res ){
assert( pFile->locktype>=SHARED_LOCK );
res = unlockReadLock(pFile);
TRACE2("unreadlock = %d\n", res);
OSTRACE2("unreadlock = %d\n", res);
res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
if( res ){
newLocktype = EXCLUSIVE_LOCK;
}else{
TRACE2("error-code = %d\n", GetLastError());
OSTRACE2("error-code = %d\n", GetLastError());
}
}
@ -1310,7 +1303,7 @@ static int winLock(OsFile *id, int locktype){
if( res ){
rc = SQLITE_OK;
}else{
TRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
OSTRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
locktype, newLocktype);
rc = SQLITE_BUSY;
}
@ -1329,14 +1322,14 @@ static int winCheckReservedLock(OsFile *id){
assert( pFile!=0 );
if( pFile->locktype>=RESERVED_LOCK ){
rc = 1;
TRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc);
OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc);
}else{
rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
if( rc ){
UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
}
rc = !rc;
TRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc);
OSTRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc);
}
return rc;
}
@ -1358,7 +1351,7 @@ static int winUnlock(OsFile *id, int locktype){
winFile *pFile = (winFile*)id;
assert( pFile!=0 );
assert( locktype<=SHARED_LOCK );
TRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
OSTRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
pFile->locktype, pFile->sharedLockByte);
type = pFile->locktype;
if( type>=EXCLUSIVE_LOCK ){
@ -1454,6 +1447,20 @@ static int winLockState(OsFile *id){
return ((winFile*)id)->locktype;
}
/*
** Return the sector size in bytes of the underlying block device for
** the specified file. This is almost always 512 bytes, but may be
** larger for some devices.
**
** SQLite code assumes this function cannot fail. It also assumes that
** if two files are created in the same file-system directory (i.e.
** a database and it's journal file) that the sector size will be the
** same for both.
*/
static int winSectorSize(OsFile *id){
return SQLITE_DEFAULT_SECTOR_SIZE;
}
/*
** This vector defines all the methods that can operate on an OsFile
** for win32.
@ -1473,6 +1480,7 @@ static const IoMethod sqlite3WinIoMethod = {
winUnlock,
winLockState,
winCheckReservedLock,
winSectorSize,
};
/*

File diff suppressed because it is too large Load diff

View file

@ -57,67 +57,91 @@ typedef unsigned int Pgno;
typedef struct Pager Pager;
/*
** Allowed values for the flags parameter to sqlite3pager_open().
** Handle type for pages.
*/
typedef struct PgHdr DbPage;
/*
** Allowed values for the flags parameter to sqlite3PagerOpen().
**
** NOTE: This values must match the corresponding BTREE_ values in btree.h.
*/
#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
#define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */
/*
** Valid values for the second argument to sqlite3PagerLockingMode().
*/
#define PAGER_LOCKINGMODE_QUERY -1
#define PAGER_LOCKINGMODE_NORMAL 0
#define PAGER_LOCKINGMODE_EXCLUSIVE 1
/*
** See source code comments for a detailed description of the following
** routines:
*/
int sqlite3pager_open(Pager **ppPager, const char *zFilename,
int sqlite3PagerOpen(Pager **ppPager, const char *zFilename,
int nExtra, int flags);
void sqlite3pager_set_busyhandler(Pager*, BusyHandler *pBusyHandler);
void sqlite3pager_set_destructor(Pager*, void(*)(void*,int));
void sqlite3pager_set_reiniter(Pager*, void(*)(void*,int));
int sqlite3pager_set_pagesize(Pager*, int);
int sqlite3pager_read_fileheader(Pager*, int, unsigned char*);
void sqlite3pager_set_cachesize(Pager*, int);
int sqlite3pager_close(Pager *pPager);
int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage);
void *sqlite3pager_lookup(Pager *pPager, Pgno pgno);
int sqlite3pager_ref(void*);
int sqlite3pager_unref(void*);
Pgno sqlite3pager_pagenumber(void*);
int sqlite3pager_write(void*);
int sqlite3pager_iswriteable(void*);
int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void*);
int sqlite3pager_pagecount(Pager*);
int sqlite3pager_truncate(Pager*,Pgno);
int sqlite3pager_begin(void*, int exFlag);
int sqlite3pager_commit(Pager*);
int sqlite3pager_sync(Pager*,const char *zMaster, Pgno);
int sqlite3pager_rollback(Pager*);
int sqlite3pager_isreadonly(Pager*);
int sqlite3pager_stmt_begin(Pager*);
int sqlite3pager_stmt_commit(Pager*);
int sqlite3pager_stmt_rollback(Pager*);
void sqlite3pager_dont_rollback(void*);
void sqlite3pager_dont_write(Pager*, Pgno);
int sqlite3pager_refcount(Pager*);
int *sqlite3pager_stats(Pager*);
void sqlite3pager_set_safety_level(Pager*,int,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);
int sqlite3pager_reset(Pager*);
int sqlite3pager_release_memory(int);
void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler);
void sqlite3PagerSetDestructor(Pager*, void(*)(DbPage*,int));
void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*,int));
int sqlite3PagerSetPagesize(Pager*, int);
int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
void sqlite3PagerSetCachesize(Pager*, int);
int sqlite3PagerClose(Pager *pPager);
int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0)
DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
int sqlite3PagerRef(DbPage*);
int sqlite3PagerUnref(DbPage*);
Pgno sqlite3PagerPagenumber(DbPage*);
int sqlite3PagerWrite(DbPage*);
int sqlite3PagerIswriteable(DbPage*);
int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void*);
int sqlite3PagerPagecount(Pager*);
int sqlite3PagerTruncate(Pager*,Pgno);
int sqlite3PagerBegin(DbPage*, int exFlag);
int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, Pgno);
int sqlite3PagerCommitPhaseTwo(Pager*);
int sqlite3PagerRollback(Pager*);
int sqlite3PagerIsreadonly(Pager*);
int sqlite3PagerStmtBegin(Pager*);
int sqlite3PagerStmtCommit(Pager*);
int sqlite3PagerStmtRollback(Pager*);
void sqlite3PagerDontRollback(DbPage*);
void sqlite3PagerDontWrite(Pager*, Pgno);
int sqlite3PagerRefcount(Pager*);
int *sqlite3PagerStats(Pager*);
void sqlite3PagerSetSafetyLevel(Pager*,int,int);
const char *sqlite3PagerFilename(Pager*);
const char *sqlite3PagerDirname(Pager*);
const char *sqlite3PagerJournalname(Pager*);
int sqlite3PagerNosync(Pager*);
int sqlite3PagerRename(Pager*, const char *zNewName);
void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*);
int sqlite3PagerMovepage(Pager*,DbPage*,Pgno);
int sqlite3PagerReset(Pager*);
int sqlite3PagerReleaseMemory(int);
void *sqlite3PagerGetData(DbPage *);
void *sqlite3PagerGetExtra(DbPage *);
int sqlite3PagerLockingMode(Pager *, int);
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
int sqlite3pager_lockstate(Pager*);
int sqlite3PagerLockstate(Pager*);
#endif
#ifdef SQLITE_TEST
void sqlite3pager_refdump(Pager*);
void sqlite3PagerRefdump(Pager*);
int pager3_refinfo_enable;
#endif
#ifdef SQLITE_TEST
void disable_simulated_io_errors(void);
void enable_simulated_io_errors(void);
#else
# define disable_simulated_io_errors()
# define enable_simulated_io_errors()
#endif
#endif /* _PAGER_H_ */

File diff suppressed because it is too large Load diff

View file

@ -49,105 +49,104 @@
#define TK_REPLACE 49
#define TK_RESTRICT 50
#define TK_ROW 51
#define TK_STATEMENT 52
#define TK_TRIGGER 53
#define TK_VACUUM 54
#define TK_VIEW 55
#define TK_VIRTUAL 56
#define TK_REINDEX 57
#define TK_RENAME 58
#define TK_CTIME_KW 59
#define TK_ANY 60
#define TK_OR 61
#define TK_AND 62
#define TK_IS 63
#define TK_BETWEEN 64
#define TK_IN 65
#define TK_ISNULL 66
#define TK_NOTNULL 67
#define TK_NE 68
#define TK_EQ 69
#define TK_GT 70
#define TK_LE 71
#define TK_LT 72
#define TK_GE 73
#define TK_ESCAPE 74
#define TK_BITAND 75
#define TK_BITOR 76
#define TK_LSHIFT 77
#define TK_RSHIFT 78
#define TK_PLUS 79
#define TK_MINUS 80
#define TK_STAR 81
#define TK_SLASH 82
#define TK_REM 83
#define TK_CONCAT 84
#define TK_COLLATE 85
#define TK_UMINUS 86
#define TK_UPLUS 87
#define TK_BITNOT 88
#define TK_STRING 89
#define TK_JOIN_KW 90
#define TK_CONSTRAINT 91
#define TK_DEFAULT 92
#define TK_NULL 93
#define TK_PRIMARY 94
#define TK_UNIQUE 95
#define TK_CHECK 96
#define TK_REFERENCES 97
#define TK_AUTOINCR 98
#define TK_ON 99
#define TK_DELETE 100
#define TK_UPDATE 101
#define TK_INSERT 102
#define TK_SET 103
#define TK_DEFERRABLE 104
#define TK_FOREIGN 105
#define TK_DROP 106
#define TK_UNION 107
#define TK_ALL 108
#define TK_EXCEPT 109
#define TK_INTERSECT 110
#define TK_SELECT 111
#define TK_DISTINCT 112
#define TK_DOT 113
#define TK_FROM 114
#define TK_JOIN 115
#define TK_USING 116
#define TK_ORDER 117
#define TK_BY 118
#define TK_GROUP 119
#define TK_HAVING 120
#define TK_LIMIT 121
#define TK_WHERE 122
#define TK_INTO 123
#define TK_VALUES 124
#define TK_INTEGER 125
#define TK_FLOAT 126
#define TK_BLOB 127
#define TK_REGISTER 128
#define TK_VARIABLE 129
#define TK_CASE 130
#define TK_WHEN 131
#define TK_THEN 132
#define TK_ELSE 133
#define TK_INDEX 134
#define TK_ALTER 135
#define TK_TO 136
#define TK_ADD 137
#define TK_COLUMNKW 138
#define TK_TO_TEXT 139
#define TK_TO_BLOB 140
#define TK_TO_NUMERIC 141
#define TK_TO_INT 142
#define TK_TO_REAL 143
#define TK_END_OF_FILE 144
#define TK_ILLEGAL 145
#define TK_SPACE 146
#define TK_UNCLOSED_STRING 147
#define TK_COMMENT 148
#define TK_FUNCTION 149
#define TK_COLUMN 150
#define TK_AGG_FUNCTION 151
#define TK_AGG_COLUMN 152
#define TK_CONST_FUNC 153
#define TK_TRIGGER 52
#define TK_VACUUM 53
#define TK_VIEW 54
#define TK_VIRTUAL 55
#define TK_REINDEX 56
#define TK_RENAME 57
#define TK_CTIME_KW 58
#define TK_ANY 59
#define TK_OR 60
#define TK_AND 61
#define TK_IS 62
#define TK_BETWEEN 63
#define TK_IN 64
#define TK_ISNULL 65
#define TK_NOTNULL 66
#define TK_NE 67
#define TK_EQ 68
#define TK_GT 69
#define TK_LE 70
#define TK_LT 71
#define TK_GE 72
#define TK_ESCAPE 73
#define TK_BITAND 74
#define TK_BITOR 75
#define TK_LSHIFT 76
#define TK_RSHIFT 77
#define TK_PLUS 78
#define TK_MINUS 79
#define TK_STAR 80
#define TK_SLASH 81
#define TK_REM 82
#define TK_CONCAT 83
#define TK_COLLATE 84
#define TK_UMINUS 85
#define TK_UPLUS 86
#define TK_BITNOT 87
#define TK_STRING 88
#define TK_JOIN_KW 89
#define TK_CONSTRAINT 90
#define TK_DEFAULT 91
#define TK_NULL 92
#define TK_PRIMARY 93
#define TK_UNIQUE 94
#define TK_CHECK 95
#define TK_REFERENCES 96
#define TK_AUTOINCR 97
#define TK_ON 98
#define TK_DELETE 99
#define TK_UPDATE 100
#define TK_INSERT 101
#define TK_SET 102
#define TK_DEFERRABLE 103
#define TK_FOREIGN 104
#define TK_DROP 105
#define TK_UNION 106
#define TK_ALL 107
#define TK_EXCEPT 108
#define TK_INTERSECT 109
#define TK_SELECT 110
#define TK_DISTINCT 111
#define TK_DOT 112
#define TK_FROM 113
#define TK_JOIN 114
#define TK_USING 115
#define TK_ORDER 116
#define TK_BY 117
#define TK_GROUP 118
#define TK_HAVING 119
#define TK_LIMIT 120
#define TK_WHERE 121
#define TK_INTO 122
#define TK_VALUES 123
#define TK_INTEGER 124
#define TK_FLOAT 125
#define TK_BLOB 126
#define TK_REGISTER 127
#define TK_VARIABLE 128
#define TK_CASE 129
#define TK_WHEN 130
#define TK_THEN 131
#define TK_ELSE 132
#define TK_INDEX 133
#define TK_ALTER 134
#define TK_TO 135
#define TK_ADD 136
#define TK_COLUMNKW 137
#define TK_TO_TEXT 138
#define TK_TO_BLOB 139
#define TK_TO_NUMERIC 140
#define TK_TO_INT 141
#define TK_TO_REAL 142
#define TK_END_OF_FILE 143
#define TK_ILLEGAL 144
#define TK_SPACE 145
#define TK_UNCLOSED_STRING 146
#define TK_COMMENT 147
#define TK_FUNCTION 148
#define TK_COLUMN 149
#define TK_AGG_FUNCTION 150
#define TK_AGG_COLUMN 151
#define TK_CONST_FUNC 152

View file

@ -175,7 +175,7 @@ id(A) ::= ID(X). {A = X;}
ABORT AFTER ANALYZE ASC ATTACH BEFORE BEGIN CASCADE CAST CONFLICT
DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH PLAN QUERY KEY
OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT
OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW
TEMP TRIGGER VACUUM VIEW VIRTUAL
%ifdef SQLITE_OMIT_COMPOUND_SELECT
EXCEPT INTERSECT UNION
@ -239,9 +239,8 @@ typetoken(A) ::= typename(X) LP signed COMMA signed RP(Y). {
%type typename {Token}
typename(A) ::= ids(X). {A = X;}
typename(A) ::= typename(X) ids(Y). {A.z=X.z; A.n=Y.n+(Y.z-X.z);}
%type signed {int}
signed(A) ::= plus_num(X). { A = atoi((char*)X.z); }
signed(A) ::= minus_num(X). { A = -atoi((char*)X.z); }
signed ::= plus_num.
signed ::= minus_num.
// "carglist" is a list of additional constraints that come after the
// column name and column type in a CREATE TABLE statement.
@ -543,10 +542,18 @@ having_opt(A) ::= . {A = 0;}
having_opt(A) ::= HAVING expr(X). {A = X;}
%type limit_opt {struct LimitVal}
%destructor limit_opt {
sqlite3ExprDelete($$.pLimit);
sqlite3ExprDelete($$.pOffset);
}
// The destructor for limit_opt will never fire in the current grammar.
// The limit_opt non-terminal only occurs at the end of a single production
// rule for SELECT statements. As soon as the rule that create the
// limit_opt non-terminal reduces, the SELECT statement rule will also
// reduce. So there is never a limit_opt non-terminal on the stack
// except as a transient. So there is never anything to destroy.
//
//%destructor limit_opt {
// sqlite3ExprDelete($$.pLimit);
// sqlite3ExprDelete($$.pOffset);
//}
limit_opt(A) ::= . {A.pLimit = 0; A.pOffset = 0;}
limit_opt(A) ::= LIMIT expr(X). {A.pLimit = X; A.pOffset = 0;}
limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y).
@ -890,8 +897,10 @@ cmd ::= DROP INDEX ifexists(E) fullname(X). {sqlite3DropIndex(pParse, X, E);}
///////////////////////////// The VACUUM command /////////////////////////////
//
%ifndef SQLITE_OMIT_VACUUM
%ifndef SQLITE_OMIT_ATTACH
cmd ::= VACUUM. {sqlite3Vacuum(pParse);}
cmd ::= VACUUM nm. {sqlite3Vacuum(pParse);}
%endif SQLITE_OMIT_ATTACH
%endif SQLITE_OMIT_VACUUM
///////////////////////////// The PRAGMA command /////////////////////////////
@ -926,8 +935,8 @@ cmd ::= CREATE trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). {
trigger_decl(A) ::= temp(T) TRIGGER ifnotexists(NOERR) nm(B) dbnm(Z)
trigger_time(C) trigger_event(D)
ON fullname(E) foreach_clause(F) when_clause(G). {
sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, E, F, G, T, NOERR);
ON fullname(E) foreach_clause when_clause(G). {
sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, E, G, T, NOERR);
A = (Z.n==0?B:Z);
}
@ -943,10 +952,8 @@ trigger_event(A) ::= DELETE|INSERT(OP). {A.a = @OP; A.b = 0;}
trigger_event(A) ::= UPDATE(OP). {A.a = @OP; A.b = 0;}
trigger_event(A) ::= UPDATE OF inscollist(X). {A.a = TK_UPDATE; A.b = X;}
%type foreach_clause {int}
foreach_clause(A) ::= . { A = TK_ROW; }
foreach_clause(A) ::= FOR EACH ROW. { A = TK_ROW; }
foreach_clause(A) ::= FOR EACH STATEMENT. { A = TK_STATEMENT; }
foreach_clause ::= .
foreach_clause ::= FOR EACH ROW.
%type when_clause {Expr*}
%destructor when_clause {sqlite3ExprDelete($$);}
@ -1018,9 +1025,14 @@ cmd ::= DROP TRIGGER ifexists(NOERR) fullname(X). {
%endif !SQLITE_OMIT_TRIGGER
//////////////////////// ATTACH DATABASE file AS name /////////////////////////
%ifndef SQLITE_OMIT_ATTACH
cmd ::= ATTACH database_kw_opt expr(F) AS expr(D) key_opt(K). {
sqlite3Attach(pParse, F, D, K);
}
cmd ::= DETACH database_kw_opt expr(D). {
sqlite3Detach(pParse, D);
}
%type key_opt {Expr *}
%destructor key_opt {sqlite3ExprDelete($$);}
key_opt(A) ::= . { A = 0; }
@ -1028,11 +1040,7 @@ key_opt(A) ::= KEY expr(X). { A = X; }
database_kw_opt ::= DATABASE.
database_kw_opt ::= .
//////////////////////// DETACH DATABASE name /////////////////////////////////
cmd ::= DETACH database_kw_opt expr(D). {
sqlite3Detach(pParse, D);
}
%endif SQLITE_OMIT_ATTACH
////////////////////////// REINDEX collation //////////////////////////////////
%ifndef SQLITE_OMIT_REINDEX

View file

@ -62,6 +62,17 @@ static int getBoolean(const char *z){
return getSafetyLevel(z)&1;
}
/*
** Interpret the given string as a locking mode value.
*/
static int getLockingMode(const char *z){
if( z ){
if( 0==sqlite3StrICmp(z, "exclusive") ) return PAGER_LOCKINGMODE_EXCLUSIVE;
if( 0==sqlite3StrICmp(z, "normal") ) return PAGER_LOCKINGMODE_NORMAL;
}
return PAGER_LOCKINGMODE_QUERY;
}
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
/*
** Interpret the given string as a temp db location. Return 1 for file
@ -89,7 +100,7 @@ static int getTempStore(const char *z){
static int invalidateTempStorage(Parse *pParse){
sqlite3 *db = pParse->db;
if( db->aDb[1].pBt!=0 ){
if( db->flags & SQLITE_InTrans ){
if( !db->autoCommit ){
sqlite3ErrorMsg(pParse, "temporary storage cannot be changed "
"from within a transaction");
return SQLITE_ERROR;
@ -157,7 +168,7 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
{ "ignore_check_constraints", SQLITE_IgnoreChecks },
#endif
/* The following is VERY experimental */
{ "writable_schema", SQLITE_WriteSchema },
{ "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode },
{ "omit_readlock", SQLITE_NoReadlock },
/* TODO: Maybe it shouldn't be possible to change the ReadUncommitted
@ -315,6 +326,53 @@ void sqlite3Pragma(
sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1);
}
}else
/*
** PRAGMA [database.]locking_mode
** PRAGMA [database.]locking_mode = (normal|exclusive)
*/
if( sqlite3StrICmp(zLeft,"locking_mode")==0 ){
const char *zRet = "normal";
int eMode = getLockingMode(zRight);
if( pId2->n==0 && eMode==PAGER_LOCKINGMODE_QUERY ){
/* Simple "PRAGMA locking_mode;" statement. This is a query for
** the current default locking mode (which may be different to
** the locking-mode of the main database).
*/
eMode = db->dfltLockMode;
}else{
Pager *pPager;
if( pId2->n==0 ){
/* This indicates that no database name was specified as part
** of the PRAGMA command. In this case the locking-mode must be
** set on all attached databases, as well as the main db file.
**
** Also, the sqlite3.dfltLockMode variable is set so that
** any subsequently attached databases also use the specified
** locking mode.
*/
int ii;
assert(pDb==&db->aDb[0]);
for(ii=2; ii<db->nDb; ii++){
pPager = sqlite3BtreePager(db->aDb[ii].pBt);
sqlite3PagerLockingMode(pPager, eMode);
}
db->dfltLockMode = eMode;
}
pPager = sqlite3BtreePager(pDb->pBt);
eMode = sqlite3PagerLockingMode(pPager, eMode);
}
assert(eMode==PAGER_LOCKINGMODE_NORMAL||eMode==PAGER_LOCKINGMODE_EXCLUSIVE);
if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){
zRet = "exclusive";
}
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", P3_STATIC);
sqlite3VdbeOp3(v, OP_String8, 0, 0, zRet, 0);
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
}else
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
/*
@ -916,7 +974,7 @@ void sqlite3Pragma(
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, P3_TRANSIENT);
}
}
}else
#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
@ -941,7 +999,7 @@ void sqlite3Pragma(
if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){
sqlite3VdbeOp3(v, OP_String8, 0, 0, "closed", P3_STATIC);
}else{
int j = sqlite3pager_lockstate(pPager);
int j = sqlite3PagerLockstate(pPager);
sqlite3VdbeOp3(v, OP_String8, 0, 0,
(j>=0 && j<=4) ? azLockName[j] : "unknown", P3_STATIC);
}

View file

@ -310,10 +310,17 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
rc = SQLITE_NOMEM;
sqlite3ResetInternalSchema(db, 0);
}
if( rc==SQLITE_OK ){
if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){
/* Black magic: If the SQLITE_RecoveryMode flag is set, then consider
** the schema loaded, even if errors occured. In this situation the
** current sqlite3_prepare() operation will fail, but the following one
** will attempt to compile the supplied statement against whatever subset
** of the schema was loaded before the error occured. The primary
** purpose of this is to allow access to the sqlite_master table
** even when it's contents have been corrupted.
*/
DbSetProperty(db, iDb, DB_SchemaLoaded);
}else{
sqlite3ResetInternalSchema(db, iDb);
rc = SQLITE_OK;
}
return rc;
}
@ -559,7 +566,7 @@ int sqlite3Prepare(
*/
int sqlite3Reprepare(Vdbe *p){
int rc;
Vdbe *pNew;
sqlite3_stmt *pNew;
const char *zSql;
sqlite3 *db;
@ -568,17 +575,17 @@ int sqlite3Reprepare(Vdbe *p){
return 0;
}
db = sqlite3VdbeDb(p);
rc = sqlite3Prepare(db, zSql, -1, 0, (sqlite3_stmt**)&pNew, 0);
rc = sqlite3Prepare(db, zSql, -1, 0, &pNew, 0);
if( rc ){
assert( pNew==0 );
return 0;
}else{
assert( pNew!=0 );
}
sqlite3VdbeSwap(pNew, p);
sqlite3_transfer_bindings((sqlite3_stmt*)pNew, (sqlite3_stmt*)p);
sqlite3VdbeResetStepResult(pNew);
sqlite3VdbeFinalize(pNew);
sqlite3VdbeSwap((Vdbe*)pNew, p);
sqlite3_transfer_bindings(pNew, (sqlite3_stmt*)p);
sqlite3VdbeResetStepResult((Vdbe*)pNew);
sqlite3VdbeFinalize((Vdbe*)pNew);
return 1;
}

View file

@ -821,9 +821,8 @@ char *sqlite3_vmprintf(const char *zFormat, va_list ap){
char *sqlite3_mprintf(const char *zFormat, ...){
va_list ap;
char *z;
char zBase[SQLITE_PRINT_BUF_SIZE];
va_start(ap, zFormat);
z = base_vprintf(sqlite3_realloc, 0, zBase, sizeof(zBase), zFormat, ap);
z = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
return z;
}

View file

@ -66,6 +66,7 @@ Select *sqlite3SelectNew(
pNew->pOrderBy = pOrderBy;
pNew->isDistinct = isDistinct;
pNew->op = TK_SELECT;
assert( pOffset==0 || pLimit!=0 );
pNew->pLimit = pLimit;
pNew->pOffset = pOffset;
pNew->iLimit = -1;
@ -532,7 +533,7 @@ static int selectInnerLoop(
}else{
sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
sqlite3VdbeAddOp(v, OP_Insert, iParm, 0);
sqlite3VdbeAddOp(v, OP_Insert, iParm, OPFLAG_APPEND);
}
break;
}
@ -691,7 +692,7 @@ static void generateSortTail(
int cont = sqlite3VdbeMakeLabel(v);
int addr;
int iTab;
int pseudoTab;
int pseudoTab = 0;
ExprList *pOrderBy = p->pOrderBy;
iTab = pOrderBy->iECursor;
@ -711,7 +712,7 @@ static void generateSortTail(
case SRT_EphemTab: {
sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
sqlite3VdbeAddOp(v, OP_Insert, iParm, 0);
sqlite3VdbeAddOp(v, OP_Insert, iParm, OPFLAG_APPEND);
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
@ -2364,6 +2365,8 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
iCol = pExpr->iColumn;
pTab = pSrc->a[0].pTab;
/* This optimization cannot be used with virtual tables. */
if( IsVirtual(pTab) ) return 0;
/* If we get to here, it means the query is of the correct form.
** Check to make sure we have an index and make pIdx point to the
@ -3142,11 +3145,7 @@ int sqlite3Select(
for(i=0; i<sAggInfo.nColumn; i++){
struct AggInfo_col *pCol = &sAggInfo.aCol[i];
if( pCol->iSorterColumn<j ) continue;
if( pCol->iColumn<0 ){
sqlite3VdbeAddOp(v, OP_Rowid, pCol->iTable, 0);
}else{
sqlite3VdbeAddOp(v, OP_Column, pCol->iTable, pCol->iColumn);
}
sqlite3ExprCodeGetColumn(v, pCol->pTab, pCol->iColumn, pCol->iTable);
j++;
}
sqlite3VdbeAddOp(v, OP_MakeRecord, j, 0);
@ -3296,7 +3295,7 @@ select_end:
return rc;
}
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
#if defined(SQLITE_DEBUG)
/*
*******************************************************************************
** The following code is used for testing and debugging only. The code

View file

@ -20,6 +20,7 @@
#include <assert.h>
#include "sqlite3.h"
#include <ctype.h>
#include <stdarg.h>
#if !defined(_WIN32) && !defined(WIN32) && !defined(__MACOS__) && !defined(__OS2__)
# include <signal.h>
@ -97,6 +98,28 @@ static char *Argv0;
static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/
static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */
/*
** Write I/O traces to the following stream.
*/
static FILE *iotrace = 0;
/*
** This routine works like printf in that its first argument is a
** format string and subsequent arguments are values to be substituted
** in place of % fields. The result of formatting this string
** is written to iotrace.
*/
static void iotracePrintf(const char *zFormat, ...){
va_list ap;
char *z;
if( iotrace==0 ) return;
va_start(ap, zFormat);
z = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
fprintf(iotrace, "%s", z);
sqlite3_free(z);
}
/*
** Determines if a string is a number of not.
@ -1219,6 +1242,26 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}
}else
if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
extern void (*sqlite3_io_trace)(const char*, ...);
if( iotrace && iotrace!=stdout ) fclose(iotrace);
iotrace = 0;
if( nArg<2 ){
sqlite3_io_trace = 0;
}else if( strcmp(azArg[1], "-")==0 ){
sqlite3_io_trace = iotracePrintf;
iotrace = stdout;
}else{
iotrace = fopen(azArg[1], "w");
if( iotrace==0 ){
fprintf(stderr, "cannot open \"%s\"\n", azArg[1]);
sqlite3_io_trace = 0;
}else{
sqlite3_io_trace = iotracePrintf;
}
}
}else
#ifndef SQLITE_OMIT_LOAD_EXTENSION
if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){
const char *zFile, *zProc;

View file

@ -182,7 +182,7 @@ int sqlite3_exec(
#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_PROTOCOL 15 /* NOT USED. Database lock protocol error */
#define SQLITE_EMPTY 16 /* Database is empty */
#define SQLITE_SCHEMA 17 /* The database schema changed */
#define SQLITE_TOOBIG 18 /* NOT USED. Too much data for one row */
@ -230,6 +230,7 @@ int sqlite3_exec(
#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8))
#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8))
#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8))
#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8))
/*
** Enable or disable the extended result codes.
@ -239,25 +240,29 @@ int sqlite3_extended_result_codes(sqlite3*, int onoff);
/*
** Each entry in an SQLite table has a unique integer key. (The key is
** the value of the INTEGER PRIMARY KEY column if there is such a column,
** otherwise the key is generated at random. The unique key is always
** otherwise the key is generated automatically. The unique key is always
** available as the ROWID, OID, or _ROWID_ column.) The following routine
** returns the integer key of the most recent insert in the database.
**
** This function is similar to the mysql_insert_id() function from MySQL.
*/
sqlite_int64 sqlite3_last_insert_rowid(sqlite3*);
/*
** This function returns the number of database rows that were changed
** (or inserted or deleted) by the most recent called sqlite3_exec().
** (or inserted or deleted) by the most recent SQL statement. Only
** changes that are directly specified by the INSERT, UPDATE, or
** DELETE statement are counted. Auxiliary changes caused by
** triggers are not counted. Within the body of a trigger, however,
** the sqlite3_changes() API can be called to find the number of
** changes in the most recently completed INSERT, UPDATE, or DELETE
** statement within the body of the trigger.
**
** All changes are counted, even if they were later undone by a
** ROLLBACK or ABORT. Except, changes associated with creating and
** dropping tables are not counted.
**
** If a callback invokes sqlite3_exec() recursively, then the changes
** in the inner, recursive call are counted together with the changes
** in the outer call.
** If a callback invokes sqlite3_exec() or sqlite3_step() recursively,
** then the changes in the inner, recursive call are counted together
** with the changes in the outer call.
**
** SQLite implements the command "DELETE FROM table" without a WHERE clause
** by dropping and recreating the table. (This is much faster than going
@ -292,6 +297,9 @@ int sqlite3_total_changes(sqlite3*);
** called in response to a user action such as pressing "Cancel"
** or Ctrl-C where the user wants a long query operation to halt
** immediately.
**
** It is safe to call this routine from a different thread that the
** thread that is currently running the database operation.
*/
void sqlite3_interrupt(sqlite3*);
@ -302,9 +310,13 @@ void sqlite3_interrupt(sqlite3*);
** sqlite3_complete16(), a nul-terminated machine byte order UTF-16 string
** is required.
**
** The algorithm is simple. If the last token other than spaces
** and comments is a semicolon, then return true. otherwise return
** false.
** This routine is useful for command-line input to see of the user has
** entered a complete statement of SQL or if the current statement needs
** to be continued on the next line. The algorithm is simple. If the
** last token other than spaces and comments is a semicolon, then return
** true. Actually, the algorithm is a little more complicated than that
** in order to deal with triggers, but the basic idea is the same: the
** statement is not complete unless it ends in a semicolon.
*/
int sqlite3_complete(const char *sql);
int sqlite3_complete16(const void *sql);
@ -743,31 +755,32 @@ typedef struct Mem sqlite3_value;
/*
** In the SQL strings input to sqlite3_prepare() and sqlite3_prepare16(),
** one or more literals can be replace by parameters "?" or ":AAA" or
** "$VVV" where AAA is an identifer and VVV is a variable name according
** to the syntax rules of the TCL programming language.
** The value of these parameters (also called "host parameter names") can
** be set using the routines listed below.
** one or more literals can be replace by parameters "?" or "?NNN" or
** ":AAA" or "@AAA" or "$VVV" where NNN is a integer, AAA is an identifer,
** and VVV is a variable name according to the syntax rules of the
** TCL programming language. The value of these parameters (also called
** "host parameter names") can be set using the routines listed below.
**
** In every case, the first parameter is a pointer to the sqlite3_stmt
** structure returned from sqlite3_prepare(). The second parameter is the
** index of the parameter. The first parameter as an index of 1. For
** named parameters (":AAA" or "$VVV") you can use
** In every case, the first argument is a pointer to the sqlite3_stmt
** structure returned from sqlite3_prepare(). The second argument is the
** index of the host parameter name. The first host parameter as an index
** of 1. For named host parameters (":AAA" or "$VVV") you can use
** sqlite3_bind_parameter_index() to get the correct index value given
** the parameters name. If the same named parameter occurs more than
** the parameter name. If the same named parameter occurs more than
** once, it is assigned the same index each time.
**
** The fifth parameter to sqlite3_bind_blob(), sqlite3_bind_text(), and
** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and
** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
** text after SQLite has finished with it. If the fifth argument is the
** special value SQLITE_STATIC, then the library assumes that the information
** is in static, unmanaged space and does not need to be freed. If the
** fifth argument has the value SQLITE_TRANSIENT, then SQLite makes its
** own private copy of the data.
** own private copy of the data before the sqlite3_bind_* routine returns.
**
** The sqlite3_bind_* routine must be called before sqlite3_step() after
** an sqlite3_prepare() or sqlite3_reset(). Unbound parameterss are
** interpreted as NULL.
** The sqlite3_bind_* routine must be called before sqlite3_step() and after
** an sqlite3_prepare() or sqlite3_reset(). Bindings persist across
** multiple calls to sqlite3_reset() and sqlite3_step(). Unbound parameters
** are interpreted as NULL.
*/
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
int sqlite3_bind_double(sqlite3_stmt*, int, double);
@ -779,13 +792,13 @@ int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
/*
** Return the number of parameters in a compiled SQL statement. This
** Return the number of host parameters in a compiled SQL statement. This
** routine was added to support DBD::SQLite.
*/
int sqlite3_bind_parameter_count(sqlite3_stmt*);
/*
** Return the name of the i-th parameter. Ordinary parameters "?" are
** Return the name of the i-th name parameter. Ordinary parameters "?" are
** nameless and a NULL is returned. For parameters of the form :AAA or
** $VVV the complete text of the parameter name is returned, including
** the initial ":" or "$". NULL is returned if the index is out of range.
@ -821,7 +834,7 @@ const char *sqlite3_column_name(sqlite3_stmt*,int);
const void *sqlite3_column_name16(sqlite3_stmt*,int);
/*
** The first parameter to the following calls is a compiled SQL statement.
** The first argument to the following calls is a compiled SQL statement.
** These functions return information about the Nth column returned by
** the statement, where N is the second function argument.
**

View file

@ -142,8 +142,11 @@ struct sqlite3_api_routines {
const void * (*value_text16be)(sqlite3_value*);
const void * (*value_text16le)(sqlite3_value*);
int (*value_type)(sqlite3_value*);
char * (*vmprintf)(const char*,va_list);
char *(*vmprintf)(const char*,va_list);
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
int (*clear_bindings)(sqlite3_stmt*);
};
/*
@ -232,6 +235,8 @@ struct sqlite3_api_routines {
#define sqlite3_open16 sqlite3_api->open16
#define sqlite3_prepare sqlite3_api->prepare
#define sqlite3_prepare16 sqlite3_api->prepare16
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
#define sqlite3_profile sqlite3_api->profile
#define sqlite3_progress_handler sqlite3_api->progress_handler
#define sqlite3_realloc sqlite3_api->realloc
@ -274,6 +279,9 @@ struct sqlite3_api_routines {
#define sqlite3_value_type sqlite3_api->value_type
#define sqlite3_vmprintf sqlite3_api->vmprintf
#define sqlite3_overload_function sqlite3_api->overload_function
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
#define sqlite3_clear_bindings sqlite3_api->clear_bindings
#endif /* SQLITE_CORE */
#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api;

View file

@ -16,11 +16,8 @@
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
/*
** Extra interface definitions for those who need them
*/
#ifdef SQLITE_EXTRA
# include "sqliteExtra.h"
#if defined(SQLITE_TCL) || defined(TCLSH)
# include <tcl.h>
#endif
/*
@ -215,8 +212,15 @@ typedef UINT8_TYPE i8; /* 1-byte signed integer */
** evaluated at runtime.
*/
extern const int sqlite3one;
#define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0)
#define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
#if defined(i386) || defined(__i386__) || defined(_M_IX86)
# define SQLITE_BIGENDIAN 0
# define SQLITE_LITTLEENDIAN 1
# define SQLITE_UTF16NATIVE SQLITE_UTF16LE
#else
# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0)
# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
#endif
/*
** An instance of the following structure is used to store the busy-handler
@ -414,7 +418,6 @@ struct Schema {
#define DB_UnresetViews 0x0002 /* Some views have defined column names */
#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */
#define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
/*
** Each database is an instance of the following structure.
@ -510,6 +513,7 @@ struct sqlite3 {
#ifdef SQLITE_SSE
sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */
#endif
u8 dfltLockMode; /* Default locking-mode for attached dbs */
};
/*
@ -545,6 +549,8 @@ struct sqlite3 {
#define SQLITE_FullFSync 0x00010000 /* Use full fsync on the backend */
#define SQLITE_LoadExtension 0x00020000 /* Enable load_extension */
#define SQLITE_RecoveryMode 0x00040000 /* Ignore schema errors */
/*
** Possible values for the sqlite.magic field.
** The numbers are obtained at random and have no special meaning, other
@ -922,6 +928,7 @@ struct AggInfo {
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 */
Table *pTab; /* Source table */
int iTable; /* Cursor number of the source table */
int iColumn; /* Column number within the source table */
int iSorterColumn; /* Column number in the sorting index */
@ -1159,12 +1166,16 @@ struct WhereLevel {
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 nxt; /* Jump here to start the next IN combination */
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 */
struct InLoop {
int iCur; /* The VDBE cursor used by this IN operator */
int topAddr; /* Top of the IN loop */
} *aInLoop; /* Information about each nested IN operator */
sqlite3_index_info *pBestIdx; /* Index information for this level */
/* The following field is really not part of the current level. But
@ -1371,6 +1382,7 @@ struct AuthContext {
#define OPFLAG_NCHANGE 1 /* Set to update db->nChange */
#define OPFLAG_LASTROWID 2 /* Set to update db->lastRowid */
#define OPFLAG_ISUPDATE 4 /* This OP_Insert is an sql UPDATE */
#define OPFLAG_APPEND 8 /* This is likely to be an append */
/*
* Each trigger present in the database schema is stored as an instance of
@ -1395,7 +1407,6 @@ struct Trigger {
Expr *pWhen; /* The WHEN clause of the expresion (may be NULL) */
IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger,
the <column-list> is stored here */
int foreach; /* One of TK_ROW or TK_STATEMENT */
Token nameToken; /* Token containing zName. Use during parsing only */
Schema *pSchema; /* Schema containing the trigger */
Schema *pTabSchema; /* Schema containing the table */
@ -1566,7 +1577,7 @@ void *sqlite3Realloc(void*,int);
char *sqlite3StrDup(const char*);
char *sqlite3StrNDup(const char*, int);
# define sqlite3CheckMemory(a,b)
void sqlite3ReallocOrFree(void**,int);
void *sqlite3ReallocOrFree(void*,int);
void sqlite3FreeX(void*);
void *sqlite3MallocX(int);
int sqlite3AllocSize(void *);
@ -1598,7 +1609,6 @@ int sqlite3InitCallback(void*, int, char**, char**);
void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
void sqlite3ResetInternalSchema(sqlite3*, int);
void sqlite3BeginParse(Parse*,int);
void sqlite3RollbackInternalChanges(sqlite3*);
void sqlite3CommitInternalChanges(sqlite3*);
Table *sqlite3ResultSetOfSelect(Parse*,char*,Select*);
void sqlite3OpenMasterTable(Parse *, int);
@ -1623,7 +1633,7 @@ void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
void sqlite3DropTable(Parse*, SrcList*, int, int);
void sqlite3DeleteTable(sqlite3*, Table*);
void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
int sqlite3ArrayAllocate(void**,int,int);
void *sqlite3ArrayAllocate(void*,int,int,int*,int*,int*);
IdList *sqlite3IdListAppend(IdList*, Token*);
int sqlite3IdListIndex(IdList*,const char*);
SrcList *sqlite3SrcListAppend(SrcList*, Token*, Token*);
@ -1650,6 +1660,7 @@ void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**);
void sqlite3WhereEnd(WhereInfo*);
void sqlite3ExprCodeGetColumn(Vdbe*, Table*, int, int);
void sqlite3ExprCode(Parse*, Expr*);
void sqlite3ExprCodeAndCache(Parse*, Expr*);
int sqlite3ExprCodeExprList(Parse*, ExprList*);
@ -1686,7 +1697,7 @@ void sqlite3GenerateRowDelete(sqlite3*, Vdbe*, Table*, int, int);
void sqlite3GenerateRowIndexDelete(Vdbe*, Table*, int, char*);
void sqlite3GenerateIndexKey(Vdbe*, Index*, int);
void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int);
void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int, int);
void sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
void sqlite3BeginWriteOperation(Parse*, int, int);
Expr *sqlite3ExprDup(Expr*);
@ -1705,7 +1716,7 @@ void sqlite3ChangeCookie(sqlite3*, Vdbe*, int);
#ifndef SQLITE_OMIT_TRIGGER
void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
int,Expr*,int, int);
Expr*,int, int);
void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
void sqlite3DropTrigger(Parse*, SrcList*, int);
void sqlite3DropTriggerPtr(Parse*, Trigger*);
@ -1895,4 +1906,18 @@ int sqlite3Reprepare(Vdbe*);
#include "sseInt.h"
#endif
/*
** If the SQLITE_ENABLE IOTRACE exists then the global variable
** sqlite3_io_trace is a pointer to a printf-like routine used to
** print I/O tracing messages.
*/
#ifdef SQLITE_ENABLE_IOTRACE
# define IOTRACE(A) if( sqlite3_io_trace ){ sqlite3_io_trace A; }
void sqlite3VdbeIOTraceSql(Vdbe*);
#else
# define IOTRACE(A)
# define sqlite3VdbeIOTraceSql(X)
#endif
extern void (*sqlite3_io_trace)(const char*,...);
#endif

View file

@ -9,19 +9,25 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** A TCL Interface to SQLite
** A TCL Interface to SQLite. Append this file to sqlite3.c and
** compile the whole thing to build a TCL-enabled version of SQLite.
**
** $Id$
*/
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
#include "sqliteInt.h"
#include "hash.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
/*
** Some additional include files are needed if this file is not
** appended to the amalgamation.
*/
#ifndef SQLITE_AMALGAMATION
# include "sqliteInt.h"
# include "hash.h"
# include <stdlib.h>
# include <string.h>
# include <assert.h>
# include <ctype.h>
#endif
/*
* Windows needs to know which symbols to export. Unix does not.
@ -2205,12 +2211,14 @@ int TCLSH_MAIN(int argc, char **argv){
extern int Sqlitetest6_Init(Tcl_Interp*);
extern int Sqlitetest7_Init(Tcl_Interp*);
extern int Sqlitetest8_Init(Tcl_Interp*);
extern int Sqlitetest9_Init(Tcl_Interp*);
extern int Md5_Init(Tcl_Interp*);
extern int Sqlitetestsse_Init(Tcl_Interp*);
extern int Sqlitetestasync_Init(Tcl_Interp*);
extern int Sqlitetesttclvar_Init(Tcl_Interp*);
extern int Sqlitetestschema_Init(Tcl_Interp*);
extern int Sqlitetest_autoext_Init(Tcl_Interp*);
extern int Sqlitetest_hexio_Init(Tcl_Interp*);
Sqlitetest1_Init(interp);
Sqlitetest2_Init(interp);
@ -2220,10 +2228,12 @@ int TCLSH_MAIN(int argc, char **argv){
Sqlitetest6_Init(interp);
Sqlitetest7_Init(interp);
Sqlitetest8_Init(interp);
Sqlitetest9_Init(interp);
Sqlitetestasync_Init(interp);
Sqlitetesttclvar_Init(interp);
Sqlitetestschema_Init(interp);
Sqlitetest_autoext_Init(interp);
Sqlitetest_hexio_Init(interp);
Md5_Init(interp);
#ifdef SQLITE_SSE
Sqlitetestsse_Init(interp);
@ -2254,5 +2264,3 @@ int TCLSH_MAIN(int argc, char **argv){
return 0;
}
#endif /* TCLSH */
#endif /* !defined(NO_TCL) */

View file

@ -112,7 +112,7 @@ const char *sqlite3TestErrorName(int rc){
}
return zName;
}
#define errorName sqlite3TestErrorName
#define t1ErrorName sqlite3TestErrorName
/*
** Convert an sqlite3_stmt* into an sqlite3*. This depends on the
@ -129,7 +129,7 @@ int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
char zBuf[200];
int r2 = sqlite3_errcode(db);
sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)",
errorName(rc), rc, errorName(r2), r2);
t1ErrorName(rc), rc, t1ErrorName(r2), r2);
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, zBuf, 0);
return 1;
@ -490,7 +490,7 @@ static int sqlite_test_close(
}
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
rc = sqlite3_close(db);
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
return TCL_OK;
}
@ -498,7 +498,11 @@ static int sqlite_test_close(
** Implementation of the x_coalesce() function.
** Return the first argument non-NULL argument.
*/
static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
static void t1_ifnullFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int i;
for(i=0; i<argc; i++){
if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
@ -682,7 +686,7 @@ static int test_create_function(
}
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,
ifnullFunc, 0, 0);
t1_ifnullFunc, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "hex8", 1, SQLITE_ANY, 0,
hex8Func, 0, 0);
@ -716,7 +720,7 @@ static int test_create_function(
#endif
if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
Tcl_SetResult(interp, (char *)errorName(rc), 0);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
return TCL_OK;
}
@ -731,12 +735,16 @@ static int test_create_function(
** is reported on the step function. If the total count is 42, then
** a UTF-8 error is reported on the finalize function.
*/
typedef struct CountCtx CountCtx;
struct CountCtx {
typedef struct t1CountCtx t1CountCtx;
struct t1CountCtx {
int n;
};
static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
CountCtx *p;
static void t1CountStep(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
t1CountCtx *p;
p = sqlite3_aggregate_context(context, sizeof(*p));
if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
p->n++;
@ -753,8 +761,8 @@ static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
}
}
}
static void countFinalize(sqlite3_context *context){
CountCtx *p;
static void t1CountFinalize(sqlite3_context *context){
t1CountCtx *p;
p = sqlite3_aggregate_context(context, sizeof(*p));
if( p ){
if( p->n==42 ){
@ -794,10 +802,10 @@ static int test_create_aggregate(
}
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
countStep,countFinalize);
t1CountStep,t1CountFinalize);
if( rc==SQLITE_OK ){
sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
countStep,countFinalize);
t1CountStep,t1CountFinalize);
}
if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
return TCL_OK;
@ -926,6 +934,40 @@ static int sqlite3_mprintf_str(
return TCL_OK;
}
/*
** Usage: sqlite3_snprintf_str INTEGER FORMAT INTEGER INTEGER STRING
**
** Call mprintf with two integer arguments and one string argument
*/
static int sqlite3_snprintf_str(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
int a[3], i;
int n;
char *z;
if( argc<5 || argc>6 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" INT FORMAT INT INT ?STRING?\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
if( n<0 ){
Tcl_AppendResult(interp, "N must be non-negative", 0);
return TCL_ERROR;
}
for(i=3; i<5; i++){
if( Tcl_GetInt(interp, argv[i], &a[i-3]) ) return TCL_ERROR;
}
z = sqlite3_malloc( n+1 );
sqlite3_snprintf(n, z, argv[2], a[0], a[1], argc>4 ? argv[5] : NULL);
Tcl_AppendResult(interp, z, 0);
sqlite3_free(z);
return TCL_OK;
}
/*
** Usage: sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE
**
@ -1497,7 +1539,7 @@ static int test_finalize(
db = StmtToDb(pStmt);
}
rc = sqlite3_finalize(pStmt);
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
return TCL_OK;
}
@ -1528,7 +1570,7 @@ static int test_reset(
if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){
return TCL_ERROR;
}
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
/*
if( rc ){
return TCL_ERROR;
@ -2052,7 +2094,7 @@ static int test_errstr(
zCode = Tcl_GetString(objv[1]);
for(i=0; i<200; i++){
if( 0==strcmp(errorName(i), zCode) ) break;
if( 0==strcmp(t1ErrorName(i), zCode) ) break;
}
Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
return TCL_OK;
@ -2504,7 +2546,7 @@ static int test_errcode(
}else{
sprintf(zBuf,"+%d", rc>>8);
}
Tcl_AppendResult(interp, (char *)errorName(rc), zBuf, 0);
Tcl_AppendResult(interp, (char *)t1ErrorName(rc), zBuf, 0);
return TCL_OK;
}
@ -2900,7 +2942,7 @@ static int test_step(
rc = sqlite3_step(pStmt);
/* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
Tcl_SetResult(interp, (char *)errorName(rc), 0);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
return TCL_OK;
}
@ -3137,7 +3179,7 @@ static int test_global_recover(
return TCL_ERROR;
}
rc = sqlite3_global_recover();
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
#endif
return TCL_OK;
}
@ -3235,7 +3277,7 @@ static int test_sqlite3OsOpenReadWrite(
rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), &pFile, &dummy);
if( rc!=SQLITE_OK ){
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
return TCL_ERROR;
}
sqlite3TestMakePointerStr(interp, zBuf, pFile);
@ -3266,7 +3308,7 @@ static int test_sqlite3OsClose(
}
rc = sqlite3OsClose(&pFile);
if( rc!=SQLITE_OK ){
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
return TCL_ERROR;
}
return TCL_OK;
@ -3314,7 +3356,7 @@ static int test_sqlite3OsLock(
}
if( rc!=SQLITE_OK ){
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
return TCL_ERROR;
}
return TCL_OK;
@ -3343,7 +3385,7 @@ static int test_sqlite3OsUnlock(
}
rc = sqlite3OsUnlock(pFile, NO_LOCK);
if( rc!=SQLITE_OK ){
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
return TCL_ERROR;
}
return TCL_OK;
@ -3363,7 +3405,7 @@ static int test_sqlite3OsTempFileName(
rc = sqlite3OsTempFileName(zFile);
if( rc!=SQLITE_OK ){
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
return TCL_ERROR;
}
Tcl_AppendResult(interp, zFile, 0);
@ -3492,7 +3534,7 @@ static int delete_function(
}
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
return TCL_OK;
}
@ -3518,7 +3560,7 @@ static int delete_collation(
}
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
return TCL_OK;
}
@ -3708,6 +3750,44 @@ static int test_thread_cleanup(
}
/*
** Usage: sqlite3_pager_refcounts DB
**
** Return a list of numbers which are the PagerRefcount for all
** pagers on each database connection.
*/
static int test_pager_refcounts(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
sqlite3 *db;
int i;
int v, *a;
Tcl_Obj *pResult;
if( objc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
pResult = Tcl_NewObj();
for(i=0; i<db->nDb; i++){
if( db->aDb[i].pBt==0 ){
v = -1;
}else{
a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt));
v = a[0];
}
Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v));
}
Tcl_SetObjResult(interp, pResult);
return TCL_OK;
}
/*
** This routine sets entries in the global ::sqlite_options() array variable
** according to the compile-time configuration of the database. Test
@ -3750,6 +3830,12 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "analyze", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_ATTACH
Tcl_SetVar2(interp, "sqlite_options", "attach", "0", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "attach", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_AUTHORIZATION
Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY);
#else
@ -3893,6 +3979,12 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "like_opt", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_LOAD_EXTENSION
Tcl_SetVar2(interp, "sqlite_options", "load_ext", "0", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "load_ext", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_MEMORYDB
Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY);
#else
@ -4008,7 +4100,7 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_VACUUM
#if defined(SQLITE_OMIT_VACUUM) || defined(SQLITE_OMIT_ATTACH)
Tcl_SetVar2(interp, "sqlite_options", "vacuum", "0", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "vacuum", "1", TCL_GLOBAL_ONLY);
@ -4025,6 +4117,25 @@ static void set_options(Tcl_Interp *interp){
#else
Tcl_SetVar2(interp, "sqlite_options", "vtab", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_DEFAULT_FILE_FORMAT
Tcl_ObjSetVar2(interp,
Tcl_NewStringObj("sqlite_default_file_format", -1), 0,
Tcl_NewIntObj(SQLITE_DEFAULT_FILE_FORMAT), TCL_GLOBAL_ONLY
);
#endif
#ifdef SQLITE_MAX_PAGE_SIZE
Tcl_ObjSetVar2(interp,
Tcl_NewStringObj("SQLITE_MAX_PAGE_SIZE", -1), 0,
Tcl_NewIntObj(SQLITE_MAX_PAGE_SIZE), TCL_GLOBAL_ONLY
);
#endif
#ifdef TEMP_STORE
Tcl_ObjSetVar2(interp,
Tcl_NewStringObj("TEMP_STORE", -1), 0,
Tcl_NewIntObj(TEMP_STORE), TCL_GLOBAL_ONLY
);
#endif
}
/*
@ -4072,6 +4183,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
{ "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 },
{ "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str },
{ "sqlite3_snprintf_str", (Tcl_CmdProc*)sqlite3_snprintf_str },
{ "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly},
{ "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double },
{ "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled },
@ -4146,6 +4258,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_clear_tsd_memdebug", test_clear_tsd_memdebug, 0},
{ "sqlite3_tsd_release", test_tsd_release, 0},
{ "sqlite3_thread_cleanup", test_thread_cleanup, 0},
{ "sqlite3_pager_refcounts", test_pager_refcounts, 0},
{ "sqlite3_load_extension", test_load_extension, 0},
{ "sqlite3_enable_load_extension", test_enable_load, 0},
@ -4220,10 +4333,11 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
extern int sqlite3_sync_count, sqlite3_fullsync_count;
extern int sqlite3_opentemp_count;
extern int sqlite3_memUsed;
extern int sqlite3_malloc_id;
extern char *sqlite3_malloc_id;
extern int sqlite3_memMax;
extern int sqlite3_like_count;
extern int sqlite3_tsd_count;
extern int sqlite3_xferopt_count;
#if OS_UNIX && defined(SQLITE_TEST) && defined(THREADSAFE) && THREADSAFE
extern int threadsOverrideEachOthersLocks;
#endif
@ -4261,6 +4375,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
(char*)&sqlite3_os_trace, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite3_tsd_count",
(char*)&sqlite3_tsd_count, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite3_xferopt_count",
(char*)&sqlite3_xferopt_count, TCL_LINK_INT);
#ifndef SQLITE_OMIT_UTF16
Tcl_LinkVar(interp, "unaligned_string_counter",
(char*)&unaligned_string_counter, TCL_LINK_INT);

View file

@ -78,13 +78,13 @@ static int pager_open(
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
rc = sqlite3pager_open(&pPager, argv[1], 0, 0);
rc = sqlite3PagerOpen(&pPager, argv[1], 0, 0);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
sqlite3pager_set_cachesize(pPager, nPage);
sqlite3pager_set_pagesize(pPager, test_pagesize);
sqlite3PagerSetCachesize(pPager, nPage);
sqlite3PagerSetPagesize(pPager, test_pagesize);
sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPager);
Tcl_AppendResult(interp, zBuf, 0);
return TCL_OK;
@ -109,7 +109,7 @@ static int pager_close(
return TCL_ERROR;
}
pPager = sqlite3TextToPtr(argv[1]);
rc = sqlite3pager_close(pPager);
rc = sqlite3PagerClose(pPager);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
@ -136,7 +136,7 @@ static int pager_rollback(
return TCL_ERROR;
}
pPager = sqlite3TextToPtr(argv[1]);
rc = sqlite3pager_rollback(pPager);
rc = sqlite3PagerRollback(pPager);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
@ -163,7 +163,12 @@ static int pager_commit(
return TCL_ERROR;
}
pPager = sqlite3TextToPtr(argv[1]);
rc = sqlite3pager_commit(pPager);
rc = sqlite3PagerCommitPhaseOne(pPager, 0, 0);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
rc = sqlite3PagerCommitPhaseTwo(pPager);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
@ -190,7 +195,7 @@ static int pager_stmt_begin(
return TCL_ERROR;
}
pPager = sqlite3TextToPtr(argv[1]);
rc = sqlite3pager_stmt_begin(pPager);
rc = sqlite3PagerStmtBegin(pPager);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
@ -217,7 +222,7 @@ static int pager_stmt_rollback(
return TCL_ERROR;
}
pPager = sqlite3TextToPtr(argv[1]);
rc = sqlite3pager_stmt_rollback(pPager);
rc = sqlite3PagerStmtRollback(pPager);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
@ -244,7 +249,7 @@ static int pager_stmt_commit(
return TCL_ERROR;
}
pPager = sqlite3TextToPtr(argv[1]);
rc = sqlite3pager_stmt_commit(pPager);
rc = sqlite3PagerStmtCommit(pPager);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
@ -271,7 +276,7 @@ static int pager_stats(
return TCL_ERROR;
}
pPager = sqlite3TextToPtr(argv[1]);
a = sqlite3pager_stats(pPager);
a = sqlite3PagerStats(pPager);
for(i=0; i<9; i++){
static char *zName[] = {
"ref", "page", "max", "size", "state", "err",
@ -304,7 +309,7 @@ static int pager_pagecount(
return TCL_ERROR;
}
pPager = sqlite3TextToPtr(argv[1]);
sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",sqlite3pager_pagecount(pPager));
sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",sqlite3PagerPagecount(pPager));
Tcl_AppendResult(interp, zBuf, 0);
return TCL_OK;
}
@ -322,7 +327,7 @@ static int page_get(
){
Pager *pPager;
char zBuf[100];
void *pPage;
DbPage *pPage;
int pgno;
int rc;
if( argc!=3 ){
@ -332,7 +337,7 @@ static int page_get(
}
pPager = sqlite3TextToPtr(argv[1]);
if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
rc = sqlite3pager_get(pPager, pgno, &pPage);
rc = sqlite3PagerGet(pPager, pgno, &pPage);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
@ -356,7 +361,7 @@ static int page_lookup(
){
Pager *pPager;
char zBuf[100];
void *pPage;
DbPage *pPage;
int pgno;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
@ -365,7 +370,7 @@ static int page_lookup(
}
pPager = sqlite3TextToPtr(argv[1]);
if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
pPage = sqlite3pager_lookup(pPager, pgno);
pPage = sqlite3PagerLookup(pPager, pgno);
if( pPage ){
sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage);
Tcl_AppendResult(interp, zBuf, 0);
@ -392,7 +397,7 @@ static int pager_truncate(
}
pPager = sqlite3TextToPtr(argv[1]);
if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
rc = sqlite3pager_truncate(pPager, pgno);
rc = sqlite3PagerTruncate(pPager, pgno);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
@ -412,15 +417,15 @@ static int page_unref(
int argc, /* Number of arguments */
const char **argv /* Text of each argument */
){
void *pPage;
DbPage *pPage;
int rc;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" PAGE\"", 0);
return TCL_ERROR;
}
pPage = sqlite3TextToPtr(argv[1]);
rc = sqlite3pager_unref(pPage);
pPage = (DbPage *)sqlite3TextToPtr(argv[1]);
rc = sqlite3PagerUnref(pPage);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
@ -440,14 +445,14 @@ static int page_read(
const char **argv /* Text of each argument */
){
char zBuf[100];
void *pPage;
DbPage *pPage;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" PAGE\"", 0);
return TCL_ERROR;
}
pPage = sqlite3TextToPtr(argv[1]);
memcpy(zBuf, pPage, sizeof(zBuf));
memcpy(zBuf, sqlite3PagerGetData(pPage), sizeof(zBuf));
Tcl_AppendResult(interp, zBuf, 0);
return TCL_OK;
}
@ -464,14 +469,14 @@ static int page_number(
const char **argv /* Text of each argument */
){
char zBuf[100];
void *pPage;
DbPage *pPage;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" PAGE\"", 0);
return TCL_ERROR;
}
pPage = sqlite3TextToPtr(argv[1]);
sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3pager_pagenumber(pPage));
pPage = (DbPage *)sqlite3TextToPtr(argv[1]);
sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3PagerPagenumber(pPage));
Tcl_AppendResult(interp, zBuf, 0);
return TCL_OK;
}
@ -487,21 +492,23 @@ static int page_write(
int argc, /* Number of arguments */
const char **argv /* Text of each argument */
){
void *pPage;
DbPage *pPage;
char *pData;
int rc;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" PAGE DATA\"", 0);
return TCL_ERROR;
}
pPage = sqlite3TextToPtr(argv[1]);
rc = sqlite3pager_write(pPage);
pPage = (DbPage *)sqlite3TextToPtr(argv[1]);
rc = sqlite3PagerWrite(pPage);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
strncpy((char*)pPage, argv[2], test_pagesize-1);
((char*)pPage)[test_pagesize-1] = 0;
pData = sqlite3PagerGetData(pPage);
strncpy(pData, argv[2], test_pagesize-1);
pData[test_pagesize-1] = 0;
return TCL_OK;
}
@ -558,10 +565,12 @@ static int fake_big_file(
** Register commands with the TCL interpreter.
*/
int Sqlitetest2_Init(Tcl_Interp *interp){
extern int sqlite3_io_error_persist;
extern int sqlite3_io_error_pending;
extern int sqlite3_io_error_hit;
extern int sqlite3_diskfull_pending;
extern int sqlite3_diskfull;
extern int sqlite3_pager_n_sort_bucket;
static struct {
char *zName;
Tcl_CmdProc *xProc;
@ -592,6 +601,8 @@ int Sqlitetest2_Init(Tcl_Interp *interp){
}
Tcl_LinkVar(interp, "sqlite_io_error_pending",
(char*)&sqlite3_io_error_pending, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_io_error_persist",
(char*)&sqlite3_io_error_persist, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_io_error_hit",
(char*)&sqlite3_io_error_hit, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_diskfull_pending",
@ -602,5 +613,7 @@ int Sqlitetest2_Init(Tcl_Interp *interp){
(char*)&sqlite3_pending_byte, TCL_LINK_INT);
Tcl_LinkVar(interp, "pager_pagesize",
(char*)&test_pagesize, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_pager_n_sort_bucket",
(char*)&sqlite3_pager_n_sort_bucket, TCL_LINK_INT);
return TCL_OK;
}

View file

@ -511,7 +511,7 @@ static int btree_pager_stats(
return TCL_ERROR;
}
pBt = sqlite3TextToPtr(argv[1]);
a = sqlite3pager_stats(sqlite3BtreePager(pBt));
a = sqlite3PagerStats(sqlite3BtreePager(pBt));
for(i=0; i<11; i++){
static char *zName[] = {
"ref", "page", "max", "size", "state", "err",
@ -545,7 +545,7 @@ static int btree_pager_ref_dump(
}
pBt = sqlite3TextToPtr(argv[1]);
#ifdef SQLITE_DEBUG
sqlite3pager_refdump(sqlite3BtreePager(pBt));
sqlite3PagerRefdump(sqlite3BtreePager(pBt));
#endif
return TCL_OK;
}
@ -706,9 +706,9 @@ static int btree_move_to(
if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){
int iKey;
if( Tcl_GetInt(interp, argv[2], &iKey) ) return TCL_ERROR;
rc = sqlite3BtreeMoveto(pCur, 0, iKey, &res);
rc = sqlite3BtreeMoveto(pCur, 0, iKey, 0, &res);
}else{
rc = sqlite3BtreeMoveto(pCur, argv[2], strlen(argv[2]), &res);
rc = sqlite3BtreeMoveto(pCur, argv[2], strlen(argv[2]), 0, &res);
}
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
@ -775,7 +775,7 @@ static int btree_insert(
unsigned char *pBuf;
if( Tcl_GetWideIntFromObj(interp, objv[2], &iKey) ) return TCL_ERROR;
pBuf = Tcl_GetByteArrayFromObj(objv[3], &len);
rc = sqlite3BtreeInsert(pCur, 0, iKey, pBuf, len);
rc = sqlite3BtreeInsert(pCur, 0, iKey, pBuf, len, 0);
}else{
int keylen;
int dlen;
@ -783,7 +783,7 @@ static int btree_insert(
unsigned char *pDBuf;
pKBuf = Tcl_GetByteArrayFromObj(objv[2], &keylen);
pDBuf = Tcl_GetByteArrayFromObj(objv[3], &dlen);
rc = sqlite3BtreeInsert(pCur, pKBuf, keylen, pDBuf, dlen);
rc = sqlite3BtreeInsert(pCur, pKBuf, keylen, pDBuf, dlen, 0);
}
if( rc ){
Tcl_AppendResult(interp, errorName(rc), 0);
@ -1229,7 +1229,7 @@ static int btree_cursor_info(
/*
** Copied from btree.c:
*/
static u32 get4byte(unsigned char *p){
static u32 t4Get4byte(unsigned char *p){
return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
}
@ -1282,15 +1282,17 @@ static int btree_ovfl_info(
n = (n + dataSize - 1)/dataSize;
pgno = (u32)aResult[10];
while( pgno && n-- ){
DbPage *pDbPage;
sprintf(zElem, "%d", pgno);
Tcl_DStringAppendElement(&str, zElem);
if( sqlite3pager_get(pPager, pgno, &pPage)!=SQLITE_OK ){
if( sqlite3PagerGet(pPager, pgno, &pDbPage)!=SQLITE_OK ){
Tcl_DStringFree(&str);
Tcl_AppendResult(interp, "unable to get page ", zElem, 0);
return TCL_ERROR;
}
pgno = get4byte((unsigned char*)pPage);
sqlite3pager_unref(pPage);
pPage = sqlite3PagerGetData(pDbPage);
pgno = t4Get4byte((unsigned char*)pPage);
sqlite3PagerUnref(pDbPage);
}
Tcl_DStringResult(interp, &str);
return SQLITE_OK;

View file

@ -47,7 +47,6 @@ void sqlite3BeginTrigger(
int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
IdList *pColumns, /* column list if this is an UPDATE OF trigger */
SrcList *pTableName,/* The name of the table/view the trigger applies to */
int foreach, /* One of TK_ROW or TK_STATEMENT */
Expr *pWhen, /* WHEN clause */
int isTemp, /* True if the TEMPORARY keyword is present */
int noErr /* Suppress errors if the trigger already exists */
@ -180,7 +179,6 @@ void sqlite3BeginTrigger(
pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
pTrigger->pWhen = sqlite3ExprDup(pWhen);
pTrigger->pColumns = sqlite3IdListDup(pColumns);
pTrigger->foreach = foreach;
sqlite3TokenCopy(&pTrigger->nameToken,pName);
assert( pParse->pNewTrigger==0 );
pParse->pNewTrigger = pTrigger;
@ -390,7 +388,11 @@ TriggerStep *sqlite3TriggerUpdateStep(
int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
if( pTriggerStep==0 ) return 0;
if( pTriggerStep==0 ){
sqlite3ExprListDelete(pEList);
sqlite3ExprDelete(pWhere);
return 0;
}
pTriggerStep->op = TK_UPDATE;
pTriggerStep->target = *pTableName;
@ -409,7 +411,10 @@ TriggerStep *sqlite3TriggerUpdateStep(
*/
TriggerStep *sqlite3TriggerDeleteStep(Token *pTableName, Expr *pWhere){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
if( pTriggerStep==0 ) return 0;
if( pTriggerStep==0 ){
sqlite3ExprDelete(pWhere);
return 0;
}
pTriggerStep->op = TK_DELETE;
pTriggerStep->target = *pTableName;

View file

@ -465,7 +465,7 @@ void sqlite3Update(
/* Create the new index entries and the new record.
*/
sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRowid, 1, -1);
sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRowid, 1, -1, 0);
}
/* Increment the row counter
@ -617,6 +617,7 @@ static void updateVirtualTable(
sqlite3VdbeOp3(v, OP_VUpdate, 0, pTab->nCol+2,
(const char*)pTab->pVtab, P3_VTAB);
sqlite3VdbeAddOp(v, OP_Next, ephemTab, addr);
sqlite3VdbeJumpHere(v, addr-1);
sqlite3VdbeAddOp(v, OP_Close, ephemTab, 0);
/* Cleanup */

View file

@ -62,6 +62,12 @@
#include <assert.h>
#include "vdbeInt.h"
/*
** The following constant value is used by the SQLITE_BIGENDIAN and
** SQLITE_LITTLEENDIAN macros.
*/
const int sqlite3one = 1;
/*
** This table maps from the first byte of a UTF-8 character to the number
** of trailing bytes expected. A value '4' indicates that the table key

View file

@ -83,7 +83,7 @@ void sqlite3_soft_heap_limit(int n){
** Release memory held by SQLite instances created by the current thread.
*/
int sqlite3_release_memory(int n){
return sqlite3pager_release_memory(n);
return sqlite3PagerReleaseMemory(n);
}
#else
/* If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, then define a version
@ -661,12 +661,13 @@ void *sqlite3Malloc(int n, int doMemManage){
}
return p;
}
void sqlite3ReallocOrFree(void **pp, int n){
void *p = sqlite3Realloc(*pp, n);
if( !p ){
sqlite3FreeX(*pp);
void *sqlite3ReallocOrFree(void *p, int n){
void *pNew;
pNew = sqlite3Realloc(p, n);
if( !pNew ){
sqlite3FreeX(p);
}
*pp = p;
return pNew;
}
/*
@ -750,7 +751,7 @@ void sqlite3SetString(char **pz, ...){
const char *z;
char *zResult;
if( pz==0 ) return;
assert( pz!=0 );
nByte = 1;
va_start(ap, pz);
while( (z = va_arg(ap, const char*))!=0 ){
@ -1132,6 +1133,13 @@ int sqlite3FitsIn64Bits(const char *zNum){
** Return an error (non-zero) if the magic was not SQLITE_MAGIC_OPEN
** when this routine is called.
**
** This routine is called when entering an SQLite API. The SQLITE_MAGIC_OPEN
** value indicates that the database connection passed into the API is
** open and is not being used by another thread. By changing the value
** to SQLITE_MAGIC_BUSY we indicate that the connection is in use.
** sqlite3SafetyOff() below will change the value back to SQLITE_MAGIC_OPEN
** when the API exits.
**
** This routine is a attempt to detect if two threads use the
** same sqlite* pointer at the same time. There is a race
** condition so it is possible that the error is not detected.
@ -1165,11 +1173,11 @@ int sqlite3SafetyOff(sqlite3 *db){
if( db->magic==SQLITE_MAGIC_BUSY ){
db->magic = SQLITE_MAGIC_OPEN;
return 0;
}else if( db->magic==SQLITE_MAGIC_OPEN ){
}else {
db->magic = SQLITE_MAGIC_ERROR;
db->u1.isInterrupted = 1;
return 1;
}
return 1;
}
/*
@ -1384,11 +1392,11 @@ void *sqlite3TextToPtr(const char *z){
z++;
}
if( sizeof(p)==sizeof(v) ){
p = *(void**)&v;
memcpy(&p, &v, sizeof(p));
}else{
assert( sizeof(p)==sizeof(v2) );
v2 = (u32)v;
p = *(void**)&v2;
memcpy(&p, &v2, sizeof(p));
}
return p;
}
@ -1461,9 +1469,11 @@ int sqlite3MallocFailed(){
** Set the "malloc has failed" condition to true for this thread.
*/
void sqlite3FailedMalloc(){
sqlite3OsEnterMutex();
assert( mallocHasFailed==0 );
mallocHasFailed = 1;
if( !sqlite3MallocFailed() ){
sqlite3OsEnterMutex();
assert( mallocHasFailed==0 );
mallocHasFailed = 1;
}
}
#ifdef SQLITE_MEMDEBUG

View file

@ -20,7 +20,7 @@
#include "vdbeInt.h"
#include "os.h"
#ifndef SQLITE_OMIT_VACUUM
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
/*
** Execute zSql on database db. Return an error code.
*/
@ -83,13 +83,11 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
char *zSql = 0; /* SQL statements */
int saved_flags; /* Saved value of the db->flags */
Db *pDb = 0; /* Database to detach at end of vacuum */
char zTemp[SQLITE_TEMPNAME_SIZE+20]; /* Name of the TEMP file */
/* Save the current value of the write-schema flag before setting it. */
saved_flags = db->flags;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
sqlite3OsTempFileName(zTemp);
if( !db->autoCommit ){
sqlite3SetString(pzErrMsg, "cannot VACUUM from within a transaction",
(char*)0);
@ -106,20 +104,18 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
**
** An optimisation would be to use a non-journaled pager.
*/
zSql = sqlite3MPrintf("ATTACH '%q' AS vacuum_db;", zTemp);
if( !zSql ){
rc = SQLITE_NOMEM;
goto end_of_vacuum;
}
zSql = "ATTACH '' AS vacuum_db;";
rc = execSql(db, zSql);
sqliteFree(zSql);
zSql = 0;
if( rc!=SQLITE_OK ) goto end_of_vacuum;
pDb = &db->aDb[db->nDb-1];
assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 );
pTemp = db->aDb[db->nDb-1].pBt;
sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain),
sqlite3BtreeGetReserve(pMain));
if( sqlite3MallocFailed() ){
rc = SQLITE_NOMEM;
goto end_of_vacuum;
}
assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) );
rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF");
if( rc!=SQLITE_OK ){
@ -259,12 +255,8 @@ end_of_vacuum:
pDb->pSchema = 0;
}
sqlite3OsDelete(zTemp);
strcat(zTemp, "-journal");
sqlite3OsDelete(zTemp);
sqliteFree( zSql );
sqlite3ResetInternalSchema(db, 0);
return rc;
}
#endif /* SQLITE_OMIT_VACUUM */
#endif /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */

View file

@ -211,7 +211,7 @@ static void applyNumericAffinity(Mem *pRec){
sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8);
if( !realnum && sqlite3atoi64(pRec->z, &value) ){
sqlite3VdbeMemRelease(pRec);
pRec->i = value;
pRec->u.i = value;
pRec->flags = MEM_Int;
}else{
sqlite3VdbeMemRealify(pRec);
@ -454,6 +454,7 @@ int sqlite3VdbeExec(
p->resOnStack = 0;
db->busyHandler.nBusy = 0;
CHECK_FOR_INTERRUPT;
sqlite3VdbeIOTraceSql(p);
#ifdef SQLITE_DEBUG
if( (p->db->flags & SQLITE_VdbeListing)!=0
|| sqlite3OsFileExists("vdbe_explain")
@ -669,7 +670,7 @@ case OP_Halt: { /* no-push */
case OP_Integer: {
pTos++;
pTos->flags = MEM_Int;
pTos->i = pOp->p1;
pTos->u.i = pOp->p1;
break;
}
@ -685,7 +686,7 @@ case OP_Int64: {
pTos->z = pOp->p3;
pTos->n = strlen(pTos->z);
pTos->enc = SQLITE_UTF8;
pTos->i = sqlite3VdbeIntValue(pTos);
pTos->u.i = sqlite3VdbeIntValue(pTos);
pTos->flags |= MEM_Int;
break;
}
@ -1098,8 +1099,8 @@ case OP_Remainder: { /* same as TK_REM, no-push */
pTos->flags = MEM_Null;
}else if( (pTos->flags & pNos->flags & MEM_Int)==MEM_Int ){
i64 a, b;
a = pTos->i;
b = pNos->i;
a = pTos->u.i;
b = pNos->u.i;
switch( pOp->opcode ){
case OP_Add: b += a; break;
case OP_Subtract: b -= a; break;
@ -1118,7 +1119,7 @@ case OP_Remainder: { /* same as TK_REM, no-push */
Release(pTos);
pTos--;
Release(pTos);
pTos->i = b;
pTos->u.i = b;
pTos->flags = MEM_Int;
}else{
double a, b;
@ -1309,7 +1310,7 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, no-push */
Release(pTos);
pTos--;
Release(pTos);
pTos->i = a;
pTos->u.i = a;
pTos->flags = MEM_Int;
break;
}
@ -1324,7 +1325,7 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, no-push */
case OP_AddImm: { /* no-push */
assert( pTos>=p->aStack );
sqlite3VdbeMemIntegerify(pTos);
pTos->i += pOp->p1;
pTos->u.i += pOp->p1;
break;
}
@ -1349,7 +1350,7 @@ case OP_ForceInt: { /* no-push */
break;
}
if( pTos->flags & MEM_Int ){
v = pTos->i + (pOp->p1!=0);
v = pTos->u.i + (pOp->p1!=0);
}else{
/* FIX ME: should this not be assert( pTos->flags & MEM_Real ) ??? */
sqlite3VdbeMemRealify(pTos);
@ -1358,7 +1359,7 @@ case OP_ForceInt: { /* no-push */
if( pOp->p1 && pTos->r==(double)v ) v++;
}
Release(pTos);
pTos->i = v;
pTos->u.i = v;
pTos->flags = MEM_Int;
break;
}
@ -1647,7 +1648,7 @@ case OP_Ge: { /* same as TK_GE, no-push */
}else{
pTos++;
pTos->flags = MEM_Int;
pTos->i = res;
pTos->u.i = res;
}
break;
}
@ -1674,13 +1675,13 @@ case OP_Or: { /* same as TK_OR, no-push */
v1 = 2;
}else{
sqlite3VdbeMemIntegerify(pTos);
v1 = pTos->i==0;
v1 = pTos->u.i==0;
}
if( pNos->flags & MEM_Null ){
v2 = 2;
}else{
sqlite3VdbeMemIntegerify(pNos);
v2 = pNos->i==0;
v2 = pNos->u.i==0;
}
if( pOp->opcode==OP_And ){
static const unsigned char and_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
@ -1694,7 +1695,7 @@ case OP_Or: { /* same as TK_OR, no-push */
if( v1==2 ){
pTos->flags = MEM_Null;
}else{
pTos->i = v1==0;
pTos->u.i = v1==0;
pTos->flags = MEM_Int;
}
break;
@ -1724,8 +1725,8 @@ case OP_AbsValue: {
pTos->flags = MEM_Real;
}else if( pTos->flags & MEM_Int ){
Release(pTos);
if( pOp->opcode==OP_Negative || pTos->i<0 ){
pTos->i = -pTos->i;
if( pOp->opcode==OP_Negative || pTos->u.i<0 ){
pTos->u.i = -pTos->u.i;
}
pTos->flags = MEM_Int;
}else if( pTos->flags & MEM_Null ){
@ -1748,7 +1749,7 @@ case OP_Not: { /* same as TK_NOT, no-push */
if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
sqlite3VdbeMemIntegerify(pTos);
assert( (pTos->flags & MEM_Dyn)==0 );
pTos->i = !pTos->i;
pTos->u.i = !pTos->u.i;
pTos->flags = MEM_Int;
break;
}
@ -1764,7 +1765,7 @@ case OP_BitNot: { /* same as TK_BITNOT, no-push */
if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
sqlite3VdbeMemIntegerify(pTos);
assert( (pTos->flags & MEM_Dyn)==0 );
pTos->i = ~pTos->i;
pTos->u.i = ~pTos->u.i;
pTos->flags = MEM_Int;
break;
}
@ -1936,6 +1937,9 @@ case OP_Column: {
** which is the number of records.
*/
pC = p->apCsr[p1];
#ifndef SQLITE_OMIT_VIRTUALTABLE
assert( pC->pVtabCursor==0 );
#endif
assert( pC!=0 );
if( pC->pCursor!=0 ){
/* The record is stored in a B-Tree */
@ -2445,7 +2449,7 @@ case OP_ReadCookie: {
*/
rc = sqlite3BtreeGetMeta(db->aDb[pOp->p1].pBt, 1 + pOp->p2, (u32 *)&iMeta);
pTos++;
pTos->i = iMeta;
pTos->u.i = iMeta;
pTos->flags = MEM_Int;
break;
}
@ -2469,14 +2473,14 @@ case OP_SetCookie: { /* no-push */
assert( pTos>=p->aStack );
sqlite3VdbeMemIntegerify(pTos);
/* See note about index shifting on OP_ReadCookie */
rc = sqlite3BtreeUpdateMeta(pDb->pBt, 1+pOp->p2, (int)pTos->i);
rc = sqlite3BtreeUpdateMeta(pDb->pBt, 1+pOp->p2, (int)pTos->u.i);
if( pOp->p2==0 ){
/* When the schema cookie changes, record the new cookie internally */
pDb->pSchema->schema_cookie = pTos->i;
pDb->pSchema->schema_cookie = pTos->u.i;
db->flags |= SQLITE_InternChanges;
}else if( pOp->p2==1 ){
/* Record changes in the file format */
pDb->pSchema->file_format = pTos->i;
pDb->pSchema->file_format = pTos->u.i;
}
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
@ -2578,7 +2582,7 @@ case OP_OpenWrite: { /* no-push */
assert( pTos>=p->aStack );
sqlite3VdbeMemIntegerify(pTos);
iDb = pTos->i;
iDb = pTos->u.i;
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
assert( iDb>=0 && iDb<db->nDb );
@ -2596,7 +2600,7 @@ case OP_OpenWrite: { /* no-push */
if( p2<=0 ){
assert( pTos>=p->aStack );
sqlite3VdbeMemIntegerify(pTos);
p2 = pTos->i;
p2 = pTos->u.i;
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
assert( p2>=2 );
@ -2822,7 +2826,7 @@ case OP_MoveGt: { /* no-push */
if( pC->isTable ){
i64 iKey;
sqlite3VdbeMemIntegerify(pTos);
iKey = intToKey(pTos->i);
iKey = intToKey(pTos->u.i);
if( pOp->p2==0 && pOp->opcode==OP_MoveGe ){
pC->movetoTarget = iKey;
pC->deferredMoveto = 1;
@ -2830,16 +2834,16 @@ case OP_MoveGt: { /* no-push */
pTos--;
break;
}
rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, &res);
rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
pC->lastRowid = pTos->i;
pC->lastRowid = pTos->u.i;
pC->rowidIsValid = res==0;
}else{
assert( pTos->flags & MEM_Blob );
/* Stringify(pTos, encoding); */
rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
@ -2946,7 +2950,7 @@ case OP_Found: { /* no-push */
int res, rx;
assert( pC->isTable==0 );
Stringify(pTos, encoding);
rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res);
alreadyExists = rx==SQLITE_OK && res==0;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
@ -2995,7 +2999,7 @@ case OP_IsUnique: { /* no-push */
*/
assert( pNos>=p->aStack );
sqlite3VdbeMemIntegerify(pTos);
R = pTos->i;
R = pTos->u.i;
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
assert( i>=0 && i<p->nCursor );
@ -3024,7 +3028,7 @@ case OP_IsUnique: { /* no-push */
*/
assert( pCx->deferredMoveto==0 );
pCx->cacheStatus = CACHE_STALE;
rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res);
rc = sqlite3BtreeMoveto(pCrsr, zKey, len, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
@ -3061,7 +3065,7 @@ case OP_IsUnique: { /* no-push */
** constraint.)
*/
pTos++;
pTos->i = v;
pTos->u.i = v;
pTos->flags = MEM_Int;
}
break;
@ -3093,15 +3097,17 @@ case OP_NotExists: { /* no-push */
u64 iKey;
assert( pTos->flags & MEM_Int );
assert( p->apCsr[i]->isTable );
iKey = intToKey(pTos->i);
rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res);
pC->lastRowid = pTos->i;
iKey = intToKey(pTos->u.i);
rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, 0,&res);
pC->lastRowid = pTos->u.i;
pC->rowidIsValid = res==0;
pC->nullRow = 0;
pC->cacheStatus = CACHE_STALE;
/* res might be uninitialized if rc!=SQLITE_OK. But if rc!=SQLITE_OK
** processing is about to abort so we really do not care whether or not
** the following jump is taken. */
** the following jump is taken. (In other words, do not stress over
** the error that valgrind sometimes shows on the next statement when
** running ioerr.test and similar failure-recovery test scripts.) */
if( res!=0 ){
pc = pOp->p2 - 1;
pC->rowidIsValid = 0;
@ -3124,7 +3130,7 @@ case OP_Sequence: {
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
pTos++;
pTos->i = p->apCsr[i]->seqCount++;
pTos->u.i = p->apCsr[i]->seqCount++;
pTos->flags = MEM_Int;
break;
}
@ -3233,14 +3239,14 @@ case OP_NewRowid: {
pMem = &p->aMem[pOp->p2];
sqlite3VdbeMemIntegerify(pMem);
assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P2) holds an integer */
if( pMem->i==MAX_ROWID || pC->useRandomRowid ){
if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
rc = SQLITE_FULL;
goto abort_due_to_error;
}
if( v<pMem->i+1 ){
v = pMem->i + 1;
if( v<pMem->u.i+1 ){
v = pMem->u.i + 1;
}
pMem->i = v;
pMem->u.i = v;
}
#endif
@ -3266,7 +3272,7 @@ case OP_NewRowid: {
}
if( v==0 ) continue;
x = intToKey(v);
rx = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)x, &res);
rx = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)x, 0, &res);
cnt++;
}while( cnt<1000 && rx==SQLITE_OK && res==0 );
db->priorNewRowid = v;
@ -3280,7 +3286,7 @@ case OP_NewRowid: {
pC->cacheStatus = CACHE_STALE;
}
pTos++;
pTos->i = v;
pTos->u.i = v;
pTos->flags = MEM_Int;
break;
}
@ -3317,11 +3323,11 @@ case OP_Insert: { /* no-push */
assert( pNos->flags & MEM_Int );
assert( pC->isTable );
iKey = intToKey(pNos->i);
iKey = intToKey(pNos->u.i);
if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i;
if( pC->nextRowidValid && pNos->i>=pC->nextRowid ){
if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->u.i;
if( pC->nextRowidValid && pNos->u.i>=pC->nextRowid ){
pC->nextRowidValid = 0;
}
if( pTos->flags & MEM_Null ){
@ -3346,7 +3352,9 @@ case OP_Insert: { /* no-push */
}
pC->nullRow = 0;
}else{
rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, pTos->z, pTos->n);
rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey,
pTos->z, pTos->n,
pOp->p2 & OPFLAG_APPEND);
}
pC->rowidIsValid = 0;
@ -3500,9 +3508,9 @@ case OP_RowData: {
pTos->z = z;
}
if( pC->isIndex ){
sqlite3BtreeKey(pCrsr, 0, n, pTos->z);
rc = sqlite3BtreeKey(pCrsr, 0, n, pTos->z);
}else{
sqlite3BtreeData(pCrsr, 0, n, pTos->z);
rc = sqlite3BtreeData(pCrsr, 0, n, pTos->z);
}
}else if( pC->pseudoTable ){
pTos->n = pC->nData;
@ -3543,7 +3551,7 @@ case OP_Rowid: {
sqlite3BtreeKeySize(pC->pCursor, &v);
v = keyToInt(v);
}
pTos->i = v;
pTos->u.i = v;
pTos->flags = MEM_Int;
break;
}
@ -3673,7 +3681,9 @@ case OP_Next: { /* no-push */
CHECK_FOR_INTERRUPT;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
if( pC==0 ){
break; /* See ticket #2273 */
}
if( (pCrsr = pC->pCursor)!=0 ){
int res;
if( pC->nullRow ){
@ -3698,12 +3708,15 @@ case OP_Next: { /* no-push */
break;
}
/* Opcode: IdxInsert P1 * *
/* Opcode: IdxInsert P1 P2 *
**
** The top of the stack holds a SQL index key made using either the
** MakeIdxRec or MakeRecord instructions. This opcode writes that key
** into the index P1. Data for the entry is nil.
**
** P2 is a flag that provides a hint to the b-tree layer that this
** insert is likely to be an append.
**
** This instruction only works for indices. The equivalent instruction
** for tables is OP_Insert.
*/
@ -3715,12 +3728,11 @@ case OP_IdxInsert: { /* no-push */
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
assert( pTos->flags & MEM_Blob );
assert( pOp->p2==0 );
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
int nKey = pTos->n;
const char *zKey = pTos->z;
assert( pC->isTable==0 );
rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0);
rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, pOp->p2);
assert( pC->deferredMoveto==0 );
pC->cacheStatus = CACHE_STALE;
}
@ -3745,7 +3757,7 @@ case OP_IdxDelete: { /* no-push */
assert( p->apCsr[i]!=0 );
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
int res;
rc = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res);
rc = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, 0, &res);
if( rc==SQLITE_OK && res==0 ){
rc = sqlite3BtreeDelete(pCrsr);
}
@ -3787,7 +3799,7 @@ case OP_IdxRowid: {
goto abort_due_to_error;
}
pTos->flags = MEM_Int;
pTos->i = rowid;
pTos->u.i = rowid;
}
}
break;
@ -3914,7 +3926,7 @@ case OP_Destroy: {
rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1, &iMoved);
pTos++;
pTos->flags = MEM_Int;
pTos->i = iMoved;
pTos->u.i = iMoved;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( rc==SQLITE_OK && iMoved!=0 ){
sqlite3RootPageMoved(&db->aDb[pOp->p2], iMoved, pOp->p1);
@ -4013,7 +4025,7 @@ case OP_CreateTable: {
rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags);
pTos++;
if( rc==SQLITE_OK ){
pTos->i = pgno;
pTos->u.i = pgno;
pTos->flags = MEM_Int;
}else{
pTos->flags = MEM_Null;
@ -4160,14 +4172,14 @@ case OP_IntegrityCk: {
assert( (pnErr->flags & MEM_Int)!=0 );
for(j=0; j<nRoot; j++){
Mem *pMem = &pTos[-j];
aRoot[j] = pMem->i;
aRoot[j] = pMem->u.i;
}
aRoot[j] = 0;
popStack(&pTos, nRoot);
pTos++;
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot,
pnErr->i, &nErr);
pnErr->i -= nErr;
pnErr->u.i, &nErr);
pnErr->u.i -= nErr;
if( nErr==0 ){
assert( z==0 );
pTos->flags = MEM_Null;
@ -4192,7 +4204,7 @@ case OP_IntegrityCk: {
case OP_FifoWrite: { /* no-push */
assert( pTos>=p->aStack );
sqlite3VdbeMemIntegerify(pTos);
sqlite3VdbeFifoPush(&p->sFifo, pTos->i);
sqlite3VdbeFifoPush(&p->sFifo, pTos->u.i);
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
break;
@ -4211,7 +4223,7 @@ case OP_FifoRead: {
pc = pOp->p2 - 1;
}else{
pTos++;
pTos->i = v;
pTos->u.i = v;
pTos->flags = MEM_Int;
}
break;
@ -4232,7 +4244,8 @@ case OP_ContextPush: { /* no-push */
/* FIX ME: This should be allocated as part of the vdbe at compile-time */
if( i>=p->contextStackDepth ){
p->contextStackDepth = i+1;
sqliteReallocOrFree((void**)&p->contextStack, sizeof(Context)*(i+1));
p->contextStack = sqliteReallocOrFree(p->contextStack,
sizeof(Context)*(i+1));
if( p->contextStack==0 ) goto no_mem;
}
pContext = &p->contextStack[i];
@ -4317,8 +4330,8 @@ case OP_MemMax: { /* no-push */
pMem = &p->aMem[i];
sqlite3VdbeMemIntegerify(pMem);
sqlite3VdbeMemIntegerify(pTos);
if( pMem->i<pTos->i){
pMem->i = pTos->i;
if( pMem->u.i<pTos->u.i){
pMem->u.i = pTos->u.i;
}
break;
}
@ -4337,7 +4350,7 @@ case OP_MemIncr: { /* no-push */
assert( i>=0 && i<p->nMem );
pMem = &p->aMem[i];
assert( pMem->flags==MEM_Int );
pMem->i += pOp->p1;
pMem->u.i += pOp->p1;
break;
}
@ -4354,7 +4367,7 @@ case OP_IfMemPos: { /* no-push */
assert( i>=0 && i<p->nMem );
pMem = &p->aMem[i];
assert( pMem->flags==MEM_Int );
if( pMem->i>0 ){
if( pMem->u.i>0 ){
pc = pOp->p2 - 1;
}
break;
@ -4373,7 +4386,7 @@ case OP_IfMemNeg: { /* no-push */
assert( i>=0 && i<p->nMem );
pMem = &p->aMem[i];
assert( pMem->flags==MEM_Int );
if( pMem->i<0 ){
if( pMem->u.i<0 ){
pc = pOp->p2 - 1;
}
break;
@ -4392,7 +4405,7 @@ case OP_IfMemZero: { /* no-push */
assert( i>=0 && i<p->nMem );
pMem = &p->aMem[i];
assert( pMem->flags==MEM_Int );
if( pMem->i==0 ){
if( pMem->u.i==0 ){
pc = pOp->p2 - 1;
}
break;
@ -4506,7 +4519,7 @@ case OP_AggFinal: { /* no-push */
}
#ifndef SQLITE_OMIT_VACUUM
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
/* Opcode: Vacuum * * *
**
** Vacuum the entire database. This opcode will cause other virtual
@ -4679,7 +4692,7 @@ case OP_VFilter: { /* no-push */
/* Grab the index number and argc parameters off the top of the stack. */
assert( (&pTos[-1])>=p->aStack );
assert( (pTos[0].flags&MEM_Int)!=0 && pTos[-1].flags==MEM_Int );
nArg = pTos[-1].i;
nArg = pTos[-1].u.i;
/* Invoke the xFilter method */
{
@ -4693,7 +4706,7 @@ case OP_VFilter: { /* no-push */
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
p->inVtabMethod = 1;
rc = pModule->xFilter(pCur->pVtabCursor, pTos->i, pOp->p3, nArg, apArg);
rc = pModule->xFilter(pCur->pVtabCursor, pTos->u.i, pOp->p3, nArg, apArg);
p->inVtabMethod = 0;
if( rc==SQLITE_OK ){
res = pModule->xEof(pCur->pVtabCursor);
@ -4735,7 +4748,7 @@ case OP_VRowid: {
pTos++;
pTos->flags = MEM_Int;
pTos->i = iRow;
pTos->u.i = iRow;
}
break;
@ -4934,9 +4947,9 @@ default: {
if( pTos[i].flags & MEM_Null ){
fprintf(p->trace, " NULL");
}else if( (pTos[i].flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
fprintf(p->trace, " si:%lld", pTos[i].i);
fprintf(p->trace, " si:%lld", pTos[i].u.i);
}else if( pTos[i].flags & MEM_Int ){
fprintf(p->trace, " i:%lld", pTos[i].i);
fprintf(p->trace, " i:%lld", pTos[i].u.i);
}else if( pTos[i].flags & MEM_Real ){
fprintf(p->trace, " r:%g", pTos[i].r);
}else{

View file

@ -31,7 +31,7 @@
** array is defined in a separate source code file named opcode.c which is
** automatically generated by the makefile.
*/
extern char *sqlite3OpcodeNames[];
extern const char *const sqlite3OpcodeNames[];
/*
** SQL is translated into a sequence of instructions to be
@ -125,7 +125,10 @@ typedef struct Cursor Cursor;
** SQLITE_BLOB.
*/
struct Mem {
i64 i; /* Integer value. Or FuncDef* when flags==MEM_Agg */
union {
i64 i; /* Integer value. Or FuncDef* when flags==MEM_Agg */
FuncDef *pDef; /* Used only when flags==MEM_Agg */
} u;
double r; /* Real value */
char *z; /* String or BLOB value */
int n; /* Number of characters in string value, including '\0' */

View file

@ -341,7 +341,7 @@ void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
}else{
pMem->flags = MEM_Agg;
pMem->xDel = sqlite3FreeX;
*(FuncDef**)&pMem->i = p->pFunc;
pMem->u.pDef = p->pFunc;
if( nByte<=NBFS ){
pMem->z = pMem->zShort;
memset(pMem->z, 0, nByte);
@ -443,7 +443,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
Vdbe *pVm = (Vdbe *)pStmt;
int vals = sqlite3_data_count(pStmt);
if( i>=vals || i<0 ){
static const Mem nullMem = {0, 0.0, "", 0, MEM_Null, MEM_Null };
static const Mem nullMem = {{0}, 0.0, "", 0, MEM_Null, MEM_Null };
sqlite3Error(pVm->db, SQLITE_RANGE, 0);
return (Mem*)&nullMem;
}

View file

@ -195,8 +195,8 @@ int sqlite3VdbeMakeLabel(Vdbe *p){
assert( p->magic==VDBE_MAGIC_INIT );
if( i>=p->nLabelAlloc ){
p->nLabelAlloc = p->nLabelAlloc*2 + 10;
sqliteReallocOrFree((void**)&p->aLabel,
p->nLabelAlloc*sizeof(p->aLabel[0]));
p->aLabel = sqliteReallocOrFree(p->aLabel,
p->nLabelAlloc*sizeof(p->aLabel[0]));
}
if( p->aLabel ){
p->aLabel[i] = -1;
@ -719,11 +719,11 @@ int sqlite3VdbeList(
Mem *pMem = p->aStack;
pMem->flags = MEM_Int;
pMem->type = SQLITE_INTEGER;
pMem->i = i; /* Program counter */
pMem->u.i = i; /* Program counter */
pMem++;
pMem->flags = MEM_Static|MEM_Str|MEM_Term;
pMem->z = sqlite3OpcodeNames[pOp->opcode]; /* Opcode */
pMem->z = (char*)sqlite3OpcodeNames[pOp->opcode]; /* Opcode */
assert( pMem->z!=0 );
pMem->n = strlen(pMem->z);
pMem->type = SQLITE_TEXT;
@ -731,12 +731,12 @@ int sqlite3VdbeList(
pMem++;
pMem->flags = MEM_Int;
pMem->i = pOp->p1; /* P1 */
pMem->u.i = pOp->p1; /* P1 */
pMem->type = SQLITE_INTEGER;
pMem++;
pMem->flags = MEM_Int;
pMem->i = pOp->p2; /* P2 */
pMem->u.i = pOp->p2; /* P2 */
pMem->type = SQLITE_INTEGER;
pMem++;
@ -757,11 +757,11 @@ int sqlite3VdbeList(
}
#endif /* SQLITE_OMIT_EXPLAIN */
#ifdef SQLITE_DEBUG
/*
** Print the SQL that was used to generate a VDBE program.
*/
void sqlite3VdbePrintSql(Vdbe *p){
#ifdef SQLITE_DEBUG
int nOp = p->nOp;
VdbeOp *pOp;
if( nOp<1 ) return;
@ -771,8 +771,39 @@ void sqlite3VdbePrintSql(Vdbe *p){
while( isspace(*(u8*)z) ) z++;
printf("SQL: [%s]\n", z);
}
#endif
}
#endif
#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
/*
** Print an IOTRACE message showing SQL content.
*/
void sqlite3VdbeIOTraceSql(Vdbe *p){
int nOp = p->nOp;
VdbeOp *pOp;
if( sqlite3_io_trace==0 ) return;
if( nOp<1 ) return;
pOp = &p->aOp[nOp-1];
if( pOp->opcode==OP_Noop && pOp->p3!=0 ){
char *z = sqlite3StrDup(pOp->p3);
int i, j;
for(i=0; isspace(z[i]); i++){}
for(j=0; z[i]; i++){
if( isspace(z[i]) ){
if( z[i-1]!=' ' ){
z[j++] = ' ';
}
}else{
z[j++] = z[i];
}
}
z[j] = 0;
sqlite3_io_trace("SQL %s\n", z);
sqliteFree(z);
}
}
#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */
/*
** Prepare a virtual machine for execution. This involves things such
@ -1059,18 +1090,22 @@ static int vdbeCommit(sqlite3 *db){
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
rc = sqlite3BtreeSync(pBt, 0);
rc = sqlite3BtreeCommitPhaseOne(pBt, 0);
}
}
/* Do the commit only if all databases successfully synced */
if( rc==SQLITE_OK ){
for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
sqlite3BtreeCommit(pBt);
}
/* Do the commit only if all databases successfully complete phase 1.
** If one of the BtreeCommitPhaseOne() calls fails, this indicates an
** IO error while deleting or truncating a journal file. It is unlikely,
** but could happen. In this case abandon processing and return the error.
*/
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
rc = sqlite3BtreeCommitPhaseTwo(pBt);
}
}
if( rc==SQLITE_OK ){
sqlite3VtabCommit(db);
}
}
@ -1147,16 +1182,16 @@ static int vdbeCommit(sqlite3 *db){
** sets the master journal pointer in each individual journal. If
** an error occurs here, do not delete the master journal file.
**
** If the error occurs during the first call to sqlite3BtreeSync(),
** then there is a chance that the master journal file will be
** orphaned. But we cannot delete it, in case the master journal
** file name was written into the journal file before the failure
** occured.
** If the error occurs during the first call to
** sqlite3BtreeCommitPhaseOne(), then there is a chance that the
** master journal file will be orphaned. But we cannot delete it,
** in case the master journal file name was written into the journal
** file before the failure occured.
*/
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt && sqlite3BtreeIsInTrans(pBt) ){
rc = sqlite3BtreeSync(pBt, zMaster);
rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster);
}
}
sqlite3OsClose(&master);
@ -1170,11 +1205,11 @@ static int vdbeCommit(sqlite3 *db){
** transaction files are deleted.
*/
rc = sqlite3OsDelete(zMaster);
sqliteFree(zMaster);
zMaster = 0;
if( rc ){
return rc;
}
sqliteFree(zMaster);
zMaster = 0;
rc = sqlite3OsSyncDirectory(zMainFile);
if( rc!=SQLITE_OK ){
/* This is not good. The master journal file has been deleted, but
@ -1188,18 +1223,21 @@ static int vdbeCommit(sqlite3 *db){
}
/* All files and directories have already been synced, so the following
** calls to sqlite3BtreeCommit() are only closing files and deleting
** journals. If something goes wrong while this is happening we don't
** really care. The integrity of the transaction is already guaranteed,
** but some stray 'cold' journals may be lying around. Returning an
** error code won't help matters.
** calls to sqlite3BtreeCommitPhaseTwo() are only closing files and
** deleting or truncating journals. If something goes wrong while
** this is happening we don't really care. The integrity of the
** transaction is already guaranteed, but some stray 'cold' journals
** may be lying around. Returning an error code won't help matters.
*/
disable_simulated_io_errors();
for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
sqlite3BtreeCommit(pBt);
sqlite3BtreeCommitPhaseTwo(pBt);
}
}
enable_simulated_io_errors();
sqlite3VtabCommit(db);
}
#endif
@ -1470,10 +1508,6 @@ void sqlite3VdbeResetStepResult(Vdbe *p){
*/
int sqlite3VdbeReset(Vdbe *p){
sqlite3 *db;
if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){
sqlite3Error(p->db, SQLITE_MISUSE, 0);
return SQLITE_MISUSE;
}
db = p->db;
/* If the VM did not run to completion or if it encountered an
@ -1624,12 +1658,7 @@ int sqlite3VdbeCursorMoveto(Cursor *p){
extern int sqlite3_search_count;
#endif
assert( p->isTable );
if( p->isTable ){
rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, &res);
}else{
rc = sqlite3BtreeMoveto(p->pCursor,(char*)&p->movetoTarget,
sizeof(i64),&res);
}
rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, 0, &res);
if( rc ) return rc;
*p->pIncrKey = 0;
p->lastRowid = keyToInt(p->movetoTarget);
@ -1701,7 +1730,7 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
if( flags&MEM_Int ){
/* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
# define MAX_6BYTE ((((i64)0x00001000)<<32)-1)
i64 i = pMem->i;
i64 i = pMem->u.i;
u64 u;
if( file_format>=4 && (i&1)==i ){
return 8+i;
@ -1722,10 +1751,8 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
assert( n>=0 );
return ((n*2) + 13);
}
if( flags&MEM_Blob ){
return (pMem->n*2 + 12);
}
return 0;
assert( (flags & MEM_Blob)!=0 );
return (pMem->n*2 + 12);
}
/*
@ -1754,9 +1781,10 @@ int sqlite3VdbeSerialPut(unsigned char *buf, Mem *pMem, int file_format){
u64 v;
int i;
if( serial_type==7 ){
v = *(u64*)&pMem->r;
assert( sizeof(v)==sizeof(pMem->r) );
memcpy(&v, &pMem->r, sizeof(v));
}else{
v = *(u64*)&pMem->i;
v = pMem->u.i;
}
len = i = sqlite3VdbeSerialTypeLen(serial_type);
while( i-- ){
@ -1794,22 +1822,22 @@ int sqlite3VdbeSerialGet(
break;
}
case 1: { /* 1-byte signed integer */
pMem->i = (signed char)buf[0];
pMem->u.i = (signed char)buf[0];
pMem->flags = MEM_Int;
return 1;
}
case 2: { /* 2-byte signed integer */
pMem->i = (((signed char)buf[0])<<8) | buf[1];
pMem->u.i = (((signed char)buf[0])<<8) | buf[1];
pMem->flags = MEM_Int;
return 2;
}
case 3: { /* 3-byte signed integer */
pMem->i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2];
pMem->u.i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2];
pMem->flags = MEM_Int;
return 3;
}
case 4: { /* 4-byte signed integer */
pMem->i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
pMem->u.i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
pMem->flags = MEM_Int;
return 4;
}
@ -1817,7 +1845,7 @@ int sqlite3VdbeSerialGet(
u64 x = (((signed char)buf[0])<<8) | buf[1];
u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
x = (x<<32) | y;
pMem->i = *(i64*)&x;
pMem->u.i = *(i64*)&x;
pMem->flags = MEM_Int;
return 6;
}
@ -1830,24 +1858,27 @@ int sqlite3VdbeSerialGet(
** byte order. The byte order differs on some (broken) architectures.
*/
static const u64 t1 = ((u64)0x3ff00000)<<32;
assert( 1.0==*(double*)&t1 );
static const double r1 = 1.0;
assert( sizeof(r1)==sizeof(t1) && memcmp(&r1, &t1, sizeof(r1))==0 );
#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;
pMem->u.i = *(i64*)&x;
pMem->flags = MEM_Int;
}else{
pMem->r = *(double*)&x;
assert( sizeof(x)==8 && sizeof(pMem->r)==8 );
memcpy(&pMem->r, &x, sizeof(x));
/* pMem->r = *(double*)&x; */
pMem->flags = MEM_Real;
}
return 8;
}
case 8: /* Integer 0 */
case 9: { /* Integer 1 */
pMem->i = serial_type-8;
pMem->u.i = serial_type-8;
pMem->flags = MEM_Int;
return 0;
}
@ -1984,7 +2015,7 @@ int sqlite3VdbeIdxRowidLen(const u8 *aKey){
** Return SQLITE_OK if everything works, or an error code otherwise.
*/
int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){
i64 nCellKey;
i64 nCellKey = 0;
int rc;
u32 szHdr; /* Size of the header */
u32 typeRowid; /* Serial type of the rowid */
@ -2003,7 +2034,7 @@ int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){
sqlite3GetVarint32((u8*)&m.z[szHdr-1], &typeRowid);
lenRowid = sqlite3VdbeSerialTypeLen(typeRowid);
sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v);
*rowid = v.i;
*rowid = v.u.i;
sqlite3VdbeMemRelease(&m);
return SQLITE_OK;
}
@ -2023,7 +2054,7 @@ int sqlite3VdbeIdxKeyCompare(
int nKey, const u8 *pKey, /* The key to compare */
int *res /* Write the comparison result here */
){
i64 nCellKey;
i64 nCellKey = 0;
int rc;
BtCursor *pCur = pC->pCursor;
int lenRowid;

View file

@ -19,7 +19,7 @@
** Allocate a new FifoPage and return a pointer to it. Return NULL if
** we run out of memory. Leave space on the page for nEntry entries.
*/
static FifoPage *allocatePage(int nEntry){
static FifoPage *allocateFifoPage(int nEntry){
FifoPage *pPage;
if( nEntry>32767 ){
nEntry = 32767;
@ -50,12 +50,12 @@ int sqlite3VdbeFifoPush(Fifo *pFifo, i64 val){
FifoPage *pPage;
pPage = pFifo->pLast;
if( pPage==0 ){
pPage = pFifo->pLast = pFifo->pFirst = allocatePage(20);
pPage = pFifo->pLast = pFifo->pFirst = allocateFifoPage(20);
if( pPage==0 ){
return SQLITE_NOMEM;
}
}else if( pPage->iWrite>=pPage->nSlot ){
pPage->pNext = allocatePage(pFifo->nEntry);
pPage->pNext = allocateFifoPage(pFifo->nEntry);
if( pPage->pNext==0 ){
return SQLITE_NOMEM;
}

View file

@ -170,7 +170,7 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){
** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
*/
if( fg & MEM_Int ){
sqlite3_snprintf(NBFS, z, "%lld", pMem->i);
sqlite3_snprintf(NBFS, z, "%lld", pMem->u.i);
}else{
assert( fg & MEM_Real );
sqlite3_snprintf(NBFS, z, "%!.15g", pMem->r);
@ -195,7 +195,7 @@ int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
int rc = SQLITE_OK;
if( pFunc && pFunc->xFinalize ){
sqlite3_context ctx;
assert( (pMem->flags & MEM_Null)!=0 || pFunc==*(FuncDef**)&pMem->i );
assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
ctx.s.flags = MEM_Null;
ctx.s.z = pMem->zShort;
ctx.pMem = pMem;
@ -225,7 +225,7 @@ void sqlite3VdbeMemRelease(Mem *p){
if( p->flags & (MEM_Dyn|MEM_Agg) ){
if( p->xDel ){
if( p->flags & MEM_Agg ){
sqlite3VdbeMemFinalize(p, *(FuncDef**)&p->i);
sqlite3VdbeMemFinalize(p, p->u.pDef);
assert( (p->flags & MEM_Agg)==0 );
sqlite3VdbeMemRelease(p);
}else{
@ -252,7 +252,7 @@ void sqlite3VdbeMemRelease(Mem *p){
i64 sqlite3VdbeIntValue(Mem *pMem){
int flags = pMem->flags;
if( flags & MEM_Int ){
return pMem->i;
return pMem->u.i;
}else if( flags & MEM_Real ){
return (i64)pMem->r;
}else if( flags & (MEM_Str|MEM_Blob) ){
@ -279,7 +279,7 @@ double sqlite3VdbeRealValue(Mem *pMem){
if( pMem->flags & MEM_Real ){
return pMem->r;
}else if( pMem->flags & MEM_Int ){
return (double)pMem->i;
return (double)pMem->u.i;
}else if( pMem->flags & (MEM_Str|MEM_Blob) ){
double val = 0.0;
if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8)
@ -300,8 +300,8 @@ double sqlite3VdbeRealValue(Mem *pMem){
*/
void sqlite3VdbeIntegerAffinity(Mem *pMem){
assert( pMem->flags & MEM_Real );
pMem->i = pMem->r;
if( ((double)pMem->i)==pMem->r ){
pMem->u.i = pMem->r;
if( ((double)pMem->u.i)==pMem->r ){
pMem->flags |= MEM_Int;
}
}
@ -310,7 +310,7 @@ void sqlite3VdbeIntegerAffinity(Mem *pMem){
** Convert pMem to type integer. Invalidate any prior representations.
*/
int sqlite3VdbeMemIntegerify(Mem *pMem){
pMem->i = sqlite3VdbeIntValue(pMem);
pMem->u.i = sqlite3VdbeIntValue(pMem);
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Int;
return SQLITE_OK;
@ -353,7 +353,7 @@ void sqlite3VdbeMemSetNull(Mem *pMem){
*/
void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
sqlite3VdbeMemRelease(pMem);
pMem->i = val;
pMem->u.i = val;
pMem->flags = MEM_Int;
pMem->type = SQLITE_INTEGER;
}
@ -538,12 +538,12 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
if( (f1 & f2 & MEM_Int)==0 ){
double r1, r2;
if( (f1&MEM_Real)==0 ){
r1 = pMem1->i;
r1 = pMem1->u.i;
}else{
r1 = pMem1->r;
}
if( (f2&MEM_Real)==0 ){
r2 = pMem2->i;
r2 = pMem2->u.i;
}else{
r2 = pMem2->r;
}
@ -553,8 +553,8 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
}else{
assert( f1&MEM_Int );
assert( f2&MEM_Int );
if( pMem1->i < pMem2->i ) return -1;
if( pMem1->i > pMem2->i ) return 1;
if( pMem1->u.i < pMem2->u.i ) return -1;
if( pMem1->u.i > pMem2->u.i ) return 1;
return 0;
}
}
@ -637,14 +637,15 @@ int sqlite3VdbeMemFromBtree(
int key, /* If true, retrieve from the btree key, not data. */
Mem *pMem /* OUT: Return data in this Mem structure. */
){
char *zData; /* Data from the btree layer */
int available; /* Number of bytes available on the local btree page */
char *zData; /* Data from the btree layer */
int available = 0; /* Number of bytes available on the local btree page */
if( key ){
zData = (char *)sqlite3BtreeKeyFetch(pCur, &available);
}else{
zData = (char *)sqlite3BtreeDataFetch(pCur, &available);
}
assert( zData!=0 );
pMem->n = amt;
if( offset+amt<=available ){
@ -735,7 +736,7 @@ void sqlite3VdbeMemSanity(Mem *pMem){
|| (pMem->flags&MEM_Null)==0 );
/* 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 );
|| pMem->r==pMem->u.i );
}
#endif
@ -831,7 +832,7 @@ int sqlite3ValueFromExpr(
}
}else if( op==TK_UMINUS ) {
if( SQLITE_OK==sqlite3ValueFromExpr(pExpr->pLeft, enc, affinity, &pVal) ){
pVal->i = -1 * pVal->i;
pVal->u.i = -1 * pVal->u.i;
pVal->r = -1.0 * pVal->r;
}
}

View file

@ -35,9 +35,9 @@
*/
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
int sqlite3_where_trace = 0;
# define TRACE(X) if(sqlite3_where_trace) sqlite3DebugPrintf X
# define WHERETRACE(X) if(sqlite3_where_trace) sqlite3DebugPrintf X
#else
# define TRACE(X)
# define WHERETRACE(X)
#endif
/* Forward reference
@ -220,6 +220,9 @@ static void whereClauseClear(WhereClause *pWC){
** Add a new entries to the WhereClause structure. Increase the allocated
** space as necessary.
**
** If the flags argument includes TERM_DYNAMIC, then responsibility
** for freeing the expression p is assumed by the WhereClause object.
**
** WARNING: This routine might reallocate the space used to store
** WhereTerms. All pointers to WhereTerms should be invalided after
** calling this routine. Such pointers may be reinitialized by referencing
@ -231,7 +234,12 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, int flags){
if( pWC->nTerm>=pWC->nSlot ){
WhereTerm *pOld = pWC->a;
pWC->a = sqliteMalloc( sizeof(pWC->a[0])*pWC->nSlot*2 );
if( pWC->a==0 ) return 0;
if( pWC->a==0 ){
if( flags & TERM_DYNAMIC ){
sqlite3ExprDelete(p);
}
return 0;
}
memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
if( pOld!=pWC->aStatic ){
sqliteFree(pOld);
@ -523,6 +531,10 @@ static int isLikeOrGlob(
}
pColl = pLeft->pColl;
if( pColl==0 ){
/* TODO: Coverage testing doesn't get this case. Is it actually possible
** for an expression of type TK_COLUMN to not have an assigned collation
** sequence at this point?
*/
pColl = db->pDfltColl;
}
if( (pColl->type!=SQLITE_COLL_BINARY || noCase) &&
@ -582,6 +594,92 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
pDerived->iRightJoinTable = pBase->iRightJoinTable;
}
#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
/*
** Return TRUE if the given term of an OR clause can be converted
** into an IN clause. The iCursor and iColumn define the left-hand
** side of the IN clause.
**
** The context is that we have multiple OR-connected equality terms
** like this:
**
** a=<expr1> OR a=<expr2> OR b=<expr3> OR ...
**
** The pOrTerm input to this routine corresponds to a single term of
** this OR clause. In order for the term to be a condidate for
** conversion to an IN operator, the following must be true:
**
** * The left-hand side of the term must be the column which
** is identified by iCursor and iColumn.
**
** * If the right-hand side is also a column, then the affinities
** of both right and left sides must be such that no type
** conversions are required on the right. (Ticket #2249)
**
** If both of these conditions are true, then return true. Otherwise
** return false.
*/
static int orTermIsOptCandidate(WhereTerm *pOrTerm, int iCursor, int iColumn){
int affLeft, affRight;
assert( pOrTerm->eOperator==WO_EQ );
if( pOrTerm->leftCursor!=iCursor ){
return 0;
}
if( pOrTerm->leftColumn!=iColumn ){
return 0;
}
affRight = sqlite3ExprAffinity(pOrTerm->pExpr->pRight);
if( affRight==0 ){
return 1;
}
affLeft = sqlite3ExprAffinity(pOrTerm->pExpr->pLeft);
if( affRight!=affLeft ){
return 0;
}
return 1;
}
/*
** Return true if the given term of an OR clause can be ignored during
** a check to make sure all OR terms are candidates for optimization.
** In other words, return true if a call to the orTermIsOptCandidate()
** above returned false but it is not necessary to disqualify the
** optimization.
**
** Suppose the original OR phrase was this:
**
** a=4 OR a=11 OR a=b
**
** During analysis, the third term gets flipped around and duplicate
** so that we are left with this:
**
** a=4 OR a=11 OR a=b OR b=a
**
** Since the last two terms are duplicates, only one of them
** has to qualify in order for the whole phrase to qualify. When
** this routine is called, we know that pOrTerm did not qualify.
** This routine merely checks to see if pOrTerm has a duplicate that
** might qualify. If there is a duplicate that has not yet been
** disqualified, then return true. If there are no duplicates, or
** the duplicate has also been disqualifed, return false.
*/
static int orTermHasOkDuplicate(WhereClause *pOr, WhereTerm *pOrTerm){
if( pOrTerm->flags & TERM_COPIED ){
/* This is the original term. The duplicate is to the left had
** has not yet been analyzed and thus has not yet been disqualified. */
return 1;
}
if( (pOrTerm->flags & TERM_VIRTUAL)!=0
&& (pOr->a[pOrTerm->iParent].flags & TERM_OR_OK)!=0 ){
/* This is a duplicate term. The original qualified so this one
** does not have to. */
return 1;
}
/* This is either a singleton term or else it is a duplicate for
** which the original did not qualify. Either way we are done for. */
return 0;
}
#endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */
/*
** The input to this routine is an WhereTerm structure with only the
@ -644,7 +742,7 @@ static void exprAnalyze(
int idxNew;
pDup = sqlite3ExprDup(pExpr);
if( sqlite3MallocFailed() ){
sqliteFree(pDup);
sqlite3ExprDelete(pDup);
return;
}
idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
@ -716,9 +814,10 @@ static void exprAnalyze(
whereClauseInit(&sOr, pWC->pParse, pMaskSet);
whereSplit(&sOr, pExpr, TK_OR);
exprAnalyzeAll(pSrc, &sOr);
assert( sOr.nTerm>0 );
assert( sOr.nTerm>=2 );
j = 0;
do{
assert( j<sOr.nTerm );
iColumn = sOr.a[j].leftColumn;
iCursor = sOr.a[j].leftCursor;
ok = iCursor>=0;
@ -726,17 +825,15 @@ static void exprAnalyze(
if( pOrTerm->eOperator!=WO_EQ ){
goto or_not_possible;
}
if( pOrTerm->leftCursor==iCursor && pOrTerm->leftColumn==iColumn ){
if( orTermIsOptCandidate(pOrTerm, iCursor, iColumn) ){
pOrTerm->flags |= TERM_OR_OK;
}else if( (pOrTerm->flags & TERM_COPIED)!=0 ||
((pOrTerm->flags & TERM_VIRTUAL)!=0 &&
(sOr.a[pOrTerm->iParent].flags & TERM_OR_OK)!=0) ){
}else if( orTermHasOkDuplicate(&sOr, pOrTerm) ){
pOrTerm->flags &= ~TERM_OR_OK;
}else{
ok = 0;
}
}
}while( !ok && (sOr.a[j++].flags & TERM_COPIED)!=0 && j<sOr.nTerm );
}while( !ok && (sOr.a[j++].flags & TERM_COPIED)!=0 && j<2 );
if( ok ){
ExprList *pList = 0;
Expr *pNew, *pDup;
@ -1041,8 +1138,7 @@ static double estLog(double N){
** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines
** are no-ops.
*/
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && \
(defined(SQLITE_TEST) || defined(SQLITE_DEBUG))
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_DEBUG)
static void TRACE_IDX_INPUTS(sqlite3_index_info *p){
int i;
if( !sqlite3_where_trace ) return;
@ -1124,7 +1220,7 @@ static double bestVirtualIndex(
if( pIdxInfo==0 ){
WhereTerm *pTerm;
int nTerm;
TRACE(("Recomputing index info for %s...\n", pTab->zName));
WHERETRACE(("Recomputing index info for %s...\n", pTab->zName));
/* Count the number of possible WHERE clause constraints referring
** to this virtual table */
@ -1207,13 +1303,19 @@ static double bestVirtualIndex(
** xBestIndex.
*/
/* The module name must be defined */
/* The module name must be defined. Also, by this point there must
** be a pointer to an sqlite3_vtab structure. Otherwise
** sqlite3ViewGetColumnNames() would have picked up the error.
*/
assert( pTab->azModuleArg && pTab->azModuleArg[0] );
assert( pTab->pVtab );
#if 0
if( pTab->pVtab==0 ){
sqlite3ErrorMsg(pParse, "undefined module %s for table %s",
pTab->azModuleArg[0], pTab->zName);
return 0.0;
}
#endif
/* Set the aConstraint[].usable fields and initialize all
** output variables to zero.
@ -1257,7 +1359,7 @@ static double bestVirtualIndex(
}
sqlite3SafetyOff(pParse->db);
TRACE(("xBestIndex for %s\n", pTab->zName));
WHERETRACE(("xBestIndex for %s\n", pTab->zName));
TRACE_IDX_INPUTS(pIdxInfo);
rc = pTab->pVtab->pModule->xBestIndex(pTab->pVtab, pIdxInfo);
TRACE_IDX_OUTPUTS(pIdxInfo);
@ -1272,6 +1374,7 @@ static double bestVirtualIndex(
rc = sqlite3SafetyOn(pParse->db);
}
*(int*)&pIdxInfo->nOrderBy = nOrderBy;
return pIdxInfo->estimatedCost;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@ -1317,7 +1420,7 @@ static double bestIndex(
int eqTermMask; /* Mask of valid equality operators */
double cost; /* Cost of using pProbe */
TRACE(("bestIndex: tbl=%s notReady=%x\n", pSrc->pTab->zName, notReady));
WHERETRACE(("bestIndex: tbl=%s notReady=%x\n", pSrc->pTab->zName, notReady));
lowestCost = SQLITE_BIG_DBL;
pProbe = pSrc->pTab->pIndex;
@ -1348,7 +1451,7 @@ static double bestIndex(
** a single row is generated, output is always in sorted order */
*pFlags = WHERE_ROWID_EQ | WHERE_UNIQUE;
*pnEq = 1;
TRACE(("... best is rowid\n"));
WHERETRACE(("... best is rowid\n"));
return 0.0;
}else if( (pExpr = pTerm->pExpr)->pList!=0 ){
/* Rowid IN (LIST): cost is NlogN where N is the number of list
@ -1361,14 +1464,14 @@ static double bestIndex(
** that value so make a wild guess. */
lowestCost = 200;
}
TRACE(("... rowid IN cost: %.9g\n", lowestCost));
WHERETRACE(("... rowid IN cost: %.9g\n", lowestCost));
}
/* Estimate the cost of a table scan. If we do not know how many
** entries are in the table, use 1 million as a guess.
*/
cost = pProbe ? pProbe->aiRowEst[0] : 1000000;
TRACE(("... table scan base cost: %.9g\n", cost));
WHERETRACE(("... table scan base cost: %.9g\n", cost));
flags = WHERE_ROWID_RANGE;
/* Check for constraints on a range of rowids in a table scan.
@ -1383,7 +1486,7 @@ static double bestIndex(
flags |= WHERE_BTM_LIMIT;
cost /= 3; /* Guess that rowid>EXPR eliminates two-thirds of rows */
}
TRACE(("... rowid range reduces cost to %.9g\n", cost));
WHERETRACE(("... rowid range reduces cost to %.9g\n", cost));
}else{
flags = 0;
}
@ -1398,7 +1501,7 @@ static double bestIndex(
}
}else{
cost += cost*estLog(cost);
TRACE(("... sorting increases cost to %.9g\n", cost));
WHERETRACE(("... sorting increases cost to %.9g\n", cost));
}
}
if( cost<lowestCost ){
@ -1423,7 +1526,7 @@ static double bestIndex(
int i; /* Loop counter */
double inMultiplier = 1;
TRACE(("... index %s:\n", pProbe->zName));
WHERETRACE(("... index %s:\n", pProbe->zName));
/* Count the number of columns in the index that are satisfied
** by x=EXPR constraints or x IN (...) constraints.
@ -1450,7 +1553,7 @@ static double bestIndex(
&& nEq==pProbe->nColumn ){
flags |= WHERE_UNIQUE;
}
TRACE(("...... nEq=%d inMult=%.9g cost=%.9g\n", nEq, inMultiplier, cost));
WHERETRACE(("...... nEq=%d inMult=%.9g cost=%.9g\n", nEq, inMultiplier, cost));
/* Look for range constraints
*/
@ -1467,7 +1570,7 @@ static double bestIndex(
flags |= WHERE_BTM_LIMIT;
cost /= 3;
}
TRACE(("...... range reduces cost to %.9g\n", cost));
WHERETRACE(("...... range reduces cost to %.9g\n", cost));
}
}
@ -1485,7 +1588,7 @@ static double bestIndex(
}
}else{
cost += cost*estLog(cost);
TRACE(("...... orderby increases cost to %.9g\n", cost));
WHERETRACE(("...... orderby increases cost to %.9g\n", cost));
}
}
@ -1505,7 +1608,7 @@ static double bestIndex(
if( m==0 ){
flags |= WHERE_IDX_ONLY;
cost /= 2;
TRACE(("...... idx-only reduces cost to %.9g\n", cost));
WHERETRACE(("...... idx-only reduces cost to %.9g\n", cost));
}
}
@ -1523,7 +1626,7 @@ static double bestIndex(
/* Report the best result
*/
*ppIndex = bestIdx;
TRACE(("best index is %s, cost=%.9g, flags=%x, nEq=%d\n",
WHERETRACE(("best index is %s, cost=%.9g, flags=%x, nEq=%d\n",
bestIdx ? bestIdx->zName : "(none)", lowestCost, bestFlags, bestNEq));
*pFlags = bestFlags | eqTermMask;
*pnEq = bestNEq;
@ -1601,7 +1704,6 @@ static void buildIndexProbe(
static void codeEqualityTerm(
Parse *pParse, /* The parsing context */
WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
int brk, /* Jump here to abandon the loop */
WhereLevel *pLevel /* When level of the FROM clause we are working on */
){
Expr *pX = pTerm->pExpr;
@ -1613,21 +1715,25 @@ static void codeEqualityTerm(
#ifndef SQLITE_OMIT_SUBQUERY
}else{
int iTab;
int *aIn;
struct InLoop *pIn;
assert( pX->op==TK_IN );
sqlite3CodeSubselect(pParse, pX);
iTab = pX->iTable;
sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0);
VdbeComment((v, "# %.*s", pX->span.n, pX->span.z));
if( pLevel->nIn==0 ){
pLevel->nxt = sqlite3VdbeMakeLabel(v);
}
pLevel->nIn++;
sqliteReallocOrFree((void**)&pLevel->aInLoop,
sizeof(pLevel->aInLoop[0])*2*pLevel->nIn);
aIn = pLevel->aInLoop;
if( aIn ){
aIn += pLevel->nIn*2 - 2;
aIn[0] = iTab;
aIn[1] = sqlite3VdbeAddOp(v, OP_Column, iTab, 0);
pLevel->aInLoop = sqliteReallocOrFree(pLevel->aInLoop,
sizeof(pLevel->aInLoop[0])*pLevel->nIn);
pIn = pLevel->aInLoop;
if( pIn ){
pIn += pLevel->nIn - 1;
pIn->iCur = iTab;
pIn->topAddr = sqlite3VdbeAddOp(v, OP_Column, iTab, 0);
sqlite3VdbeAddOp(v, OP_IsNull, -1, 0);
}else{
pLevel->nIn = 0;
}
@ -1663,8 +1769,7 @@ static void codeAllEqualityTerms(
Parse *pParse, /* Parsing context */
WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */
WhereClause *pWC, /* The WHERE clause */
Bitmask notReady, /* Which parts of FROM have not yet been coded */
int brk /* Jump here to end the loop */
Bitmask notReady /* Which parts of FROM have not yet been coded */
){
int nEq = pLevel->nEq; /* The number of == or IN constraints to code */
int termsInMem = 0; /* If true, store value in mem[] cells */
@ -1693,9 +1798,9 @@ static void codeAllEqualityTerms(
pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx);
if( pTerm==0 ) break;
assert( (pTerm->flags & TERM_CODED)==0 );
codeEqualityTerm(pParse, pTerm, brk, pLevel);
if( (pTerm->eOperator & WO_ISNULL)==0 ){
sqlite3VdbeAddOp(v, OP_IsNull, termsInMem ? -1 : -(j+1), brk);
codeEqualityTerm(pParse, pTerm, pLevel);
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
sqlite3VdbeAddOp(v, OP_IsNull, termsInMem ? -1 : -(j+1), pLevel->brk);
}
if( termsInMem ){
sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem+j+1, 1);
@ -1734,6 +1839,10 @@ static void whereInfoFree(WhereInfo *pWInfo){
sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
if( pInfo ){
if( pInfo->needToFreeIdxStr ){
/* Coverage: Don't think this can be reached. By the time this
** function is called, the index-strings have been passed
** to the vdbe layer for deletion.
*/
sqlite3_free(pInfo->idxStr);
}
sqliteFree(pInfo);
@ -1917,7 +2026,7 @@ WhereInfo *sqlite3WhereBegin(
pTabItem = pTabList->a;
pLevel = pWInfo->a;
andFlags = ~0;
TRACE(("*** Optimizer Start ***\n"));
WHERETRACE(("*** Optimizer Start ***\n"));
for(i=iFrom=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
Index *pIdx; /* Index for FROM table at pTabItem */
int flags; /* Flags asssociated with pIdx */
@ -1958,6 +2067,14 @@ WhereInfo *sqlite3WhereBegin(
}
pIdx = 0;
nEq = 0;
if( (SQLITE_BIG_DBL/2.0)<cost ){
/* The cost is not allowed to be larger than SQLITE_BIG_DBL (the
** inital value of lowestCost in this loop. If it is, then
** the (cost<lowestCost) test below will never be true and
** pLevel->pBestIdx never set.
*/
cost = (SQLITE_BIG_DBL/2.0);
}
}else
#endif
{
@ -1977,7 +2094,7 @@ WhereInfo *sqlite3WhereBegin(
}
if( doNotReorder ) break;
}
TRACE(("*** Optimizer choose table %d for loop %d\n", bestJ,
WHERETRACE(("*** Optimizer choose table %d for loop %d\n", bestJ,
pLevel-pWInfo->a));
if( (bestFlags & WHERE_ORDERBY)!=0 ){
*ppOrderBy = 0;
@ -1996,7 +2113,7 @@ WhereInfo *sqlite3WhereBegin(
notReady &= ~getMask(&maskSet, pTabList->a[bestJ].iCursor);
pLevel->iFrom = bestJ;
}
TRACE(("*** Optimizer Finished ***\n"));
WHERETRACE(("*** Optimizer Finished ***\n"));
/* If the total query only selects a single row, then the ORDER BY
** clause is irrelevant.
@ -2090,6 +2207,7 @@ WhereInfo *sqlite3WhereBegin(
int j;
int iCur = pTabItem->iCursor; /* The VDBE cursor for the table */
Index *pIdx; /* The index we will be using */
int nxt; /* Where to jump to continue with the next IN case */
int iIdxCur; /* The VDBE cursor for the index */
int omitTable; /* True if we use the index only */
int bRev; /* True if we need to scan in reverse order */
@ -2105,8 +2223,13 @@ WhereInfo *sqlite3WhereBegin(
** for the current loop. Jump to brk to break out of a loop.
** Jump to cont to go immediately to the next iteration of the
** loop.
**
** When there is an IN operator, we also have a "nxt" label that
** means to continue with the next IN value combination. When
** there are no IN operators in the constraints, the "nxt" label
** is the same as "brk".
*/
brk = pLevel->brk = sqlite3VdbeMakeLabel(v);
brk = pLevel->brk = pLevel->nxt = sqlite3VdbeMakeLabel(v);
cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
/* If this is the right table of a LEFT OUTER JOIN, allocate and
@ -2172,9 +2295,10 @@ WhereInfo *sqlite3WhereBegin(
assert( pTerm->pExpr!=0 );
assert( pTerm->leftCursor==iCur );
assert( omitTable==0 );
codeEqualityTerm(pParse, pTerm, brk, pLevel);
sqlite3VdbeAddOp(v, OP_MustBeInt, 1, brk);
sqlite3VdbeAddOp(v, OP_NotExists, iCur, brk);
codeEqualityTerm(pParse, pTerm, pLevel);
nxt = pLevel->nxt;
sqlite3VdbeAddOp(v, OP_MustBeInt, 1, nxt);
sqlite3VdbeAddOp(v, OP_NotExists, iCur, nxt);
VdbeComment((v, "pk"));
pLevel->op = OP_Noop;
}else if( pLevel->flags & WHERE_ROWID_RANGE ){
@ -2253,7 +2377,7 @@ WhereInfo *sqlite3WhereBegin(
/* Generate code to evaluate all constraint terms using == or IN
** and level the values of those terms on the stack.
*/
codeAllEqualityTerms(pParse, pLevel, &wc, notReady, brk);
codeAllEqualityTerms(pParse, pLevel, &wc, notReady);
/* Duplicate the equality term values because they will all be
** used twice: once to make the termination key and once to make the
@ -2284,6 +2408,7 @@ WhereInfo *sqlite3WhereBegin(
** 2002-Dec-04: On a reverse-order scan, the so-called "termination"
** key computed here really ends up being the start key.
*/
nxt = pLevel->nxt;
if( topLimit ){
Expr *pX;
int k = pIdx->aiColumn[j];
@ -2292,7 +2417,7 @@ WhereInfo *sqlite3WhereBegin(
pX = pTerm->pExpr;
assert( (pTerm->flags & TERM_CODED)==0 );
sqlite3ExprCode(pParse, pX->pRight);
sqlite3VdbeAddOp(v, OP_IsNull, -(nEq+1), brk);
sqlite3VdbeAddOp(v, OP_IsNull, -(nEq+1), nxt);
topEq = pTerm->eOperator & (WO_LE|WO_GE);
disableTerm(pLevel, pTerm);
testOp = OP_IdxGE;
@ -2306,7 +2431,7 @@ WhereInfo *sqlite3WhereBegin(
buildIndexProbe(v, nCol, pIdx);
if( bRev ){
int op = topEq ? OP_MoveLe : OP_MoveLt;
sqlite3VdbeAddOp(v, op, iIdxCur, brk);
sqlite3VdbeAddOp(v, op, iIdxCur, nxt);
}else{
sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
}
@ -2331,7 +2456,7 @@ WhereInfo *sqlite3WhereBegin(
pX = pTerm->pExpr;
assert( (pTerm->flags & TERM_CODED)==0 );
sqlite3ExprCode(pParse, pX->pRight);
sqlite3VdbeAddOp(v, OP_IsNull, -(nEq+1), brk);
sqlite3VdbeAddOp(v, OP_IsNull, -(nEq+1), nxt);
btmEq = pTerm->eOperator & (WO_LE|WO_GE);
disableTerm(pLevel, pTerm);
}else{
@ -2346,7 +2471,7 @@ WhereInfo *sqlite3WhereBegin(
testOp = OP_IdxLT;
}else{
int op = btmEq ? OP_MoveGe : OP_MoveGt;
sqlite3VdbeAddOp(v, op, iIdxCur, brk);
sqlite3VdbeAddOp(v, op, iIdxCur, nxt);
}
}else if( bRev ){
testOp = OP_Noop;
@ -2361,7 +2486,7 @@ WhereInfo *sqlite3WhereBegin(
start = sqlite3VdbeCurrentAddr(v);
if( testOp!=OP_Noop ){
sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
sqlite3VdbeAddOp(v, testOp, iIdxCur, brk);
sqlite3VdbeAddOp(v, testOp, iIdxCur, nxt);
if( (topEq && !bRev) || (!btmEq && bRev) ){
sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC);
}
@ -2390,7 +2515,8 @@ WhereInfo *sqlite3WhereBegin(
/* Generate code to evaluate all constraint terms using == or IN
** and leave the values of those terms on the stack.
*/
codeAllEqualityTerms(pParse, pLevel, &wc, notReady, brk);
codeAllEqualityTerms(pParse, pLevel, &wc, notReady);
nxt = pLevel->nxt;
/* Generate a single key that will be used to both start and terminate
** the search
@ -2399,21 +2525,21 @@ WhereInfo *sqlite3WhereBegin(
sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);
/* Generate code (1) to move to the first matching element of the table.
** Then generate code (2) that jumps to "brk" after the cursor is past
** Then generate code (2) that jumps to "nxt" after the cursor is past
** the last matching element of the table. The code (1) is executed
** once to initialize the search, the code (2) is executed before each
** iteration of the scan to see if the scan has finished. */
if( bRev ){
/* Scan in reverse order */
sqlite3VdbeAddOp(v, OP_MoveLe, iIdxCur, brk);
sqlite3VdbeAddOp(v, OP_MoveLe, iIdxCur, nxt);
start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
sqlite3VdbeAddOp(v, OP_IdxLT, iIdxCur, brk);
sqlite3VdbeAddOp(v, OP_IdxLT, iIdxCur, nxt);
pLevel->op = OP_Prev;
}else{
/* Scan in the forward order */
sqlite3VdbeAddOp(v, OP_MoveGe, iIdxCur, brk);
sqlite3VdbeAddOp(v, OP_MoveGe, iIdxCur, nxt);
start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
sqlite3VdbeOp3(v, OP_IdxGE, iIdxCur, brk, "+", P3_STATIC);
sqlite3VdbeOp3(v, OP_IdxGE, iIdxCur, nxt, "+", P3_STATIC);
pLevel->op = OP_Next;
}
if( !omitTable ){
@ -2546,16 +2672,18 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
if( pLevel->op!=OP_Noop ){
sqlite3VdbeAddOp(v, pLevel->op, pLevel->p1, pLevel->p2);
}
sqlite3VdbeResolveLabel(v, pLevel->brk);
if( pLevel->nIn ){
int *a;
struct InLoop *pIn;
int j;
for(j=pLevel->nIn, a=&pLevel->aInLoop[j*2-2]; j>0; j--, a-=2){
sqlite3VdbeAddOp(v, OP_Next, a[0], a[1]);
sqlite3VdbeJumpHere(v, a[1]-1);
sqlite3VdbeResolveLabel(v, pLevel->nxt);
for(j=pLevel->nIn, pIn=&pLevel->aInLoop[j-1]; j>0; j--, pIn--){
sqlite3VdbeJumpHere(v, pIn->topAddr+1);
sqlite3VdbeAddOp(v, OP_Next, pIn->iCur, pIn->topAddr);
sqlite3VdbeJumpHere(v, pIn->topAddr-1);
}
sqliteFree(pLevel->aInLoop);
}
sqlite3VdbeResolveLabel(v, pLevel->brk);
if( pLevel->iLeftJoin ){
int addr;
addr = sqlite3VdbeAddOp(v, OP_IfMemPos, pLevel->iLeftJoin, 0);