Merge branch 'sqlite-release' into release-integration

This commit is contained in:
Stephen Lombardo 2010-05-18 12:24:16 -04:00
commit 11a0e2bb8f
136 changed files with 13237 additions and 6074 deletions

View File

@ -174,7 +174,7 @@ NAWK = @AWK@
# Object files for the SQLite library (non-amalgamation).
#
OBJS0 = alter.lo analyze.lo attach.lo auth.lo backup.lo bitvec.lo btmutex.lo \
btree.lo build.lo callback.lo complete.lo date.lo \
btree.lo build.lo callback.lo complete.lo ctime.lo date.lo \
delete.lo expr.lo fault.lo fkey.lo func.lo global.lo \
hash.lo journal.lo insert.lo legacy.lo loadext.lo \
main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
@ -215,6 +215,7 @@ SRC = \
$(TOP)/src/build.c \
$(TOP)/src/callback.c \
$(TOP)/src/complete.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
@ -350,6 +351,7 @@ TESTSRC2 = \
$(TOP)/src/btree.c \
$(TOP)/src/build.c \
$(TOP)/src/date.c \
$(TOP)/src/ctime.c \
$(TOP)/src/expr.c \
$(TOP)/src/func.c \
$(TOP)/src/insert.c \
@ -558,6 +560,9 @@ callback.lo: $(TOP)/src/callback.c $(HDR)
complete.lo: $(TOP)/src/complete.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/complete.c
ctime.lo: $(TOP)/src/ctime.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/ctime.c
date.lo: $(TOP)/src/date.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/date.c

View File

@ -231,6 +231,7 @@ SRC = \
$(TOP)/src/build.c \
$(TOP)/src/callback.c \
$(TOP)/src/complete.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
@ -392,7 +393,7 @@ TESTSRC = \
TESTSRC2 = \
$(TOP)/src/attach.c $(TOP)/src/backup.c $(TOP)/src/btree.c \
$(TOP)/src/build.c $(TOP)/src/date.c \
$(TOP)/src/build.c $(TOP)/src/ctime.c $(TOP)/src/date.c \
$(TOP)/src/expr.c $(TOP)/src/func.c $(TOP)/src/insert.c $(TOP)/src/os.c \
$(TOP)/src/os_os2.c $(TOP)/src/os_unix.c $(TOP)/src/os_win.c \
$(TOP)/src/pager.c $(TOP)/src/pragma.c $(TOP)/src/prepare.c \

View File

@ -1 +1 @@
3.6.21
3.6.23.1

18
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.62 for sqlite 3.6.21.
# Generated by GNU Autoconf 2.62 for sqlite 3.6.23.1.
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.6.21'
PACKAGE_STRING='sqlite 3.6.21'
PACKAGE_VERSION='3.6.23.1'
PACKAGE_STRING='sqlite 3.6.23.1'
PACKAGE_BUGREPORT=''
# Factoring default headers for most tests.
@ -1487,7 +1487,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.6.21 to adapt to many kinds of systems.
\`configure' configures sqlite 3.6.23.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1552,7 +1552,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.6.21:";;
short | recursive ) echo "Configuration of sqlite 3.6.23.1:";;
esac
cat <<\_ACEOF
@ -1670,7 +1670,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.6.21
sqlite configure 3.6.23.1
generated by GNU Autoconf 2.62
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@ -1684,7 +1684,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.6.21, which was
It was created by sqlite $as_me 3.6.23.1, which was
generated by GNU Autoconf 2.62. Invocation command line was
$ $0 $@
@ -13972,7 +13972,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.6.21, which was
This file was extended by sqlite $as_me 3.6.23.1, which was
generated by GNU Autoconf 2.62. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -14025,7 +14025,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_version="\\
sqlite config.status 3.6.21
sqlite config.status 3.6.23.1
configured by $0, generated by GNU Autoconf 2.62,
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"

File diff suppressed because it is too large Load Diff

View File

@ -70,6 +70,8 @@
*/
typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */
typedef short int i16; /* 2-byte (or larger) signed integer */
typedef unsigned int u32; /* 4-byte unsigned integer */
typedef sqlite3_uint64 u64; /* 8-byte unsigned integer */
/*
** Macro used to suppress compiler warnings for unused parameters.
*/
@ -102,7 +104,7 @@ struct Fts3Table {
/* Precompiled statements used by the implementation. Each of these
** statements is run and reset within a single virtual table API call.
*/
sqlite3_stmt *aStmt[18];
sqlite3_stmt *aStmt[25];
/* Pointer to string containing the SQL:
**
@ -116,14 +118,17 @@ struct Fts3Table {
sqlite3_stmt **aLeavesStmt; /* Array of prepared zSelectLeaves stmts */
int nNodeSize; /* Soft limit for node size */
u8 bHasContent; /* True if %_content table exists */
u8 bHasDocsize; /* True if %_docsize table exists */
/* The following hash table is used to buffer pending index updates during
** transactions. Variable nPendingData estimates the memory size of the
** pending data, including hash table overhead, but not malloc overhead.
** When nPendingData exceeds FTS3_MAX_PENDING_DATA, the buffer is flushed
** When nPendingData exceeds nMaxPendingData, the buffer is flushed
** automatically. Variable iPrevDocid is the docid of the most recently
** inserted record.
*/
int nMaxPendingData;
int nPendingData;
sqlite_int64 iPrevDocid;
Fts3Hash pendingTerms;
@ -145,6 +150,8 @@ struct Fts3Cursor {
char *pNextId; /* Pointer into the body of aDoclist */
char *aDoclist; /* List of docids for full-text queries */
int nDoclist; /* Size of buffer at aDoclist */
int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
u32 *aMatchinfo; /* Information about most recent match */
};
/*
@ -185,6 +192,16 @@ struct Fts3Phrase {
/*
** A tree of these objects forms the RHS of a MATCH operator.
**
** If Fts3Expr.eType is either FTSQUERY_NEAR or FTSQUERY_PHRASE and isLoaded
** is true, then aDoclist points to a malloced buffer, size nDoclist bytes,
** containing the results of the NEAR or phrase query in FTS3 doclist
** format. As usual, the initial "Length" field found in doclists stored
** on disk is omitted from this buffer.
**
** Variable pCurrent always points to the start of a docid field within
** aDoclist. Since the doclist is usually scanned in docid order, this can
** be used to accelerate seeking to the required docid within the doclist.
*/
struct Fts3Expr {
int eType; /* One of the FTSQUERY_XXX values defined below */
@ -193,6 +210,13 @@ struct Fts3Expr {
Fts3Expr *pLeft; /* Left operand */
Fts3Expr *pRight; /* Right operand */
Fts3Phrase *pPhrase; /* Valid if eType==FTSQUERY_PHRASE */
int isLoaded; /* True if aDoclist/nDoclist are initialized. */
char *aDoclist; /* Buffer containing doclist */
int nDoclist; /* Size of aDoclist in bytes */
sqlite3_int64 iCurrent;
char *pCurrent;
};
/*
@ -225,6 +249,7 @@ void sqlite3Fts3PendingTermsClear(Fts3Table *);
int sqlite3Fts3Optimize(Fts3Table *);
int sqlite3Fts3SegReaderNew(Fts3Table *,int, sqlite3_int64,
sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**);
int sqlite3Fts3SegReaderPending(Fts3Table*,const char*,int,int,Fts3SegReader**);
void sqlite3Fts3SegReaderFree(Fts3Table *, Fts3SegReader *);
int sqlite3Fts3SegReaderIterate(
Fts3Table *, Fts3SegReader **, int, Fts3SegFilter *,
@ -232,6 +257,8 @@ int sqlite3Fts3SegReaderIterate(
);
int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char const**, int*);
int sqlite3Fts3AllSegdirs(Fts3Table*, sqlite3_stmt **);
int sqlite3Fts3MatchinfoDocsizeLocal(Fts3Cursor*, u32*);
int sqlite3Fts3MatchinfoDocsizeGlobal(Fts3Cursor*, u32*);
/* Flags allowed as part of the 4th argument to SegmentReaderIterate() */
#define FTS3_SEGMENT_REQUIRE_POS 0x00000001
@ -254,6 +281,10 @@ int sqlite3Fts3GetVarint32(const char *, int *);
int sqlite3Fts3VarintLen(sqlite3_uint64);
void sqlite3Fts3Dequote(char *);
char *sqlite3Fts3FindPositions(Fts3Expr *, sqlite3_int64, int);
int sqlite3Fts3ExprLoadDoclist(Fts3Table *, Fts3Expr *);
int sqlite3Fts3ExprNearTrim(Fts3Expr *, Fts3Expr *, int);
/* fts3_tokenizer.c */
const char *sqlite3Fts3NextToken(const char *, int *);
int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
@ -263,9 +294,10 @@ int sqlite3Fts3InitTokenizer(Fts3Hash *pHash,
/* fts3_snippet.c */
void sqlite3Fts3Offsets(sqlite3_context*, Fts3Cursor*);
void sqlite3Fts3Snippet(sqlite3_context*, Fts3Cursor*,
const char *, const char *, const char *
void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *,
const char *, const char *, int, int
);
void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *);
/* fts3_expr.c */
int sqlite3Fts3ExprParse(sqlite3_tokenizer *,
@ -273,7 +305,7 @@ int sqlite3Fts3ExprParse(sqlite3_tokenizer *,
);
void sqlite3Fts3ExprFree(Fts3Expr *);
#ifdef SQLITE_TEST
void sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
#endif
#endif /* _FTSINT_H */

View File

@ -181,7 +181,7 @@ static int getNextToken(
** Enlarge a memory allocation. If an out-of-memory allocation occurs,
** then free the old allocation.
*/
void *fts3ReallocOrFree(void *pOrig, int nNew){
static void *fts3ReallocOrFree(void *pOrig, int nNew){
void *pRet = sqlite3_realloc(pOrig, nNew);
if( !pRet ){
sqlite3_free(pOrig);
@ -735,6 +735,7 @@ void sqlite3Fts3ExprFree(Fts3Expr *p){
if( p ){
sqlite3Fts3ExprFree(p->pLeft);
sqlite3Fts3ExprFree(p->pRight);
sqlite3_free(p->aDoclist);
sqlite3_free(p);
}
}
@ -913,8 +914,8 @@ exprtest_out:
** Register the query expression parser test function fts3_exprtest()
** with database connection db.
*/
void sqlite3Fts3ExprInitTestInterface(sqlite3* db){
sqlite3_create_function(
int sqlite3Fts3ExprInitTestInterface(sqlite3* db){
return sqlite3_create_function(
db, "fts3_exprtest", -1, SQLITE_UTF8, 0, fts3ExprTest, 0, 0
);
}

View File

@ -279,13 +279,12 @@ static void fts3RemoveElementByHash(
}
}
/* Attempt to locate an element of the hash table pH with a key
** that matches pKey,nKey. Return the data for this element if it is
** found, or NULL if there is no match.
*/
void *sqlite3Fts3HashFind(const Fts3Hash *pH, const void *pKey, int nKey){
int h; /* A hash on key */
Fts3HashElem *elem; /* The element that matches key */
Fts3HashElem *sqlite3Fts3HashFindElem(
const Fts3Hash *pH,
const void *pKey,
int nKey
){
int h; /* A hash on key */
int (*xHash)(const void*,int); /* The hash function */
if( pH==0 || pH->ht==0 ) return 0;
@ -293,8 +292,19 @@ void *sqlite3Fts3HashFind(const Fts3Hash *pH, const void *pKey, int nKey){
assert( xHash!=0 );
h = (*xHash)(pKey,nKey);
assert( (pH->htsize & (pH->htsize-1))==0 );
elem = fts3FindElementByHash(pH,pKey,nKey, h & (pH->htsize-1));
return elem ? elem->data : 0;
return fts3FindElementByHash(pH,pKey,nKey, h & (pH->htsize-1));
}
/*
** Attempt to locate an element of the hash table pH with a key
** that matches pKey,nKey. Return the data for this element if it is
** found, or NULL if there is no match.
*/
void *sqlite3Fts3HashFind(const Fts3Hash *pH, const void *pKey, int nKey){
Fts3HashElem *pElem; /* The element that matches key (if any) */
pElem = sqlite3Fts3HashFindElem(pH, pKey, nKey);
return pElem ? pElem->data : 0;
}
/* Insert an element into the hash table pH. The key is pKey,nKey

View File

@ -75,14 +75,16 @@ void sqlite3Fts3HashInit(Fts3Hash *pNew, char keyClass, char copyKey);
void *sqlite3Fts3HashInsert(Fts3Hash*, const void *pKey, int nKey, void *pData);
void *sqlite3Fts3HashFind(const Fts3Hash*, const void *pKey, int nKey);
void sqlite3Fts3HashClear(Fts3Hash*);
Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const void *, int);
/*
** Shorthand for the functions above
*/
#define fts3HashInit sqlite3Fts3HashInit
#define fts3HashInsert sqlite3Fts3HashInsert
#define fts3HashFind sqlite3Fts3HashFind
#define fts3HashClear sqlite3Fts3HashClear
#define fts3HashInit sqlite3Fts3HashInit
#define fts3HashInsert sqlite3Fts3HashInsert
#define fts3HashFind sqlite3Fts3HashFind
#define fts3HashClear sqlite3Fts3HashClear
#define fts3HashFindElem sqlite3Fts3HashFindElem
/*
** Macros for looping over all elements of a hash table. The idiom is

View File

@ -605,9 +605,11 @@ static int porterNext(
if( c->iOffset>iStartOffset ){
int n = c->iOffset-iStartOffset;
if( n>c->nAllocated ){
char *pNew;
c->nAllocated = n+20;
c->zToken = sqlite3_realloc(c->zToken, c->nAllocated);
if( c->zToken==NULL ) return SQLITE_NOMEM;
pNew = sqlite3_realloc(c->zToken, c->nAllocated);
if( !pNew ) return SQLITE_NOMEM;
c->zToken = pNew;
}
porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes);
*pzToken = c->zToken;

File diff suppressed because it is too large Load Diff

View File

@ -119,14 +119,14 @@ const char *sqlite3Fts3NextToken(const char *zStr, int *pn){
/* Find the start of the next token. */
z1 = zStr;
while( z2==0 ){
switch( *z1 ){
char c = *z1;
switch( c ){
case '\0': return 0; /* No more tokens here */
case '\'':
case '"':
case '`': {
z2 = &z1[1];
while( *z2 && (z2[0]!=*z1 || z2[1]==*z1) ) z2++;
if( *z2 ) z2++;
z2 = z1;
while( *++z2 && (*z2!=c || *++z2==c) );
break;
}
case '[':
@ -466,10 +466,10 @@ int sqlite3Fts3InitHashTable(
int rc = SQLITE_OK;
void *p = (void *)pHash;
const int any = SQLITE_ANY;
char *zTest = 0;
char *zTest2 = 0;
#ifdef SQLITE_TEST
char *zTest = 0;
char *zTest2 = 0;
void *pdb = (void *)db;
zTest = sqlite3_mprintf("%s_test", zName);
zTest2 = sqlite3_mprintf("%s_internal_test", zName);
@ -486,10 +486,13 @@ int sqlite3Fts3InitHashTable(
|| SQLITE_OK!=(rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0))
|| SQLITE_OK!=(rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0))
#endif
);
);
#ifdef SQLITE_TEST
sqlite3_free(zTest);
sqlite3_free(zTest2);
#endif
return rc;
}

View File

@ -145,4 +145,8 @@ struct sqlite3_tokenizer_cursor {
/* Tokenizer implementations will typically add additional fields */
};
int fts3_global_term_cnt(int iTerm, int iCol);
int fts3_term_cnt(int iTerm, int iCol);
#endif /* _FTS3_TOKENIZER_H_ */

View File

@ -182,9 +182,11 @@ static int simpleNext(
if( c->iOffset>iStartOffset ){
int i, n = c->iOffset-iStartOffset;
if( n>c->nTokenAllocated ){
char *pNew;
c->nTokenAllocated = n+20;
c->pToken = sqlite3_realloc(c->pToken, c->nTokenAllocated);
if( c->pToken==NULL ) return SQLITE_NOMEM;
pNew = sqlite3_realloc(c->pToken, c->nTokenAllocated);
if( !pNew ) return SQLITE_NOMEM;
c->pToken = pNew;
}
for(i=0; i<n; i++){
/* TODO(shess) This needs expansion to handle UTF-8

File diff suppressed because it is too large Load Diff

View File

@ -454,7 +454,7 @@ int sqlite3IcuInit(sqlite3 *db){
void *pContext; /* sqlite3_user_data() context */
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} scalars[] = {
{"regexp",-1, SQLITE_ANY, 0, icuRegexpFunc},
{"regexp", 2, SQLITE_ANY, 0, icuRegexpFunc},
{"lower", 1, SQLITE_UTF16, 0, icuCaseFunc16},
{"lower", 2, SQLITE_UTF16, 0, icuCaseFunc16},

View File

@ -423,6 +423,7 @@ nodeAcquire(
rc = sqlite3_step(pRtree->pReadNode);
if( rc==SQLITE_ROW ){
const u8 *zBlob = sqlite3_column_blob(pRtree->pReadNode, 0);
assert( sqlite3_column_bytes(pRtree->pReadNode, 0)==pRtree->iNodeSize );
memcpy(pNode->zData, zBlob, pRtree->iNodeSize);
nodeReference(pParent);
}else{
@ -2619,31 +2620,69 @@ static int rtreeSqlInit(
}
/*
** This routine queries database handle db for the page-size used by
** database zDb. If successful, the page-size in bytes is written to
** *piPageSize and SQLITE_OK returned. Otherwise, and an SQLite error
** code is returned.
** The second argument to this function contains the text of an SQL statement
** that returns a single integer value. The statement is compiled and executed
** using database connection db. If successful, the integer value returned
** is written to *piVal and SQLITE_OK returned. Otherwise, an SQLite error
** code is returned and the value of *piVal after returning is not defined.
*/
static int getPageSize(sqlite3 *db, const char *zDb, int *piPageSize){
static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){
int rc = SQLITE_NOMEM;
if( zSql ){
sqlite3_stmt *pStmt = 0;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
if( rc==SQLITE_OK ){
if( SQLITE_ROW==sqlite3_step(pStmt) ){
*piVal = sqlite3_column_int(pStmt, 0);
}
rc = sqlite3_finalize(pStmt);
}
}
return rc;
}
/*
** This function is called from within the xConnect() or xCreate() method to
** determine the node-size used by the rtree table being created or connected
** to. If successful, pRtree->iNodeSize is populated and SQLITE_OK returned.
** Otherwise, an SQLite error code is returned.
**
** If this function is being called as part of an xConnect(), then the rtree
** table already exists. In this case the node-size is determined by inspecting
** the root node of the tree.
**
** Otherwise, for an xCreate(), use 64 bytes less than the database page-size.
** This ensures that each node is stored on a single database page. If the
** database page-size is so large that more than RTREE_MAXCELLS entries
** would fit in a single node, use a smaller node-size.
*/
static int getNodeSize(
sqlite3 *db, /* Database handle */
Rtree *pRtree, /* Rtree handle */
int isCreate /* True for xCreate, false for xConnect */
){
int rc;
char *zSql;
sqlite3_stmt *pStmt = 0;
zSql = sqlite3_mprintf("PRAGMA %Q.page_size", zDb);
if( !zSql ){
return SQLITE_NOMEM;
if( isCreate ){
int iPageSize;
zSql = sqlite3_mprintf("PRAGMA %Q.page_size", pRtree->zDb);
rc = getIntFromStmt(db, zSql, &iPageSize);
if( rc==SQLITE_OK ){
pRtree->iNodeSize = iPageSize-64;
if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
}
}
}else{
zSql = sqlite3_mprintf(
"SELECT length(data) FROM '%q'.'%q_node' WHERE nodeno = 1",
pRtree->zDb, pRtree->zName
);
rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
}
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc!=SQLITE_OK ){
return rc;
}
if( SQLITE_ROW==sqlite3_step(pStmt) ){
*piPageSize = sqlite3_column_int(pStmt, 0);
}
return sqlite3_finalize(pStmt);
return rc;
}
/*
@ -2664,7 +2703,6 @@ static int rtreeInit(
int isCreate /* True for xCreate, false for xConnect */
){
int rc = SQLITE_OK;
int iPageSize = 0;
Rtree *pRtree;
int nDb; /* Length of string argv[1] */
int nName; /* Length of string argv[2] */
@ -2683,11 +2721,6 @@ static int rtreeInit(
return SQLITE_ERROR;
}
rc = getPageSize(db, argv[1], &iPageSize);
if( rc!=SQLITE_OK ){
return rc;
}
/* Allocate the sqlite3_vtab structure */
nDb = strlen(argv[1]);
nName = strlen(argv[2]);
@ -2706,44 +2739,37 @@ static int rtreeInit(
memcpy(pRtree->zDb, argv[1], nDb);
memcpy(pRtree->zName, argv[2], nName);
/* Figure out the node size to use. By default, use 64 bytes less than
** the database page-size. This ensures that each node is stored on
** a single database page.
**
** If the databasd page-size is so large that more than RTREE_MAXCELLS
** entries would fit in a single node, use a smaller node-size.
*/
pRtree->iNodeSize = iPageSize-64;
if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
}
/* Figure out the node size to use. */
rc = getNodeSize(db, pRtree, isCreate);
/* Create/Connect to the underlying relational database schema. If
** that is successful, call sqlite3_declare_vtab() to configure
** the r-tree table schema.
*/
if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}else{
char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]);
char *zTmp;
int ii;
for(ii=4; zSql && ii<argc; ii++){
zTmp = zSql;
zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]);
sqlite3_free(zTmp);
}
if( zSql ){
zTmp = zSql;
zSql = sqlite3_mprintf("%s);", zTmp);
sqlite3_free(zTmp);
}
if( !zSql ){
rc = SQLITE_NOMEM;
}else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
if( rc==SQLITE_OK ){
if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}else{
char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]);
char *zTmp;
int ii;
for(ii=4; zSql && ii<argc; ii++){
zTmp = zSql;
zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]);
sqlite3_free(zTmp);
}
if( zSql ){
zTmp = zSql;
zSql = sqlite3_mprintf("%s);", zTmp);
sqlite3_free(zTmp);
}
if( !zSql ){
rc = SQLITE_NOMEM;
}else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}
sqlite3_free(zSql);
}
sqlite3_free(zSql);
}
if( rc==SQLITE_OK ){

58
ext/rtree/rtree7.test Normal file
View File

@ -0,0 +1,58 @@
# 2010 February 16
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Test that nothing goes wrong if an rtree table is created, then the
# database page-size is modified. At one point (3.6.22), this was causing
# malfunctions.
#
if {![info exists testdir]} {
set testdir [file join [file dirname $argv0] .. .. test]
}
source $testdir/tester.tcl
ifcapable !rtree||!vacuum {
finish_test
return
}
do_test rtree7-1.1 {
execsql {
PRAGMA page_size = 1024;
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, y1, y2);
INSERT INTO rt VALUES(1, 1, 2, 3, 4);
}
} {}
do_test rtree7-1.2 {
execsql { SELECT * FROM rt }
} {1 1.0 2.0 3.0 4.0}
do_test rtree7-1.3 {
execsql {
PRAGMA page_size = 2048;
VACUUM;
SELECT * FROM rt;
}
} {1 1.0 2.0 3.0 4.0}
do_test rtree7-1.4 {
for {set i 2} {$i <= 51} {incr i} {
execsql { INSERT INTO rt VALUES($i, 1, 2, 3, 4) }
}
execsql { SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt }
} {51.0 102.0 153.0 204.0}
do_test rtree7-1.5 {
execsql {
PRAGMA page_size = 512;
VACUUM;
SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt
}
} {51.0 102.0 153.0 204.0}
finish_test

View File

@ -52,7 +52,7 @@ TCCX += -I$(TOP)/ext/async
#
LIBOBJ+= alter.o analyze.o attach.o auth.o \
backup.o bitvec.o btmutex.o btree.o build.o \
callback.o complete.o date.o delete.o expr.o fault.o fkey.o \
callback.o complete.o ctime.o date.o delete.o expr.o fault.o fkey.o \
fts3.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o fts3_write.o \
func.o global.o hash.o \
@ -86,6 +86,7 @@ SRC = \
$(TOP)/src/build.c \
$(TOP)/src/callback.c \
$(TOP)/src/complete.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
@ -262,7 +263,7 @@ TESTSRC2 = \
$(TOP)/src/utf.c $(TOP)/src/util.c $(TOP)/src/vdbeapi.c $(TOP)/src/vdbeaux.c \
$(TOP)/src/vdbe.c $(TOP)/src/vdbemem.c $(TOP)/src/where.c parse.c \
$(TOP)/ext/fts3/fts3.c $(TOP)/ext/fts3/fts3_expr.c \
$(TOP)/ext/fts3/fts3_tokenizer.c \
$(TOP)/ext/fts3/fts3_tokenizer.c $(TOP)/ext/fts3/fts3_write.c \
$(TOP)/ext/async/sqlite3async.c
# Header files used by all library source files.

266
manifest
View File

@ -1,14 +1,14 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
C Version\s3.6.21\srelease\scandidate\s3.
D 2009-12-07T16:39:13
C Update\sthe\sversion\snumber\sto\s3.6.23.1.
D 2010-03-26T22:28:06
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3
F Makefile.in 4f2f967b7e58a35bb74fb7ec8ae90e0f4ca7868b
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F Makefile.vxworks 10010ddbf52e2503c7c49c7c0b7c7a096f8638a6
F Makefile.vxworks ab005d301296c40e021ccd0133ce49ca811e319f
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
F VERSION aa30c4b131a981624ab576df19eb4c5c9cd582ac
F VERSION 09d2dfb6a4a47d07b3b2091e349eedef78fb0f77
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F addopcodes.awk 17dc593f791f874d2c23a0f9360850ded0286531
F art/2005osaward.gif 0d1851b2a7c1c9d0ccce545f3e14bca42d7fd248
@ -22,7 +22,7 @@ F art/src_logo.gif 9341ef09f0e53cd44c0c9b6fc3c16f7f3d6c2ad9
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 868fdb48c028421a203470e15c69ada15b9ba673
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure beb6a7b293d15978ac274e6b43b37b356d3070b2
F configure 17dee87ba9b797ea22940dc0fb5b08147bfb246a
F configure.ac 14740970ddb674d92a9f5da89083dff1179014ff
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
@ -59,25 +59,25 @@ F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c 684a55d603f11c8432323171082ff8a9437b4681
F ext/fts3/fts3.c 2bb2045d1412184e9eea71eb151b159168be5131
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h cc716c74afa7da8e0f8ef39404f33ea62a823eb3
F ext/fts3/fts3_expr.c c18794a62c257d3456d3314c5a18e348ae0d84bd
F ext/fts3/fts3_hash.c 18feef38fca216992725e9eae775a0c7735e6724
F ext/fts3/fts3_hash.h d410ff2c93c81a56b927fcf07b2099ccbfa7a479
F ext/fts3/fts3Int.h df812ef35f1b47a44ec68a44ec0c2a769c973d85
F ext/fts3/fts3_expr.c f4ff02ebe854e97ac03ff00b38b728a9ab57fd4b
F ext/fts3/fts3_hash.c 3c8f6387a4a7f5305588b203fa7c887d753e1f1c
F ext/fts3/fts3_hash.h 8331fb2206c609f9fc4c4735b9ab5ad6137c88ec
F ext/fts3/fts3_icu.c ac494aed69835008185299315403044664bda295
F ext/fts3/fts3_porter.c a651e287e02b49b565a6ccf9441959d434489156
F ext/fts3/fts3_snippet.c 6c2eb6d872d66b2a9aa5663f2662e993f18a6496
F ext/fts3/fts3_tokenizer.c 52112e7b50fbf24eb68e356081c5969917406cc6
F ext/fts3/fts3_tokenizer.h 7ff73caa3327589bf6550f60d93ebdd1f6a0fb5c
F ext/fts3/fts3_tokenizer1.c 11a604a53cff5e8c28882727bf794e5252e5227b
F ext/fts3/fts3_write.c ec51fb6886f910e78ae32158ec0301aa675f52d8
F ext/fts3/fts3_porter.c 7546e4503e286a67fd4f2a82159620e3e9c7a1bc
F ext/fts3/fts3_snippet.c 538bd27a76e465cb4ef6bfcb5479d897e4d5a536
F ext/fts3/fts3_tokenizer.c 1a49ee3d79cbf0b9386250370d9cbfe4bb89c8ff
F ext/fts3/fts3_tokenizer.h 13ffd9fcb397fec32a05ef5cd9e0fa659bf3dbd3
F ext/fts3/fts3_tokenizer1.c b6d86d1d750787db5c168c73da4e87670ed890a1
F ext/fts3/fts3_write.c 4b21a0c6f2772b261f14e3a2e80e1e3e849268b0
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/icu/README.txt 3b130aa66e7a681136f6add198b076a2f90d1e33
F ext/icu/icu.c 12e763d288d23b5a49de37caa30737b971a2f1e2
F ext/icu/icu.c 850e9a36567bbcce6bd85a4b68243cad8e3c2de2
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 038d59b05783c2e6c927a7352bb118a76c31065a
F ext/rtree/rtree.c a354f6be11a91706680936fdf77b4588f0b34dbe
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
F ext/rtree/rtree1.test f72885ed80a329d6bd7991043016d74b51edf2c5
F ext/rtree/rtree2.test 7b665c44d25e51b3098068d983a39902b2e2d7a1
@ -85,13 +85,14 @@ F ext/rtree/rtree3.test dece988c363368af8c11862995c762071894918f
F ext/rtree/rtree4.test 94fdd570ab5bc47244d87d4590023be43ac786bd
F ext/rtree/rtree5.test 92508f5152a50110af6551fa5b769d1bbd7c4ef3
F ext/rtree/rtree6.test 11aade5311789068ca659be24a47cc0d852b1971
F ext/rtree/rtree7.test 6fd29fb8e13795c822f4ceeea92ab5d61c96976d
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
F ext/rtree/tkt3363.test 2bf324f7908084a5f463de3109db9c6e607feb1b
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F main.mk a92b99b264c3b277f8cf74d50aadc22c55967ef0
F main.mk a36a05a481afcc00388c4d6d4db0e12cacb546e3
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
@ -104,79 +105,80 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
F src/alter.c 92ba938565d7cc6bfe92aad6cc90c00800ff21d3
F src/analyze.c 55155f05ee9ab4ce33b7a4d19c449053f8935200
F src/attach.c 0ba38b38252a34bb9721de35514a1d14058a8e49
F src/alter.c e6f4d11b1c0b23642fc46bac9abe0753c4294e05
F src/analyze.c 92a65a5a402898a52b03695c7f0cd383724d711f
F src/attach.c 7abe1607c2054585377cdba3c219e8572f84ca5e
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 744e98359dfc79fed43e8dec911e33e108b06aae
F src/backup.c b293534bc2df23c57668a585b17ee7faaaef0939
F src/bitvec.c 06ad2c36a9c3819c0b9cbffec7b15f58d5d834e0
F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff
F src/btree.c efdef3953c49e28f8b8fa9cc0ac5754cc1a7489a
F src/btree.h 7944a9dac59eb3e541aad45fd2747f1051e7c63d
F src/btreeInt.h 54f4245decd0409ea52cf9aee422d3d761d7ac10
F src/build.c a48e74d24897100017d39ceba5de255e53ec9488
F src/btree.c 0d6e44d664b1775b269ea7e6f66fdffcfc32ceb3
F src/btree.h 0e193b7e90f1d78b79c79474040e3d66a553a4fa
F src/btreeInt.h 71ed5e7f009caf17b7dc304350b3cb64b5970135
F src/build.c 11100b66fb97638d2d874c1d34d8db90650bb1d7
F src/callback.c 908f3e0172c3d4058f4ca0acd42c637c52e9669f
F src/complete.c 417df1ef5ea798532bb6290b0cc4265fef82980a
F src/date.c a79c0a8f219370b972e320741f995a3bef9df33f
F src/delete.c 8b8afb9cd7783d573eae55a3f4208bc0637a2bb8
F src/expr.c 50385ed51f1cd7f1ab289629cd0f87d5b2fcca52
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c ceb247eb31620bba66a94c3f697db489a1652353
F src/date.c 485a4409a384310e6d93fd1104a9d0a8658becd9
F src/delete.c 610dc008e88a9599f905f5cbe9577ac9c36e0581
F src/expr.c 6baed2a0448d494233d9c0a610eea018ab386a32
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c e2116672a6bd610dc888e27df292ebc7999c9bb0
F src/func.c bf54e1202cbfb28bf4b1fd9b58899009ae76716f
F src/global.c 75946a4a2ab41c6ae58f10ca0ed31b3449694b26
F src/func.c 5dca069d98eca0ff70c9a8fb8ab9e1d6467187b5
F src/global.c 5a9c1e3c93213ca574786ac1caa976ce8f709105
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c f9c6098988675ac258b2f98ea5f7e370fc9990fa
F src/insert.c 76d6b44a9f9050134fd81205f4b792cbdac7c925
F src/journal.c b0ea6b70b532961118ab70301c00a33089f9315c
F src/legacy.c 9304428e71b1d622b764913e1432e69156814755
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
F src/loadext.c 1c7a61ce1281041f437333f366a96aa0d29bb581
F src/main.c aae32d5af35b88faff0664e0f937ee7133d77c8d
F src/main.c 7d89bb6dcc6993a8d32f4f22dae3e57c50a41399
F src/malloc.c 5fa175797f982b178eaf38afba9c588a866be729
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 552f7e11486272f27948d2de9c012884d1f52908
F src/mem2.c 3f196f6fd3f4320035eb4acbe4530686da2f14b1
F src/mem1.c 89d4ea8d5cdd55635cbaa48ad53132af6294cbb2
F src/mem2.c ee752297650632935218dcf3b20c5ed5899cb4b5
F src/mem3.c 9b237d911ba9904142a804be727cc6664873f8a3
F src/mem5.c 4837b795ebdecc0cfe1522cd0c8b2c5d84ea490d
F src/mem5.c eb7a5cb98915dd7a086fa415ce3a5a0f20d0acff
F src/memjournal.c 5bfc2f33c914946e2f77ed3f882aff14dfc9355d
F src/mutex.c 581a272e09098040ca3ef543cb5f3d643eff7d50
F src/mutex.h 6fde601e55fa6c3fae768783c439797ab84c87c6
F src/mutex_noop.c 5f58eaa31f2d742cb8957a747f7887ae98f16053
F src/mutex_os2.c 20477db50cf3817c2f1cd3eb61e5c177e50231db
F src/mutex_unix.c 04a25238abce7e3d06b358dcf706e26624270809
F src/mutex_w32.c 9ec75bcef0ca722821be7968c320fd725abfb984
F src/mutex_w32.c 4cc201c1bfd11d1562810554ff5500e735559d7e
F src/notify.c f799bbda67ab6619b36b0a24153b49518874a203
F src/os.c 4500ff276e277730776fe9b6c6c5930383ec4000
F src/os.c 8bc63cf91e9802e2b807198e54e50227fa889306
F src/os.h 534b082c3cb349ad05fa6fa0b06087e022af282c
F src/os_common.h 240c88b163b02c21a9f21f87d49678a0aa21ff30
F src/os_os2.c 75a8c7b9a00a2cf1a65f9fa4afbc27d46634bb2f
F src/os_unix.c fe85acfeded5cc13c2340ab73c9baf841de4e6d9
F src/os_win.c 5ffab20249a61e0625f869efe157fa009747039b
F src/pager.c a0ed14b86de9d012a962b83389ca01003b6acccb
F src/os_unix.c 148d2f625db3727250c0b880481ae7630b6d0eb0
F src/os_win.c 1c7453c2df4dab26d90ff6f91272aea18bcf7053
F src/pager.c 1915e3ec1a2157d0c29086b7fc0c936a2d97029e
F src/pager.h 1b32faf2e578ac3e7bcf9c9d11217128261c5c54
F src/parse.y b172fba9a954855502271556497c440506b6daf4
F src/pcache.c 3b079306376e0e04c0d3df40c0a4b750a1839310
F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e
F src/pcache.c 4956b41d6ba913f7a8a56fbf32be78caed0e45c2
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
F src/pcache1.c 2bb2261190b42a348038f5b1c285c8cef415fcc8
F src/pragma.c 6936d7df5e04b9f996f8f320d15e65b6944b2caa
F src/prepare.c ad90970bba3aead154266d8bb6faf9fbb5233b94
F src/printf.c 644bc7d59df3dc56d6d8b9a510914bfc6b51bc69
F src/pragma.c 56d95f76154a5f873c32eae485bb625f3c70be46
F src/prepare.c 18292e5f365655cd5c5693e09508e90668f7d547
F src/printf.c 5f5b65a83e63f2096a541a340722a509fa0240a7
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c d052e5c44bab34f83b3c1741aaa07478d18b5dd5
F src/resolve.c a1648d98e869937b29f4f697461fe4d60f220a7b
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c 2f9ed7482e7a25b0b127fc41693bbdbe1caf5647
F src/shell.c f4948cb6d30665d755a6b5e0ec313d1094aab828
F src/sqlite.h.in 2d34605565e021851255e0bbcb15f8c1930d1f6f
F src/select.c 4113ef360430ed4e7533690ef46d06c20204adce
F src/shell.c c40427c7245535a04a9cb4a417b6cc05c022e6a4
F src/sqlite.h.in 08a2d9a278ff0dfd65055a7ec9c599f7ae1a3c18
F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
F src/sqliteInt.h e946a6a3f2df015cdbc7668e9626987e8badbb5f
F src/sqliteInt.h 6873f7f4c24fcdceece8777f2a1cbec049df77a0
F src/sqliteLimit.h 3afab2291762b5d09ae20c18feb8e9fa935a60a6
F src/status.c e651be6b30d397d86384c6867bc016e4913bcac7
F src/status.c d329385a2cba3ea49d9d68af0ad84b22d46b4f40
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c bad6570a005b234ea670b9f7b48256da19a032d3
F src/test1.c db4d8fd2849ab9aca0f27fd3773b8d68d078cf86
F src/test1.c aa9b1e10e834330e7759afb639420117e2422ded
F src/test2.c b6b43413d495addd039a88b87d65c839f86b18cb
F src/test3.c f17eeaf8114205844d76f4e69bab27ea341087af
F src/test3.c 4c21700c73a890a47fc685c1097bfb661346ac94
F src/test4.c ad03bb987ddedce928f4258c1e7fa4109a73497d
F src/test5.c cc55900118fa4add8ec9cf69fc4225a4662f76b1
F src/test6.c a8ece4284d0e34477f349ac05655db73c48e0926
@ -187,10 +189,10 @@ F src/test_async.c c1656facbaf43cb2e71b62621e5b9eb080e2621c
F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e
F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de
F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2
F src/test_config.c 220a67047af393756f55760fdf442d935d0d88f3
F src/test_config.c 5844274bf6cec4af3e6461fb3e2d349082635e81
F src/test_devsym.c de3c9af2bb9a8b1e44525c449e4ec3f88e3d4110
F src/test_func.c 1c94388a23d4a9e7cd62ec79d612d1bae2451fa2
F src/test_hexio.c 415adbdb88cd9388831ce10edff76cb9e73d8a0b
F src/test_func.c 13b582345fb1185a93e46c53310fae8547dcce20
F src/test_hexio.c 1237f000ec7a491009b1233f5c626ea71bce1ea2
F src/test_init.c 5d624ffd0409d424cf9adbfe1f056b200270077c
F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
@ -206,23 +208,23 @@ F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
F src/test_thread.c 00fed80690ae7f1525483a35861511c48bc579f2
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c 9f7d39da1a1346fa0cf106ea0bf10bb6b8b61ddf
F src/trigger.c d46f9389e3bf3dd1cc1d288aba2f289c96b34200
F src/tokenize.c 25ceb0f0a746ea1d0f9553787f3f0a56853cfaeb
F src/trigger.c 340c9eca0fb24b1197468d96ba059f867c9834c7
F src/update.c c0dc6b75ad28b76b619042d934f337b02acee208
F src/utf.c dad16adcc0c35ef2437dca125a4b07419d361052
F src/util.c ad4f03079ba0fe83590d1cc9197e8e4844e38592
F src/vacuum.c 03309a08d549f9389cc3a3589afd4fadbdaf0679
F src/vdbe.c 5ed06318aac5d57849170a8bf39e807c22c5fedd
F src/vdbe.h bea1f0cd530775bdb58a340265f3cf3ee920e9b2
F src/vdbeInt.h d7ea821ac7813c9bea0fe87558c35e07b2c7c44d
F src/vdbeapi.c bb128b819b9ef1a2ce211a36a6cb70a1643fa239
F src/vdbeaux.c 0981dcb5b933b74ae7bc9bfa7770df5e4da849b3
F src/vdbeblob.c 84f924700a7a889152aeebef77ca5f4e3875ffb4
F src/vdbemem.c 1e16e3a16e55f4c3452834f0e041726021aa66e0
F src/utf.c 1baeeac91707a4df97ccc6141ec0f808278af685
F src/util.c 32aebf04c10e51ad3977a928b7416bed671b620b
F src/vacuum.c b1d542c8919d4d11119f78069e1906a1ad07e0ee
F src/vdbe.c 8acca6dab2505e9650f6f014ada6ef30570cba99
F src/vdbe.h 471f6a3dcec4817ca33596fe7f6654d56c0e75f3
F src/vdbeInt.h ae1e6ba0dd3fb4a886898d2829d748be701b01f8
F src/vdbeapi.c 74c25680046a116b24b95393914d3669c23305dc
F src/vdbeaux.c 0f352f63be78138bd94275aa3c8361e760ecc639
F src/vdbeblob.c 5327132a42a91e8b7acfb60b9d2c3b1c5c863e0e
F src/vdbemem.c 2a82f455f6ca6f78b59fb312f96054c04ae0ead1
F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
F src/vtab.c 456fc226614569f0e46f216e33265bea268bd917
F src/vtab.c 606adf51cd6d4ba51a8c6dccede06a6f7b0dd72d
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c 11b5b00c49d53e767a7eb855bc60790edeca6185
F src/where.c 399ea4c090284c9d16f76d685b9b44e8b9b4442b
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45
@ -233,24 +235,24 @@ F test/alter4.test 9386ffd1e9c7245f43eca412b2058d747509cc1f
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
F test/analyze.test ad5329098fe4de4a96852231d53e3e9e6283ad4b
F test/analyze2.test a2ad7b0a4e13801ee3968fe70f22aff52326569c
F test/analyze3.test ae06e0f8b3eaae0dd644ac9ac9d617058b5ac131
F test/analyze3.test 506203875258ffd8ffa879b9c3c5432022d2b6d8
F test/async.test 8c75d31b8330f8b70cf2571b014d4476a063efdb
F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
F test/async4.test aafa6328c559d3e4bb587de770cbdecfca06f0da
F test/async5.test f3592d79c84d6e83a5f50d3fd500445f7d97dfdf
F test/attach.test 826f7676c41c12b035181d257299b8c8a17d64f3
F test/attach.test ce9660e51768fab93cf129787be886c5d6c4fd81
F test/attach2.test a295d2d7061adcee5884ef4a93c7c96a82765437
F test/attach3.test bd9830bc3a0d22ed1310c9bff6896927937017dc
F test/attachmalloc.test cf8cf17d183de357b1147a9baacbdfc85b940b61
F test/attachmalloc.test 38d2da5fdaf09ba0add57296967a3061e5842584
F test/auth.test 8f21c160a4562f54f27618e85bac869efcecbcaf
F test/auth2.test ee3ba272e2b975e913afc9b041ee75706e190005
F test/auth2.test 270baddc8b9c273682760cffba6739d907bd2882
F test/auth3.test a4755e6a2a2fea547ffe63c874eb569e60a28eb5
F test/autoinc.test 85ef3180a737e6580086a018c09c6f1a52759b46
F test/autovacuum.test 25f891bc343a8bf5d9229e2e9ddab9f31a9ab5ec
F test/autovacuum_ioerr2.test 598b0663074d3673a9c1bc9a16e80971313bafe6
F test/avtrans.test 1e901d8102706b63534dbd2bdd4d8f16c4082650
F test/backup.test 9b184cc3cccb153e73387a88c6e6d23210212f86
F test/backup.test 3549ea8f541a08205c0eb813b21e81ea8301f6ed
F test/backup2.test 159419073d9769fdb1780ed7e5b391a046f898d5
F test/backup_ioerr.test 1f012e692f42c0442ae652443258f70e9f20fa38
F test/backup_malloc.test 1e063c6d75143d0d6e0ae77971dd690070369387
@ -275,10 +277,10 @@ F test/cache.test 3ff445c445742a7b6b9ba6e1d62a25263f9424b9
F test/capi2.test 172c717ed101e78e0798dd21b9896a22366f35b4
F test/capi3.test 168e2cd66c58c510955b0f299750e4de73b8d952
F test/capi3b.test 664eb55318132f292f2c436f90906f578cad6b97
F test/capi3c.test d9d293ce8fd4dc2944ce2dae5718fc7a6184a567
F test/capi3c.test 493385107dcedfaf4f2b1c3738c8c1fa00362006
F test/capi3d.test 57d83b690d7364bde02cddbf8339a4b50d80ce23
F test/cast.test 166951664a0b0a2e0f8fb5997a152490c6363932
F test/check.test b897cd3cc839b34b31cdd073e9882ccd03da977b
F test/check.test db2b29d557544347d28e25b8406f5d5ecc3d1bc3
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
F test/collate1.test e3eaa48c21e150814be1a7b852d2a8af24458d04
F test/collate2.test 04cebe4a033be319d6ddbb3bbc69464e01700b49
@ -293,19 +295,20 @@ F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
F test/colmeta.test 087c42997754b8c648819832241daf724f813322
F test/colname.test 08948a4809d22817e0e5de89c7c0a8bd90cb551b
F test/conflict.test 0ed68b11f22721052d880ee80bd528a0e0828236
F test/corrupt.test 85c3fececa01bc6d24ff5d7bf1373844840c0b98
F test/corrupt.test 0d346c9fe064ca71281685a8a732fcc83461bb99
F test/corrupt2.test a571e30ea4e82318f319a24b6cc55935ce862079
F test/corrupt3.test 263e8bb04e2728df832fddf6973cf54c91db0c32
F test/corrupt4.test acdb01afaedf529004b70e55de1a6f5a05ae7fff
F test/corrupt5.test c23da7bfb20917cc7fdbb13ee25c7cc4e9fffeff
F test/corrupt6.test e69b877d478224deab7b66844566258cecacd25e
F test/corrupt7.test e66cb109ed64e7ac985d8b4a3422c213d074c62d
F test/corrupt7.test 1eb2214f29474fa6b155aa3da8a7d46bf52089e1
F test/corrupt8.test 9992ef7f67cefc576b92373f6bf5ab8775280f51
F test/corrupt9.test 4aa1cb1ef091cb0e13e89a819c72911631b5176a
F test/corruptA.test 99e95620b980161cb3e79f06a884a4bb8ae265ff
F test/corruptB.test 66b4544104dd03d0f33ea69ddac3fa4a682cd3c2
F test/corruptC.test 691ed070baef5e1345939caadf270a52837a5064
F test/corruptD.test 3ae6e2dc6e2226c6935a8a40d4b5ee3eba75f8c0
F test/corruptE.test dbf66cae4c0e977ca9625a9114cdd01df8967bef
F test/count.test 454e1ce985c94d13efeac405ce54439f49336163
F test/crash.test 1b6ac8410689ff78028887f445062dc897c9ac89
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
@ -314,10 +317,11 @@ F test/crash4.test 02ff4f15c149ca1e88a5c299b4896c84d9450c3b
F test/crash5.test 80a2f7073381837fc082435c97df52a830abcd80
F test/crash6.test 9c730cf06335003cb1f5cfceddacd044155336e0
F test/crash7.test e20a7b9ee1d16eaef7c94a4cb7ed2191b4d05970
F test/crash8.test 5b32966fcb58fd616d24ce94303420351d076eb9
F test/crash8.test 3af0fc90c3e593b85e810b8d6c50fc7d0df30008
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
F test/createtab.test 199cf68f44e5d9e87a0b8afc7130fdeb4def3272
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
F test/ctime.test f5040beef89c1b2bdb6a9edb7358a519213ff80c
F test/date.test 0b8473ed9ab6fd4283b4a01f035e1067762ba734
F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
F test/delete.test f7629d9eb245dfca170169cc5c7a735dec34aeb4
@ -328,8 +332,8 @@ F test/descidx2.test 1310ed1326cdfed4ea2c55169631579f082d174f
F test/descidx3.test 3394ad4d089335cac743c36a14129d6d931c316f
F test/diskfull.test 0cede7ef9d8f415d9d3944005c76be7589bb5ebb
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
F test/e_fkey.test fd1fcf89badd5f2773d7ac04775b5ff3488eda17
F test/e_fts3.test 8907e25b2c7d6bda9f7077356f64bc5e26c251a7
F test/e_fkey.test 6721a741c6499b3ab7e5385923233343c8f1ad05
F test/e_fts3.test 5adb033fae6e07002d11f4a7c8f8e8ff9f31e8ec
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 6d91a5286f59add0cfcbb2d0da913b76f2242398
F test/enc3.test 5c550d59ff31dccdba5d1a02ae11c7047d77c041
@ -341,7 +345,7 @@ F test/expr.test 9f521ae22f00e074959f72ce2e55d46b9ed23f68
F test/filectrl.test 8923a6dc7630f31c8a9dd3d3d740aa0922df7bf8
F test/filefmt.test 84e3d0fe9f12d0d2ac852465c6f8450aea0d6f43
F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da
F test/fkey2.test add654160d1b066f7b866d63d4435954ccbcab7d
F test/fkey2.test e71f5baf9bb42cdba4700d73cba6f4d82fd6b925
F test/fkey3.test 42f88d6048d8dc079e2a8cf7baad1cc1483a7620
F test/fkey_malloc.test a5ede29bd2f6e56dea78c3d43fb86dd696c068c8
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
@ -380,36 +384,40 @@ F test/fts2q.test b2fbbe038b7a31a52a6079b215e71226d8c6a682
F test/fts2r.test b154c30b63061d8725e320fba1a39e2201cadd5e
F test/fts2token.test d8070b241a15ff13592a9ae4a8b7c171af6f445a
F test/fts3.test ae0433b09b12def08105640e57693726c4949338
F test/fts3_common.tcl 31935839b1b601a5955572cb4e8060513c96bde0
F test/fts3_common.tcl 1d887ded06dac9b993cfb175618df7f70c796de2
F test/fts3aa.test 5327d4c1d9b6c61021696746cc9a6cdc5bf159c0
F test/fts3ab.test 09aeaa162aee6513d9ff336b6932211008b9d1f9
F test/fts3ac.test 356280144a2c92aa7b11474afadfe62a437fcd69
F test/fts3ac.test 636ed7486043055d4f126a0e385f2d5a82ebbf63
F test/fts3ad.test e40570cb6f74f059129ad48bcef3d7cbc20dda49
F test/fts3ae.test ce32a13b34b0260928e4213b4481acf801533bda
F test/fts3af.test d394978c534eabf22dd0837e718b913fd66b499c
F test/fts3ag.test 38d9c7dd4b607929498e8e0b32299af5665da1ab
F test/fts3ag.test 0b7d303f61ae5d620c4efb5e825713ea34ff9441
F test/fts3ah.test ba181d6a3dee0c929f0d69df67cac9c47cda6bff
F test/fts3ai.test d29cee6ed653e30de478066881cec8aa766531b2
F test/fts3aj.test 584facbc9ac4381a7ec624bfde677340ffc2a5a4
F test/fts3ak.test bd14deafe9d1586e8e9bf032411026ac4f8c925d
F test/fts3al.test 6d19619402d2133773262652fc3f185cdf6be667
F test/fts3al.test 07d64326e79bbdbab20ee87fc3328fbf01641c9f
F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8
F test/fts3an.test 931fa21bd80641ca594bfa32e105250a8a07918b
F test/fts3ao.test 0aa29dd4fc1c8d46b1f7cfe5926f7ac97551bea9
F test/fts3atoken.test 25c2070e1e8755d414bf9c8200427b277a9f99fa
F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
F test/fts3cov.test 3a9d8618a3107166530c447e808f8992372e0415
F test/fts3d.test 95fb3c862cbc4297c93fceb9a635543744e9ef52
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
F test/fts3expr.test 05dab77387801e4900009917bb18f556037d82da
F test/fts3expr.test 5e745b2b6348499d9ef8d59015de3182072c564c
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
F test/fts3malloc.test d02ee86b21edd2b43044e0d6dfdcd26cb6efddcb
F test/fts3near.test dc196dd17b4606f440c580d45b3d23aa975fd077
F test/fts3rnd.test ec82795eb358b7a4d6ce79e764d8d55556197584
F test/func.test af106ed834001738246d276659406823e35cde7b
F test/fts3malloc.test 059592c4f37ccd30138bbf8e3e5b7982cb5c8f2e
F test/fts3near.test 2e318ee434d32babd27c167142e2b94ddbab4844
F test/fts3query.test 154fe4b015fd61af523ee083570a134f508f5be7
F test/fts3rnd.test 2f5761db9dd92f6fe09d08976ac658ef521846ed
F test/fts3snippet.test 9f9a4a7e396c5d8ce2898be65ebabc429555430f
F test/fts4aa.test eadf85621c0a113d4c7ad3ccbf8441130e007b8f
F test/func.test 6c5ce11e3a0021ca3c0649234e2d4454c89110ca
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/fuzz.test a4174c3009a3e2c2e14b31b364ebf7ddb49de2c9
F test/fuzz2.test ea38692ce2da99ad79fe0be5eb1a452c1c4d37bb
F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test 4eca9d345f06d5b0b0105f7a2ef9e7f22658827b
@ -433,7 +441,7 @@ F test/init.test 3f9e97948cf2335c08a5e3edc3df3a26cdaa76f2
F test/insert.test aef273dd1cee84cc92407469e6bd1b3cdcb76908
F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
F test/insert4.test 6e382eaf7295a4463e6f29ea20fcd8e63d097eeb
F test/insert4.test c1469999a58e86a85b74df645a820f4cc7a8273b
F test/insert5.test 1f93cbe9742110119133d7e8e3ccfe6d7c249766
F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4
F test/interrupt.test 42e7cf98646fd9cb4a3b131a93ed3c50b9e149f1
@ -449,6 +457,7 @@ F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
F test/join5.test 86675fc2919269aa923c84dd00ee4249b97990fe
F test/join6.test bf82cf3f979e9eade83ad0d056a66c5ed71d1901
F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19
F test/jrnlmode.test a765844f22b3f6d72d78a68d5decd26c64bb859c
F test/jrnlmode2.test fe79ea1f0375c926b8de0362ddf94f34a64135fd
@ -469,7 +478,7 @@ F test/lock5.test 6b1f78f09ad1522843dad571b76b321e6f439bf7
F test/lock6.test 862aa71e97b288d6b3f92ba3313f51bd0b003776
F test/lock7.test 64006c84c1c616657e237c7ad6532b765611cf64
F test/lookaside.test 1dd350dc6dff015c47c07fcc5a727a72fc5bae02
F test/main.test 347ab987f16167858781383427476b33dc69fdb7
F test/main.test 2be2352ac77ac5b238c6337a5469aeeef57677e6
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
F test/malloc.test d23580e15c33ee0353717129421b077541e910dc
F test/malloc3.test 4bc57f850b212f706f3e1b37c4eced1d5a727cd1
@ -499,7 +508,7 @@ F test/memsubsys1.test fd8a33046b6e758e3eb93747dc4eec21fe56bf64
F test/memsubsys2.test 72a731225997ad5e8df89fdbeae9224616b6aecc
F test/minmax.test 722d80816f7e096bf2c04f4111f1a6c1ba65453d
F test/minmax2.test 33504c01a03bd99226144e4b03f7631a274d66e0
F test/minmax3.test 94742aa922153953ce3562702815e4f1f079bdb8
F test/minmax3.test a38686c33b07d595e98a2fc6d3aa84a5e886a972
F test/misc1.test 1b89c02c4a33b49dee4cd1d20d161aaaba719075
F test/misc2.test a628db7b03e18973e5d446c67696b03de718c9fd
F test/misc3.test 72c5dc87a78e7865c5ec7a969fc572913dbe96b6
@ -517,10 +526,10 @@ F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
F test/null.test a8b09b8ed87852742343b33441a9240022108993
F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
F test/pageropt.test 3ee6578891baaca967f0bd349e4abfa736229e1a
F test/pagesize.test 0d9ff3fedfce6e5ffe8fa7aca9b6d3433a2e843b
F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb
F test/pcache.test eebc4420b37cb07733ae9b6e99c9da7c40dd6d58
F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16
F test/permutations.test 1ce2874df8fec876d0b963c7a3ef61c4e9df8827
F test/permutations.test 91928573ca2db2c88dbc50ab34e4a585d912b580
F test/pragma.test 5aeb48a442dba3c3e8e38773b121371814ab3b17
F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
@ -536,22 +545,22 @@ F test/rollback.test 73355ad4492ff9a3a31e61c7e5eb5e01a1de94ca
F test/rowhash.test 97f56043ba11f0679920416c0cdbc72e5272267b
F test/rowid.test e58e0acef38b527ed1b0b70d3ada588f804af287
F test/rtree.test 55466a200af3591946c5da77ad5dbfbc1e5e05f9
F test/safety.test b69e2b2dd5d52a3f78e216967086884bbc1a09c6
F test/savepoint.test f2ede4b643ad87ead36c041c72d774a1f5c8a564
F test/savepoint2.test 427c8b20f43d3edf17a290c6788ae9e2703ac51c
F test/savepoint3.test e328085853b14898d78ceea00dfe7db18bb6a9ec
F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0
F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
F test/savepoint6.test 2df1d093e59e78d688c64eb20e0457aaea7d08f9
F test/schema.test 3d8b19e3cf1105929940d387e3577da5a58d8fc0
F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
F test/securedel.test 328d2921c0ca49bdd3352e516b0377fc07143254
F test/select1.test f67ca2dfc05df41c7b86eb32ca409b427a5f43b0
F test/select2.test 9735da20ccd41e42bf2b4c19fd939141b591adae
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
F test/select4.test 44aa6e7110592e18110b0b9cf5c024d37d23be17
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
F test/select6.test 2b5e8500d8ec3dd4c8e0c99eb1431b3d11fcc24c
F test/select7.test 7906735805cfbee4dddc0bed4c14e68d7f5f9c5f
F test/select7.test dad6f00f0d49728a879d6eb6451d4752db0b0abe
F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
F test/select9.test b4007b15396cb7ba2615cab31e1973b572e43210
F test/selectA.test 06d1032fa9009314c95394f2ca2e60d9f7ae8532
@ -580,6 +589,7 @@ F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/sqllimits1.test e90a0ed94452076f6a10209d378e06b5f75ef0a0
F test/stmt.test ac97e59879fd3bd52ecd60ef4efb03ba16292829
F test/subquery.test b524f57c9574b2c0347045b4510ef795d4686796
F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
@ -590,7 +600,7 @@ F test/tclsqlite.test bf4227eb236a4c097aa7974a2bf7d3225acf34be
F test/tempdb.test 1bf52da28a9c24e29717362a87722dff08feb72b
F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a
F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05
F test/tester.tcl 02f671e71d1646440d226bed2dde8433f0a7bfa9
F test/tester.tcl e1f581c7a2648a0aaa51135c4d2e7be68f4b9292
F test/thread001.test a3e6a7254d1cb057836cb3145b60c10bf5b7e60f
F test/thread002.test afd20095e6e845b405df4f2c920cb93301ca69db
F test/thread003.test b824d4f52b870ae39fc5bae4d8070eca73085dca
@ -602,11 +612,13 @@ F test/thread_common.tcl b65e6b1d1d90dc885e10ad080896c6c56eef0819
F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
F test/threadtest2.c ace893054fa134af3fc8d6e7cfecddb8e3acefb9
F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
F test/tkt-3fe897352e.test 8084dad39807eac10b10720c84193bd1a5980973
F test/tkt-31338dca7e.test 5741cd48de500347a437ba1be58c8335e83c5a5e
F test/tkt-3fe897352e.test 10de1a67bd5c66b238a4c96abe55531b37bb4f00
F test/tkt-4a03edc4c8.test 2865e4edbc075b954daa82f8da7cc973033ec76e
F test/tkt-5ee23731f.test 3581260f2a71e51db94e1506ba6b0f7311d002a9
F test/tkt-78e04e52ea.test fb5430c675e708f5cbafdf3e7e5593da5145a527
F test/tkt-94c04eaadb.test be5ea61cb04dfdc047d19b5c5a9e75fa3da67a7f
F test/tkt-d82e3f3721.txt cbed12b1a1e4740382de43ef1bb45c6bc0f8f473
F test/tkt-d82e3f3721.test 731359dfdcdb36fea0559cd33fec39dd0ceae8e6
F test/tkt-f777251dc7a.test 6f24c053bc5cdb7e1e19be9a72c8887cf41d5e87
F test/tkt1435.test f8c52c41de6e5ca02f1845f3a46e18e25cadac00
F test/tkt1443.test bacc311da5c96a227bf8c167e77a30c99f8e8368
@ -693,7 +705,7 @@ F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da
F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd
F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
F test/trace.test 2739f8dcc6739a9235523819c4cd30e78c44985c
F test/trace.test 4b36a41a3e9c7842151af6da5998f5080cdad9e5
F test/trans.test d887cb07630dc39879a322d958ad8b006137485c
F test/trans2.test d5337e61de45e66b1fcbf9db833fa8c82e624b22
F test/trans3.test d728abaa318ca364dc370e06576aa7e5fbed7e97
@ -709,6 +721,7 @@ F test/trigger9.test 5b0789f1c5c4600961f8e68511b825b87be53e31
F test/triggerA.test 0718ad2d9bfef27c7af00e636df79bee6b988da7
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
F test/triggerC.test 4083c64d80854d271bad211268a08985f3d61cbd
F test/triggerD.test c6add3817351451e419f6ff9e9a259b02b6e2de7
F test/types.test 9a825ec8eea4e965d7113b74c76a78bb5240f2ac
F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
F test/types3.test a0f66bf12f80fad89493535474f7a6d16fa58150
@ -718,6 +731,7 @@ F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
F test/vacuum.test 68e39b2228b4b772166debef4a82accf6ddd32f3
F test/vacuum2.test ec57f21d394b7b72249b11f8e4b5d487bab56539
F test/vacuum3.test f39ad1428347c5808cd2da7578c470f186a4d0ce
F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
F test/veryquick.test e265401afefa994cdf2fe4b6f286b1e87c2f9b9d
F test/view.test 45f518205ecdb6dd23a86dd4a99bb4ae945e625d
@ -730,7 +744,7 @@ F test/vtab6.test c7f290d172609d636fbfc58166eadcb55d5c117c
F test/vtab7.test a8c3c3cb3eb60be364991bd714e4927e26c4cd85
F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583
F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b
F test/vtabA.test 0dcd4c81ffb56649f47d1b5fb9c5ae807ccf41f7
F test/vtabA.test c86e1990b7e1e2bb34602a06fffa4c69f2b516dc
F test/vtabB.test 04df5dc531b9f44d9ca65b9c1b79f12b5922a796
F test/vtabC.test 1cf7896ab6859bfe3074244b2b0e12de5cbdd766
F test/vtabD.test 74167b1578e5886fe4c886d6bef2fd1406444c42
@ -743,12 +757,12 @@ F test/where2.test 45eacc126aabb37959a387aa83e59ce1f1f03820
F test/where3.test 97d3936e6a443b968f1a61cdcc0f673252000e94
F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 42c4373595f4409d9c6a9987b4a60000ad664faf
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
F test/where7.test fdd58ab9dec9f97679e65d4414bf5e07d725d79f
F test/where8.test 434f08974964b10378d67867773a2c3aedaf1d4b
F test/where8.test 2bb8ea44b745fcc93db150fac9ce33d12e499760
F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739
F test/where9.test be19e1a92f80985c1a121b4678bf7d2123eaa623
F test/whereA.test 1d1674254614147c866ab9b59af6582f454a858c
F test/whereA.test 24c234263c8fe358f079d5e57d884fb569d2da0a
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
@ -756,18 +770,20 @@ F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/lemon.c 3088e4dec7f93c6b0925cf5bac04c8b7c8688835
F tool/lemon.c 6958cb9935be265bf51dbc718ef325e3b77685b6
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
F tool/mkkeywordhash.c 9216336085e7a7c226a35c0bd780239968f8304f
F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c.tcl 1da28229695fdebdfe8a7d19902ef6c76d6c1c2d
F tool/mksqlite3c.tcl 4c6924c7e877defa8f9a12ef1e6867de614acf3f
F tool/mksqlite3h.tcl eb100dce83f24b501b325b340f8b5eb8e5106b3b
F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
F tool/omittest.tcl 27d6f6e3b1e95aeb26a1c140e6eb57771c6d794a
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/shell1.test f85b976bef45f435fa39bf3690501cd5c0bdbb86
F tool/shell2.test c985140ca75d96dad5bef8a5f49ed51b9c002dfb
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/shell1.test ef08a3e738b9fee4fc228920956950bc35db0575
F tool/shell2.test 8f51f61c13b88618e71c17439fe0847c2421c5d1
F tool/shell3.test ff663e83100670a295d473515c12beb8103a78b6
F tool/showdb.c 8ab8b3b53884312aafb7ef60982e255a6c31d238
F tool/showjournal.c ec3b171be148656827c4949fbfb8ab4370822f87
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
@ -779,14 +795,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P cd50acf37fd1e3b388f98fb2df7ed03cff454b24
R 5d0b6a47a50c8a9cdc60d3d4d61a8cf2
P b1f342a6643829020beef542a0700d90822e6467
R 590a011d9441875bded2c173c371f1c1
U drh
Z 8b76b0c0726e570aef93558fa0c3fdc7
Z f7171db765620a4ccff85bc2ced22202
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFLHS+0oxKgR168RlERArAKAJ97NTyJvzQHmWC2GXt2Xt7D52m04QCeLeQt
HYPTNDWgvT/KRZ19RtHNjDQ=
=tE2+
iD8DBQFLrTT6oxKgR168RlERArP2AJ0UeA3bKxomgH1prR7M+4tHuMlN7wCfXBZE
Jr7IGDFSJ/vsM6VpeiKkkf4=
=diSA
-----END PGP SIGNATURE-----

View File

@ -1 +1 @@
1ed88e9d01e9eda5cbc622e7614277f29bcc551c
b078b588d617e07886ad156e9f54ade6d823568e

View File

@ -479,9 +479,9 @@ void sqlite3AlterRenameTable(
** for which the renamed table is the parent table. */
if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){
sqlite3NestedParse(pParse,
"UPDATE sqlite_master SET "
"UPDATE \"%w\".%s SET "
"sql = sqlite_rename_parent(sql, %Q, %Q) "
"WHERE %s;", zTabName, zName, zWhere);
"WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere);
sqlite3DbFree(db, zWhere);
}
}

View File

@ -559,9 +559,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
(void)sqlite3SafetyOff(db);
rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
(void)sqlite3SafetyOn(db);
sqlite3DbFree(db, zSql);
}
@ -579,14 +577,11 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
if( !zSql ){
rc = SQLITE_NOMEM;
}else{
(void)sqlite3SafetyOff(db);
rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
(void)sqlite3SafetyOn(db);
sqlite3DbFree(db, zSql);
}
if( rc==SQLITE_OK ){
(void)sqlite3SafetyOff(db);
while( sqlite3_step(pStmt)==SQLITE_ROW ){
char *zIndex = (char *)sqlite3_column_text(pStmt, 0);
Index *pIdx = sqlite3FindIndex(db, zIndex, sInfo.zDatabase);
@ -636,7 +631,6 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
}
}
rc = sqlite3_finalize(pStmt);
(void)sqlite3SafetyOn(db);
}
}
#endif

View File

@ -144,11 +144,17 @@ static void attachFunc(
pPager = sqlite3BtreePager(aNew->pBt);
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
sqlite3PagerJournalMode(pPager, db->dfltJournalMode);
sqlite3BtreeSecureDelete(aNew->pBt,
sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
}
aNew->zName = sqlite3DbStrDup(db, zName);
aNew->safety_level = 3;
aNew->zName = sqlite3DbStrDup(db, zName);
if( rc==SQLITE_OK && aNew->zName==0 ){
rc = SQLITE_NOMEM;
}
#if SQLITE_HAS_CODEC
#ifdef SQLITE_HAS_CODEC
if( rc==SQLITE_OK ){
extern int sqlite3CodecAttach(sqlite3*, int, const void*, int);
extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
@ -184,11 +190,9 @@ static void attachFunc(
** we found it.
*/
if( rc==SQLITE_OK ){
(void)sqlite3SafetyOn(db);
sqlite3BtreeEnterAll(db);
rc = sqlite3Init(db, &zErrDyn);
sqlite3BtreeLeaveAll(db);
(void)sqlite3SafetyOff(db);
}
if( rc ){
int iDb = db->nDb - 1;

View File

@ -98,10 +98,10 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
}else{
pParse->db = pDb;
if( sqlite3OpenTempDatabase(pParse) ){
sqlite3ErrorClear(pParse);
sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg);
rc = SQLITE_ERROR;
}
sqlite3DbFree(pErrorDb, pParse->zErrMsg);
sqlite3StackFree(pErrorDb, pParse);
}
if( rc ){

View File

@ -1247,11 +1247,11 @@ static int freeSpace(MemPage *pPage, int start, int size){
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( size>=0 ); /* Minimum cell size is 4 */
#ifdef SQLITE_SECURE_DELETE
/* Overwrite deleted information with zeros when the SECURE_DELETE
** option is enabled at compile-time */
memset(&data[start], 0, size);
#endif
if( pPage->pBt->secureDelete ){
/* Overwrite deleted information with zeros when the secure_delete
** option is enabled */
memset(&data[start], 0, size);
}
/* Add the space back into the linked list of freeblocks. Note that
** even though the freeblock list was checked by btreeInitPage(),
@ -1483,9 +1483,9 @@ static void zeroPage(MemPage *pPage, int flags){
assert( sqlite3PagerGetData(pPage->pDbPage) == data );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( sqlite3_mutex_held(pBt->mutex) );
#ifdef SQLITE_SECURE_DELETE
memset(&data[hdr], 0, pBt->usableSize - hdr);
#endif
if( pBt->secureDelete ){
memset(&data[hdr], 0, pBt->usableSize - hdr);
}
data[hdr] = (char)flags;
first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0);
memset(&data[hdr+1], 0, 4);
@ -1805,6 +1805,9 @@ int sqlite3BtreeOpen(
pBt->pCursor = 0;
pBt->pPage1 = 0;
pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager);
#ifdef SQLITE_SECURE_DELETE
pBt->secureDelete = 1;
#endif
pBt->pageSize = get2byte(&zDbHeader[16]);
if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
|| ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
@ -2161,6 +2164,23 @@ int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
sqlite3BtreeLeave(p);
return n;
}
/*
** Set the secureDelete flag if newFlag is 0 or 1. If newFlag is -1,
** then make no changes. Always return the value of the secureDelete
** setting after the change.
*/
int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
int b;
if( p==0 ) return 0;
sqlite3BtreeEnter(p);
if( newFlag>=0 ){
p->pBt->secureDelete = (newFlag!=0) ? 1 : 0;
}
b = p->pBt->secureDelete;
sqlite3BtreeLeave(p);
return b;
}
#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */
/*
@ -4904,17 +4924,17 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
nFree = get4byte(&pPage1->aData[36]);
put4byte(&pPage1->aData[36], nFree+1);
#ifdef SQLITE_SECURE_DELETE
/* If the SQLITE_SECURE_DELETE compile-time option is enabled, then
** always fully overwrite deleted information with zeros.
*/
if( (!pPage && (rc = btreeGetPage(pBt, iPage, &pPage, 0)))
|| (rc = sqlite3PagerWrite(pPage->pDbPage))
){
goto freepage_out;
if( pBt->secureDelete ){
/* If the secure_delete option is enabled, then
** always fully overwrite deleted information with zeros.
*/
if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
|| ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
){
goto freepage_out;
}
memset(pPage->aData, 0, pPage->pBt->pageSize);
}
memset(pPage->aData, 0, pPage->pBt->pageSize);
#endif
/* If the database supports auto-vacuum, write an entry in the pointer-map
** to indicate that the page is free.
@ -4965,11 +4985,9 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
if( rc==SQLITE_OK ){
put4byte(&pTrunk->aData[4], nLeaf+1);
put4byte(&pTrunk->aData[8+nLeaf*4], iPage);
#ifndef SQLITE_SECURE_DELETE
if( pPage ){
if( pPage && !pBt->secureDelete ){
sqlite3PagerDontWrite(pPage->pDbPage);
}
#endif
rc = btreeSetHasContent(pBt, iPage);
}
TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno));
@ -5043,7 +5061,25 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext);
if( rc ) return rc;
}
rc = freePage2(pBt, pOvfl, ovflPgno);
if( ( pOvfl || ((pOvfl = btreePageLookup(pBt, ovflPgno))!=0) )
&& sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1
){
/* There is no reason any cursor should have an outstanding reference
** to an overflow page belonging to a cell that is being deleted/updated.
** So if there exists more than one reference to this page, then it
** must not really be an overflow page and the database must be corrupt.
** It is helpful to detect this before calling freePage2(), as
** freePage2() may zero the page contents if secure-delete mode is
** enabled. If this 'overflow' page happens to be a page that the
** caller is iterating through or using in some other way, this
** can be problematic.
*/
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = freePage2(pBt, pOvfl, ovflPgno);
}
if( pOvfl ){
sqlite3PagerUnref(pOvfl->pDbPage);
}
@ -5287,7 +5323,7 @@ static void insertCell(
Pgno iChild, /* If non-zero, replace first 4 bytes with this value */
int *pRC /* Read and write return code from here */
){
int idx; /* Where to write new cell content in data[] */
int idx = 0; /* Where to write new cell content in data[] */
int j; /* Loop counter */
int end; /* First byte past the last cell pointer in data[] */
int ins; /* Index in data[] where new cell pointer is inserted */
@ -5778,10 +5814,17 @@ static int balance_nonroot(
** In this case, temporarily copy the cell into the aOvflSpace[]
** buffer. It will be copied out again as soon as the aSpace[] buffer
** is allocated. */
#ifdef SQLITE_SECURE_DELETE
memcpy(&aOvflSpace[apDiv[i]-pParent->aData], apDiv[i], szNew[i]);
apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
#endif
if( pBt->secureDelete ){
int iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
if( (iOff+szNew[i])>pBt->usableSize ){
rc = SQLITE_CORRUPT_BKPT;
memset(apOld, 0, (i+1)*sizeof(MemPage*));
goto balance_cleanup;
}else{
memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
}
}
dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc);
}
}
@ -5901,7 +5944,7 @@ static int balance_nonroot(
if( leafData ){ i--; }
subtotal = 0;
k++;
if( k>NB+1 ){ rc = SQLITE_CORRUPT; goto balance_cleanup; }
if( k>NB+1 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; }
}
}
szNew[k] = subtotal;
@ -5955,7 +5998,7 @@ static int balance_nonroot(
** Allocate k new pages. Reuse old pages where possible.
*/
if( apOld[0]->pgno<=1 ){
rc = SQLITE_CORRUPT;
rc = SQLITE_CORRUPT_BKPT;
goto balance_cleanup;
}
pageFlags = apOld[0]->aData[0];
@ -7393,7 +7436,9 @@ static void checkList(
static int checkTreePage(
IntegrityCk *pCheck, /* Context for the sanity check */
int iPage, /* Page number of the page to check */
char *zParentContext /* Parent context */
char *zParentContext, /* Parent context */
i64 *pnParentMinKey,
i64 *pnParentMaxKey
){
MemPage *pPage;
int i, rc, depth, d2, pgno, cnt;
@ -7404,6 +7449,8 @@ static int checkTreePage(
int usableSize;
char zContext[100];
char *hit = 0;
i64 nMinKey = 0;
i64 nMaxKey = 0;
sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage);
@ -7446,6 +7493,16 @@ static int checkTreePage(
btreeParseCellPtr(pPage, pCell, &info);
sz = info.nData;
if( !pPage->intKey ) sz += (int)info.nKey;
/* For intKey pages, check that the keys are in order.
*/
else if( i==0 ) nMinKey = nMaxKey = info.nKey;
else{
if( info.nKey <= nMaxKey ){
checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey);
}
nMaxKey = info.nKey;
}
assert( sz==info.nPayload );
if( (sz>info.nLocal)
&& (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize])
@ -7469,25 +7526,62 @@ static int checkTreePage(
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
}
#endif
d2 = checkTreePage(pCheck, pgno, zContext);
d2 = checkTreePage(pCheck, pgno, zContext, &nMinKey, i==0 ? NULL : &nMaxKey);
if( i>0 && d2!=depth ){
checkAppendMsg(pCheck, zContext, "Child page depth differs");
}
depth = d2;
}
}
if( !pPage->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
sqlite3_snprintf(sizeof(zContext), zContext,
"On page %d at right child: ", iPage);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0);
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
}
#endif
checkTreePage(pCheck, pgno, zContext);
checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey);
}
/* For intKey leaf pages, check that the min/max keys are in order
** with any left/parent/right pages.
*/
if( pPage->leaf && pPage->intKey ){
/* if we are a left child page */
if( pnParentMinKey ){
/* if we are the left most child page */
if( !pnParentMaxKey ){
if( nMaxKey > *pnParentMinKey ){
checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (max larger than parent min of %lld)",
nMaxKey, *pnParentMinKey);
}
}else{
if( nMinKey <= *pnParentMinKey ){
checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (min less than parent min of %lld)",
nMinKey, *pnParentMinKey);
}
if( nMaxKey > *pnParentMaxKey ){
checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (max larger than parent max of %lld)",
nMaxKey, *pnParentMaxKey);
}
*pnParentMinKey = nMaxKey;
}
/* else if we're a right child page */
} else if( pnParentMaxKey ){
if( nMinKey <= *pnParentMaxKey ){
checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (min less than parent max of %lld)",
nMinKey, *pnParentMaxKey);
}
}
}
/* Check for complete coverage of the page
*/
data = pPage->aData;
@ -7511,7 +7605,7 @@ static int checkTreePage(
}
if( (pc+size-1)>=usableSize ){
checkAppendMsg(pCheck, 0,
"Corruption detected in cell %d on page %d",i,iPage,0);
"Corruption detected in cell %d on page %d",i,iPage);
}else{
for(j=pc+size-1; j>=pc; j--) hit[j]++;
}
@ -7617,7 +7711,7 @@ char *sqlite3BtreeIntegrityCheck(
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0);
}
#endif
checkTreePage(&sCheck, aRoot[i], "List of tree roots: ");
checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL);
}
/* Make sure every page in the file is referenced

View File

@ -81,6 +81,7 @@ int sqlite3BtreeSyncDisabled(Btree*);
int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
int sqlite3BtreeGetPageSize(Btree*);
int sqlite3BtreeMaxPageCount(Btree*,int);
int sqlite3BtreeSecureDelete(Btree*,int);
int sqlite3BtreeGetReserve(Btree*);
int sqlite3BtreeSetAutoVacuum(Btree *, int);
int sqlite3BtreeGetAutoVacuum(Btree *);

View File

@ -407,6 +407,7 @@ struct BtShared {
MemPage *pPage1; /* First page of the database */
u8 readOnly; /* True if the underlying file is readonly */
u8 pageSizeFixed; /* True if the page size can no longer be changed */
u8 secureDelete; /* True if secure_delete is enabled */
#ifndef SQLITE_OMIT_AUTOVACUUM
u8 autoVacuum; /* True if auto-vacuum is enabled */
u8 incrVacuum; /* True if incr-vacuum is enabled */

View File

@ -202,7 +202,7 @@ void sqlite3FinishCoding(Parse *pParse){
pParse->isMultiWrite && pParse->mayAbort);
pParse->rc = SQLITE_DONE;
pParse->colNamesSet = 0;
}else if( pParse->rc==SQLITE_OK ){
}else{
pParse->rc = SQLITE_ERROR;
}
pParse->nTab = 0;
@ -549,7 +549,8 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
assert( db!=0 );
assert( iDb>=0 && iDb<db->nDb );
assert( zTabName && zTabName[0] );
assert( zTabName );
testcase( zTabName[0]==0 ); /* Zero-length table names are allowed */
pDb = &db->aDb[iDb];
p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName,
sqlite3Strlen30(zTabName),0);
@ -1973,13 +1974,12 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
}
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
if( noErr ) db->suppressErr++;
pTab = sqlite3LocateTable(pParse, isView,
pName->a[0].zName, pName->a[0].zDatabase);
if( noErr ) db->suppressErr--;
if( pTab==0 ){
if( noErr ){
sqlite3ErrorClear(pParse);
}
goto exit_drop_table;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@ -3401,6 +3401,7 @@ int sqlite3OpenTempDatabase(Parse *pParse){
sqlite3 *db = pParse->db;
if( db->aDb[1].pBt==0 && !pParse->explain ){
int rc;
Btree *pBt;
static const int flags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
@ -3408,18 +3409,20 @@ int sqlite3OpenTempDatabase(Parse *pParse){
SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_TEMP_DB;
rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags,
&db->aDb[1].pBt);
rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags, &pBt);
if( rc!=SQLITE_OK ){
sqlite3ErrorMsg(pParse, "unable to open a temporary database "
"file for storing temporary tables");
pParse->rc = rc;
return 1;
}
assert( (db->flags & SQLITE_InTrans)==0 || db->autoCommit );
db->aDb[1].pBt = pBt;
assert( db->aDb[1].pSchema );
sqlite3PagerJournalMode(sqlite3BtreePager(db->aDb[1].pBt),
db->dfltJournalMode);
if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){
db->mallocFailed = 1;
return 1;
}
sqlite3PagerJournalMode(sqlite3BtreePager(pBt), db->dfltJournalMode);
}
return 0;
}

View File

@ -40,11 +40,13 @@ extern const char sqlite3IsEbcdicIdChar[];
#define tkSEMI 0
#define tkWS 1
#define tkOTHER 2
#ifndef SQLITE_OMIT_TRIGGER
#define tkEXPLAIN 3
#define tkCREATE 4
#define tkTEMP 5
#define tkTRIGGER 6
#define tkEND 7
#endif
/*
** Return TRUE if the given SQL string ends in a semicolon.
@ -53,36 +55,38 @@ extern const char sqlite3IsEbcdicIdChar[];
** Whenever the CREATE TRIGGER keywords are seen, the statement
** must end with ";END;".
**
** This implementation uses a state machine with 7 states:
** This implementation uses a state machine with 8 states:
**
** (0) START At the beginning or end of an SQL statement. This routine
** (0) INVALID We have not yet seen a non-whitespace character.
**
** (1) START At the beginning or end of an SQL statement. This routine
** returns 1 if it ends in the START state and 0 if it ends
** in any other state.
**
** (1) NORMAL We are in the middle of statement which ends with a single
** (2) NORMAL We are in the middle of statement which ends with a single
** semicolon.
**
** (2) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
** a statement.
**
** (3) CREATE The keyword CREATE has been seen at the beginning of a
** (4) CREATE The keyword CREATE has been seen at the beginning of a
** statement, possibly preceeded by EXPLAIN and/or followed by
** TEMP or TEMPORARY
**
** (4) TRIGGER We are in the middle of a trigger definition that must be
** (5) TRIGGER We are in the middle of a trigger definition that must be
** ended by a semicolon, the keyword END, and another semicolon.
**
** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at
** (6) SEMI We've seen the first semicolon in the ";END;" that occurs at
** the end of a trigger definition.
**
** (6) END We've seen the ";END" of the ";END;" that occurs at the end
** (7) END We've seen the ";END" of the ";END;" that occurs at the end
** of a trigger difinition.
**
** Transitions between states above are determined by tokens extracted
** from the input. The following tokens are significant:
**
** (0) tkSEMI A semicolon.
** (1) tkWS Whitespace
** (1) tkWS Whitespace.
** (2) tkOTHER Any other SQL token.
** (3) tkEXPLAIN The "explain" keyword.
** (4) tkCREATE The "create" keyword.
@ -91,6 +95,7 @@ extern const char sqlite3IsEbcdicIdChar[];
** (7) tkEND The "end" keyword.
**
** Whitespace never causes a state transition and is always ignored.
** This means that a SQL string of all whitespace is invalid.
**
** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed
** to recognize the end of a trigger can be omitted. All we have to do
@ -104,26 +109,28 @@ int sqlite3_complete(const char *zSql){
/* A complex statement machine used to detect the end of a CREATE TRIGGER
** statement. This is the normal case.
*/
static const u8 trans[7][8] = {
static const u8 trans[8][8] = {
/* Token: */
/* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */
/* 0 START: */ { 0, 0, 1, 2, 3, 1, 1, 1, },
/* 1 NORMAL: */ { 0, 1, 1, 1, 1, 1, 1, 1, },
/* 2 EXPLAIN: */ { 0, 2, 2, 1, 3, 1, 1, 1, },
/* 3 CREATE: */ { 0, 3, 1, 1, 1, 3, 4, 1, },
/* 4 TRIGGER: */ { 5, 4, 4, 4, 4, 4, 4, 4, },
/* 5 SEMI: */ { 5, 5, 4, 4, 4, 4, 4, 6, },
/* 6 END: */ { 0, 6, 4, 4, 4, 4, 4, 4, },
/* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */
/* 0 INVALID: */ { 1, 0, 2, 3, 4, 2, 2, 2, },
/* 1 START: */ { 1, 1, 2, 3, 4, 2, 2, 2, },
/* 2 NORMAL: */ { 1, 2, 2, 2, 2, 2, 2, 2, },
/* 3 EXPLAIN: */ { 1, 3, 3, 2, 4, 2, 2, 2, },
/* 4 CREATE: */ { 1, 4, 2, 2, 2, 4, 5, 2, },
/* 5 TRIGGER: */ { 6, 5, 5, 5, 5, 5, 5, 5, },
/* 6 SEMI: */ { 6, 6, 5, 5, 5, 5, 5, 7, },
/* 7 END: */ { 1, 7, 5, 5, 5, 5, 5, 5, },
};
#else
/* If triggers are not suppored by this compile then the statement machine
/* If triggers are not supported by this compile then the statement machine
** used to detect the end of a statement is much simplier
*/
static const u8 trans[2][3] = {
static const u8 trans[3][3] = {
/* Token: */
/* State: ** SEMI WS OTHER */
/* 0 START: */ { 0, 0, 1, },
/* 1 NORMAL: */ { 0, 1, 1, },
/* 0 INVALID: */ { 1, 0, 2, },
/* 1 START: */ { 1, 1, 2, },
/* 2 NORMAL: */ { 1, 2, 2, },
};
#endif /* SQLITE_OMIT_TRIGGER */
@ -159,7 +166,7 @@ int sqlite3_complete(const char *zSql){
break;
}
while( *zSql && *zSql!='\n' ){ zSql++; }
if( *zSql==0 ) return state==0;
if( *zSql==0 ) return state==1;
token = tkWS;
break;
}
@ -243,7 +250,7 @@ int sqlite3_complete(const char *zSql){
state = trans[state][token];
zSql++;
}
return state==0;
return state==1;
}
#ifndef SQLITE_OMIT_UTF16

385
src/ctime.c Normal file
View File

@ -0,0 +1,385 @@
/*
** 2010 February 23
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file implements routines used to report what compile-time options
** SQLite was built with.
*/
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
#include "sqliteInt.h"
/*
** An array of names of all compile-time options. This array should
** be sorted A-Z.
**
** This array looks large, but in a typical installation actually uses
** only a handful of compile-time options, so most times this array is usually
** rather short and uses little memory space.
*/
static const char * const azCompileOpt[] = {
/* These macros are provided to "stringify" the value of the define
** for those options in which the value is meaningful. */
#define CTIMEOPT_VAL_(opt) #opt
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
#ifdef SQLITE_32BIT_ROWID
"32BIT_ROWID",
#endif
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
"4_BYTE_ALIGNED_MALLOC",
#endif
#ifdef SQLITE_CASE_SENSITIVE_LIKE
"CASE_SENSITIVE_LIKE",
#endif
#ifdef SQLITE_CHECK_PAGES
"CHECK_PAGES",
#endif
#ifdef SQLITE_COVERAGE_TEST
"COVERAGE_TEST",
#endif
#ifdef SQLITE_DEBUG
"DEBUG",
#endif
#ifdef SQLITE_DEFAULT_LOCKING_MODE
"DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
#endif
#ifdef SQLITE_DISABLE_DIRSYNC
"DISABLE_DIRSYNC",
#endif
#ifdef SQLITE_DISABLE_LFS
"DISABLE_LFS",
#endif
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
"ENABLE_ATOMIC_WRITE",
#endif
#ifdef SQLITE_ENABLE_CEROD
"ENABLE_CEROD",
#endif
#ifdef SQLITE_ENABLE_COLUMN_METADATA
"ENABLE_COLUMN_METADATA",
#endif
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
"ENABLE_EXPENSIVE_ASSERT",
#endif
#ifdef SQLITE_ENABLE_FTS1
"ENABLE_FTS1",
#endif
#ifdef SQLITE_ENABLE_FTS2
"ENABLE_FTS2",
#endif
#ifdef SQLITE_ENABLE_FTS3
"ENABLE_FTS3",
#endif
#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
"ENABLE_FTS3_PARENTHESIS",
#endif
#ifdef SQLITE_ENABLE_FTS4
"ENABLE_FTS4",
#endif
#ifdef SQLITE_ENABLE_ICU
"ENABLE_ICU",
#endif
#ifdef SQLITE_ENABLE_IOTRACE
"ENABLE_IOTRACE",
#endif
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
"ENABLE_LOAD_EXTENSION",
#endif
#ifdef SQLITE_ENABLE_LOCKING_STYLE
"ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
#endif
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
"ENABLE_MEMORY_MANAGEMENT",
#endif
#ifdef SQLITE_ENABLE_MEMSYS3
"ENABLE_MEMSYS3",
#endif
#ifdef SQLITE_ENABLE_MEMSYS5
"ENABLE_MEMSYS5",
#endif
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
"ENABLE_OVERSIZE_CELL_CHECK",
#endif
#ifdef SQLITE_ENABLE_RTREE
"ENABLE_RTREE",
#endif
#ifdef SQLITE_ENABLE_STAT2
"ENABLE_STAT2",
#endif
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
"ENABLE_UNLOCK_NOTIFY",
#endif
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
"ENABLE_UPDATE_DELETE_LIMIT",
#endif
#ifdef SQLITE_HAS_CODEC
"HAS_CODEC",
#endif
#ifdef SQLITE_HAVE_ISNAN
"HAVE_ISNAN",
#endif
#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
"HOMEGROWN_RECURSIVE_MUTEX",
#endif
#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
"IGNORE_AFP_LOCK_ERRORS",
#endif
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
"IGNORE_FLOCK_LOCK_ERRORS",
#endif
#ifdef SQLITE_INT64_TYPE
"INT64_TYPE",
#endif
#ifdef SQLITE_LOCK_TRACE
"LOCK_TRACE",
#endif
#ifdef SQLITE_MEMDEBUG
"MEMDEBUG",
#endif
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
"MIXED_ENDIAN_64BIT_FLOAT",
#endif
#ifdef SQLITE_NO_SYNC
"NO_SYNC",
#endif
#ifdef SQLITE_OMIT_ALTERTABLE
"OMIT_ALTERTABLE",
#endif
#ifdef SQLITE_OMIT_ANALYZE
"OMIT_ANALYZE",
#endif
#ifdef SQLITE_OMIT_ATTACH
"OMIT_ATTACH",
#endif
#ifdef SQLITE_OMIT_AUTHORIZATION
"OMIT_AUTHORIZATION",
#endif
#ifdef SQLITE_OMIT_AUTOINCREMENT
"OMIT_AUTOINCREMENT",
#endif
#ifdef SQLITE_OMIT_AUTOINIT
"OMIT_AUTOINIT",
#endif
#ifdef SQLITE_OMIT_AUTOVACUUM
"OMIT_AUTOVACUUM",
#endif
#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
"OMIT_BETWEEN_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_BLOB_LITERAL
"OMIT_BLOB_LITERAL",
#endif
#ifdef SQLITE_OMIT_BTREECOUNT
"OMIT_BTREECOUNT",
#endif
#ifdef SQLITE_OMIT_BUILTIN_TEST
"OMIT_BUILTIN_TEST",
#endif
#ifdef SQLITE_OMIT_CAST
"OMIT_CAST",
#endif
#ifdef SQLITE_OMIT_CHECK
"OMIT_CHECK",
#endif
#ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS
"OMIT_COMPILEOPTION_DIAGS",
#endif
#ifdef SQLITE_OMIT_COMPLETE
"OMIT_COMPLETE",
#endif
#ifdef SQLITE_OMIT_COMPOUND_SELECT
"OMIT_COMPOUND_SELECT",
#endif
#ifdef SQLITE_OMIT_DATETIME_FUNCS
"OMIT_DATETIME_FUNCS",
#endif
#ifdef SQLITE_OMIT_DECLTYPE
"OMIT_DECLTYPE",
#endif
#ifdef SQLITE_OMIT_DEPRECATED
"OMIT_DEPRECATED",
#endif
#ifdef SQLITE_OMIT_DISKIO
"OMIT_DISKIO",
#endif
#ifdef SQLITE_OMIT_EXPLAIN
"OMIT_EXPLAIN",
#endif
#ifdef SQLITE_OMIT_FLAG_PRAGMAS
"OMIT_FLAG_PRAGMAS",
#endif
#ifdef SQLITE_OMIT_FLOATING_POINT
"OMIT_FLOATING_POINT",
#endif
#ifdef SQLITE_OMIT_FOREIGN_KEY
"OMIT_FOREIGN_KEY",
#endif
#ifdef SQLITE_OMIT_GET_TABLE
"OMIT_GET_TABLE",
#endif
#ifdef SQLITE_OMIT_GLOBALRECOVER
"OMIT_GLOBALRECOVER",
#endif
#ifdef SQLITE_OMIT_INCRBLOB
"OMIT_INCRBLOB",
#endif
#ifdef SQLITE_OMIT_INTEGRITY_CHECK
"OMIT_INTEGRITY_CHECK",
#endif
#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
"OMIT_LIKE_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_LOAD_EXTENSION
"OMIT_LOAD_EXTENSION",
#endif
#ifdef SQLITE_OMIT_LOCALTIME
"OMIT_LOCALTIME",
#endif
#ifdef SQLITE_OMIT_LOOKASIDE
"OMIT_LOOKASIDE",
#endif
#ifdef SQLITE_OMIT_MEMORYDB
"OMIT_MEMORYDB",
#endif
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
"OMIT_OR_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_PAGER_PRAGMAS
"OMIT_PAGER_PRAGMAS",
#endif
#ifdef SQLITE_OMIT_PRAGMA
"OMIT_PRAGMA",
#endif
#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
"OMIT_PROGRESS_CALLBACK",
#endif
#ifdef SQLITE_OMIT_QUICKBALANCE
"OMIT_QUICKBALANCE",
#endif
#ifdef SQLITE_OMIT_REINDEX
"OMIT_REINDEX",
#endif
#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
"OMIT_SCHEMA_PRAGMAS",
#endif
#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
"OMIT_SCHEMA_VERSION_PRAGMAS",
#endif
#ifdef SQLITE_OMIT_SHARED_CACHE
"OMIT_SHARED_CACHE",
#endif
#ifdef SQLITE_OMIT_SUBQUERY
"OMIT_SUBQUERY",
#endif
#ifdef SQLITE_OMIT_TCL_VARIABLE
"OMIT_TCL_VARIABLE",
#endif
#ifdef SQLITE_OMIT_TEMPDB
"OMIT_TEMPDB",
#endif
#ifdef SQLITE_OMIT_TRACE
"OMIT_TRACE",
#endif
#ifdef SQLITE_OMIT_TRIGGER
"OMIT_TRIGGER",
#endif
#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
"OMIT_TRUNCATE_OPTIMIZATION",
#endif
#ifdef SQLITE_OMIT_UTF16
"OMIT_UTF16",
#endif
#ifdef SQLITE_OMIT_VACUUM
"OMIT_VACUUM",
#endif
#ifdef SQLITE_OMIT_VIEW
"OMIT_VIEW",
#endif
#ifdef SQLITE_OMIT_VIRTUALTABLE
"OMIT_VIRTUALTABLE",
#endif
#ifdef SQLITE_OMIT_WSD
"OMIT_WSD",
#endif
#ifdef SQLITE_OMIT_XFER_OPT
"OMIT_XFER_OPT",
#endif
#ifdef SQLITE_PERFORMANCE_TRACE
"PERFORMANCE_TRACE",
#endif
#ifdef SQLITE_PROXY_DEBUG
"PROXY_DEBUG",
#endif
#ifdef SQLITE_SECURE_DELETE
"SECURE_DELETE",
#endif
#ifdef SQLITE_SMALL_STACK
"SMALL_STACK",
#endif
#ifdef SQLITE_SOUNDEX
"SOUNDEX",
#endif
#ifdef SQLITE_TCL
"TCL",
#endif
#ifdef SQLITE_TEMP_STORE
"TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
#endif
#ifdef SQLITE_TEST
"TEST",
#endif
#ifdef SQLITE_THREADSAFE
"THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
#endif
#ifdef SQLITE_USE_ALLOCA
"USE_ALLOCA",
#endif
#ifdef SQLITE_ZERO_MALLOC
"ZERO_MALLOC"
#endif
};
/*
** Given the name of a compile-time option, return true if that option
** was used and false if not.
**
** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
** is not required for a match.
*/
int sqlite3_compileoption_used(const char *zOptName){
int i, n;
if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
n = sqlite3Strlen30(zOptName);
/* Since ArraySize(azCompileOpt) is normally in single digits, a
** linear search is adequate. No need for a binary search. */
for(i=0; i<ArraySize(azCompileOpt); i++){
if( (sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0)
&& ( (azCompileOpt[i][n]==0) || (azCompileOpt[i][n]=='=') ) ) return 1;
}
return 0;
}
/*
** Return the N-th compile-time option string. If N is out of range,
** return a NULL pointer.
*/
const char *sqlite3_compileoption_get(int N){
if( N>=0 && N<ArraySize(azCompileOpt) ){
return azCompileOpt[N];
}
return 0;
}
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */

View File

@ -1092,8 +1092,8 @@ void sqlite3RegisterDateTimeFunctions(void){
FUNCTION(current_date, 0, 0, 0, cdateFunc ),
#else
STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc),
STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d", 0, currentTimeFunc),
STR_FUNCTION(current_date, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc),
STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
#endif
};
int i;

View File

@ -364,7 +364,7 @@ void sqlite3DeleteFrom(
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK);
if( pWInfo==0 ) goto delete_from_cleanup;
regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0);
regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid);
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
if( db->flags & SQLITE_CountRows ){
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
@ -630,7 +630,6 @@ int sqlite3GenerateIndexKey(
if( doMakeRec ){
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), 0);
sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1);
}
sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
return regBase;

View File

@ -227,30 +227,6 @@ CollSeq *sqlite3BinaryCompareCollSeq(
return pColl;
}
/*
** Generate the operands for a comparison operation. Before
** generating the code for each operand, set the EP_AnyAff
** flag on the expression so that it will be able to used a
** cached column value that has previously undergone an
** affinity change.
*/
static void codeCompareOperands(
Parse *pParse, /* Parsing and code generating context */
Expr *pLeft, /* The left operand */
int *pRegLeft, /* Register where left operand is stored */
int *pFreeLeft, /* Free this register when done */
Expr *pRight, /* The right operand */
int *pRegRight, /* Register where right operand is stored */
int *pFreeRight /* Write temp register for right operand there */
){
while( pLeft->op==TK_UPLUS ) pLeft = pLeft->pLeft;
pLeft->flags |= EP_AnyAff;
*pRegLeft = sqlite3ExprCodeTemp(pParse, pLeft, pFreeLeft);
while( pRight->op==TK_UPLUS ) pRight = pRight->pLeft;
pRight->flags |= EP_AnyAff;
*pRegRight = sqlite3ExprCodeTemp(pParse, pRight, pFreeRight);
}
/*
** Generate code for a comparison operator.
*/
@ -272,10 +248,6 @@ static int codeCompare(
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
(void*)p4, P4_COLLSEQ);
sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5);
if( (p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_NONE ){
sqlite3ExprCacheAffinityChange(pParse, in1, 1);
sqlite3ExprCacheAffinityChange(pParse, in2, 1);
}
return addr;
}
@ -1906,6 +1878,7 @@ static char *dup8bytes(Vdbe *v, const char *in){
return out;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Generate an instruction that will put the floating point
** value described by z[0..n-1] into register iMem.
@ -1925,6 +1898,7 @@ static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL);
}
}
#endif
/*
@ -1935,7 +1909,8 @@ static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
** z[n] character is guaranteed to be something that does not look
** like the continuation of the number.
*/
static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){
static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
Vdbe *v = pParse->pVdbe;
if( pExpr->flags & EP_IntValue ){
int i = pExpr->u.iValue;
if( negFlag ) i = -i;
@ -1951,7 +1926,11 @@ static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){
zV = dup8bytes(v, (char*)&value);
sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
}else{
#ifdef SQLITE_OMIT_FLOATING_POINT
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
#else
codeReal(v, z, negFlag, iMem);
#endif
}
}
}
@ -1982,17 +1961,31 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
assert( iReg>0 ); /* Register numbers are always positive */
assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */
/* First replace any existing entry */
/* The SQLITE_ColumnCache flag disables the column cache. This is used
** for testing only - to verify that SQLite always gets the same answer
** with and without the column cache.
*/
if( pParse->db->flags & SQLITE_ColumnCache ) return;
/* First replace any existing entry.
**
** Actually, the way the column cache is currently used, we are guaranteed
** that the object will never already be in cache. Verify this guarantee.
*/
#ifndef NDEBUG
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
#if 0 /* This code wold remove the entry from the cache if it existed */
if( p->iReg && p->iTable==iTab && p->iColumn==iCol ){
cacheEntryClear(pParse, p);
p->iLevel = pParse->iCacheLevel;
p->iReg = iReg;
p->affChange = 0;
p->lru = pParse->iCacheCnt++;
return;
}
#endif
assert( p->iReg==0 || p->iTable!=iTab || p->iColumn!=iCol );
}
#endif
/* Find an empty slot and replace it */
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
@ -2001,7 +1994,6 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
p->iTable = iTab;
p->iColumn = iCol;
p->iReg = iReg;
p->affChange = 0;
p->tempReg = 0;
p->lru = pParse->iCacheCnt++;
return;
@ -2023,7 +2015,6 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
p->iTable = iTab;
p->iColumn = iCol;
p->iReg = iReg;
p->affChange = 0;
p->tempReg = 0;
p->lru = pParse->iCacheCnt++;
return;
@ -2031,14 +2022,16 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
}
/*
** Indicate that a register is being overwritten. Purge the register
** from the column cache.
** Indicate that registers between iReg..iReg+nReg-1 are being overwritten.
** Purge the range of registers from the column cache.
*/
void sqlite3ExprCacheRemove(Parse *pParse, int iReg){
void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){
int i;
int iLast = iReg + nReg - 1;
struct yColCache *p;
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
if( p->iReg==iReg ){
int r = p->iReg;
if( r>=iReg && r<=iLast ){
cacheEntryClear(pParse, p);
p->iReg = 0;
}
@ -2097,28 +2090,20 @@ static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
**
** There must be an open cursor to pTab in iTable when this routine
** is called. If iColumn<0 then code is generated that extracts the rowid.
**
** This routine might attempt to reuse the value of the column that
** has already been loaded into a register. The value will always
** be used if it has not undergone any affinity changes. But if
** an affinity change has occurred, then the cached value will only be
** used if allowAffChng is true.
*/
int sqlite3ExprCodeGetColumn(
Parse *pParse, /* Parsing and code generating context */
Table *pTab, /* Description of the table we are reading from */
int iColumn, /* Index of the table column */
int iTable, /* The cursor pointing to the table */
int iReg, /* Store results here */
int allowAffChng /* True if prior affinity changes are OK */
int iReg /* Store results here */
){
Vdbe *v = pParse->pVdbe;
int i;
struct yColCache *p;
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn
&& (!p->affChange || allowAffChng) ){
if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn ){
p->lru = pParse->iCacheCnt++;
sqlite3ExprCachePinRegister(pParse, p->iReg);
return p->iReg;
@ -2156,15 +2141,7 @@ void sqlite3ExprCacheClear(Parse *pParse){
** registers starting with iStart.
*/
void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
int iEnd = iStart + iCount - 1;
int i;
struct yColCache *p;
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
int r = p->iReg;
if( r>=iStart && r<=iEnd ){
p->affChange = 1;
}
}
sqlite3ExprCacheRemove(pParse, iStart, iCount);
}
/*
@ -2196,19 +2173,24 @@ void sqlite3ExprCodeCopy(Parse *pParse, int iFrom, int iTo, int nReg){
}
}
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
/*
** Return true if any register in the range iFrom..iTo (inclusive)
** is used as part of the column cache.
**
** This routine is used within assert() and testcase() macros only
** and does not appear in a normal build.
*/
static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
int i;
struct yColCache *p;
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
int r = p->iReg;
if( r>=iFrom && r<=iTo ) return 1;
if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/
}
return 0;
}
#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */
/*
** If the last instruction coded is an ephemeral copy of any of
@ -2329,22 +2311,22 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
assert( pParse->ckBase>0 );
inReg = pExpr->iColumn + pParse->ckBase;
}else{
testcase( (pExpr->flags & EP_AnyAff)!=0 );
inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
pExpr->iColumn, pExpr->iTable, target,
pExpr->flags & EP_AnyAff);
pExpr->iColumn, pExpr->iTable, target);
}
break;
}
case TK_INTEGER: {
codeInteger(v, pExpr, 0, target);
codeInteger(pParse, pExpr, 0, target);
break;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
case TK_FLOAT: {
assert( !ExprHasProperty(pExpr, EP_IntValue) );
codeReal(v, pExpr->u.zToken, 0, target);
break;
}
#endif
case TK_STRING: {
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0);
@ -2449,8 +2431,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
testcase( op==TK_GE );
testcase( op==TK_EQ );
testcase( op==TK_NE );
codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
pExpr->pRight, &r2, &regFree2);
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, inReg, SQLITE_STOREP2);
testcase( regFree1==0 );
@ -2461,8 +2443,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
case TK_ISNOT: {
testcase( op==TK_IS );
testcase( op==TK_ISNOT );
codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
pExpr->pRight, &r2, &regFree2);
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
op = (op==TK_IS) ? TK_EQ : TK_NE;
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ);
@ -2514,11 +2496,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
case TK_UMINUS: {
Expr *pLeft = pExpr->pLeft;
assert( pLeft );
if( pLeft->op==TK_FLOAT ){
if( pLeft->op==TK_INTEGER ){
codeInteger(pParse, pLeft, 1, target);
#ifndef SQLITE_OMIT_FLOATING_POINT
}else if( pLeft->op==TK_FLOAT ){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
codeReal(v, pLeft->u.zToken, 1, target);
}else if( pLeft->op==TK_INTEGER ){
codeInteger(v, pLeft, 1, target);
#endif
}else{
regFree1 = r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Integer, 0, r1);
@ -2606,7 +2590,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
for(i=1; i<nFarg; i++){
sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
sqlite3ExprCacheRemove(pParse, target);
sqlite3ExprCacheRemove(pParse, target, 1);
sqlite3ExprCachePush(pParse);
sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
sqlite3ExprCachePop(pParse, 1);
@ -2661,7 +2645,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
if( nFarg ){
sqlite3ReleaseTempRange(pParse, r1, nFarg);
}
sqlite3ExprCacheAffinityChange(pParse, r1, nFarg);
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
@ -2702,8 +2685,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
struct ExprList_item *pLItem = pExpr->x.pList->a;
Expr *pRight = pLItem->pExpr;
codeCompareOperands(pParse, pLeft, &r1, &regFree1,
pRight, &r2, &regFree2);
r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pRight, &regFree2);
testcase( regFree1==0 );
testcase( regFree2==0 );
r3 = sqlite3GetTempReg(pParse);
@ -2767,6 +2750,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
target
));
#ifndef SQLITE_OMIT_FLOATING_POINT
/* If the column has REAL affinity, it may currently be stored as an
** integer. Use OP_RealAffinity to make sure it is really real. */
if( pExpr->iColumn>=0
@ -2774,6 +2758,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
){
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
}
#endif
break;
}
@ -3238,8 +3223,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( op==TK_EQ );
testcase( op==TK_NE );
testcase( jumpIfNull==0 );
codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
pExpr->pRight, &r2, &regFree2);
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull);
testcase( regFree1==0 );
@ -3250,8 +3235,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_ISNOT: {
testcase( op==TK_IS );
testcase( op==TK_ISNOT );
codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
pExpr->pRight, &r2, &regFree2);
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
op = (op==TK_IS) ? TK_EQ : TK_NE;
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, SQLITE_NULLEQ);
@ -3381,8 +3366,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( op==TK_EQ );
testcase( op==TK_NE );
testcase( jumpIfNull==0 );
codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
pExpr->pRight, &r2, &regFree2);
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull);
testcase( regFree1==0 );
@ -3393,8 +3378,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_ISNOT: {
testcase( pExpr->op==TK_IS );
testcase( pExpr->op==TK_ISNOT );
codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
pExpr->pRight, &r2, &regFree2);
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, SQLITE_NULLEQ);
@ -3439,57 +3424,61 @@ 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.
** Do a deep comparison of two expression trees. Return 0 if the two
** expressions are completely identical. Return 1 if they differ only
** by a COLLATE operator at the top level. Return 2 if there are differences
** other than the top-level COLLATE operator.
**
** Sometimes this routine will return FALSE even if the two expressions
** Sometimes this routine will return 2 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
** identical, we return 2 just to be safe. So if this routine
** returns 2, then you do not really know for certain if the two
** expressions are the same. But if you get a 0 or 1 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
** this routine is used, it does not hurt to get an extra 2 - that
** just might result in some slightly slower code. But returning
** an incorrect TRUE could lead to a malfunction.
** an incorrect 0 or 1 could lead to a malfunction.
*/
int sqlite3ExprCompare(Expr *pA, Expr *pB){
int i;
if( pA==0||pB==0 ){
return pB==pA;
return pB==pA ? 0 : 2;
}
assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
return 0;
return 2;
}
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0;
if( pA->op!=pB->op ) return 0;
if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0;
if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0;
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
if( pA->op!=pB->op ) return 2;
if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
if( pA->x.pList && pB->x.pList ){
if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 0;
if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 2;
for(i=0; i<pA->x.pList->nExpr; i++){
Expr *pExprA = pA->x.pList->a[i].pExpr;
Expr *pExprB = pB->x.pList->a[i].pExpr;
if( !sqlite3ExprCompare(pExprA, pExprB) ) return 0;
if( sqlite3ExprCompare(pExprA, pExprB) ) return 2;
}
}else if( pA->x.pList || pB->x.pList ){
return 0;
return 2;
}
if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0;
if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2;
if( ExprHasProperty(pA, EP_IntValue) ){
if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
return 0;
return 2;
}
}else if( pA->op!=TK_COLUMN && pA->u.zToken ){
if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 0;
if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ){
return 0;
return 2;
}
}
return 1;
if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1;
if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2;
return 0;
}
@ -3620,7 +3609,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
if( sqlite3ExprCompare(pItem->pExpr, pExpr) ){
if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){
break;
}
}
@ -3741,7 +3730,8 @@ int sqlite3GetTempRange(Parse *pParse, int nReg){
int i, n;
i = pParse->iRangeReg;
n = pParse->nRangeReg;
if( nReg<=n && !usedAsColumnCache(pParse, i, i+n-1) ){
if( nReg<=n ){
assert( !usedAsColumnCache(pParse, i, i+n-1) );
pParse->iRangeReg += nReg;
pParse->nRangeReg -= nReg;
}else{
@ -3751,6 +3741,7 @@ int sqlite3GetTempRange(Parse *pParse, int nReg){
return i;
}
void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
sqlite3ExprCacheRemove(pParse, iReg, nReg);
if( nReg>pParse->nRangeReg ){
pParse->nRangeReg = nReg;
pParse->iRangeReg = iReg;

View File

@ -117,7 +117,10 @@ static void lengthFunc(
}
/*
** Implementation of the abs() function
** Implementation of the abs() function.
**
** IMP: R-23979-26855 The abs(X) function returns the absolute value of
** the numeric argument X.
*/
static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
assert( argc==1 );
@ -127,6 +130,9 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
i64 iVal = sqlite3_value_int64(argv[0]);
if( iVal<0 ){
if( (iVal<<1)==0 ){
/* IMP: R-35460-15084 If X is the integer -9223372036854775807 then
** abs(X) throws an integer overflow error since there is no
** equivalent positive 64-bit two complement value. */
sqlite3_result_error(context, "integer overflow", -1);
return;
}
@ -136,10 +142,16 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
break;
}
case SQLITE_NULL: {
/* IMP: R-37434-19929 Abs(X) returns NULL if X is NULL. */
sqlite3_result_null(context);
break;
}
default: {
/* Because sqlite3_value_double() returns 0.0 if the argument is not
** something that can be converted into a number, we have:
** IMP: R-57326-31541 Abs(X) return 0.0 if X is a string or blob that
** cannot be converted to a numeric value.
*/
double rVal = sqlite3_value_double(argv[0]);
if( rVal<0 ) rVal = -rVal;
sqlite3_result_double(context, rVal);
@ -259,14 +271,24 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
}
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
r = sqlite3_value_double(argv[0]);
zBuf = sqlite3_mprintf("%.*f",n,r);
if( zBuf==0 ){
sqlite3_result_error_nomem(context);
/* If Y==0 and X will fit in a 64-bit int,
** handle the rounding directly,
** otherwise use printf.
*/
if( n==0 && r>=0 && r<LARGEST_INT64-1 ){
r = (double)((sqlite_int64)(r+0.5));
}else if( n==0 && r<0 && (-r)<LARGEST_INT64-1 ){
r = -(double)((sqlite_int64)((-r)+0.5));
}else{
zBuf = sqlite3_mprintf("%.*f",n,r);
if( zBuf==0 ){
sqlite3_result_error_nomem(context);
return;
}
sqlite3AtoF(zBuf, &r);
sqlite3_free(zBuf);
sqlite3_result_double(context, r);
}
sqlite3_result_double(context, r);
}
#endif
@ -428,12 +450,18 @@ static void last_insert_rowid(
){
sqlite3 *db = sqlite3_context_db_handle(context);
UNUSED_PARAMETER2(NotUsed, NotUsed2);
/* IMP: R-51513-12026 The last_insert_rowid() SQL function is a
** wrapper around the sqlite3_last_insert_rowid() C/C++ interface
** function. */
sqlite3_result_int64(context, sqlite3_last_insert_rowid(db));
}
/*
** Implementation of the changes() SQL function. The return value is the
** same as the sqlite3_changes() API function.
** Implementation of the changes() SQL function.
**
** IMP: R-62073-11209 The changes() SQL function is a wrapper
** around the sqlite3_changes() C/C++ function and hence follows the same
** rules for counting changes.
*/
static void changes(
sqlite3_context *context,
@ -456,6 +484,8 @@ static void total_changes(
){
sqlite3 *db = sqlite3_context_db_handle(context);
UNUSED_PARAMETER2(NotUsed, NotUsed2);
/* IMP: R-52756-41993 This function is a wrapper around the
** sqlite3_total_changes() C/C++ interface. */
sqlite3_result_int(context, sqlite3_total_changes(db));
}
@ -723,7 +753,9 @@ static void versionFunc(
sqlite3_value **NotUsed2
){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);
/* IMP: R-48699-48617 This function is an SQL wrapper around the
** sqlite3_libversion() C-interface. */
sqlite3_result_text(context, sqlite3_libversion(), -1, SQLITE_STATIC);
}
/*
@ -737,9 +769,54 @@ static void sourceidFunc(
sqlite3_value **NotUsed2
){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_result_text(context, SQLITE_SOURCE_ID, -1, SQLITE_STATIC);
/* IMP: R-24470-31136 This function is an SQL wrapper around the
** sqlite3_sourceid() C interface. */
sqlite3_result_text(context, sqlite3_sourceid(), -1, SQLITE_STATIC);
}
/*
** Implementation of the sqlite_compileoption_used() function.
** The result is an integer that identifies if the compiler option
** was used to build SQLite.
*/
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
static void compileoptionusedFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zOptName;
assert( argc==1 );
UNUSED_PARAMETER(argc);
/* IMP: R-xxxx This function is an SQL wrapper around the
** sqlite3_compileoption_used() C interface. */
if( (zOptName = (const char*)sqlite3_value_text(argv[0]))!=0 ){
sqlite3_result_int(context, sqlite3_compileoption_used(zOptName));
}
}
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
/*
** Implementation of the sqlite_compileoption_get() function.
** The result is a string that identifies the compiler options
** used to build SQLite.
*/
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
static void compileoptiongetFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int n;
assert( argc==1 );
UNUSED_PARAMETER(argc);
/* IMP: R-xxxx This function is an SQL wrapper around the
** sqlite3_compileoption_get() C interface. */
n = sqlite3_value_int(argv[0]);
sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC);
}
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
/* Array for converting from half-bytes (nybbles) into ASCII hex
** digits. */
static const char hexdigits[] = {
@ -866,7 +943,7 @@ static void zeroblobFunc(
if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
}else{
sqlite3_result_zeroblob(context, (int)n);
sqlite3_result_zeroblob(context, (int)n); /* IMP: R-00293-64994 */
}
}
@ -1041,9 +1118,16 @@ static void trimFunc(
}
/* IMP: R-25361-16150 This function is omitted from SQLite by default. It
** is only available if the SQLITE_SOUNDEX compile-time option is used
** when SQLite is built.
*/
#ifdef SQLITE_SOUNDEX
/*
** Compute the soundex encoding of a word.
**
** IMP: R-59782-00072 The soundex(X) function returns a string that is the
** soundex encoding of the string X.
*/
static void soundexFunc(
sqlite3_context *context,
@ -1087,10 +1171,12 @@ static void soundexFunc(
zResult[j] = 0;
sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT);
}else{
/* IMP: R-64894-50321 The string "?000" is returned if the argument
** is NULL or contains no ASCII alphabetic characters. */
sqlite3_result_text(context, "?000", 4, SQLITE_STATIC);
}
}
#endif
#endif /* SQLITE_SOUNDEX */
#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
@ -1462,6 +1548,10 @@ void sqlite3RegisterGlobalFunctions(void){
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
FUNCTION(quote, 1, 0, 0, quoteFunc ),
FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
FUNCTION(changes, 0, 0, 0, changes ),

View File

@ -164,6 +164,8 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* isPCacheInit */
0, /* pInitMutex */
0, /* nRefInitMutex */
0, /* xLog */
0, /* pLogArg */
};

View File

@ -1261,19 +1261,33 @@ void sqlite3GenerateConstraintChecks(
** the triggers and remove both the table and index b-tree entries.
**
** Otherwise, if there are no triggers or the recursive-triggers
** flag is not set, call GenerateRowIndexDelete(). This removes
** the index b-tree entries only. The table b-tree entry will be
** replaced by the new entry when it is inserted. */
** flag is not set, but the table has one or more indexes, call
** GenerateRowIndexDelete(). This removes the index b-tree entries
** only. The table b-tree entry will be replaced by the new entry
** when it is inserted.
**
** If either GenerateRowDelete() or GenerateRowIndexDelete() is called,
** also invoke MultiWrite() to indicate that this VDBE may require
** statement rollback (if the statement is aborted after the delete
** takes place). Earlier versions called sqlite3MultiWrite() regardless,
** but being more selective here allows statements like:
**
** REPLACE INTO t(rowid) VALUES($newrowid)
**
** to run without a statement journal if there are no indexes on the
** table.
*/
Trigger *pTrigger = 0;
if( pParse->db->flags&SQLITE_RecTriggers ){
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
}
sqlite3MultiWrite(pParse);
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
sqlite3MultiWrite(pParse);
sqlite3GenerateRowDelete(
pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace
);
}else{
}else if( pTab->pIndex ){
sqlite3MultiWrite(pParse);
sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
}
seenReplace = 1;
@ -1715,7 +1729,7 @@ static int xferOptimization(
}
}
#ifndef SQLITE_OMIT_CHECK
if( pDest->pCheck && !sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
}
#endif

View File

@ -41,6 +41,7 @@ int sqlite3_exec(
int nRetry = 0; /* Number of retry attempts */
int callbackIsInit; /* True if callback data is initialized */
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
if( zSql==0 ) zSql = "";
sqlite3_mutex_enter(db->mutex);

View File

@ -257,7 +257,7 @@ int sqlite3_config(int op, ...){
/* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while
** the SQLite library is in use. */
if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE;
if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT;
va_start(ap, op);
switch( op ){
@ -265,7 +265,7 @@ int sqlite3_config(int op, ...){
/* Mutex configuration options are only available in a threadsafe
** compile.
*/
#if SQLITE_THREADSAFE
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0
case SQLITE_CONFIG_SINGLETHREAD: {
/* Disable all mutexing */
sqlite3GlobalConfig.bCoreMutex = 0;
@ -378,6 +378,21 @@ int sqlite3_config(int op, ...){
sqlite3GlobalConfig.nLookaside = va_arg(ap, int);
break;
}
/* Record a pointer to the logger funcction and its first argument.
** The default is NULL. Logging is disabled if the function pointer is
** NULL.
*/
case SQLITE_CONFIG_LOG: {
/* MSVC is picky about pulling func ptrs from va lists.
** http://support.microsoft.com/kb/47961
** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*));
*/
typedef void(*LOGFUNC_t)(void*,int,const char*);
sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t);
sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
break;
}
default: {
rc = SQLITE_ERROR;
@ -591,7 +606,7 @@ int sqlite3_close(sqlite3 *db){
return SQLITE_OK;
}
if( !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(db->mutex);
@ -938,7 +953,7 @@ int sqlite3CreateFunc(
(!xFunc && (!xFinal && xStep)) ||
(nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) ||
(255<(nName = sqlite3Strlen30( zFunctionName))) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
#ifndef SQLITE_OMIT_UTF16
@ -1035,7 +1050,7 @@ int sqlite3_create_function16(
char *zFunc8;
sqlite3_mutex_enter(db->mutex);
assert( !db->mallocFailed );
zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1);
zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE);
rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal);
sqlite3DbFree(db, zFunc8);
rc = sqlite3ApiExit(db, rc);
@ -1269,7 +1284,7 @@ const char *sqlite3_errmsg(sqlite3 *db){
return sqlite3ErrStr(SQLITE_NOMEM);
}
if( !sqlite3SafetyCheckSickOrOk(db) ){
return sqlite3ErrStr(SQLITE_MISUSE);
return sqlite3ErrStr(SQLITE_MISUSE_BKPT);
}
sqlite3_mutex_enter(db->mutex);
if( db->mallocFailed ){
@ -1338,7 +1353,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){
*/
int sqlite3_errcode(sqlite3 *db){
if( db && !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
if( !db || db->mallocFailed ){
return SQLITE_NOMEM;
@ -1347,7 +1362,7 @@ int sqlite3_errcode(sqlite3 *db){
}
int sqlite3_extended_errcode(sqlite3 *db){
if( db && !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
if( !db || db->mallocFailed ){
return SQLITE_NOMEM;
@ -1385,7 +1400,7 @@ static int createCollation(
enc2 = SQLITE_UTF16NATIVE;
}
if( enc2<SQLITE_UTF8 || enc2>SQLITE_UTF16BE ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
/* Check if this call is removing or replacing an existing collation
@ -1858,7 +1873,7 @@ int sqlite3_create_collation16(
char *zName8;
sqlite3_mutex_enter(db->mutex);
assert( !db->mallocFailed );
zName8 = sqlite3Utf16to8(db, zName, -1);
zName8 = sqlite3Utf16to8(db, zName, -1, SQLITE_UTF16NATIVE);
if( zName8 ){
rc = createCollation(db, zName8, (u8)enc, SQLITE_COLL_USER, pCtx, xCompare, 0);
sqlite3DbFree(db, zName8);
@ -1929,16 +1944,34 @@ int sqlite3_get_autocommit(sqlite3 *db){
return db->autoCommit;
}
#ifdef SQLITE_DEBUG
/*
** The following routine is subtituted for constant SQLITE_CORRUPT in
** debugging builds. This provides a way to set a breakpoint for when
** corruption is first detected.
** The following routines are subtitutes for constants SQLITE_CORRUPT,
** SQLITE_MISUSE, SQLITE_CANTOPEN, SQLITE_IOERR and possibly other error
** constants. They server two purposes:
**
** 1. Serve as a convenient place to set a breakpoint in a debugger
** to detect when version error conditions occurs.
**
** 2. Invoke sqlite3_log() to provide the source code location where
** a low-level error is first detected.
*/
int sqlite3Corrupt(void){
int sqlite3CorruptError(int lineno){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_CORRUPT,
"database corruption found by source line %d", lineno);
return SQLITE_CORRUPT;
}
#endif
int sqlite3MisuseError(int lineno){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_MISUSE, "misuse detected by source line %d", lineno);
return SQLITE_MISUSE;
}
int sqlite3CantopenError(int lineno){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_CANTOPEN, "cannot open file at source line %d", lineno);
return SQLITE_CANTOPEN;
}
#ifndef SQLITE_OMIT_DEPRECATED
/*
@ -1982,7 +2015,6 @@ int sqlite3_table_column_metadata(
/* Ensure the database schema has been loaded */
sqlite3_mutex_enter(db->mutex);
(void)sqlite3SafetyOn(db);
sqlite3BtreeEnterAll(db);
rc = sqlite3Init(db, &zErrMsg);
if( SQLITE_OK!=rc ){
@ -2041,7 +2073,6 @@ int sqlite3_table_column_metadata(
error_out:
sqlite3BtreeLeaveAll(db);
(void)sqlite3SafetyOff(db);
/* Whether the function call succeeded or failed, set the output parameters
** to whatever their local counterparts contain. If an error did occur,
@ -2281,6 +2312,40 @@ int sqlite3_test_control(int op, ...){
break;
}
/* sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, sqlite3 *db, int N)
**
** Enable or disable various optimizations for testing purposes. The
** argument N is a bitmask of optimizations to be disabled. For normal
** operation N should be 0. The idea is that a test program (like the
** SQL Logic Test or SLT test module) can run the same SQL multiple times
** with various optimizations disabled to verify that the same answer
** is obtained in every case.
*/
case SQLITE_TESTCTRL_OPTIMIZATIONS: {
sqlite3 *db = va_arg(ap, sqlite3*);
int x = va_arg(ap,int);
db->flags = (x & SQLITE_OptMask) | (db->flags & ~SQLITE_OptMask);
break;
}
#ifdef SQLITE_N_KEYWORD
/* sqlite3_test_control(SQLITE_TESTCTRL_ISKEYWORD, const char *zWord)
**
** If zWord is a keyword recognized by the parser, then return the
** number of keywords. Or if zWord is not a keyword, return 0.
**
** This test feature is only available in the amalgamation since
** the SQLITE_N_KEYWORD macro is not defined in this file if SQLite
** is built using separate source files.
*/
case SQLITE_TESTCTRL_ISKEYWORD: {
const char *zWord = va_arg(ap, const char*);
int n = sqlite3Strlen30(zWord);
rc = (sqlite3KeywordCode((u8*)zWord, n)!=TK_ID) ? SQLITE_N_KEYWORD : 0;
break;
}
#endif
}
va_end(ap);
#endif /* SQLITE_OMIT_BUILTIN_TEST */

View File

@ -42,6 +42,9 @@ static void *sqlite3MemMalloc(int nByte){
if( p ){
p[0] = nByte;
p++;
}else{
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
}
return (void *)p;
}
@ -61,6 +64,18 @@ static void sqlite3MemFree(void *pPrior){
free(p);
}
/*
** Report the allocated size of a prior return from xMalloc()
** or xRealloc().
*/
static int sqlite3MemSize(void *pPrior){
sqlite3_int64 *p;
if( pPrior==0 ) return 0;
p = (sqlite3_int64*)pPrior;
p--;
return (int)p[0];
}
/*
** Like realloc(). Resize an allocation previously obtained from
** sqlite3MemMalloc().
@ -75,28 +90,20 @@ static void *sqlite3MemRealloc(void *pPrior, int nByte){
sqlite3_int64 *p = (sqlite3_int64*)pPrior;
assert( pPrior!=0 && nByte>0 );
nByte = ROUND8(nByte);
p = (sqlite3_int64*)pPrior;
p--;
p = realloc(p, nByte+8 );
if( p ){
p[0] = nByte;
p++;
}else{
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM,
"failed memory resize %u to %u bytes",
sqlite3MemSize(pPrior), nByte);
}
return (void*)p;
}
/*
** Report the allocated size of a prior return from xMalloc()
** or xRealloc().
*/
static int sqlite3MemSize(void *pPrior){
sqlite3_int64 *p;
if( pPrior==0 ) return 0;
p = (sqlite3_int64*)pPrior;
p--;
return (int)p[0];
}
/*
** Round up a request size to the next valid allocation size.
*/

View File

@ -210,6 +210,31 @@ static int sqlite3MemRoundup(int n){
return ROUND8(n);
}
/*
** Fill a buffer with pseudo-random bytes. This is used to preset
** the content of a new memory allocation to unpredictable values and
** to clear the content of a freed allocation to unpredictable values.
*/
static void randomFill(char *pBuf, int nByte){
unsigned int x, y, r;
x = SQLITE_PTR_TO_INT(pBuf);
y = nByte | 1;
while( nByte >= 4 ){
x = (x>>1) ^ (-(x&1) & 0xd0000001);
y = y*1103515245 + 12345;
r = x ^ y;
*(int*)pBuf = r;
pBuf += 4;
nByte -= 4;
}
while( nByte-- > 0 ){
x = (x>>1) ^ (-(x&1) & 0xd0000001);
y = y*1103515245 + 12345;
r = x ^ y;
*(pBuf++) = r & 0xff;
}
}
/*
** Allocate nByte bytes of memory.
*/
@ -260,7 +285,8 @@ static void *sqlite3MemMalloc(int nByte){
adjustStats(nByte, +1);
pInt = (int*)&pHdr[1];
pInt[nReserve/sizeof(int)] = REARGUARD;
memset(pInt, 0x65, nReserve);
randomFill((char*)pInt, nByte);
memset(((char*)pInt)+nByte, 0x65, nReserve-nByte);
p = (void*)pInt;
}
sqlite3_mutex_leave(mem.mutex);
@ -274,7 +300,8 @@ static void sqlite3MemFree(void *pPrior){
struct MemBlockHdr *pHdr;
void **pBt;
char *z;
assert( sqlite3GlobalConfig.bMemstat || mem.mutex!=0 );
assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0
|| mem.mutex!=0 );
pHdr = sqlite3MemsysGetHeader(pPrior);
pBt = (void**)pHdr;
pBt -= pHdr->nBacktraceSlots;
@ -296,8 +323,8 @@ static void sqlite3MemFree(void *pPrior){
z = (char*)pBt;
z -= pHdr->nTitle;
adjustStats(pHdr->iSize, -1);
memset(z, 0x2b, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
pHdr->iSize + sizeof(int) + pHdr->nTitle);
randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
pHdr->iSize + sizeof(int) + pHdr->nTitle);
free(z);
sqlite3_mutex_leave(mem.mutex);
}
@ -320,7 +347,7 @@ static void *sqlite3MemRealloc(void *pPrior, int nByte){
if( pNew ){
memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
if( nByte>pOldHdr->iSize ){
memset(&((char*)pNew)[pOldHdr->iSize], 0x2b, nByte - pOldHdr->iSize);
randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize);
}
sqlite3MemFree(pPrior);
}

View File

@ -268,7 +268,11 @@ static void *memsys5MallocUnsafe(int nByte){
** two in order to create a new free block of size iLogsize.
*/
for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
if( iBin>LOGMAX ) return 0;
if( iBin>LOGMAX ){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
return 0;
}
i = memsys5UnlinkFirst(iBin);
while( iBin>iLogsize ){
int newSize;

View File

@ -27,7 +27,16 @@ struct sqlite3_mutex {
int id; /* Mutex type */
int nRef; /* Number of enterances */
DWORD owner; /* Thread holding this mutex */
#ifdef SQLITE_DEBUG
int trace; /* True to trace changes */
#endif
};
#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
#ifdef SQLITE_DEBUG
#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 }
#else
#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0 }
#endif
/*
** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
@ -71,8 +80,12 @@ struct sqlite3_mutex {
static int winMutexHeld(sqlite3_mutex *p){
return p->nRef!=0 && p->owner==GetCurrentThreadId();
}
static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
return p->nRef==0 || p->owner!=tid;
}
static int winMutexNotheld(sqlite3_mutex *p){
return p->nRef==0 || p->owner!=GetCurrentThreadId();
DWORD tid = GetCurrentThreadId();
return winMutexNotheld2(p, tid);
}
#endif
@ -80,7 +93,14 @@ static int winMutexNotheld(sqlite3_mutex *p){
/*
** Initialize and deinitialize the mutex subsystem.
*/
static sqlite3_mutex winMutex_staticMutexes[6];
static sqlite3_mutex winMutex_staticMutexes[6] = {
SQLITE3_MUTEX_INITIALIZER,
SQLITE3_MUTEX_INITIALIZER,
SQLITE3_MUTEX_INITIALIZER,
SQLITE3_MUTEX_INITIALIZER,
SQLITE3_MUTEX_INITIALIZER,
SQLITE3_MUTEX_INITIALIZER
};
static int winMutex_isInit = 0;
/* As winMutexInit() and winMutexEnd() are called as part
** of the sqlite3_initialize and sqlite3_shutdown()
@ -214,14 +234,23 @@ static void winMutexFree(sqlite3_mutex *p){
** more than once, the behavior is undefined.
*/
static void winMutexEnter(sqlite3_mutex *p){
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
DWORD tid = GetCurrentThreadId();
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
EnterCriticalSection(&p->mutex);
p->owner = GetCurrentThreadId();
p->owner = tid;
p->nRef++;
#ifdef SQLITE_DEBUG
if( p->trace ){
printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
}
#endif
}
static int winMutexTry(sqlite3_mutex *p){
#ifndef NDEBUG
DWORD tid = GetCurrentThreadId();
#endif
int rc = SQLITE_BUSY;
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
/*
** The sqlite3_mutex_try() routine is very rarely used, and when it
** is used it is merely an optimization. So it is OK for it to always
@ -235,12 +264,17 @@ static int winMutexTry(sqlite3_mutex *p){
*/
#if 0
if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
p->owner = GetCurrentThreadId();
p->owner = tid;
p->nRef++;
rc = SQLITE_OK;
}
#else
UNUSED_PARAMETER(p);
#endif
#ifdef SQLITE_DEBUG
if( rc==SQLITE_OK && p->trace ){
printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
}
#endif
return rc;
}
@ -252,11 +286,19 @@ static int winMutexTry(sqlite3_mutex *p){
** is not currently allocated. SQLite will never do either.
*/
static void winMutexLeave(sqlite3_mutex *p){
#ifndef NDEBUG
DWORD tid = GetCurrentThreadId();
#endif
assert( p->nRef>0 );
assert( p->owner==GetCurrentThreadId() );
assert( p->owner==tid );
p->nRef--;
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
LeaveCriticalSection(&p->mutex);
#ifdef SQLITE_DEBUG
if( p->trace ){
printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
}
#endif
}
sqlite3_mutex_methods *sqlite3DefaultMutex(void){

View File

@ -112,11 +112,11 @@ int sqlite3OsOpen(
){
int rc;
DO_OS_MALLOC_TEST(0);
/* 0x7f1f is a mask of SQLITE_OPEN_ flags that are valid to be passed
/* 0x7f3f is a mask of SQLITE_OPEN_ flags that are valid to be passed
** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
** reaching the VFS. */
rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x7f1f, pFlagsOut);
rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x7f3f, pFlagsOut);
assert( rc==SQLITE_OK || pFile->pMethods==0 );
return rc;
}

File diff suppressed because it is too large Load Diff

View File

@ -1417,7 +1417,7 @@ static int winOpen(
return winOpen(pVfs, zName, id,
((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags);
}else{
return SQLITE_CANTOPEN;
return SQLITE_CANTOPEN_BKPT;
}
}
if( pOutFlags ){
@ -1439,7 +1439,7 @@ static int winOpen(
){
CloseHandle(h);
free(zConverted);
return SQLITE_CANTOPEN;
return SQLITE_CANTOPEN_BKPT;
}
if( isTemp ){
pFile->zDeleteOnClose = zConverted;

View File

@ -2019,6 +2019,9 @@ end_playback:
rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
testcase( rc!=SQLITE_OK );
}
if( rc==SQLITE_OK && pPager->noSync==0 && pPager->state>=PAGER_EXCLUSIVE ){
rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
}
if( rc==SQLITE_OK ){
rc = pager_end_transaction(pPager, zMaster[0]!='\0');
testcase( rc!=SQLITE_OK );
@ -2875,9 +2878,7 @@ static int pager_write_pagelist(PgHdr *pList){
** any such pages to the file.
**
** Also, do not write out any page that has the PGHDR_DONT_WRITE flag
** set (set by sqlite3PagerDontWrite()). Note that if compiled with
** SQLITE_SECURE_DELETE the PGHDR_DONT_WRITE bit is never set and so
** the second test is always true.
** set (set by sqlite3PagerDontWrite()).
*/
if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */
@ -3164,7 +3165,7 @@ int sqlite3PagerOpen(
** as it will not be possible to open the journal file or even
** check for a hot-journal before reading.
*/
rc = SQLITE_CANTOPEN;
rc = SQLITE_CANTOPEN_BKPT;
}
if( rc!=SQLITE_OK ){
sqlite3_free(zPathname);
@ -3341,6 +3342,7 @@ int sqlite3PagerOpen(
/* pPager->pBusyHandlerArg = 0; */
pPager->xReiniter = xReinit;
/* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
*ppPager = pPager;
return SQLITE_OK;
}
@ -3490,8 +3492,24 @@ static int readDbPage(PgHdr *pPg){
rc = SQLITE_OK;
}
if( pgno==1 ){
u8 *dbFileVers = &((u8*)pPg->pData)[24];
memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
if( rc ){
/* If the read is unsuccessful, set the dbFileVers[] to something
** that will never be a valid file version. dbFileVers[] is a copy
** of bytes 24..39 of the database. Bytes 28..31 should always be
** zero. Bytes 32..35 and 35..39 should be page numbers which are
** never 0xffffffff. So filling pPager->dbFileVers[] with all 0xff
** bytes should suffice.
**
** For an encrypted database, the situation is more complex: bytes
** 24..39 of the database are white noise. But the probability of
** white noising equaling 16 bytes of 0xff is vanishingly small so
** we should still be ok.
*/
memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers));
}else{
u8 *dbFileVers = &((u8*)pPg->pData)[24];
memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
}
}
CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM);
@ -3623,7 +3641,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){
rc = SQLITE_CANTOPEN;
rc = SQLITE_CANTOPEN_BKPT;
sqlite3OsClose(pPager->jfd);
}
}else{
@ -3842,7 +3860,7 @@ int sqlite3PagerAcquire(
goto pager_acquire_err;
}
if( MEMDB || nMax<(int)pgno || noContent ){
if( MEMDB || nMax<(int)pgno || noContent || !isOpen(pPager->fd) ){
if( pgno>pPager->mxPgno ){
rc = SQLITE_FULL;
goto pager_acquire_err;
@ -3862,9 +3880,8 @@ int sqlite3PagerAcquire(
TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
testcase( rc==SQLITE_NOMEM );
sqlite3EndBenignMalloc();
}else{
memset(pPg->pData, 0, pPager->pageSize);
}
memset(pPg->pData, 0, pPager->pageSize);
IOTRACE(("ZERO %p %d\n", pPager, pgno));
}else{
assert( pPg->pPager==pPager );
@ -4386,7 +4403,6 @@ int sqlite3PagerIswriteable(DbPage *pPg){
}
#endif
#ifndef SQLITE_SECURE_DELETE
/*
** A call to this routine tells the pager that it is not necessary to
** write the information on page pPg back to the disk, even though
@ -4412,7 +4428,6 @@ void sqlite3PagerDontWrite(PgHdr *pPg){
#endif
}
}
#endif /* !defined(SQLITE_SECURE_DELETE) */
/*
** This routine is called to increment the value of the database file
@ -4982,30 +4997,35 @@ int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
** operation. Store this value in nNew. Then free resources associated
** with any savepoints that are destroyed by this operation.
*/
nNew = iSavepoint + (op==SAVEPOINT_ROLLBACK);
nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1);
for(ii=nNew; ii<pPager->nSavepoint; ii++){
sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
}
pPager->nSavepoint = nNew;
/* If this is a rollback operation, playback the specified savepoint.
/* If this is a release of the outermost savepoint, truncate
** the sub-journal to zero bytes in size. */
if( op==SAVEPOINT_RELEASE ){
if( nNew==0 && isOpen(pPager->sjfd) ){
/* Only truncate if it is an in-memory sub-journal. */
if( sqlite3IsMemJournal(pPager->sjfd) ){
rc = sqlite3OsTruncate(pPager->sjfd, 0);
assert( rc==SQLITE_OK );
}
pPager->nSubRec = 0;
}
}
/* Else this is a rollback operation, playback the specified savepoint.
** If this is a temp-file, it is possible that the journal file has
** not yet been opened. In this case there have been no changes to
** the database file, so the playback operation can be skipped.
*/
if( op==SAVEPOINT_ROLLBACK && isOpen(pPager->jfd) ){
else if( isOpen(pPager->jfd) ){
PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1];
rc = pagerPlaybackSavepoint(pPager, pSavepoint);
assert(rc!=SQLITE_DONE);
}
/* If this is a release of the outermost savepoint, truncate
** the sub-journal to zero bytes in size. */
if( nNew==0 && op==SAVEPOINT_RELEASE && isOpen(pPager->sjfd) ){
assert( rc==SQLITE_OK );
rc = sqlite3OsTruncate(pPager->sjfd, 0);
pPager->nSubRec = 0;
}
}
return rc;
}

View File

@ -316,6 +316,7 @@ refargs(A) ::= . { A = OE_None*0x0101; /* EV: R-19803-45884 */}
refargs(A) ::= refargs(X) refarg(Y). { A = (X & ~Y.mask) | Y.value; }
%type refarg {struct {int value; int mask;}}
refarg(A) ::= MATCH nm. { A.value = 0; A.mask = 0x000000; }
refarg(A) ::= ON INSERT refact. { A.value = 0; A.mask = 0x000000; }
refarg(A) ::= ON DELETE refact(X). { A.value = X; A.mask = 0x0000ff; }
refarg(A) ::= ON UPDATE refact(X). { A.value = X<<8; A.mask = 0x00ff00; }
%type refact {int}

View File

@ -189,6 +189,7 @@ void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
if( pCache->pCache ){
sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache);
pCache->pCache = 0;
pCache->pPage1 = 0;
}
pCache->szPage = szPage;
}
@ -242,6 +243,7 @@ int sqlite3PcacheFetch(
pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
pPg=pPg->pDirtyPrev
);
pCache->pSynced = pPg;
if( !pPg ){
for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
}

View File

@ -285,6 +285,7 @@ void sqlite3Pragma(
Db *pDb;
Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db);
if( v==0 ) return;
sqlite3VdbeRunOnlyOnce(v);
pParse->nMem = 2;
/* Interpret the [database.] part of the pragma statement. iDb is the
@ -416,6 +417,31 @@ void sqlite3Pragma(
returnSingleInt(pParse, "max_page_count", newMax);
}else
/*
** PRAGMA [database.]secure_delete
** PRAGMA [database.]secure_delete=ON/OFF
**
** The first form reports the current setting for the
** secure_delete flag. The second form changes the secure_delete
** flag setting and reports thenew value.
*/
if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){
Btree *pBt = pDb->pBt;
int b = -1;
assert( pBt!=0 );
if( zRight ){
b = getBoolean(zRight);
}
if( pId2->n==0 && b>=0 ){
int ii;
for(ii=0; ii<db->nDb; ii++){
sqlite3BtreeSecureDelete(db->aDb[ii].pBt, b);
}
}
b = sqlite3BtreeSecureDelete(pBt, b);
returnSingleInt(pParse, "secure_delete", b);
}else
/*
** PRAGMA [database.]page_count
**
@ -1334,6 +1360,26 @@ void sqlite3Pragma(
}else
#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
/*
** PRAGMA compile_options
**
** Return the names of all compile-time options used in this build,
** one option per row.
*/
if( sqlite3StrICmp(zLeft, "compile_options")==0 ){
int i = 0;
const char *zOpt;
sqlite3VdbeSetNumCols(v, 1);
pParse->nMem = 1;
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "compile_option", SQLITE_STATIC);
while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
}
}else
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/*
** Report the current state of file logs for all databases
@ -1368,7 +1414,7 @@ void sqlite3Pragma(
}else
#endif
#if SQLITE_HAS_CODEC
#ifdef SQLITE_HAS_CODEC
if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){
sqlite3_key(db, zRight, sqlite3Strlen30(zRight));
}else
@ -1409,17 +1455,15 @@ void sqlite3Pragma(
}else
/** END CRYPTO **/
#endif
#if SQLITE_HAS_CODEC || defined(SQLITE_ENABLE_CEROD)
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){
#if SQLITE_HAS_CODEC
#ifdef SQLITE_HAS_CODEC
if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
extern void sqlite3_activate_see(const char*);
sqlite3_activate_see(&zRight[4]);
}
#endif
#ifdef SQLITE_ENABLE_CEROD
if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){
extern void sqlite3_activate_cerod(const char*);
sqlite3_activate_cerod(&zRight[6]);
}
#endif
@ -1429,12 +1473,6 @@ void sqlite3Pragma(
{/* Empty ELSE clause */}
/* Code an OP_Expire at the end of each PRAGMA program to cause
** the VDBE implementing the pragma to expire. Most (all?) pragmas
** are only valid for a single execution.
*/
sqlite3VdbeAddOp2(v, OP_Expire, 1, 0);
/*
** Reset the safety level, in case the fullfsync flag or synchronous
** setting changed.

View File

@ -192,9 +192,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
initData.iDb = iDb;
initData.rc = SQLITE_OK;
initData.pzErrMsg = pzErrMsg;
(void)sqlite3SafetyOff(db);
sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
(void)sqlite3SafetyOn(db);
if( initData.rc ){
rc = initData.rc;
goto error_out;
@ -315,9 +313,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
{
char *zSql;
zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s",
"SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid",
db->aDb[iDb].zName, zMasterName);
(void)sqlite3SafetyOff(db);
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
@ -330,7 +327,6 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
}
#endif
if( rc==SQLITE_OK ) rc = initData.rc;
(void)sqlite3SafetyOn(db);
sqlite3DbFree(db, zSql);
#ifndef SQLITE_OMIT_ANALYZE
if( rc==SQLITE_OK ){
@ -469,7 +465,7 @@ static void schemaIsValid(Parse *pParse){
}
/* Read the schema cookie from the database. If it does not match the
** value stored as part of the in the in-memory schema representation,
** value stored as part of the in-memory schema representation,
** set Parse.rc to SQLITE_SCHEMA. */
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){
@ -539,11 +535,6 @@ static int sqlite3Prepare(
goto end_prepare;
}
pParse->pReprepare = pReprepare;
if( sqlite3SafetyOn(db) ){
rc = SQLITE_MISUSE;
goto end_prepare;
}
assert( ppStmt && *ppStmt==0 );
assert( !db->mallocFailed );
assert( sqlite3_mutex_held(db->mutex) );
@ -579,7 +570,6 @@ static int sqlite3Prepare(
if( rc ){
const char *zDb = db->aDb[i].zName;
sqlite3Error(db, rc, "database schema is locked: %s", zDb);
(void)sqlite3SafetyOff(db);
testcase( db->flags & SQLITE_ReadUncommitted );
goto end_prepare;
}
@ -596,7 +586,6 @@ static int sqlite3Prepare(
testcase( nBytes==mxLen+1 );
if( nBytes>mxLen ){
sqlite3Error(db, SQLITE_TOOBIG, "statement too long");
(void)sqlite3SafetyOff(db);
rc = sqlite3ApiExit(db, SQLITE_TOOBIG);
goto end_prepare;
}
@ -653,10 +642,6 @@ static int sqlite3Prepare(
}
#endif
if( sqlite3SafetyOff(db) ){
rc = SQLITE_MISUSE;
}
assert( db->init.busy==0 || saveSqlFlag==0 );
if( db->init.busy==0 ){
Vdbe *pVdbe = pParse->pVdbe;
@ -704,7 +689,7 @@ static int sqlite3LockAndPrepare(
assert( ppStmt!=0 );
*ppStmt = 0;
if( !sqlite3SafetyCheckOk(db) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(db->mutex);
sqlite3BtreeEnterAll(db);
@ -743,7 +728,7 @@ int sqlite3Reprepare(Vdbe *p){
db->mallocFailed = 1;
}
assert( pNew==0 );
return (rc==SQLITE_LOCKED) ? SQLITE_LOCKED : SQLITE_SCHEMA;
return rc;
}else{
assert( pNew!=0 );
}
@ -812,10 +797,10 @@ static int sqlite3Prepare16(
assert( ppStmt );
*ppStmt = 0;
if( !sqlite3SafetyCheckOk(db) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(db->mutex);
zSql8 = sqlite3Utf16to8(db, zSql, nBytes);
zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
if( zSql8 ){
rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8);
}

View File

@ -460,7 +460,9 @@ void sqlite3VXPrintf(
case etEXP:
case etGENERIC:
realvalue = va_arg(ap,double);
#ifndef SQLITE_OMIT_FLOATING_POINT
#ifdef SQLITE_OMIT_FLOATING_POINT
length = 0;
#else
if( precision<0 ) precision = 6; /* Set default precision */
if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10;
if( realvalue<0.0 ){
@ -606,7 +608,7 @@ void sqlite3VXPrintf(
while( nPad-- ) bufpt[i++] = '0';
length = width;
}
#endif
#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
break;
case etSIZE:
*(va_arg(ap,int*)) = pAccum->nChar;
@ -653,7 +655,7 @@ void sqlite3VXPrintf(
isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
k = precision;
for(i=n=0; (ch=escarg[i])!=0 && k!=0; i++, k--){
for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
if( ch==q ) n++;
}
needQuote = !isnull && xtype==etSQLESCAPE2;
@ -937,6 +939,38 @@ char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
return z;
}
/*
** This is the routine that actually formats the sqlite3_log() message.
** We house it in a separate routine from sqlite3_log() to avoid using
** stack space on small-stack systems when logging is disabled.
**
** sqlite3_log() must render into a static buffer. It cannot dynamically
** allocate memory because it might be called while the memory allocator
** mutex is held.
*/
static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
StrAccum acc; /* String accumulator */
char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
acc.useMalloc = 0;
sqlite3VXPrintf(&acc, 0, zFormat, ap);
sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
sqlite3StrAccumFinish(&acc));
}
/*
** Format and write a message to the log if logging is enabled.
*/
void sqlite3_log(int iErrCode, const char *zFormat, ...){
va_list ap; /* Vararg list */
if( sqlite3GlobalConfig.xLog ){
va_start(ap, zFormat);
renderLogMsg(iErrCode, zFormat, ap);
va_end(ap);
}
}
#if defined(SQLITE_DEBUG)
/*
** A version of printf() that understands %lld. Used for debugging.

View File

@ -243,19 +243,18 @@ static int lookupName(
int iCol;
pSchema = pTab->pSchema;
cntTab++;
if( sqlite3IsRowid(zCol) ){
iCol = -1;
}else{
for(iCol=0; iCol<pTab->nCol; iCol++){
Column *pCol = &pTab->aCol[iCol];
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
if( iCol==pTab->iPKey ){
iCol = -1;
}
break;
for(iCol=0; iCol<pTab->nCol; iCol++){
Column *pCol = &pTab->aCol[iCol];
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
if( iCol==pTab->iPKey ){
iCol = -1;
}
break;
}
}
if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) ){
iCol = -1; /* IMP: R-44911-55124 */
}
if( iCol<pTab->nCol ){
cnt++;
if( iCol<0 ){
@ -282,7 +281,7 @@ static int lookupName(
*/
if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
cnt = 1;
pExpr->iColumn = -1;
pExpr->iColumn = -1; /* IMP: R-44911-55124 */
pExpr->affinity = SQLITE_AFF_INTEGER;
}
@ -665,6 +664,9 @@ static int resolveOrderByTermToExprList(
int i; /* Loop counter */
ExprList *pEList; /* The columns of the result set */
NameContext nc; /* Name context for resolving pE */
sqlite3 *db; /* Database connection */
int rc; /* Return code from subprocedures */
u8 savedSuppErr; /* Saved value of db->suppressErr */
assert( sqlite3ExprIsInteger(pE, &i)==0 );
pEList = pSelect->pEList;
@ -677,17 +679,19 @@ static int resolveOrderByTermToExprList(
nc.pEList = pEList;
nc.allowAgg = 1;
nc.nErr = 0;
if( sqlite3ResolveExprNames(&nc, pE) ){
sqlite3ErrorClear(pParse);
return 0;
}
db = pParse->db;
savedSuppErr = db->suppressErr;
db->suppressErr = 1;
rc = sqlite3ResolveExprNames(&nc, pE);
db->suppressErr = savedSuppErr;
if( rc ) return 0;
/* Try to match the ORDER BY expression against an expression
** in the result set. Return an 1-based index of the matching
** result-set entry.
*/
for(i=0; i<pEList->nExpr; i++){
if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){
if( sqlite3ExprCompare(pEList->a[i].pExpr, pE)<2 ){
return i+1;
}
}

View File

@ -189,6 +189,39 @@ static int columnIndex(Table *pTab, const char *zCol){
return -1;
}
/*
** Search the first N tables in pSrc, from left to right, looking for a
** table that has a column named zCol.
**
** When found, set *piTab and *piCol to the table index and column index
** of the matching column and return TRUE.
**
** If not found, return FALSE.
*/
static int tableAndColumnIndex(
SrcList *pSrc, /* Array of tables to search */
int N, /* Number of tables in pSrc->a[] to search */
const char *zCol, /* Name of the column we are looking for */
int *piTab, /* Write index of pSrc->a[] here */
int *piCol /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
){
int i; /* For looping over tables in pSrc */
int iCol; /* Index of column matching zCol */
assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
for(i=0; i<N; i++){
iCol = columnIndex(pSrc->a[i].pTab, zCol);
if( iCol>=0 ){
if( piTab ){
*piTab = i;
*piCol = iCol;
}
return 1;
}
}
return 0;
}
/*
** This function is used to add terms implied by JOIN syntax to the
** WHERE clause expression of a SELECT statement. The new term, which
@ -203,8 +236,9 @@ static int columnIndex(Table *pTab, const char *zCol){
static void addWhereTerm(
Parse *pParse, /* Parsing context */
SrcList *pSrc, /* List of tables in FROM clause */
int iSrc, /* Index of first table to join in pSrc */
int iLeft, /* Index of first table to join in pSrc */
int iColLeft, /* Index of column in first table */
int iRight, /* Index of second table in pSrc */
int iColRight, /* Index of column in second table */
int isOuterJoin, /* True if this is an OUTER join */
Expr **ppWhere /* IN/OUT: The WHERE clause to add to */
@ -214,12 +248,13 @@ static void addWhereTerm(
Expr *pE2;
Expr *pEq;
assert( pSrc->nSrc>(iSrc+1) );
assert( pSrc->a[iSrc].pTab );
assert( pSrc->a[iSrc+1].pTab );
assert( iLeft<iRight );
assert( pSrc->nSrc>iRight );
assert( pSrc->a[iLeft].pTab );
assert( pSrc->a[iRight].pTab );
pE1 = sqlite3CreateColumnExpr(db, pSrc, iSrc, iColLeft);
pE2 = sqlite3CreateColumnExpr(db, pSrc, iSrc+1, iColRight);
pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft);
pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight);
pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0);
if( pEq && isOuterJoin ){
@ -308,11 +343,15 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
"an ON or USING clause", 0);
return 1;
}
for(j=0; j<pLeftTab->nCol; j++){
char *zName = pLeftTab->aCol[j].zName;
int iRightCol = columnIndex(pRightTab, zName);
if( iRightCol>=0 ){
addWhereTerm(pParse, pSrc, i, j, iRightCol, isOuter, &p->pWhere);
for(j=0; j<pRightTab->nCol; j++){
char *zName; /* Name of column in the right table */
int iLeft; /* Matching left table */
int iLeftCol; /* Matching column in the left table */
zName = pRightTab->aCol[j].zName;
if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) ){
addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j,
isOuter, &p->pWhere);
}
}
}
@ -344,15 +383,22 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
if( pRight->pUsing ){
IdList *pList = pRight->pUsing;
for(j=0; j<pList->nId; j++){
char *zName = pList->a[j].zName;
int iLeftCol = columnIndex(pLeftTab, zName);
int iRightCol = columnIndex(pRightTab, zName);
if( iLeftCol<0 || iRightCol<0 ){
char *zName; /* Name of the term in the USING clause */
int iLeft; /* Table on the left with matching column name */
int iLeftCol; /* Column number of matching column on the left */
int iRightCol; /* Column number of matching column on the right */
zName = pList->a[j].zName;
iRightCol = columnIndex(pRightTab, zName);
if( iRightCol<0
|| !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol)
){
sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
"not present in both tables", zName);
return 1;
}
addWhereTerm(pParse, pSrc, i, iLeftCol, iRightCol, isOuter, &p->pWhere);
addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, iRightCol,
isOuter, &p->pWhere);
}
}
}
@ -911,7 +957,7 @@ static const char *columnType(
** of the SELECT statement. Return the declaration type and origin
** data for the result-set column of the sub-select.
*/
if( ALWAYS(iCol>=0 && iCol<pS->pEList->nExpr) ){
if( iCol>=0 && ALWAYS(iCol<pS->pEList->nExpr) ){
/* If iCol is less than zero, then the expression requests the
** rowid of the sub-select or view. This expression is legal (see
** test case misc2.2.2) - it always evaluates to NULL.
@ -2472,7 +2518,7 @@ static void substSelect(
**
** (11) The subquery and the outer query do not both have ORDER BY clauses.
**
** (12) Not implemented. Subsumed into restriction (3). Was previously
** (**) Not implemented. Subsumed into restriction (3). Was previously
** a separate restriction deriving from ticket #350.
**
** (13) The subquery and outer query do not both use LIMIT
@ -2546,6 +2592,7 @@ static int flattenSubquery(
*/
assert( p!=0 );
assert( p->pPrior==0 ); /* Unable to flatten compound queries */
if( db->flags & SQLITE_QueryFlattener ) return 0;
pSrc = p->pSrc;
assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
pSubitem = &pSrc->a[iFrom];
@ -3169,14 +3216,14 @@ static int selectExpander(Walker *pWalker, Select *p){
}
if( i>0 && zTName==0 ){
struct SrcList_item *pLeft = &pTabList->a[i-1];
if( (pLeft[1].jointype & JT_NATURAL)!=0 &&
columnIndex(pLeft->pTab, zName)>=0 ){
if( (pFrom->jointype & JT_NATURAL)!=0
&& tableAndColumnIndex(pTabList, i, zName, 0, 0)
){
/* In a NATURAL join, omit the join columns from the
** table on the right */
** table to the right of the join */
continue;
}
if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){
if( sqlite3IdListIndex(pFrom->pUsing, zName)>=0 ){
/* In a join with a USING clause, omit columns in the
** using clause from the table on the right. */
continue;
@ -3280,18 +3327,19 @@ static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
struct SrcList_item *pFrom;
assert( p->selFlags & SF_Resolved );
assert( (p->selFlags & SF_HasTypeInfo)==0 );
p->selFlags |= SF_HasTypeInfo;
pParse = pWalker->pParse;
pTabList = p->pSrc;
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
Table *pTab = pFrom->pTab;
if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
/* A sub-query in the FROM clause of a SELECT */
Select *pSel = pFrom->pSelect;
assert( pSel );
while( pSel->pPrior ) pSel = pSel->pPrior;
selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
if( (p->selFlags & SF_HasTypeInfo)==0 ){
p->selFlags |= SF_HasTypeInfo;
pParse = pWalker->pParse;
pTabList = p->pSrc;
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
Table *pTab = pFrom->pTab;
if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
/* A sub-query in the FROM clause of a SELECT */
Select *pSel = pFrom->pSelect;
assert( pSel );
while( pSel->pPrior ) pSel = pSel->pPrior;
selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
}
}
}
return WRC_Continue;
@ -3443,8 +3491,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
(void*)pF->pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nArg);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
if( addrNext ){
sqlite3VdbeResolveLabel(v, addrNext);
sqlite3ExprCacheClear(pParse);
@ -3870,7 +3918,7 @@ int sqlite3Select(
int r2;
r2 = sqlite3ExprCodeGetColumn(pParse,
pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0);
pCol->pTab, pCol->iColumn, pCol->iTable, r1);
if( r1!=r2 ){
sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -76,41 +76,43 @@
#include <inttypes.h>
#endif
/*
** The number of samples of an index that SQLite takes in order to
** construct a histogram of the table content when running ANALYZE
** and with SQLITE_ENABLE_STAT2
*/
#define SQLITE_INDEX_SAMPLES 10
/*
** This macro is used to "hide" some ugliness in casting an int
** value to a ptr value under the MSVC 64-bit compiler. Casting
** non 64-bit values to ptr types results in a "hard" error with
** the MSVC 64-bit compiler which this attempts to avoid.
** The following macros are used to cast pointers to integers and
** integers to pointers. The way you do this varies from one compiler
** to the next, so we have developed the following set of #if statements
** to generate appropriate macros for a wide range of compilers.
**
** A simple compiler pragma or casting sequence could not be found
** to correct this in all situations, so this macro was introduced.
**
** It could be argued that the intptr_t type could be used in this
** case, but that type is not available on all compilers, or
** requires the #include of specific headers which differs between
** platforms.
** The correct "ANSI" way to do this is to use the intptr_t type.
** Unfortunately, that typedef is not available on all compilers, or
** if it is available, it requires an #include of specific headers
** that very from one machine to the next.
**
** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on
** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)).
** So we have to define the macros in different ways depending on the
** compiler.
*/
#if defined(__GNUC__)
# if defined(HAVE_STDINT_H)
# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
# else
# define SQLITE_INT_TO_PTR(X) ((void*)(X))
# define SQLITE_PTR_TO_INT(X) ((int)(X))
# endif
#else
# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X))
# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X))
#elif !defined(__GNUC__) /* Works for compilers other than LLVM */
# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
#else /* Generates a warning - but it always works */
# define SQLITE_INT_TO_PTR(X) ((void*)(X))
# define SQLITE_PTR_TO_INT(X) ((int)(X))
#endif
/*
** The SQLITE_THREADSAFE macro must be defined as either 0 or 1.
** Older versions of SQLite used an optional THREADSAFE macro.
@ -140,23 +142,18 @@
**
** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
** SQLITE_MEMDEBUG // Debugging version of system malloc()
** SQLITE_MEMORY_SIZE // internal allocator #1
** SQLITE_MMAP_HEAP_SIZE // internal mmap() allocator
** SQLITE_POW2_MEMORY_SIZE // internal power-of-two allocator
**
** (Historical note: There used to be several other options, but we've
** pared it down to just these two.)
**
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
** the default.
*/
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\
defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\
defined(SQLITE_POW2_MEMORY_SIZE)>1
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)>1
# error "At most one of the following compile-time configuration options\
is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG, SQLITE_MEMORY_SIZE,\
SQLITE_MMAP_HEAP_SIZE, SQLITE_POW2_MEMORY_SIZE"
is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG"
#endif
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\
defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\
defined(SQLITE_POW2_MEMORY_SIZE)==0
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)==0
# define SQLITE_SYSTEM_MALLOC 1
#endif
@ -328,20 +325,6 @@
#define OMIT_TEMPDB 0
#endif
/*
** If the following macro is set to 1, then NULL values are considered
** distinct when determining whether or not two entries are the same
** in a UNIQUE index. This is the way PostgreSQL, Oracle, DB2, MySQL,
** OCELOT, and Firebird all work. The SQL92 spec explicitly says this
** is the way things are suppose to work.
**
** If the following macro is set to 0, the NULLs are indistinct for
** a UNIQUE index. In this mode, you can only have a single NULL entry
** for a column declared UNIQUE. This is the way Informix and SQL Server
** work.
*/
#define NULL_DISTINCT_FOR_UNIQUE 1
/*
** The "file format" number is an integer that is incremented whenever
** the VDBE-level file format changes. The following macros define the
@ -353,6 +336,10 @@
# define SQLITE_DEFAULT_FILE_FORMAT 1
#endif
/*
** Determine whether triggers are recursive by default. This can be
** changed at run-time using a pragma.
*/
#ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS
# define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0
#endif
@ -597,7 +584,6 @@ typedef struct AggInfo AggInfo;
typedef struct AuthContext AuthContext;
typedef struct AutoincInfo AutoincInfo;
typedef struct Bitvec Bitvec;
typedef struct RowSet RowSet;
typedef struct CollSeq CollSeq;
typedef struct Column Column;
typedef struct Db Db;
@ -618,6 +604,7 @@ typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module;
typedef struct NameContext NameContext;
typedef struct Parse Parse;
typedef struct RowSet RowSet;
typedef struct Savepoint Savepoint;
typedef struct Select Select;
typedef struct SrcList SrcList;
@ -625,9 +612,9 @@ typedef struct StrAccum StrAccum;
typedef struct Table Table;
typedef struct TableLock TableLock;
typedef struct Token Token;
typedef struct Trigger Trigger;
typedef struct TriggerPrg TriggerPrg;
typedef struct TriggerStep TriggerStep;
typedef struct Trigger Trigger;
typedef struct UnpackedRecord UnpackedRecord;
typedef struct VTable VTable;
typedef struct Walker Walker;
@ -693,7 +680,7 @@ struct Schema {
/*
** These macros can be used to test, set, or clear bits in the
** Db.flags field.
** Db.pSchema->flags field.
*/
#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P))
#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0)
@ -701,7 +688,7 @@ struct Schema {
#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P)
/*
** Allowed values for the DB.flags field.
** Allowed values for the DB.pSchema->flags field.
**
** The DB_SchemaLoaded flag is set after the database schema has been
** read into internal hash tables.
@ -765,7 +752,7 @@ struct FuncDefHash {
};
/*
** Each database is an instance of the following structure.
** Each database connection is an instance of the following structure.
**
** The sqlite.lastRowid records the last insert rowid generated by an
** insert statement. Inserts on views do not affect its value. Each
@ -804,6 +791,7 @@ struct sqlite3 {
u8 dfltLockMode; /* Default locking-mode for attached dbs */
u8 dfltJournalMode; /* Default journal mode for attached dbs */
signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */
u8 suppressErr; /* Do not issue error messages if true */
int nextPagesize; /* Pagesize after VACUUM if >0 */
int nTable; /* Number of tables in the database */
CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
@ -898,37 +886,43 @@ struct sqlite3 {
#define ENC(db) ((db)->aDb[0].pSchema->enc)
/*
** Possible values for the sqlite.flags and or Db.flags fields.
**
** On sqlite.flags, the SQLITE_InTrans value means that we have
** executed a BEGIN. On Db.flags, SQLITE_InTrans means a statement
** transaction is active on that particular database file.
** Possible values for the sqlite3.flags.
*/
#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
#define SQLITE_InTrans 0x00000008 /* True if in a transaction */
#define SQLITE_InternChanges 0x00000010 /* Uncommitted Hash table changes */
#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */
#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */
#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */
#define SQLITE_VdbeTrace 0x00000100 /* True to trace VDBE execution */
#define SQLITE_InternChanges 0x00000200 /* Uncommitted Hash table changes */
#define SQLITE_FullColNames 0x00000400 /* Show full column names on SELECT */
#define SQLITE_ShortColNames 0x00000800 /* Show short columns names */
#define SQLITE_CountRows 0x00001000 /* Count rows changed by INSERT, */
/* DELETE, or UPDATE and return */
/* the count using a callback. */
#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */
#define SQLITE_NullCallback 0x00002000 /* Invoke the callback once if the */
/* result set is empty */
#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */
#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */
#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */
#define SQLITE_NoReadlock 0x00001000 /* Readlocks are omitted when
#define SQLITE_SqlTrace 0x00004000 /* Debug print SQL as it executes */
#define SQLITE_VdbeListing 0x00008000 /* Debug listings of VDBE programs */
#define SQLITE_WriteSchema 0x00010000 /* OK to update SQLITE_MASTER */
#define SQLITE_NoReadlock 0x00020000 /* Readlocks are omitted when
** accessing read-only databases */
#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */
#define SQLITE_ReadUncommitted 0x00004000 /* For shared-cache mode */
#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */
#define SQLITE_FullFSync 0x00010000 /* Use full fsync on the backend */
#define SQLITE_LoadExtension 0x00020000 /* Enable load_extension */
#define SQLITE_IgnoreChecks 0x00040000 /* Do not enforce check constraints */
#define SQLITE_ReadUncommitted 0x0080000 /* For shared-cache mode */
#define SQLITE_LegacyFileFmt 0x00100000 /* Create new databases in format 1 */
#define SQLITE_FullFSync 0x00200000 /* Use full fsync on the backend */
#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */
#define SQLITE_RecoveryMode 0x00800000 /* Ignore schema errors */
#define SQLITE_ReverseOrder 0x01000000 /* Reverse unordered SELECTs */
#define SQLITE_RecTriggers 0x02000000 /* Enable recursive triggers */
#define SQLITE_ForeignKeys 0x04000000 /* Enforce foreign key constraints */
#define SQLITE_RecoveryMode 0x00040000 /* Ignore schema errors */
#define SQLITE_ReverseOrder 0x00100000 /* Reverse unordered SELECTs */
#define SQLITE_RecTriggers 0x00200000 /* Enable recursive triggers */
#define SQLITE_ForeignKeys 0x00400000 /* Enforce foreign key constraints */
/*
** Bits of the sqlite3.flags field that are used by the
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface.
** These must be the low-order bits of the flags field.
*/
#define SQLITE_QueryFlattener 0x01 /* Disable query flattening */
#define SQLITE_ColumnCache 0x02 /* Disable the column cache */
#define SQLITE_IndexSort 0x04 /* Disable indexes for sorting */
#define SQLITE_IndexSearch 0x08 /* Disable indexes for searching */
#define SQLITE_IndexCover 0x10 /* Disable index covering table */
#define SQLITE_OptMask 0x1f /* Mask of all disablable opts */
/*
** Possible values for the sqlite.magic field.
@ -1642,14 +1636,13 @@ struct Expr {
#define EP_DblQuoted 0x0040 /* token.z was originally in "..." */
#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
#define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */
#define EP_AnyAff 0x0200 /* Can take a cached column of any affinity */
#define EP_FixedDest 0x0400 /* Result needed in a specific register */
#define EP_IntValue 0x0800 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x1000 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_FixedDest 0x0200 /* Result needed in a specific register */
#define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
#define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
#define EP_Static 0x8000 /* Held in memory not obtained from malloc() */
#define EP_Reduced 0x1000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
#define EP_TokenOnly 0x2000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
#define EP_Static 0x4000 /* Held in memory not obtained from malloc() */
/*
** The following are the meanings of bits in the Expr.flags2 field.
@ -1894,6 +1887,7 @@ struct WhereLevel {
#define WHERE_OMIT_OPEN 0x0010 /* Table cursor are already open */
#define WHERE_OMIT_CLOSE 0x0020 /* Omit close of table & index cursors */
#define WHERE_FORCE_TABLE 0x0040 /* Do not use an index-only search */
#define WHERE_ONETABLE_ONLY 0x0080 /* Only code the 1st table in pTabList */
/*
** The WHERE clause processing routine has two halves. The
@ -1906,6 +1900,7 @@ struct WhereInfo {
Parse *pParse; /* Parsing and code generating context */
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
SrcList *pTabList; /* List of tables in the join */
int iTop; /* The very beginning of the WHERE loop */
int iContinue; /* Jump here to continue with next record */
@ -2125,7 +2120,6 @@ struct Parse {
struct yColCache {
int iTable; /* Table cursor number */
int iColumn; /* Table column number */
u8 affChange; /* True if this register has had an affinity change */
u8 tempReg; /* iReg is a temp register that needs to be freed */
int iLevel; /* Nesting level */
int iReg; /* Reg with value of this column. 0 means none. */
@ -2374,6 +2368,8 @@ struct Sqlite3Config {
int isPCacheInit; /* True after malloc is initialized */
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
int nRefInitMutex; /* Number of users of pInitMutex */
void (*xLog)(void*,int,const char*); /* Function for logging */
void *pLogArg; /* First argument to xLog() */
};
/*
@ -2415,16 +2411,27 @@ int sqlite3WalkSelectFrom(Walker*, Select*);
}
/*
** The SQLITE_CORRUPT_BKPT macro can be either a constant (for production
** builds) or a function call (for debugging). If it is a function call,
** it allows the operator to set a breakpoint at the spot where database
** corruption is first detected.
** The SQLITE_*_BKPT macros are substitutes for the error codes with
** the same name but without the _BKPT suffix. These macros invoke
** routines that report the line-number on which the error originated
** using sqlite3_log(). The routines also provide a convenient place
** to set a debugger breakpoint.
*/
#ifdef SQLITE_DEBUG
int sqlite3Corrupt(void);
# define SQLITE_CORRUPT_BKPT sqlite3Corrupt()
#else
# define SQLITE_CORRUPT_BKPT SQLITE_CORRUPT
int sqlite3CorruptError(int);
int sqlite3MisuseError(int);
int sqlite3CantopenError(int);
#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__)
#define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__)
#define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__)
/*
** FTS4 is really an extension for FTS3. It is enabled using the
** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all
** the SQLITE_ENABLE_FTS4 macro to serve as an alisse for SQLITE_ENABLE_FTS3.
*/
#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
# define SQLITE_ENABLE_FTS3
#endif
/*
@ -2526,7 +2533,11 @@ int sqlite3StatusValue(int);
void sqlite3StatusAdd(int, int);
void sqlite3StatusSet(int, int);
int sqlite3IsNaN(double);
#ifndef SQLITE_OMIT_FLOATING_POINT
int sqlite3IsNaN(double);
#else
# define sqlite3IsNaN(X) 0
#endif
void sqlite3VXPrintf(StrAccum*, int, const char*, va_list);
#ifndef SQLITE_OMIT_TRACE
@ -2543,7 +2554,6 @@ char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
#endif
void sqlite3SetString(char **, sqlite3*, const char*, ...);
void sqlite3ErrorMsg(Parse*, const char*, ...);
void sqlite3ErrorClear(Parse*);
int sqlite3Dequote(char*);
int sqlite3KeywordCode(const unsigned char*, int);
int sqlite3RunParser(Parse*, const char*, char **);
@ -2644,13 +2654,13 @@ void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16);
void sqlite3WhereEnd(WhereInfo*);
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int);
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
void sqlite3ExprCodeMove(Parse*, int, int, int);
void sqlite3ExprCodeCopy(Parse*, int, int, int);
void sqlite3ExprCacheStore(Parse*, int, int, int);
void sqlite3ExprCachePush(Parse*);
void sqlite3ExprCachePop(Parse*, int);
void sqlite3ExprCacheRemove(Parse*, int);
void sqlite3ExprCacheRemove(Parse*, int, int);
void sqlite3ExprCacheClear(Parse*);
void sqlite3ExprCacheAffinityChange(Parse*, int, int);
void sqlite3ExprHardCopy(Parse*,int,int);
@ -2713,13 +2723,6 @@ FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int);
void sqlite3RegisterBuiltinFunctions(sqlite3*);
void sqlite3RegisterDateTimeFunctions(void);
void sqlite3RegisterGlobalFunctions(void);
#ifdef SQLITE_DEBUG
int sqlite3SafetyOn(sqlite3*);
int sqlite3SafetyOff(sqlite3*);
#else
# define sqlite3SafetyOn(A) 0
# define sqlite3SafetyOff(A) 0
#endif
int sqlite3SafetyCheckOk(sqlite3*);
int sqlite3SafetyCheckSickOrOk(sqlite3*);
void sqlite3ChangeCookie(Parse*, int);
@ -2855,7 +2858,7 @@ void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
void(*)(void*));
void sqlite3ValueFree(sqlite3_value*);
sqlite3_value *sqlite3ValueNew(sqlite3 *);
char *sqlite3Utf16to8(sqlite3 *, const void*, int);
char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
#ifdef SQLITE_ENABLE_STAT2
char *sqlite3Utf8to16(sqlite3 *, u8, char *, int, int *);
#endif

View File

@ -83,7 +83,7 @@ void sqlite3StatusSet(int op, int X){
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
wsdStatInit;
if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
*pCurrent = wsdStat.nowValue[op];
*pHighwater = wsdStat.mxValue[op];

View File

@ -4909,7 +4909,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
extern int sqlite3_open_file_count;
extern int sqlite3_sort_count;
extern int sqlite3_current_time;
#if SQLITE_OS_UNIX && defined(__APPLE__)
#if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
extern int sqlite3_hostid_num;
#endif
extern int sqlite3_max_blobsize;
@ -5140,7 +5140,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
(char*)&sqlite3_open_file_count, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_current_time",
(char*)&sqlite3_current_time, TCL_LINK_INT);
#if SQLITE_OS_UNIX && defined(__APPLE__)
#if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
Tcl_LinkVar(interp, "sqlite_hostid_num",
(char*)&sqlite3_hostid_num, TCL_LINK_INT);
#endif

View File

@ -219,7 +219,7 @@ static int btree_cursor(
Btree *pBt;
int iTable;
BtCursor *pCur;
int rc;
int rc = SQLITE_OK;
int wrFlag;
char zBuf[30];
@ -234,7 +234,9 @@ static int btree_cursor(
pCur = (BtCursor *)ckalloc(sqlite3BtreeCursorSize());
memset(pCur, 0, sqlite3BtreeCursorSize());
sqlite3BtreeEnter(pBt);
#ifndef SQLITE_OMIT_SHARED_CACHE
rc = sqlite3BtreeLockTable(pBt, iTable, wrFlag);
#endif
if( rc==SQLITE_OK ){
rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur);
}

View File

@ -183,7 +183,11 @@ static void set_options(Tcl_Interp *interp){
TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS
Tcl_SetVar2(interp, "sqlite_options", "compileoption_diags", "0", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "compileoption_diags", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_COMPLETE
Tcl_SetVar2(interp, "sqlite_options", "complete", "0", TCL_GLOBAL_ONLY);

View File

@ -341,6 +341,7 @@ static void testHexToBin(const char *zIn, char *zOut){
** Convert the input string from HEX into binary. Then return the
** result using sqlite3_result_text16le().
*/
#ifndef SQLITE_OMIT_UTF16
static void testHexToUtf16be(
sqlite3_context *pCtx,
int nArg,
@ -360,6 +361,7 @@ static void testHexToUtf16be(
sqlite3_result_text16be(pCtx, zOut, n/2, sqlite3_free);
}
}
#endif
/*
** hex_to_utf8(HEX)
@ -393,6 +395,7 @@ static void testHexToUtf8(
** Convert the input string from HEX into binary. Then return the
** result using sqlite3_result_text16le().
*/
#ifndef SQLITE_OMIT_UTF16
static void testHexToUtf16le(
sqlite3_context *pCtx,
int nArg,
@ -412,6 +415,7 @@ static void testHexToUtf16le(
sqlite3_result_text16le(pCtx, zOut, n/2, sqlite3_free);
}
}
#endif
static int registerTestFunctions(sqlite3 *db){
static const struct {

View File

@ -330,12 +330,12 @@ static int getFts3Varint(const char *p, sqlite_int64 *v){
/*
** USAGE: read_varint BLOB VARNAME
** USAGE: read_fts3varint BLOB VARNAME
**
** Read a varint from the start of BLOB. Set variable VARNAME to contain
** the interpreted value. Return the number of bytes of BLOB consumed.
*/
static int read_varint(
static int read_fts3varint(
void * clientData,
Tcl_Interp *interp,
int objc,
@ -373,7 +373,7 @@ int Sqlitetest_hexio_Init(Tcl_Interp *interp){
{ "hexio_render_int16", hexio_render_int16 },
{ "hexio_render_int32", hexio_render_int32 },
{ "utf8_to_utf8", utf8_to_utf8 },
{ "read_varint", read_varint },
{ "read_fts3varint", read_fts3varint },
};
int i;
for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){

View File

@ -123,8 +123,9 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
}
case '-': {
if( z[1]=='-' ){
/* IMP: R-15891-05542 -- syntax diagram for comments */
for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
*tokenType = TK_SPACE;
*tokenType = TK_SPACE; /* IMP: R-22934-25134 */
return i;
}
*tokenType = TK_MINUS;
@ -155,9 +156,10 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
*tokenType = TK_SLASH;
return 1;
}
/* IMP: R-15891-05542 -- syntax diagram for comments */
for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
if( c ) i++;
*tokenType = TK_SPACE;
*tokenType = TK_SPACE; /* IMP: R-22934-25134 */
return i;
}
case '%': {
@ -478,6 +480,7 @@ abort_parse:
assert( pzErrMsg!=0 );
if( pParse->zErrMsg ){
*pzErrMsg = pParse->zErrMsg;
sqlite3_log(pParse->rc, "%s", *pzErrMsg);
pParse->zErrMsg = 0;
nErr++;
}

View File

@ -126,7 +126,8 @@ void sqlite3BeginTrigger(
goto trigger_cleanup;
}
pTab = sqlite3SrcListLookup(pParse, pTableName);
if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){
if( db->init.busy==0 && pName2->n==0 && pTab
&& pTab->pSchema==db->aDb[1].pSchema ){
iDb = 1;
}
@ -254,12 +255,12 @@ void sqlite3FinishTrigger(
TriggerStep *pStepList, /* The triggered program */
Token *pAll /* Token that describes the complete CREATE TRIGGER */
){
Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */
char *zName; /* Name of trigger */
sqlite3 *db = pParse->db; /* The database */
DbFixer sFix;
int iDb; /* Database containing the trigger */
Token nameToken; /* Trigger name for error reporting */
Trigger *pTrig = pParse->pNewTrigger; /* Trigger being finished */
char *zName; /* Name of trigger */
sqlite3 *db = pParse->db; /* The database */
DbFixer sFix; /* Fixer object */
int iDb; /* Database containing the trigger */
Token nameToken; /* Trigger name for error reporting */
pTrig = pParse->pNewTrigger;
pParse->pNewTrigger = 0;
@ -278,7 +279,7 @@ void sqlite3FinishTrigger(
goto triggerfinish_cleanup;
}
/* if we are not initializing, and this trigger is not on a TEMP table,
/* if we are not initializing,
** build the sqlite_master entry
*/
if( !db->init.busy ){

View File

@ -437,11 +437,11 @@ int sqlite3Utf8To8(unsigned char *zIn){
**
** NULL is returned if there is an allocation error.
*/
char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte){
char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
Mem m;
memset(&m, 0, sizeof(m));
m.db = db;
sqlite3VdbeMemSetStr(&m, z, nByte, SQLITE_UTF16NATIVE, SQLITE_STATIC);
sqlite3VdbeMemSetStr(&m, z, nByte, enc, SQLITE_STATIC);
sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8);
if( db->mallocFailed ){
sqlite3VdbeMemRelease(&m);
@ -449,7 +449,9 @@ char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte){
}
assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
return (m.flags & MEM_Dyn)!=0 ? m.z : sqlite3DbStrDup(db, m.z);
assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
assert( m.z || db->mallocFailed );
return m.z;
}
/*

View File

@ -31,6 +31,7 @@ void sqlite3Coverage(int x){
}
#endif
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Return true if the floating point value is Not a Number (NaN).
**
@ -75,6 +76,7 @@ int sqlite3IsNaN(double x){
testcase( rc );
return rc;
}
#endif /* SQLITE_OMIT_FLOATING_POINT */
/*
** Compute a string length that is limited to what can be stored in
@ -146,23 +148,20 @@ void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){
** (sqlite3_step() etc.).
*/
void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
char *zMsg;
va_list ap;
sqlite3 *db = pParse->db;
pParse->nErr++;
sqlite3DbFree(db, pParse->zErrMsg);
va_start(ap, zFormat);
pParse->zErrMsg = sqlite3VMPrintf(db, zFormat, ap);
zMsg = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
pParse->rc = SQLITE_ERROR;
}
/*
** Clear the error message in pParse, if any
*/
void sqlite3ErrorClear(Parse *pParse){
sqlite3DbFree(pParse->db, pParse->zErrMsg);
pParse->zErrMsg = 0;
pParse->nErr = 0;
if( db->suppressErr ){
sqlite3DbFree(db, zMsg);
}else{
pParse->nErr++;
sqlite3DbFree(db, pParse->zErrMsg);
pParse->zErrMsg = zMsg;
pParse->rc = SQLITE_ERROR;
}
}
/*
@ -255,6 +254,7 @@ int sqlite3IsNumber(const char *z, int *realnum, u8 enc){
z += incr;
*realnum = 0;
while( sqlite3Isdigit(*z) ){ z += incr; }
#ifndef SQLITE_OMIT_FLOATING_POINT
if( *z=='.' ){
z += incr;
if( !sqlite3Isdigit(*z) ) return 0;
@ -268,6 +268,7 @@ int sqlite3IsNumber(const char *z, int *realnum, u8 enc){
while( sqlite3Isdigit(*z) ){ z += incr; }
*realnum = 1;
}
#endif
return *z==0;
}
@ -429,6 +430,9 @@ static int compare2pow63(const char *zNum){
c = memcmp(zNum,"922337203685477580",18)*10;
if( c==0 ){
c = zNum[18] - '8';
testcase( c==(-1) );
testcase( c==0 );
testcase( c==(+1) );
}
return c;
}
@ -465,6 +469,9 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum){
v = v*10 + c - '0';
}
*pNum = neg ? -v : v;
testcase( i==18 );
testcase( i==19 );
testcase( i==20 );
if( c!=0 || (i==0 && zStart==zNum) || i>19 ){
/* zNum is empty or contains non-numeric text or is longer
** than 19 digits (thus guaranting that it is too large) */
@ -508,6 +515,9 @@ int sqlite3FitsIn64Bits(const char *zNum, int negFlag){
zNum++; /* Skip leading zeros. Ticket #2454 */
}
for(i=0; zNum[i]; i++){ assert( zNum[i]>='0' && zNum[i]<='9' ); }
testcase( i==18 );
testcase( i==19 );
testcase( i==20 );
if( i<19 ){
/* Guaranteed to fit if less than 19 digits */
return 1;
@ -548,9 +558,11 @@ int sqlite3GetInt32(const char *zNum, int *pValue){
** 1234567890
** 2^31 -> 2147483648
*/
testcase( i==10 );
if( i>10 ){
return 0;
}
testcase( v-neg==2147483647 );
if( v-neg>2147483647 ){
return 0;
}
@ -638,6 +650,19 @@ int sqlite3PutVarint32(unsigned char *p, u32 v){
return sqlite3PutVarint(p, v);
}
/*
** Bitmasks used by sqlite3GetVarint(). These precomputed constants
** are defined here rather than simply putting the constant expressions
** inline in order to work around bugs in the RVT compiler.
**
** SLOT_2_0 A mask for (0x7f<<14) | 0x7f
**
** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0
*/
#define SLOT_2_0 0x001fc07f
#define SLOT_4_2_0 0xf01fc07f
/*
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read. The value is stored in *v.
@ -665,13 +690,17 @@ u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
return 2;
}
/* Verify that constants are precomputed correctly */
assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );
p++;
a = a<<14;
a |= *p;
/* a: p0<<14 | p2 (unmasked) */
if (!(a&0x80))
{
a &= (0x7f<<14)|(0x7f);
a &= SLOT_2_0;
b &= 0x7f;
b = b<<7;
a |= b;
@ -680,14 +709,14 @@ u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
}
/* CSE1 from below */
a &= (0x7f<<14)|(0x7f);
a &= SLOT_2_0;
p++;
b = b<<14;
b |= *p;
/* b: p1<<14 | p3 (unmasked) */
if (!(b&0x80))
{
b &= (0x7f<<14)|(0x7f);
b &= SLOT_2_0;
/* moved CSE1 up */
/* a &= (0x7f<<14)|(0x7f); */
a = a<<7;
@ -701,7 +730,7 @@ u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
/* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
/* moved CSE1 up */
/* a &= (0x7f<<14)|(0x7f); */
b &= (0x7f<<14)|(0x7f);
b &= SLOT_2_0;
s = a;
/* s: p0<<14 | p2 (masked) */
@ -734,7 +763,7 @@ u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
{
/* we can skip this cause it was (effectively) done above in calc'ing s */
/* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
a &= (0x7f<<14)|(0x7f);
a &= SLOT_2_0;
a = a<<7;
a |= b;
s = s>>18;
@ -748,8 +777,8 @@ u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
/* a: p2<<28 | p4<<14 | p6 (unmasked) */
if (!(a&0x80))
{
a &= (0x1f<<28)|(0x7f<<14)|(0x7f);
b &= (0x7f<<14)|(0x7f);
a &= SLOT_4_2_0;
b &= SLOT_2_0;
b = b<<7;
a |= b;
s = s>>11;
@ -758,14 +787,14 @@ u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
}
/* CSE2 from below */
a &= (0x7f<<14)|(0x7f);
a &= SLOT_2_0;
p++;
b = b<<14;
b |= *p;
/* b: p3<<28 | p5<<14 | p7 (unmasked) */
if (!(b&0x80))
{
b &= (0x1f<<28)|(0x7f<<14)|(0x7f);
b &= SLOT_4_2_0;
/* moved CSE2 up */
/* a &= (0x7f<<14)|(0x7f); */
a = a<<7;
@ -782,7 +811,7 @@ u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
/* moved CSE2 up */
/* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
b &= (0x7f<<14)|(0x7f);
b &= SLOT_2_0;
b = b<<8;
a |= b;
@ -902,9 +931,9 @@ u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
/* a: p0<<28 | p2<<14 | p4 (unmasked) */
if (!(a&0x80))
{
/* Walues between 268435456 and 34359738367 */
a &= (0x1f<<28)|(0x7f<<14)|(0x7f);
b &= (0x1f<<28)|(0x7f<<14)|(0x7f);
/* Values between 268435456 and 34359738367 */
a &= SLOT_4_2_0;
b &= SLOT_4_2_0;
b = b<<7;
*v = a | b;
return 5;
@ -997,64 +1026,17 @@ void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
}
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
/*
** Change the sqlite.magic from SQLITE_MAGIC_OPEN to SQLITE_MAGIC_BUSY.
** 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.
** But usually the problem will be seen. The result will be an
** error which can be used to debug the application that is
** using SQLite incorrectly.
**
** Ticket #202: If db->magic is not a valid open value, take care not
** to modify the db structure at all. It could be that db is a stale
** pointer. In other words, it could be that there has been a prior
** call to sqlite3_close(db) and db has been deallocated. And we do
** not want to write into deallocated memory.
** Log an error that is an API call on a connection pointer that should
** not have been used. The "type" of connection pointer is given as the
** argument. The zType is a word like "NULL" or "closed" or "invalid".
*/
#ifdef SQLITE_DEBUG
int sqlite3SafetyOn(sqlite3 *db){
if( db->magic==SQLITE_MAGIC_OPEN ){
db->magic = SQLITE_MAGIC_BUSY;
assert( sqlite3_mutex_held(db->mutex) );
return 0;
}else if( db->magic==SQLITE_MAGIC_BUSY ){
db->magic = SQLITE_MAGIC_ERROR;
db->u1.isInterrupted = 1;
}
return 1;
static void logBadConnection(const char *zType){
sqlite3_log(SQLITE_MISUSE,
"API call with %s database connection pointer",
zType
);
}
#endif
/*
** Change the magic from SQLITE_MAGIC_BUSY to SQLITE_MAGIC_OPEN.
** Return an error (non-zero) if the magic was not SQLITE_MAGIC_BUSY
** when this routine is called.
*/
#ifdef SQLITE_DEBUG
int sqlite3SafetyOff(sqlite3 *db){
if( db->magic==SQLITE_MAGIC_BUSY ){
db->magic = SQLITE_MAGIC_OPEN;
assert( sqlite3_mutex_held(db->mutex) );
return 0;
}else{
db->magic = SQLITE_MAGIC_ERROR;
db->u1.isInterrupted = 1;
return 1;
}
}
#endif
/*
** Check to make sure we have a valid db pointer. This test is not
@ -1072,13 +1054,16 @@ int sqlite3SafetyOff(sqlite3 *db){
*/
int sqlite3SafetyCheckOk(sqlite3 *db){
u32 magic;
if( db==0 ) return 0;
if( db==0 ){
logBadConnection("NULL");
return 0;
}
magic = db->magic;
if( magic!=SQLITE_MAGIC_OPEN
#ifdef SQLITE_DEBUG
&& magic!=SQLITE_MAGIC_BUSY
#endif
){
if( magic!=SQLITE_MAGIC_OPEN ){
if( sqlite3SafetyCheckSickOrOk(db) ){
testcase( sqlite3GlobalConfig.xLog!=0 );
logBadConnection("unopened");
}
return 0;
}else{
return 1;
@ -1089,6 +1074,11 @@ int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
magic = db->magic;
if( magic!=SQLITE_MAGIC_SICK &&
magic!=SQLITE_MAGIC_OPEN &&
magic!=SQLITE_MAGIC_BUSY ) return 0;
return 1;
magic!=SQLITE_MAGIC_BUSY ){
testcase( sqlite3GlobalConfig.xLog!=0 );
logBadConnection("invalid");
return 0;
}else{
return 1;
}
}

View File

@ -18,28 +18,42 @@
#include "vdbeInt.h"
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
/*
** Finalize a prepared statement. If there was an error, store the
** text of the error message in *pzErrMsg. Return the result code.
*/
static int vacuumFinalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){
int rc;
rc = sqlite3VdbeFinalize((Vdbe*)pStmt);
if( rc ){
sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
}
return rc;
}
/*
** Execute zSql on database db. Return an error code.
*/
static int execSql(sqlite3 *db, const char *zSql){
static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
sqlite3_stmt *pStmt;
VVA_ONLY( int rc; )
if( !zSql ){
return SQLITE_NOMEM;
}
if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
return sqlite3_errcode(db);
}
VVA_ONLY( rc = ) sqlite3_step(pStmt);
assert( rc!=SQLITE_ROW );
return sqlite3_finalize(pStmt);
return vacuumFinalize(db, pStmt, pzErrMsg);
}
/*
** Execute zSql on database db. The statement returns exactly
** one column. Execute this as SQL on the same database.
*/
static int execExecSql(sqlite3 *db, const char *zSql){
static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
sqlite3_stmt *pStmt;
int rc;
@ -47,14 +61,14 @@ static int execExecSql(sqlite3 *db, const char *zSql){
if( rc!=SQLITE_OK ) return rc;
while( SQLITE_ROW==sqlite3_step(pStmt) ){
rc = execSql(db, (char*)sqlite3_column_text(pStmt, 0));
rc = execSql(db, pzErrMsg, (char*)sqlite3_column_text(pStmt, 0));
if( rc!=SQLITE_OK ){
sqlite3_finalize(pStmt);
vacuumFinalize(db, pStmt, pzErrMsg);
return rc;
}
}
return sqlite3_finalize(pStmt);
return vacuumFinalize(db, pStmt, pzErrMsg);
}
/*
@ -86,6 +100,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
int saved_flags; /* Saved value of the db->flags */
int saved_nChange; /* Saved value of db->nChange */
int saved_nTotalChange; /* Saved value of db->nTotalChange */
void (*saved_xTrace)(void*,const char*); /* Saved db->xTrace */
Db *pDb = 0; /* Database to detach at end of vacuum */
int isMemDb; /* True if vacuuming a :memory: database */
int nRes;
@ -101,8 +116,10 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
saved_flags = db->flags;
saved_nChange = db->nChange;
saved_nTotalChange = db->nTotalChange;
saved_xTrace = db->xTrace;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
db->flags &= ~SQLITE_ForeignKeys;
db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder);
db->xTrace = 0;
pMain = db->aDb[0].pBt;
isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain));
@ -121,8 +138,12 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
** time to parse and run the PRAGMA to turn journalling off than it does
** to write the journal header file.
*/
zSql = "ATTACH '' AS vacuum_db;";
rc = execSql(db, zSql);
if( sqlite3TempInMemory(db) ){
zSql = "ATTACH ':memory:' AS vacuum_db;";
}else{
zSql = "ATTACH '' AS vacuum_db;";
}
rc = execSql(db, pzErrMsg, zSql);
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 );
@ -154,7 +175,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
rc = SQLITE_NOMEM;
goto end_of_vacuum;
}
rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF");
rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF");
if( rc!=SQLITE_OK ){
goto end_of_vacuum;
}
@ -165,23 +186,23 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
#endif
/* Begin a transaction */
rc = execSql(db, "BEGIN EXCLUSIVE;");
rc = execSql(db, pzErrMsg, "BEGIN EXCLUSIVE;");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Query the schema of the main database. Create a mirror schema
** in the temporary database.
*/
rc = execExecSql(db,
rc = execExecSql(db, pzErrMsg,
"SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) "
" FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
" AND rootpage>0"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
rc = execExecSql(db, pzErrMsg,
"SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)"
" FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' ");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
rc = execExecSql(db, pzErrMsg,
"SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) "
" FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
@ -190,24 +211,23 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy
** the contents to the temporary database.
*/
rc = execExecSql(db,
rc = execExecSql(db, pzErrMsg,
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
"|| ' SELECT * FROM main.' || quote(name) || ';'"
"FROM main.sqlite_master "
"WHERE type = 'table' AND name!='sqlite_sequence' "
" AND rootpage>0"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Copy over the sequence table
*/
rc = execExecSql(db,
rc = execExecSql(db, pzErrMsg,
"SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' "
"FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' "
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
rc = execExecSql(db, pzErrMsg,
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
"|| ' SELECT * FROM main.' || quote(name) || ';' "
"FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';"
@ -220,7 +240,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
** associated storage, so all we have to do is copy their entries
** from the SQLITE_MASTER table.
*/
rc = execSql(db,
rc = execSql(db, pzErrMsg,
"INSERT INTO vacuum_db.sqlite_master "
" SELECT type, name, tbl_name, rootpage, sql"
" FROM main.sqlite_master"
@ -283,6 +303,7 @@ end_of_vacuum:
db->flags = saved_flags;
db->nChange = saved_nChange;
db->nTotalChange = saved_nTotalChange;
db->xTrace = saved_xTrace;
/* Currently there is an SQL level transaction open on the vacuum
** database. No locks are held on any other files (since the main file

View File

@ -239,17 +239,30 @@ static VdbeCursor *allocateCursor(
static void applyNumericAffinity(Mem *pRec){
if( (pRec->flags & (MEM_Real|MEM_Int))==0 ){
int realnum;
u8 enc = pRec->enc;
sqlite3VdbeMemNulTerminate(pRec);
if( (pRec->flags&MEM_Str)
&& sqlite3IsNumber(pRec->z, &realnum, pRec->enc) ){
if( (pRec->flags&MEM_Str) && sqlite3IsNumber(pRec->z, &realnum, enc) ){
i64 value;
sqlite3VdbeChangeEncoding(pRec, SQLITE_UTF8);
if( !realnum && sqlite3Atoi64(pRec->z, &value) ){
char *zUtf8 = pRec->z;
#ifndef SQLITE_OMIT_UTF16
if( enc!=SQLITE_UTF8 ){
assert( pRec->db );
zUtf8 = sqlite3Utf16to8(pRec->db, pRec->z, pRec->n, enc);
if( !zUtf8 ) return;
}
#endif
if( !realnum && sqlite3Atoi64(zUtf8, &value) ){
pRec->u.i = value;
MemSetTypeFlag(pRec, MEM_Int);
}else{
sqlite3VdbeMemRealify(pRec);
sqlite3AtoF(zUtf8, &pRec->r);
MemSetTypeFlag(pRec, MEM_Real);
}
#ifndef SQLITE_OMIT_UTF16
if( enc!=SQLITE_UTF8 ){
sqlite3DbFree(pRec->db, zUtf8);
}
#endif
}
}
}
@ -538,7 +551,7 @@ static int checkSavepointCount(sqlite3 *db){
int sqlite3VdbeExec(
Vdbe *p /* The VDBE */
){
int pc; /* The program counter */
int pc=0; /* The program counter */
Op *aOp = p->aOp; /* Copy of p->aOp */
Op *pOp; /* Current operation */
int rc = SQLITE_OK; /* Value to return */
@ -563,7 +576,6 @@ int sqlite3VdbeExec(
/*** INSERT STACK UNION HERE ***/
assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
assert( db->magic==SQLITE_MAGIC_BUSY );
sqlite3VdbeMutexArrayEnter(p);
if( p->rc==SQLITE_NOMEM ){
/* This happens if a malloc() inside a call to sqlite3_column_text() or
@ -648,9 +660,7 @@ int sqlite3VdbeExec(
if( checkProgress ){
if( db->nProgressOps==nProgressOps ){
int prc;
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
prc =db->xProgress(db->pProgressArg);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
prc = db->xProgress(db->pProgressArg);
if( prc!=0 ){
rc = SQLITE_INTERRUPT;
goto vdbe_error_halt;
@ -850,7 +860,13 @@ case OP_Halt: {
p->errorAction = (u8)pOp->p2;
p->pc = pc;
if( pOp->p4.z ){
assert( p->rc!=SQLITE_OK );
sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z);
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pc, p->zSql, pOp->p4.z);
}else if( p->rc ){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql);
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
@ -884,6 +900,7 @@ case OP_Int64: { /* out2-prerelease */
break;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
/* Opcode: Real * P2 * P4 *
**
** P4 is a pointer to a 64-bit floating point value.
@ -895,6 +912,7 @@ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
pOut->r = *pOp->p4.pReal;
break;
}
#endif
/* Opcode: String8 * P2 * P4 *
**
@ -1295,6 +1313,10 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
break;
}
}
#ifdef SQLITE_OMIT_FLOATING_POINT
pOut->u.i = rB;
MemSetTypeFlag(pOut, MEM_Int);
#else
if( sqlite3IsNaN(rB) ){
goto arithmetic_result_is_null;
}
@ -1303,6 +1325,7 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
if( (flags & MEM_Real)==0 ){
sqlite3VdbeIntegerAffinity(pOut);
}
#endif
}
break;
@ -1393,21 +1416,12 @@ case OP_Function: {
assert( pOp[-1].opcode==OP_CollSeq );
ctx.pColl = pOp[-1].p4.pColl;
}
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
(*ctx.pFunc->xFunc)(&ctx, n, apVal);
if( sqlite3SafetyOn(db) ){
sqlite3VdbeMemRelease(&ctx.s);
goto abort_due_to_misuse;
}
if( db->mallocFailed ){
/* Even though a malloc() has failed, the implementation of the
** user function may have called an sqlite3_result_XXX() function
** to return a value. The following call releases any resources
** associated with such a value.
**
** Note: Maybe MemRelease() should be called if sqlite3SafetyOn()
** fails also (the if(...) statement above). But if people are
** misusing sqlite, they have bigger problems than a leaked value.
*/
sqlite3VdbeMemRelease(&ctx.s);
goto no_mem;
@ -1530,6 +1544,7 @@ case OP_MustBeInt: { /* jump, in1 */
break;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
/* Opcode: RealAffinity P1 * * * *
**
** If register P1 holds an integer convert it to a real value.
@ -1546,6 +1561,7 @@ case OP_RealAffinity: { /* in1 */
}
break;
}
#endif
#ifndef SQLITE_OMIT_CAST
/* Opcode: ToText P1 * * * *
@ -1629,7 +1645,7 @@ case OP_ToInt: { /* same as TK_TO_INT, in1 */
break;
}
#ifndef SQLITE_OMIT_CAST
#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT)
/* Opcode: ToReal P1 * * * *
**
** Force the value in register P1 to be a floating point number.
@ -1646,7 +1662,7 @@ case OP_ToReal: { /* same as TK_TO_REAL, in1 */
}
break;
}
#endif /* SQLITE_OMIT_CAST */
#endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */
/* Opcode: Lt P1 P2 P3 P4 P5
**
@ -1728,9 +1744,13 @@ case OP_Gt: /* same as TK_GT, jump, in1, in3 */
case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
int res; /* Result of the comparison of pIn1 against pIn3 */
char affinity; /* Affinity to use for comparison */
u16 flags1; /* Copy of initial value of pIn1->flags */
u16 flags3; /* Copy of initial value of pIn3->flags */
pIn1 = &aMem[pOp->p1];
pIn3 = &aMem[pOp->p3];
flags1 = pIn1->flags;
flags3 = pIn3->flags;
if( (pIn1->flags | pIn3->flags)&MEM_Null ){
/* One or both operands are NULL */
if( pOp->p5 & SQLITE_NULLEQ ){
@ -1785,6 +1805,10 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
}else if( res ){
pc = pOp->p2-1;
}
/* Undo any changes made by applyAffinity() to the input registers. */
pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask);
pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask);
break;
}
@ -2059,7 +2083,7 @@ case OP_Column: {
u8 *zIdx; /* Index into header */
u8 *zEndHdr; /* Pointer to first byte after the header */
u32 offset; /* Offset into the data */
u64 offset64; /* 64-bit offset. 64 bits needed to catch overflow */
u32 szField; /* Number of bytes in the content of a field */
int szHdr; /* Size of the header size field at start of record */
int avail; /* Number of bytes of available data */
Mem *pReg; /* PseudoTable input register */
@ -2234,12 +2258,16 @@ case OP_Column: {
** column and aOffset[i] will contain the offset from the beginning
** of the record to the start of the data for the i-th column
*/
offset64 = offset;
for(i=0; i<nField; i++){
if( zIdx<zEndHdr ){
aOffset[i] = (u32)offset64;
aOffset[i] = offset;
zIdx += getVarint32(zIdx, aType[i]);
offset64 += sqlite3VdbeSerialTypeLen(aType[i]);
szField = sqlite3VdbeSerialTypeLen(aType[i]);
offset += szField;
if( offset<szField ){ /* True if offset overflows */
zIdx = &zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
break;
}
}else{
/* If i is less that nField, then there are less fields in this
** record than SetNumColumns indicated there are columns in the
@ -2259,8 +2287,8 @@ case OP_Column: {
** of the record (when all fields present), then we must be dealing
** with a corrupt database.
*/
if( (zIdx > zEndHdr)|| (offset64 > payloadSize)
|| (zIdx==zEndHdr && offset64!=(u64)payloadSize) ){
if( (zIdx > zEndHdr) || (offset > payloadSize)
|| (zIdx==zEndHdr && offset!=payloadSize) ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_out;
}
@ -3106,7 +3134,7 @@ case OP_OpenEphemeral: {
** register P2. In other words, cursor P1 becomes an alias for the
** MEM_Blob content contained in register P2.
**
** A pseudo-table created by this opcode is used to hold the a single
** A pseudo-table created by this opcode is used to hold a single
** row output from the sorter so that the row can be decomposed into
** individual columns using the OP_Column opcode. The OP_Column opcode
** is the only cursor opcode that works with a pseudo-table.
@ -3663,7 +3691,7 @@ case OP_NewRowid: { /* out2-prerelease */
goto abort_due_to_error;
}
if( res ){
v = 1;
v = 1; /* IMP: R-61914-48074 */
}else{
assert( sqlite3BtreeCursorIsValid(pC->pCursor) );
rc = sqlite3BtreeKeySize(pC->pCursor, &v);
@ -3671,7 +3699,7 @@ case OP_NewRowid: { /* out2-prerelease */
if( v==MAX_ROWID ){
pC->useRandomRowid = 1;
}else{
v++;
v++; /* IMP: R-29538-34987 */
}
}
}
@ -3695,7 +3723,7 @@ case OP_NewRowid: { /* out2-prerelease */
sqlite3VdbeMemIntegerify(pMem);
assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
rc = SQLITE_FULL;
rc = SQLITE_FULL; /* IMP: R-12275-61338 */
goto abort_due_to_error;
}
if( v<pMem->u.i+1 ){
@ -3708,6 +3736,11 @@ case OP_NewRowid: { /* out2-prerelease */
sqlite3BtreeSetCachedRowid(pC->pCursor, v<MAX_ROWID ? v+1 : 0);
}
if( pC->useRandomRowid ){
/* IMPLEMENTATION-OF: R-48598-02938 If the largest ROWID is equal to the
** largest possible integer (9223372036854775807) then the database
** engine starts picking candidate ROWIDs at random until it finds one
** that is not previously used.
*/
assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
** an AUTOINCREMENT table. */
v = db->lastRowid;
@ -3723,7 +3756,7 @@ case OP_NewRowid: { /* out2-prerelease */
cnt++;
}while( cnt<100 && rc==SQLITE_OK && res==0 );
if( rc==SQLITE_OK && res==0 ){
rc = SQLITE_FULL;
rc = SQLITE_FULL; /* IMP: R-38219-53002 */
goto abort_due_to_error;
}
}
@ -4031,12 +4064,10 @@ case OP_Rowid: { /* out2-prerelease */
pVtab = pC->pVtabCursor->pVtab;
pModule = pVtab->pModule;
assert( pModule->xRowid );
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xRowid(pC->pVtabCursor, &v);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}else{
assert( pC->pCursor!=0 );
@ -4567,12 +4598,11 @@ case OP_ParseSchema: {
initData.iDb = pOp->p1;
initData.pzErrMsg = &p->zErrMsg;
zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s WHERE %s",
"SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
db->aDb[iDb].zName, zMaster, pOp->p4.z);
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
(void)sqlite3SafetyOff(db);
assert( db->init.busy==0 );
db->init.busy = 1;
initData.rc = SQLITE_OK;
@ -4581,7 +4611,6 @@ case OP_ParseSchema: {
if( rc==SQLITE_OK ) rc = initData.rc;
sqlite3DbFree(db, zSql);
db->init.busy = 0;
(void)sqlite3SafetyOn(db);
}
}
sqlite3BtreeLeaveAll(db);
@ -5151,9 +5180,7 @@ case OP_AggFinal: {
** a transaction.
*/
case OP_Vacuum: {
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = sqlite3RunVacuum(&p->zErrMsg, db);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
break;
}
#endif
@ -5297,12 +5324,10 @@ case OP_VOpen: {
pVtab = pOp->p4.pVtab->pVtab;
pModule = (sqlite3_module *)pVtab->pModule;
assert(pVtab && pModule);
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xOpen(pVtab, &pVtabCursor);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( SQLITE_OK==rc ){
/* Initialize sqlite3_vtab_cursor base class */
pVtabCursor->pVtab = pVtab;
@ -5376,7 +5401,6 @@ case OP_VFilter: { /* jump */
sqlite3VdbeMemStoreType(apArg[i]);
}
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
p->inVtabMethod = 1;
rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
p->inVtabMethod = 0;
@ -5386,7 +5410,6 @@ case OP_VFilter: { /* jump */
if( rc==SQLITE_OK ){
res = pModule->xEof(pVtabCursor);
}
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( res ){
pc = pOp->p2 - 1;
@ -5432,7 +5455,6 @@ case OP_VColumn: {
sqlite3VdbeMemMove(&sContext.s, pDest);
MemSetTypeFlag(&sContext.s, MEM_Null);
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
@ -5450,9 +5472,6 @@ case OP_VColumn: {
REGISTER_TRACE(pOp->p3, pDest);
UPDATE_MAX_BLOBSIZE(pDest);
if( sqlite3SafetyOn(db) ){
goto abort_due_to_misuse;
}
if( sqlite3VdbeMemTooBig(pDest) ){
goto too_big;
}
@ -5489,7 +5508,6 @@ case OP_VNext: { /* jump */
** data is available) and the error code returned when xColumn or
** some other method is next invoked on the save virtual table cursor.
*/
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
p->inVtabMethod = 1;
rc = pModule->xNext(pCur->pVtabCursor);
p->inVtabMethod = 0;
@ -5499,7 +5517,6 @@ case OP_VNext: { /* jump */
if( rc==SQLITE_OK ){
res = pModule->xEof(pCur->pVtabCursor);
}
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( !res ){
/* If there is data, jump to P2 */
@ -5525,12 +5542,10 @@ case OP_VRename: {
assert( pVtab->pModule->xRename );
REGISTER_TRACE(pOp->p1, pName);
assert( pName->flags & MEM_Str );
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pVtab->pModule->xRename(pVtab, pName->z);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
break;
}
@ -5581,12 +5596,10 @@ case OP_VUpdate: {
apArg[i] = pX;
pX++;
}
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( rc==SQLITE_OK && pOp->p1 ){
assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
db->lastRowid = rowid;
@ -5659,6 +5672,7 @@ case OP_Trace: {
** the same as a no-op. This opcodesnever appears in a real VM program.
*/
default: { /* This is really OP_Noop and OP_Explain */
assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
break;
}
@ -5710,6 +5724,9 @@ default: { /* This is really OP_Noop and OP_Explain */
vdbe_error_halt:
assert( rc );
p->rc = rc;
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(rc, "statement aborts at %d: [%s] %s",
pc, p->zSql, p->zErrMsg);
sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
rc = SQLITE_ERROR;
@ -5738,12 +5755,6 @@ no_mem:
rc = SQLITE_NOMEM;
goto vdbe_error_halt;
/* Jump to here for an SQLITE_MISUSE error.
*/
abort_due_to_misuse:
rc = SQLITE_MISUSE;
/* Fall thru into abort_due_to_error */
/* Jump to here for any other kind of fatal error. The "rc" variable
** should hold the error number.
*/

View File

@ -182,6 +182,7 @@ void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
void sqlite3VdbeUsesBtree(Vdbe*, int);
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
int sqlite3VdbeMakeLabel(Vdbe*);
void sqlite3VdbeRunOnlyOnce(Vdbe*);
void sqlite3VdbeDelete(Vdbe*);
void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int);
int sqlite3VdbeFinalize(Vdbe*);

View File

@ -301,6 +301,7 @@ struct Vdbe {
u8 explain; /* True if EXPLAIN present on SQL command */
u8 changeCntOn; /* True to update the change-counter */
u8 expired; /* True if the VM needs to be recompiled */
u8 runOnlyOnce; /* Automatically expire on reset */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
u8 inVtabMethod; /* See comments above */
u8 usesStmtJournal; /* True if uses a statement journal */
@ -362,7 +363,11 @@ void sqlite3VdbeMemMove(Mem*, Mem*);
int sqlite3VdbeMemNulTerminate(Mem*);
int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
void sqlite3VdbeMemSetInt64(Mem*, i64);
void sqlite3VdbeMemSetDouble(Mem*, double);
#ifdef SQLITE_OMIT_FLOATING_POINT
# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
#else
void sqlite3VdbeMemSetDouble(Mem*, double);
#endif
void sqlite3VdbeMemSetNull(Mem*);
void sqlite3VdbeMemSetZeroBlob(Mem*,int);
void sqlite3VdbeMemSetRowSet(Mem*);

View File

@ -31,6 +31,28 @@ int sqlite3_expired(sqlite3_stmt *pStmt){
}
#endif
/*
** Check on a Vdbe to make sure it has not been finalized. Log
** an error and return true if it has been finalized (or is otherwise
** invalid). Return false if it is ok.
*/
static int vdbeSafety(Vdbe *p){
if( p->db==0 ){
sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement");
return 1;
}else{
return 0;
}
}
static int vdbeSafetyNotNull(Vdbe *p){
if( p==0 ){
sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement");
return 1;
}else{
return vdbeSafety(p);
}
}
/*
** The following routine destroys a virtual machine that is created by
** the sqlite3_compile() routine. The integer returned is an SQLITE_
@ -48,7 +70,11 @@ int sqlite3_finalize(sqlite3_stmt *pStmt){
Vdbe *v = (Vdbe*)pStmt;
sqlite3 *db = v->db;
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = v->db->mutex;
sqlite3_mutex *mutex;
#endif
if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT;
#if SQLITE_THREADSAFE
mutex = v->db->mutex;
#endif
sqlite3_mutex_enter(mutex);
rc = sqlite3VdbeFinalize(v);
@ -295,26 +321,23 @@ static int sqlite3Step(Vdbe *p){
assert(p);
if( p->magic!=VDBE_MAGIC_RUN ){
return SQLITE_MISUSE;
sqlite3_log(SQLITE_MISUSE,
"attempt to step a halted statement: [%s]", p->zSql);
return SQLITE_MISUSE_BKPT;
}
/* Assert that malloc() has not failed */
/* Check that malloc() has not failed. If it has, return early. */
db = p->db;
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM;
return SQLITE_NOMEM;
}
if( p->pc<=0 && p->expired ){
if( ALWAYS(p->rc==SQLITE_OK || p->rc==SQLITE_SCHEMA) ){
p->rc = SQLITE_SCHEMA;
}
p->rc = SQLITE_SCHEMA;
rc = SQLITE_ERROR;
goto end_of_step;
}
if( sqlite3SafetyOn(db) ){
p->rc = SQLITE_MISUSE;
return SQLITE_MISUSE;
}
if( p->pc<0 ){
/* If there are no other statements currently running, then
** reset the interrupt flag. This prevents a call to sqlite3_interrupt
@ -347,10 +370,6 @@ static int sqlite3Step(Vdbe *p){
rc = sqlite3VdbeExec(p);
}
if( sqlite3SafetyOff(db) ){
rc = SQLITE_MISUSE;
}
#ifndef SQLITE_OMIT_TRACE
/* Invoke the profile callback if there is one
*/
@ -397,39 +416,44 @@ end_of_step:
** call sqlite3Reprepare() and try again.
*/
int sqlite3_step(sqlite3_stmt *pStmt){
int rc = SQLITE_MISUSE;
if( pStmt ){
int cnt = 0;
Vdbe *v = (Vdbe*)pStmt;
sqlite3 *db = v->db;
sqlite3_mutex_enter(db->mutex);
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
&& cnt++ < 5
&& (rc = sqlite3Reprepare(v))==SQLITE_OK ){
sqlite3_reset(pStmt);
v->expired = 0;
}
if( rc==SQLITE_SCHEMA && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
/* This case occurs after failing to recompile an sql statement.
** The error message from the SQL compiler has already been loaded
** into the database handle. This block copies the error message
** from the database handle into the statement and sets the statement
** program counter to 0 to ensure that when the statement is
** finalized or reset the parser error message is available via
** sqlite3_errmsg() and sqlite3_errcode().
*/
const char *zErr = (const char *)sqlite3_value_text(db->pErr);
sqlite3DbFree(db, v->zErrMsg);
if( !db->mallocFailed ){
v->zErrMsg = sqlite3DbStrDup(db, zErr);
} else {
v->zErrMsg = 0;
v->rc = SQLITE_NOMEM;
}
}
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
int rc = SQLITE_OK; /* Result from sqlite3Step() */
int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */
Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */
int cnt = 0; /* Counter to prevent infinite loop of reprepares */
sqlite3 *db; /* The database connection */
if( vdbeSafetyNotNull(v) ){
return SQLITE_MISUSE_BKPT;
}
db = v->db;
sqlite3_mutex_enter(db->mutex);
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
&& cnt++ < 5
&& (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
sqlite3_reset(pStmt);
v->expired = 0;
}
if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
/* This case occurs after failing to recompile an sql statement.
** The error message from the SQL compiler has already been loaded
** into the database handle. This block copies the error message
** from the database handle into the statement and sets the statement
** program counter to 0 to ensure that when the statement is
** finalized or reset the parser error message is available via
** sqlite3_errmsg() and sqlite3_errcode().
*/
const char *zErr = (const char *)sqlite3_value_text(db->pErr);
sqlite3DbFree(db, v->zErrMsg);
if( !db->mallocFailed ){
v->zErrMsg = sqlite3DbStrDup(db, zErr);
v->rc = rc2;
} else {
v->zErrMsg = 0;
v->rc = rc = SQLITE_NOMEM;
}
}
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
@ -483,8 +507,9 @@ void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
assert( p && p->pFunc && p->pFunc->xStep );
assert( sqlite3_mutex_held(p->s.db->mutex) );
pMem = p->pMem;
testcase( nByte<0 );
if( (pMem->flags & MEM_Agg)==0 ){
if( nByte==0 ){
if( nByte<=0 ){
sqlite3VdbeMemReleaseExternal(pMem);
pMem->flags = MEM_Null;
pMem->z = 0;
@ -898,12 +923,16 @@ const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
*/
static int vdbeUnbind(Vdbe *p, int i){
Mem *pVar;
if( p==0 ) return SQLITE_MISUSE;
if( vdbeSafetyNotNull(p) ){
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(p->db->mutex);
if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
sqlite3Error(p->db, SQLITE_MISUSE, 0);
sqlite3_mutex_leave(p->db->mutex);
return SQLITE_MISUSE;
sqlite3_log(SQLITE_MISUSE,
"bind on a busy prepared statement: [%s]", p->zSql);
return SQLITE_MISUSE_BKPT;
}
if( i<1 || i>p->nVar ){
sqlite3Error(p->db, SQLITE_RANGE, 0);

View File

@ -66,7 +66,7 @@ void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){
*/
const char *sqlite3_sql(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe *)pStmt;
return (p->isPrepareV2 ? p->zSql : 0);
return (p && p->isPrepareV2) ? p->zSql : 0;
}
/*
@ -255,6 +255,13 @@ void sqlite3VdbeResolveLabel(Vdbe *p, int x){
}
}
/*
** Mark the VDBE as one that can only be run one time.
*/
void sqlite3VdbeRunOnlyOnce(Vdbe *p){
p->runOnlyOnce = 1;
}
#ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */
/*
@ -1041,22 +1048,24 @@ void sqlite3VdbeFrameDelete(VdbeFrame *p){
** p->explain==2, only OP_Explain instructions are listed and these
** are shown in a different format. p->explain==2 is used to implement
** EXPLAIN QUERY PLAN.
**
** When p->explain==1, first the main program is listed, then each of
** the trigger subprograms are listed one by one.
*/
int sqlite3VdbeList(
Vdbe *p /* The VDBE */
){
int nRow; /* Total number of rows to return */
int nRow; /* Stop when row count reaches this */
int nSub = 0; /* Number of sub-vdbes seen so far */
SubProgram **apSub = 0; /* Array of sub-vdbes */
Mem *pSub = 0;
sqlite3 *db = p->db;
int i;
int rc = SQLITE_OK;
Mem *pMem = p->pResultSet = &p->aMem[1];
Mem *pSub = 0; /* Memory cell hold array of subprogs */
sqlite3 *db = p->db; /* The database connection */
int i; /* Loop counter */
int rc = SQLITE_OK; /* Return code */
Mem *pMem = p->pResultSet = &p->aMem[1]; /* First Mem of result set */
assert( p->explain );
assert( p->magic==VDBE_MAGIC_RUN );
assert( db->magic==SQLITE_MAGIC_BUSY );
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
/* Even though this opcode does not use dynamic strings for
@ -1072,12 +1081,24 @@ int sqlite3VdbeList(
return SQLITE_ERROR;
}
/* Figure out total number of rows that will be returned by this
** EXPLAIN program. */
/* When the number of output rows reaches nRow, that means the
** listing has finished and sqlite3_step() should return SQLITE_DONE.
** nRow is the sum of the number of rows in the main program, plus
** the sum of the number of rows in all trigger subprograms encountered
** so far. The nRow value will increase as new trigger subprograms are
** encountered, but p->pc will eventually catch up to nRow.
*/
nRow = p->nOp;
if( p->explain==1 ){
/* The first 8 memory cells are used for the result set. So we will
** commandeer the 9th cell to use as storage for an array of pointers
** to trigger subprograms. The VDBE is guaranteed to have at least 9
** cells. */
assert( p->nMem>9 );
pSub = &p->aMem[9];
if( pSub->flags&MEM_Blob ){
/* On the first call to sqlite3_step(), pSub will hold a NULL. It is
** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */
nSub = pSub->n/sizeof(Vdbe*);
apSub = (SubProgram **)pSub->z;
}
@ -1100,8 +1121,12 @@ int sqlite3VdbeList(
char *z;
Op *pOp;
if( i<p->nOp ){
/* The output line number is small enough that we are still in the
** main program. */
pOp = &p->aOp[i];
}else{
/* We are currently listing subprograms. Figure out which one and
** pick up the appropriate opcode. */
int j;
i -= p->nOp;
for(j=0; i>=apSub[j]->nOp; j++){
@ -1123,6 +1148,11 @@ int sqlite3VdbeList(
pMem->enc = SQLITE_UTF8;
pMem++;
/* When an OP_Program opcode is encounter (the only opcode that has
** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
** kept in p->aMem[9].z to hold the new program - assuming this subprogram
** has not already been seen.
*/
if( pOp->p4type==P4_SUBPROGRAM ){
int nByte = (nSub+1)*sizeof(SubProgram*);
int j;
@ -1254,38 +1284,43 @@ void sqlite3VdbeIOTraceSql(Vdbe *p){
#endif /* !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */
/*
** Allocate space from a fixed size buffer. Make *pp point to the
** allocated space. (Note: pp is a char* rather than a void** to
** work around the pointer aliasing rules of C.) *pp should initially
** be zero. If *pp is not zero, that means that the space has already
** been allocated and this routine is a noop.
** Allocate space from a fixed size buffer and return a pointer to
** that space. If insufficient space is available, return NULL.
**
** The pBuf parameter is the initial value of a pointer which will
** receive the new memory. pBuf is normally NULL. If pBuf is not
** NULL, it means that memory space has already been allocated and that
** this routine should not allocate any new memory. When pBuf is not
** NULL simply return pBuf. Only allocate new memory space when pBuf
** is NULL.
**
** nByte is the number of bytes of space needed.
**
** *ppFrom point to available space and pEnd points to the end of the
** available space.
** *ppFrom points to available space and pEnd points to the end of the
** available space. When space is allocated, *ppFrom is advanced past
** the end of the allocated space.
**
** *pnByte is a counter of the number of bytes of space that have failed
** to allocate. If there is insufficient space in *ppFrom to satisfy the
** request, then increment *pnByte by the amount of the request.
*/
static void allocSpace(
char *pp, /* IN/OUT: Set *pp to point to allocated buffer */
static void *allocSpace(
void *pBuf, /* Where return pointer will be stored */
int nByte, /* Number of bytes to allocate */
u8 **ppFrom, /* IN/OUT: Allocate from *ppFrom */
u8 *pEnd, /* Pointer to 1 byte past the end of *ppFrom buffer */
int *pnByte /* If allocation cannot be made, increment *pnByte */
){
assert( EIGHT_BYTE_ALIGNMENT(*ppFrom) );
if( (*(void**)pp)==0 ){
nByte = ROUND8(nByte);
if( &(*ppFrom)[nByte] <= pEnd ){
*(void**)pp = (void *)*ppFrom;
*ppFrom += nByte;
}else{
*pnByte += nByte;
}
if( pBuf ) return pBuf;
nByte = ROUND8(nByte);
if( &(*ppFrom)[nByte] <= pEnd ){
pBuf = (void*)*ppFrom;
*ppFrom += nByte;
}else{
*pnByte += nByte;
}
return pBuf;
}
/*
@ -1344,9 +1379,10 @@ void sqlite3VdbeMakeReady(
** being called from sqlite3_reset() to reset the virtual machine.
*/
if( nVar>=0 && ALWAYS(db->mallocFailed==0) ){
u8 *zCsr = (u8 *)&p->aOp[p->nOp];
u8 *zEnd = (u8 *)&p->aOp[p->nOpAlloc];
int nByte;
u8 *zCsr = (u8 *)&p->aOp[p->nOp]; /* Memory avaliable for alloation */
u8 *zEnd = (u8 *)&p->aOp[p->nOpAlloc]; /* First byte past available mem */
int nByte; /* How much extra memory needed */
resolveP2Values(p, &nArg);
p->usesStmtJournal = (u8)usesStmtJournal;
if( isExplain && nMem<10 ){
@ -1356,15 +1392,24 @@ void sqlite3VdbeMakeReady(
zCsr += (zCsr - (u8*)0)&7;
assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
/* Memory for registers, parameters, cursor, etc, is allocated in two
** passes. On the first pass, we try to reuse unused space at the
** end of the opcode array. If we are unable to satisfy all memory
** requirements by reusing the opcode array tail, then the second
** pass will fill in the rest using a fresh allocation.
**
** This two-pass approach that reuses as much memory as possible from
** the leftover space at the end of the opcode array can significantly
** reduce the amount of memory held by a prepared statement.
*/
do {
nByte = 0;
allocSpace((char*)&p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte);
allocSpace((char*)&p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte);
allocSpace((char*)&p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte);
allocSpace((char*)&p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
allocSpace((char*)&p->apCsr,
nCursor*sizeof(VdbeCursor*), &zCsr, zEnd, &nByte
);
p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte);
p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte);
p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte);
p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
&zCsr, zEnd, &nByte);
if( nByte ){
p->pFree = sqlite3DbMallocZero(db, nByte);
}
@ -1435,9 +1480,7 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
const sqlite3_module *pModule = pCx->pModule;
p->inVtabMethod = 1;
(void)sqlite3SafetyOff(p->db);
pModule->xClose(pVtabCursor);
(void)sqlite3SafetyOn(p->db);
p->inVtabMethod = 0;
}
#endif
@ -1618,9 +1661,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
/* If there are any write-transactions at all, invoke the commit hook */
if( needXcommit && db->xCommitCallback ){
(void)sqlite3SafetyOff(db);
rc = db->xCommitCallback(db->pCommitArg);
(void)sqlite3SafetyOn(db);
if( rc ){
return SQLITE_CONSTRAINT;
}
@ -1706,10 +1747,11 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
*/
for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( i==1 ) continue; /* Ignore the TEMP database */
if( sqlite3BtreeIsInTrans(pBt) ){
char const *zFile = sqlite3BtreeGetJournalname(pBt);
if( zFile[0]==0 ) continue; /* Ignore :memory: databases */
if( zFile==0 || zFile[0]==0 ){
continue; /* Ignore TEMP and :memory: databases */
}
if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){
needSync = 1;
}
@ -2085,12 +2127,17 @@ int sqlite3VdbeHalt(Vdbe *p){
/* If eStatementOp is non-zero, then a statement transaction needs to
** be committed or rolled back. Call sqlite3VdbeCloseStatement() to
** do so. If this operation returns an error, and the current statement
** error code is SQLITE_OK or SQLITE_CONSTRAINT, then set the error
** code to the new value.
** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the
** current statement error code.
**
** Note that sqlite3VdbeCloseStatement() can only fail if eStatementOp
** is SAVEPOINT_ROLLBACK. But if p->rc==SQLITE_OK then eStatementOp
** must be SAVEPOINT_RELEASE. Hence the NEVER(p->rc==SQLITE_OK) in
** the following code.
*/
if( eStatementOp ){
rc = sqlite3VdbeCloseStatement(p, eStatementOp);
if( rc && (p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT) ){
if( rc && (NEVER(p->rc==SQLITE_OK) || p->rc==SQLITE_CONSTRAINT) ){
p->rc = rc;
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
@ -2173,9 +2220,7 @@ int sqlite3VdbeReset(Vdbe *p){
** error, then it might not have been halted properly. So halt
** it now.
*/
(void)sqlite3SafetyOn(db);
sqlite3VdbeHalt(p);
(void)sqlite3SafetyOff(db);
/* If the VDBE has be run even partially, then transfer the error code
** and error message from the VDBE into the main database structure. But
@ -2195,6 +2240,7 @@ int sqlite3VdbeReset(Vdbe *p){
}else{
sqlite3Error(db, SQLITE_OK, 0);
}
if( p->runOnlyOnce ) p->expired = 1;
}else if( p->rc && p->expired ){
/* The expired flag was set on the VDBE before the first call
** to sqlite3_step(). For consistency (since sqlite3_step() was
@ -2296,6 +2342,7 @@ void sqlite3VdbeDelete(Vdbe *p){
sqlite3DbFree(db, p->zSql);
p->magic = VDBE_MAGIC_DEAD;
sqlite3DbFree(db, p->pFree);
p->db = 0;
sqlite3DbFree(db, p);
}
@ -2976,7 +3023,7 @@ int sqlite3VdbeIdxKeyCompare(
** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
if( nCellKey<=0 || nCellKey>0x7fffffff ){
*res = 0;
return SQLITE_CORRUPT;
return SQLITE_CORRUPT_BKPT;
}
memset(&m, 0, sizeof(m));
rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m);

View File

@ -95,13 +95,6 @@ int sqlite3_blob_open(
memset(pParse, 0, sizeof(Parse));
pParse->db = db;
if( sqlite3SafetyOn(db) ){
sqlite3DbFree(db, zErr);
sqlite3StackFree(db, pParse);
sqlite3_mutex_leave(db->mutex);
return SQLITE_MISUSE;
}
sqlite3BtreeEnterAll(db);
pTab = sqlite3LocateTable(pParse, 0, zTable, zDb);
if( pTab && IsVirtual(pTab) ){
@ -121,7 +114,6 @@ int sqlite3_blob_open(
pParse->zErrMsg = 0;
}
rc = SQLITE_ERROR;
(void)sqlite3SafetyOff(db);
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
@ -136,7 +128,6 @@ int sqlite3_blob_open(
sqlite3DbFree(db, zErr);
zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn);
rc = SQLITE_ERROR;
(void)sqlite3SafetyOff(db);
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
@ -177,7 +168,6 @@ int sqlite3_blob_open(
sqlite3DbFree(db, zErr);
zErr = sqlite3MPrintf(db, "cannot open %s column for writing", zFault);
rc = SQLITE_ERROR;
(void)sqlite3SafetyOff(db);
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
@ -227,8 +217,7 @@ int sqlite3_blob_open(
}
sqlite3BtreeLeaveAll(db);
rc = sqlite3SafetyOff(db);
if( NEVER(rc!=SQLITE_OK) || db->mallocFailed ){
if( db->mallocFailed ){
goto blob_open_out;
}
@ -329,7 +318,7 @@ static int blobReadWrite(
Vdbe *v;
sqlite3 *db;
if( p==0 ) return SQLITE_MISUSE;
if( p==0 ) return SQLITE_MISUSE_BKPT;
db = p->db;
sqlite3_mutex_enter(db->mutex);
v = (Vdbe*)p->pStmt;

View File

@ -315,6 +315,10 @@ void sqlite3VdbeMemRelease(Mem *p){
** before attempting the conversion.
*/
static i64 doubleToInt64(double r){
#ifdef SQLITE_OMIT_FLOATING_POINT
/* When floating-point is omitted, double and int64 are the same thing */
return r;
#else
/*
** Many compilers we encounter do not define constants for the
** minimum and maximum 64-bit integers, or they define them
@ -336,6 +340,7 @@ static i64 doubleToInt64(double r){
}else{
return (i64)r;
}
#endif
}
/*
@ -463,21 +468,26 @@ int sqlite3VdbeMemRealify(Mem *pMem){
/*
** Convert pMem so that it has types MEM_Real or MEM_Int or both.
** Invalidate any prior representations.
**
** Every effort is made to force the conversion, even if the input
** is a string that does not look completely like a number. Convert
** as much of the string as we can and ignore the rest.
*/
int sqlite3VdbeMemNumerify(Mem *pMem){
double r1, r2;
i64 i;
int rc;
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 );
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
r1 = sqlite3VdbeRealValue(pMem);
i = doubleToInt64(r1);
r2 = (double)i;
if( r1==r2 ){
sqlite3VdbeMemIntegerify(pMem);
rc = sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8);
if( rc ) return rc;
rc = sqlite3VdbeMemNulTerminate(pMem);
if( rc ) return rc;
if( sqlite3Atoi64(pMem->z, &pMem->u.i) ){
MemSetTypeFlag(pMem, MEM_Int);
}else{
pMem->r = r1;
pMem->r = sqlite3VdbeRealValue(pMem);
MemSetTypeFlag(pMem, MEM_Real);
sqlite3VdbeIntegerAffinity(pMem);
}
return SQLITE_OK;
}
@ -529,6 +539,7 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
pMem->type = SQLITE_INTEGER;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Delete any previous value and set the value stored in *pMem to val,
** manifest type REAL.
@ -543,6 +554,7 @@ void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
pMem->type = SQLITE_FLOAT;
}
}
#endif
/*
** Delete any previous value and set the value of pMem to be an
@ -597,7 +609,7 @@ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
sqlite3VdbeMemReleaseExternal(pTo);
memcpy(pTo, pFrom, MEMCELLSIZE);
pTo->xDel = 0;
if( (pFrom->flags&MEM_Dyn)!=0 || pFrom->z==pFrom->zMalloc ){
if( (pFrom->flags&MEM_Static)==0 ){
pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
assert( srcType==MEM_Ephem || srcType==MEM_Static );
pTo->flags |= srcType;

View File

@ -123,16 +123,7 @@ void sqlite3VtabUnlock(VTable *pVTab){
if( pVTab->nRef==0 ){
sqlite3_vtab *p = pVTab->pVtab;
if( p ){
#ifdef SQLITE_DEBUG
if( pVTab->db->magic==SQLITE_MAGIC_BUSY ){
(void)sqlite3SafetyOff(db);
p->pModule->xDisconnect(p);
(void)sqlite3SafetyOn(db);
} else
#endif
{
p->pModule->xDisconnect(p);
}
p->pModule->xDisconnect(p);
}
sqlite3DbFree(db, pVTab);
}
@ -468,9 +459,7 @@ static int vtabCallConstructor(
db->pVTab = pTab;
/* Invoke the virtual table constructor */
(void)sqlite3SafetyOff(db);
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
(void)sqlite3SafetyOn(db);
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
if( SQLITE_OK!=rc ){
@ -658,7 +647,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
if( !pTab ){
sqlite3Error(db, SQLITE_MISUSE, 0);
sqlite3_mutex_leave(db->mutex);
return SQLITE_MISUSE;
return SQLITE_MISUSE_BKPT;
}
assert( (pTab->tabFlags & TF_Virtual)!=0 );
@ -669,11 +658,11 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
pParse->declareVtab = 1;
pParse->db = db;
if(
SQLITE_OK == sqlite3RunParser(pParse, zCreateTable, &zErr) &&
pParse->pNewTable &&
!pParse->pNewTable->pSelect &&
(pParse->pNewTable->tabFlags & TF_Virtual)==0
if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr)
&& pParse->pNewTable
&& !db->mallocFailed
&& !pParse->pNewTable->pSelect
&& (pParse->pNewTable->tabFlags & TF_Virtual)==0
){
if( !pTab->aCol ){
pTab->aCol = pParse->pNewTable->aCol;
@ -682,7 +671,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
pParse->pNewTable->aCol = 0;
}
db->pVTab = 0;
} else {
}else{
sqlite3Error(db, SQLITE_ERROR, zErr);
sqlite3DbFree(db, zErr);
rc = SQLITE_ERROR;
@ -717,10 +706,8 @@ int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){
if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){
VTable *p = vtabDisconnectAll(db, pTab);
rc = sqlite3SafetyOff(db);
assert( rc==SQLITE_OK );
rc = p->pMod->pModule->xDestroy(p->pVtab);
(void)sqlite3SafetyOn(db);
/* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */
if( rc==SQLITE_OK ){
@ -772,10 +759,8 @@ static void callFinaliser(sqlite3 *db, int offset){
int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
int i;
int rc = SQLITE_OK;
int rcsafety;
VTable **aVTrans = db->aVTrans;
rc = sqlite3SafetyOff(db);
db->aVTrans = 0;
for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
int (*x)(sqlite3_vtab *);
@ -788,11 +773,6 @@ int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
}
}
db->aVTrans = aVTrans;
rcsafety = sqlite3SafetyOn(db);
if( rc==SQLITE_OK ){
rc = rcsafety;
}
return rc;
}

View File

@ -653,7 +653,7 @@ static int isLikeOrGlob(
}
assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
pColl = sqlite3ExprCollSeq(pParse, pLeft);
assert( pColl!=0 ); /* Every non-IPK column has a collating sequence */
if( pColl==0 ) return 0; /* Happens when LHS has an undefined collation */
if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) &&
(pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){
/* IMP: R-09003-32046 For the GLOB operator, the column must use the
@ -1096,7 +1096,7 @@ static void exprAnalyze(
Expr *pExpr; /* The expression to be analyzed */
Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */
Bitmask prereqAll; /* Prerequesites of pExpr */
Bitmask extraRight = 0; /* */
Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */
Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */
int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
int noCase = 0; /* LIKE/GLOB distinguishes case */
@ -1168,7 +1168,8 @@ static void exprAnalyze(
pLeft = pDup->pLeft;
pNew->leftCursor = pLeft->iTable;
pNew->u.leftColumn = pLeft->iColumn;
pNew->prereqRight = prereqLeft;
testcase( (prereqLeft | extraRight) != prereqLeft );
pNew->prereqRight = prereqLeft | extraRight;
pNew->prereqAll = prereqAll;
pNew->eOperator = operatorMask(pDup->op);
}
@ -1758,12 +1759,10 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
int i;
int rc;
(void)sqlite3SafetyOff(pParse->db);
WHERETRACE(("xBestIndex for %s\n", pTab->zName));
TRACE_IDX_INPUTS(p);
rc = pVtab->pModule->xBestIndex(pVtab, p);
TRACE_IDX_OUTPUTS(p);
(void)sqlite3SafetyOn(pParse->db);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_NOMEM ){
@ -3160,7 +3159,7 @@ static Bitmask codeOneLoopStart(
nConstraint = nEq;
if( pRangeEnd ){
Expr *pRight = pRangeEnd->pExpr->pRight;
sqlite3ExprCacheRemove(pParse, regBase+nEq);
sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
sqlite3ExprCode(pParse, pRight, regBase+nEq);
sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
if( zAff ){
@ -3265,13 +3264,14 @@ static Bitmask codeOneLoopStart(
*/
WhereClause *pOrWc; /* The OR-clause broken out into subterms */
WhereTerm *pFinal; /* Final subterm within the OR-clause. */
SrcList oneTab; /* Shortened table list */
SrcList *pOrTab; /* Shortened table list or OR-clause generation */
int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */
int regRowset = 0; /* Register for RowSet object */
int regRowid = 0; /* Register holding rowid */
int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
int iRetInit; /* Address of regReturn init */
int untestedTerms = 0; /* Some terms not completely tested */
int ii;
pTerm = pLevel->plan.u.pTerm;
@ -3280,11 +3280,30 @@ static Bitmask codeOneLoopStart(
assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
pOrWc = &pTerm->u.pOrInfo->wc;
pFinal = &pOrWc->a[pOrWc->nTerm-1];
pLevel->op = OP_Return;
pLevel->p1 = regReturn;
/* Set up a SrcList containing just the table being scanned by this loop. */
oneTab.nSrc = 1;
oneTab.nAlloc = 1;
oneTab.a[0] = *pTabItem;
/* Set up a new SrcList ni pOrTab containing the table being scanned
** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
*/
if( pWInfo->nLevel>1 ){
int nNotReady; /* The number of notReady tables */
struct SrcList_item *origSrc; /* Original list of tables */
nNotReady = pWInfo->nLevel - iLevel - 1;
pOrTab = sqlite3StackAllocRaw(pParse->db,
sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
if( pOrTab==0 ) return notReady;
pOrTab->nAlloc = (i16)(nNotReady + 1);
pOrTab->nSrc = pOrTab->nAlloc;
memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
origSrc = pWInfo->pTabList->a;
for(k=1; k<=nNotReady; k++){
memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
}
}else{
pOrTab = pWInfo->pTabList;
}
/* Initialize the rowset register to contain NULL. An SQL NULL is
** equivalent to an empty rowset.
@ -3309,32 +3328,38 @@ static Bitmask codeOneLoopStart(
if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
/* Loop through table entries that match term pOrTerm. */
pSubWInfo = sqlite3WhereBegin(pParse, &oneTab, pOrTerm->pExpr, 0,
WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE | WHERE_FORCE_TABLE);
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm->pExpr, 0,
WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
if( pSubWInfo ){
if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
int r;
r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
regRowid, 0);
regRowid);
sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
sqlite3VdbeCurrentAddr(v)+2, r, iSet);
}
sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
/* The pSubWInfo->untestedTerms flag means that this OR term
** contained one or more AND term from a notReady table. The
** terms from the notReady table could not be tested and will
** need to be tested later.
*/
if( pSubWInfo->untestedTerms ) untestedTerms = 1;
/* Finish the loop through table entries that match term pOrTerm. */
sqlite3WhereEnd(pSubWInfo);
}
}
}
sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
/* sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset); */
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
sqlite3VdbeResolveLabel(v, iLoopBody);
pLevel->op = OP_Return;
pLevel->p1 = regReturn;
disableTerm(pLevel, pTerm);
if( pWInfo->nLevel>1 ) sqlite3StackFree(pParse->db, pOrTab);
if( !untestedTerms ) disableTerm(pLevel, pTerm);
}else
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
@ -3362,7 +3387,12 @@ static Bitmask codeOneLoopStart(
testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & notReady)!=0 ) continue;
if( (pTerm->prereqAll & notReady)!=0 ){
testcase( pWInfo->untestedTerms==0
&& (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 );
pWInfo->untestedTerms = 1;
continue;
}
pE = pTerm->pExpr;
assert( pE!=0 );
if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
@ -3385,7 +3415,10 @@ static Bitmask codeOneLoopStart(
testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & notReady)!=0 ) continue;
if( (pTerm->prereqAll & notReady)!=0 ){
assert( pWInfo->untestedTerms );
continue;
}
assert( pTerm->pExpr );
sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
pTerm->wtFlags |= TERM_CODED;
@ -3528,6 +3561,7 @@ WhereInfo *sqlite3WhereBegin(
){
int i; /* Loop counter */
int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
int nTabList; /* Number of elements in pTabList */
WhereInfo *pWInfo; /* Will become the return value of this function */
Vdbe *v = pParse->pVdbe; /* The virtual database engine */
Bitmask notReady; /* Cursors that are not yet positioned */
@ -3547,6 +3581,13 @@ WhereInfo *sqlite3WhereBegin(
return 0;
}
/* This function normally generates a nested loop for all tables in
** pTabList. But if the WHERE_ONETABLE_ONLY flag is set, then we should
** only generate code for the first table in pTabList and assume that
** any cursors associated with subsequent tables are uninitialized.
*/
nTabList = (wctrlFlags & WHERE_ONETABLE_ONLY) ? 1 : pTabList->nSrc;
/* Allocate and initialize the WhereInfo structure that will become the
** return value. A single allocation is used to store the WhereInfo
** struct, the contents of WhereInfo.a[], the WhereClause structure
@ -3555,7 +3596,7 @@ WhereInfo *sqlite3WhereBegin(
** some architectures. Hence the ROUND8() below.
*/
db = pParse->db;
nByteWInfo = ROUND8(sizeof(WhereInfo)+(pTabList->nSrc-1)*sizeof(WhereLevel));
nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
pWInfo = sqlite3DbMallocZero(db,
nByteWInfo +
sizeof(WhereClause) +
@ -3564,7 +3605,7 @@ WhereInfo *sqlite3WhereBegin(
if( db->mallocFailed ){
goto whereBeginError;
}
pWInfo->nLevel = pTabList->nSrc;
pWInfo->nLevel = nTabList;
pWInfo->pParse = pParse;
pWInfo->pTabList = pTabList;
pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
@ -3583,7 +3624,7 @@ WhereInfo *sqlite3WhereBegin(
/* Special case: a WHERE clause that is constant. Evaluate the
** expression and either jump over all of the code or fall thru.
*/
if( pWhere && (pTabList->nSrc==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){
if( pWhere && (nTabList==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){
sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL);
pWhere = 0;
}
@ -3603,6 +3644,11 @@ WhereInfo *sqlite3WhereBegin(
** to virtual table cursors are set. This is used to selectively disable
** the OR-to-IN transformation in exprAnalyzeOrTerm(). It is not helpful
** with virtual tables.
**
** Note that bitmasks are created for all pTabList->nSrc tables in
** pTabList, not just the first nTabList tables. nTabList is normally
** equal to pTabList->nSrc but might be shortened to 1 if the
** WHERE_ONETABLE_ONLY flag is set.
*/
assert( pWC->vmask==0 && pMaskSet->n==0 );
for(i=0; i<pTabList->nSrc; i++){
@ -3654,7 +3700,7 @@ WhereInfo *sqlite3WhereBegin(
pLevel = pWInfo->a;
andFlags = ~0;
WHERETRACE(("*** Optimizer Start ***\n"));
for(i=iFrom=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
for(i=iFrom=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
WhereCost bestPlan; /* Most efficient plan seen so far */
Index *pIdx; /* Index for FROM table at pTabItem */
int j; /* For looping over FROM tables */
@ -3699,8 +3745,8 @@ WhereInfo *sqlite3WhereBegin(
*/
for(isOptimal=1; isOptimal>=0 && bestJ<0; isOptimal--){
Bitmask mask = (isOptimal ? 0 : notReady);
assert( (pTabList->nSrc-iFrom)>1 || isOptimal );
for(j=iFrom, pTabItem=&pTabList->a[j]; j<pTabList->nSrc; j++, pTabItem++){
assert( (nTabList-iFrom)>1 || isOptimal );
for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
int doNotReorder; /* True if this table should not be reordered */
WhereCost sCost; /* Cost information from best[Virtual]Index() */
ExprList *pOrderBy; /* ORDER BY clause for index to optimize */
@ -3797,7 +3843,7 @@ WhereInfo *sqlite3WhereBegin(
** searching those tables.
*/
sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
for(i=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
Table *pTab; /* Table to open */
int iDb; /* Index of database containing table/index */
@ -3876,7 +3922,7 @@ WhereInfo *sqlite3WhereBegin(
** program.
*/
notReady = ~(Bitmask)0;
for(i=0; i<pTabList->nSrc; i++){
for(i=0; i<nTabList; i++){
notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady);
pWInfo->iContinue = pWInfo->a[i].addrCont;
}
@ -3888,7 +3934,7 @@ WhereInfo *sqlite3WhereBegin(
** the index is listed as "{}". If the primary key is used the
** index name is '*'.
*/
for(i=0; i<pTabList->nSrc; i++){
for(i=0; i<nTabList; i++){
char *z;
int n;
pLevel = &pWInfo->a[i];
@ -3956,7 +4002,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
/* Generate loop termination code.
*/
sqlite3ExprCacheClear(pParse);
for(i=pTabList->nSrc-1; i>=0; i--){
for(i=pWInfo->nLevel-1; i>=0; i--){
pLevel = &pWInfo->a[i];
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
if( pLevel->op!=OP_Noop ){
@ -4002,7 +4048,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
/* Close all of the cursors that were opened by sqlite3WhereBegin.
*/
for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
assert( pWInfo->nLevel==1 || pWInfo->nLevel==pTabList->nSrc );
for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );

View File

@ -481,10 +481,10 @@ do_test analyze3-4.1.2 {
sqlite3_bind_text $S 2 "abc" 3
execsql { DROP TABLE t1 }
sqlite3_step $S
} {SQLITE_SCHEMA}
} {SQLITE_ERROR}
do_test analyze3-4.1.3 {
sqlite3_finalize $S
} {SQLITE_SCHEMA}
} {SQLITE_ERROR}
# Check an authorization error.
#
@ -511,10 +511,10 @@ do_test analyze3-4.2.2 {
sqlite3_reset $S
sqlite3_bind_text $S 2 "abc" 3
sqlite3_step $S
} {SQLITE_SCHEMA}
} {SQLITE_AUTH}
do_test analyze3-4.2.4 {
sqlite3_finalize $S
} {SQLITE_SCHEMA}
} {SQLITE_AUTH}
# Check the effect of an authorization error that occurs in a re-prepare
# performed by sqlite3_step() is the same as one that occurs within
@ -526,10 +526,10 @@ do_test analyze3-4.3.1 {
execsql { CREATE TABLE t2(d, e, f) }
db auth auth
sqlite3_step $S
} {SQLITE_SCHEMA}
} {SQLITE_AUTH}
do_test analyze3-4.3.2 {
sqlite3_finalize $S
} {SQLITE_SCHEMA}
} {SQLITE_AUTH}
db auth {}
#-------------------------------------------------------------------------

View File

@ -814,5 +814,25 @@ do_test attach-9.3 {
}
} {1 2 3 4}
# Ticket [abe728bbc311d81334dae9762f0db87c07a98f79].
# Multi-database commit on an attached TEMP database.
#
do_test attach-10.1 {
execsql {
ATTACH '' AS noname;
ATTACH ':memory:' AS inmem;
BEGIN;
CREATE TABLE noname.noname(x);
CREATE TABLE inmem.inmem(y);
CREATE TABLE main.main(z);
COMMIT;
SELECT name FROM noname.sqlite_master;
SELECT name FROM inmem.sqlite_master;
}
} {noname inmem}
do_test attach-10.2 {
lrange [execsql {
PRAGMA database_list;
}] 9 end
} {4 noname {} 5 inmem {}}
finish_test

View File

@ -60,4 +60,17 @@ do_malloc_test attachmalloc-2 -tclprep {
ATTACH 'test2.db' AS db1;
}
set enable_shared_cache [sqlite3_enable_shared_cache 1]
sqlite3 dbaux test2.db
dbaux eval {SELECT * FROM sqlite_master}
do_malloc_test attachmalloc-3 -sqlbody {
SELECT * FROM sqlite_master;
ATTACH 'test2.db' AS two;
} -cleanup {
db eval { DETACH two }
}
dbaux close
sqlite3_enable_shared_cache $enable_shared_cache
finish_test

View File

@ -102,6 +102,7 @@ SQLITE_READ sqlite_master name main {}
SQLITE_READ sqlite_master rootpage main {}
SQLITE_READ sqlite_master sql main {}
SQLITE_READ sqlite_master tbl_name main {}
SQLITE_READ sqlite_master ROWID main {}
}
do_test auth2-2.2 {
set ::authargs {}
@ -121,6 +122,7 @@ SQLITE_READ sqlite_master name main {}
SQLITE_READ sqlite_master rootpage main {}
SQLITE_READ sqlite_master sql main {}
SQLITE_READ sqlite_master tbl_name main {}
SQLITE_READ sqlite_master ROWID main {}
}
do_test auth2-2.3 {
set ::authargs {}

View File

@ -904,4 +904,63 @@ ifcapable memorymanage {
db3 close
}
# Test that if the database is written to via the same database handle being
# used as the source by a backup operation:
#
# 10.1.*: If the db is in-memory, the backup is restarted.
# 10.2.*: If the db is a file, the backup is not restarted.
#
db close
file delete -force test.db test.db-journal
foreach {tn file rc} {
1 test.db SQLITE_DONE
2 :memory: SQLITE_OK
} {
do_test backup-10.$tn.1 {
sqlite3 db $file
execsql {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB);
BEGIN;
INSERT INTO t1 VALUES(NULL, randomblob(200));
INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
COMMIT;
SELECT count(*) FROM t1;
}
} {256}
do_test backup-10.$tn.2 {
set pgs [execsql {pragma page_count}]
expr {$pgs > 50 && $pgs < 75}
} {1}
do_test backup-10.$tn.3 {
file delete -force bak.db bak.db-journal
sqlite3 db2 bak.db
sqlite3_backup B db2 main db main
B step 50
} {SQLITE_OK}
do_test backup-10.$tn.4 {
execsql { UPDATE t1 SET b = randomblob(200) WHERE a IN (1, 250) }
} {}
do_test backup-10.$tn.5 {
B step 50
} $rc
do_test backup-10.$tn.6 {
B finish
} {SQLITE_OK}
db2 close
}
finish_test

View File

@ -1176,7 +1176,7 @@ do_test capi3c-19.4 {
sqlite3_reset $STMT
db eval {DROP TABLE t3}
sqlite3_step $STMT
} SQLITE_SCHEMA
} SQLITE_ERROR
do_test capi3c-19.4.1 {
sqlite3_errmsg $DB
} {no such table: t3}

View File

@ -239,43 +239,43 @@ do_test check-4.3 {
SELECT * FROM t4
}
} {4 3}
do_test check-4.3 {
do_test check-4.4 {
execsql {
UPDATE t4 SET x=12, y=2;
SELECT * FROM t4
}
} {12 2}
do_test check-4.4 {
do_test check-4.5 {
execsql {
UPDATE t4 SET x=12, y=-22;
SELECT * FROM t4
}
} {12 -22}
do_test check-4.5 {
do_test check-4.6 {
catchsql {
UPDATE t4 SET x=0, y=1;
}
} {1 {constraint failed}}
do_test check-4.6 {
do_test check-4.7 {
execsql {
SELECT * FROM t4;
}
} {12 -22}
do_test check-4.7 {
do_test check-4.8 {
execsql {
PRAGMA ignore_check_constraints=ON;
UPDATE t4 SET x=0, y=1;
SELECT * FROM t4;
}
} {0 1}
do_test check-4.8 {
do_test check-4.9 {
catchsql {
PRAGMA ignore_check_constraints=OFF;
UPDATE t4 SET x=0, y=2;
}
} {1 {constraint failed}}
ifcapable vacuum {
do_test check_4.9 {
do_test check_4.10 {
catchsql {
VACUUM
}

View File

@ -1,4 +1,4 @@
# 2004 August 30
# 2004 August 30 {}
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
@ -311,4 +311,41 @@ ifcapable oversize_cell_check {
} {1 {database disk image is malformed}}
}
db close
file delete -force test.db test.db-journal
do_test corrupt-8.1 {
sqlite3 db test.db
execsql {
PRAGMA page_size = 1024;
PRAGMA secure_delete = on;
PRAGMA auto_vacuum = 0;
CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
INSERT INTO t1 VALUES(5, randomblob(1900));
}
hexio_write test.db 2044 [hexio_render_int32 2]
hexio_write test.db 24 [hexio_render_int32 45]
catchsql { INSERT OR REPLACE INTO t1 VALUES(5, randomblob(1900)) }
} {1 {database disk image is malformed}}
db close
file delete -force test.db test.db-journal
do_test corrupt-8.2 {
sqlite3 db test.db
execsql {
PRAGMA page_size = 1024;
PRAGMA secure_delete = on;
PRAGMA auto_vacuum = 0;
CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
INSERT INTO t1 VALUES(5, randomblob(900));
INSERT INTO t1 VALUES(6, randomblob(900));
}
hexio_write test.db 2047 FF
hexio_write test.db 24 [hexio_render_int32 45]
catchsql { INSERT INTO t1 VALUES(4, randomblob(1900)) }
} {1 {database disk image is malformed}}
finish_test

View File

@ -89,7 +89,7 @@ Corruption detected in cell 15 on page 2}}
sqlite3 db test.db
db eval {PRAGMA integrity_check(1)}
} {{*** in database main ***
Corruption detected in cell 15 on page 2}}
On tree page 2 cell 15: Rowid 0 out of order (previous was 15)}}
}
# The code path that was causing the buffer overrun that this test

171
test/corruptE.test Normal file
View File

@ -0,0 +1,171 @@
# 2010 February 18
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file. It specifcally
# focuses on rowid order corruption.
#
# $Id: corruptE.test,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $
catch {file delete -force test.db test.db-journal test.bu}
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Construct a compact, dense database for testing.
#
do_test corruptE-1.1 {
execsql {
PRAGMA auto_vacuum = 0;
PRAGMA legacy_file_format=1;
BEGIN;
CREATE TABLE t1(x,y);
INSERT INTO t1 VALUES(1,1);
INSERT OR IGNORE INTO t1 SELECT x*2,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*3,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*5,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*7,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*11,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*13,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*17,y FROM t1;
INSERT OR IGNORE INTO t1 SELECT x*19,y FROM t1;
CREATE INDEX t1i1 ON t1(x);
CREATE TABLE t2 AS SELECT x,2 as y FROM t1 WHERE rowid%5!=0;
COMMIT;
}
} {}
ifcapable {integrityck} {
integrity_check corruptE-1.2
}
# Copy file $from into $to
#
proc copy_file {from to} {
file copy -force $from $to
}
# Setup for the tests. Make a backup copy of the good database in test.bu.
#
db close
copy_file test.db test.bu
sqlite3 db test.db
set fsize [file size test.db]
do_test corruptE-2.1 {
db close
copy_file test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 2041 [format %02x 0x2e]
sqlite3 db test.db
set res [ catchsql {PRAGMA integrity_check} ]
set ans [lindex $res 1]
list [regexp {out of order.*previous was} $ans] \
[regexp {out of order.*max larger than parent max} $ans]
} {1 1}
do_test corruptE-2.2 {
db close
copy_file test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 2047 [format %02x 0x84]
sqlite3 db test.db
set res [ catchsql {PRAGMA integrity_check} ]
set ans [lindex $res 1]
list [regexp {out of order.*previous was} $ans] \
[regexp {out of order.*min less than parent min} $ans]
} {1 1}
do_test corruptE-2.3 {
db close
copy_file test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 7420 [format %02x 0xa8]
hexio_write test.db 10459 [format %02x 0x8d]
sqlite3 db test.db
set res [ catchsql {PRAGMA integrity_check} ]
set ans [lindex $res 1]
list [regexp {out of order.*max larger than parent min} $ans]
} {1}
do_test corruptE-2.4 {
db close
copy_file test.bu test.db
# insert corrupt byte(s)
hexio_write test.db 10233 [format %02x 0xd0]
sqlite3 db test.db
set res [ catchsql {PRAGMA integrity_check} ]
set ans [lindex $res 1]
list [regexp {out of order.*min less than parent max} $ans]
} {1}
set tests [list {10233 0xd0} \
{941 0x42} \
{1028 0x53} \
{2041 0xd0} \
{2042 0x1f} \
{2047 0xaa} \
{2263 0x29} \
{2274 0x75} \
{3267 0xf2} \
{4104 0x2c} \
{5113 0x36} \
{10233 0x84} \
{10234 0x74} \
{10239 0x41} \
{10453 0x11} \
{11273 0x28} \
{11455 0x11} \
{11461 0xe6} \
{12281 0x99} \
{12296 0x9e} \
{12297 0xd7} \
{13303 0x53} ]
set tc 1
foreach test $tests {
do_test corruptE-3.$tc {
db close
copy_file test.bu test.db
# insert corrupt byte(s)
hexio_write test.db [lindex $test 0] [format %02x [lindex $test 1]]
sqlite3 db test.db
set res [ catchsql {PRAGMA integrity_check} ]
set ans [lindex $res 1]
list [regexp {out of order} $ans]
} {1}
incr tc 1
}
finish_test

View File

@ -340,4 +340,62 @@ ifcapable pragma {
} {jkl}
}
for {set i 1} {$i < 10} {incr i} {
catch { db close }
file delete -force test.db test.db-journal
sqlite3 db test.db
do_test crash8-5.$i.1 {
execsql {
CREATE TABLE t1(x PRIMARY KEY);
INSERT INTO t1 VALUES(randomblob(900));
INSERT INTO t1 SELECT randomblob(900) FROM t1;
INSERT INTO t1 SELECT randomblob(900) FROM t1;
INSERT INTO t1 SELECT randomblob(900) FROM t1;
INSERT INTO t1 SELECT randomblob(900) FROM t1;
INSERT INTO t1 SELECT randomblob(900) FROM t1;
INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 64 rows */
}
crashsql -file test.db -delay [expr ($::i%2) + 1] {
PRAGMA cache_size = 10;
BEGIN;
UPDATE t1 SET x = randomblob(900);
ROLLBACK;
INSERT INTO t1 VALUES(randomblob(900));
}
execsql { PRAGMA integrity_check }
} {ok}
catch { db close }
file delete -force test.db test.db-journal
sqlite3 db test.db
do_test crash8-5.$i.2 {
execsql {
PRAGMA cache_size = 10;
CREATE TABLE t1(x PRIMARY KEY);
INSERT INTO t1 VALUES(randomblob(900));
INSERT INTO t1 SELECT randomblob(900) FROM t1;
INSERT INTO t1 SELECT randomblob(900) FROM t1;
INSERT INTO t1 SELECT randomblob(900) FROM t1;
INSERT INTO t1 SELECT randomblob(900) FROM t1;
INSERT INTO t1 SELECT randomblob(900) FROM t1;
INSERT INTO t1 SELECT randomblob(900) FROM t1; /* 64 rows */
BEGIN;
UPDATE t1 SET x = randomblob(900);
}
file delete -force testX.db testX.db-journal
copy_file test.db testX.db
copy_file test.db-journal testX.db-journal
db close
crashsql -file test.db -delay [expr ($::i%2) + 1] {
SELECT * FROM sqlite_master;
INSERT INTO t1 VALUES(randomblob(900));
}
sqlite3 db2 testX.db
execsql { PRAGMA integrity_check } db2
} {ok}
}
catch {db2 close}
finish_test

224
test/ctime.test Normal file
View File

@ -0,0 +1,224 @@
# 2009 February 24
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the compile time diagnostic
# functions.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Test organization:
#
# ctime-1.*: Test pragma support.
# ctime-2.*: Test function support.
#
ifcapable !pragma||!compileoption_diags {
finish_test
return
}
#####################
# ctime-1.*: Test pragma support.
do_test ctime-1.1.1 {
catchsql {
PRAGMA compile_options();
}
} {1 {near ")": syntax error}}
do_test ctime-1.1.2 {
catchsql {
PRAGMA compile_options(NULL);
}
} {1 {near "NULL": syntax error}}
do_test ctime-1.1.3 {
catchsql {
PRAGMA compile_options *;
}
} {1 {near "*": syntax error}}
do_test ctime-1.2.1 {
set ans [ catchsql {
PRAGMA compile_options;
} ]
list [ lindex $ans 0 ]
} {0}
# the results should be in sorted order already
do_test ctime-1.2.2 {
set ans [ catchsql {
PRAGMA compile_options;
} ]
list [ lindex $ans 0 ] [ expr { [lsort [lindex $ans 1]]==[lindex $ans 1] } ]
} {0 1}
# SQLITE_THREADSAFE should pretty much always be defined
# one way or the other, and it must have a value of 0 or 1.
do_test ctime-1.4.1 {
catchsql {
SELECT sqlite_compileoption_used('SQLITE_THREADSAFE');
}
} {0 1}
do_test ctime-1.4.2 {
catchsql {
SELECT sqlite_compileoption_used('THREADSAFE');
}
} {0 1}
do_test ctime-1.4.3 {
catchsql {
SELECT sqlite_compileoption_used("THREADSAFE");
}
} {0 1}
do_test ctime-1.5 {
set ans1 [ catchsql {
SELECT sqlite_compileoption_used('THREADSAFE=0');
} ]
set ans2 [ catchsql {
SELECT sqlite_compileoption_used('THREADSAFE=1');
} ]
lsort [ list $ans1 $ans2 ]
} {{0 0} {0 1}}
do_test ctime-1.6 {
execsql {
SELECT sqlite_compileoption_used('THREADSAFE=');
}
} {0}
do_test ctime-1.7.1 {
execsql {
SELECT sqlite_compileoption_used('SQLITE_OMIT_COMPILEOPTION_DIAGS');
}
} {0}
do_test ctime-1.7.2 {
execsql {
SELECT sqlite_compileoption_used('OMIT_COMPILEOPTION_DIAGS');
}
} {0}
#####################
# ctime-2.*: Test function support.
do_test ctime-2.1.1 {
catchsql {
SELECT sqlite_compileoption_used();
}
} {1 {wrong number of arguments to function sqlite_compileoption_used()}}
do_test ctime-2.1.2 {
catchsql {
SELECT sqlite_compileoption_used(NULL);
}
} {0 {{}}}
do_test ctime-2.1.3 {
catchsql {
SELECT sqlite_compileoption_used("");
}
} {0 0}
do_test ctime-2.1.4 {
catchsql {
SELECT sqlite_compileoption_used('');
}
} {0 0}
do_test ctime-2.1.5 {
catchsql {
SELECT sqlite_compileoption_used(foo);
}
} {1 {no such column: foo}}
do_test ctime-2.1.6 {
catchsql {
SELECT sqlite_compileoption_used('THREADSAFE', 0);
}
} {1 {wrong number of arguments to function sqlite_compileoption_used()}}
do_test ctime-2.1.7 {
catchsql {
SELECT sqlite_compileoption_used(0);
}
} {0 0}
do_test ctime-2.1.8 {
catchsql {
SELECT sqlite_compileoption_used('0');
}
} {0 0}
do_test ctime-2.1.9 {
catchsql {
SELECT sqlite_compileoption_used(1.0);
}
} {0 0}
do_test ctime-2.2.1 {
catchsql {
SELECT sqlite_compileoption_get();
}
} {1 {wrong number of arguments to function sqlite_compileoption_get()}}
do_test ctime-2.2.2 {
catchsql {
SELECT sqlite_compileoption_get(0, 0);
}
} {1 {wrong number of arguments to function sqlite_compileoption_get()}}
# This assumes there is at least 1 compile time option
# (see SQLITE_THREADSAFE above).
do_test ctime-2.3 {
catchsql {
SELECT sqlite_compileoption_used(sqlite_compileoption_get(0));
}
} {0 1}
# This assumes there is at least 1 compile time option
# (see SQLITE_THREADSAFE above).
do_test ctime-2.4 {
set ans [ catchsql {
SELECT sqlite_compileoption_get(0);
} ]
list [lindex $ans 0]
} {0}
# Get the list of defines using the pragma,
# then try querying each one with the functions.
set ans [ catchsql {
PRAGMA compile_options;
} ]
set opts [ lindex $ans 1 ]
set tc 1
foreach opt $opts {
do_test ctime-2.5.$tc {
set N [ expr {$tc-1} ]
set ans1 [ catchsql {
SELECT sqlite_compileoption_get($N);
} ]
set ans2 [ catchsql {
SELECT sqlite_compileoption_used($opt);
} ]
list [ lindex $ans1 0 ] [ expr { [lindex $ans1 1]==$opt } ] \
[ expr { $ans2 } ]
} {0 1 {0 1}}
incr tc 1
}
# test 1 past array bounds
do_test ctime-2.5.$tc {
set N [ expr {$tc-1} ]
set ans [ catchsql {
SELECT sqlite_compileoption_get($N);
} ]
} {0 {{}}}
incr tc 1
# test 1 before array bounds (N=-1)
do_test ctime-2.5.$tc {
set N -1
set ans [ catchsql {
SELECT sqlite_compileoption_get($N);
} ]
} {0 {{}}}
finish_test

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,7 @@ source $testdir/tester.tcl
#
ifcapable !fts3 { finish_test ; return }
source $testdir/fts3_common.tcl
source $testdir/malloc_common.tcl
# Procs used to make the tests in this file easier to read.
#
@ -46,7 +47,14 @@ proc error_test {tn sql result} {
# DO_MALLOC_TEST=1: Run tests with transient OOM errors.
# DO_MALLOC_TEST=2: Run tests with persistent OOM errors.
#
foreach DO_MALLOC_TEST [lrange {0 1 2} 0 end] {
foreach {DO_MALLOC_TEST enc} {
0 utf-8
1 utf-8
2 utf-8
1 utf-16
} {
#if {$DO_MALLOC_TEST} break
# Reset the database and database connection. If this iteration of the
# [foreach] loop is testing with OOM errors, disable the lookaside buffer.
@ -55,6 +63,15 @@ db close
file delete -force test.db test.db-journal
sqlite3 db test.db
if {$DO_MALLOC_TEST} { sqlite3_db_config_lookaside db 0 0 0 }
db eval "PRAGMA encoding = '$enc'"
proc mit {blob} {
set scan(littleEndian) i*
set scan(bigEndian) I*
binary scan $blob $scan($::tcl_platform(byteOrder)) r
return $r
}
db func mit mit
##########################################################################
# Test the example CREATE VIRTUAL TABLE statements in section 1.1
@ -175,7 +192,7 @@ write_test 1.2.2.4 docs_content {
}
read_test 1.2.2.5 { SELECT count(*) FROM docs_segdir } {3}
write_test 1.2.2.6 docs_segdir {
SELECT * FROM (SELECT optimize(docs) FROM docs LIMIT 1) WHERE 0;
INSERT INTO docs(docs) VALUES('optimize');
}
read_test 1.2.2.7 { SELECT count(*) FROM docs_segdir } {1}
ddl_test 1.2.2.8 { DROP TABLE docs }
@ -402,7 +419,7 @@ read_test 1.7.1.6 {
ddl_test 1.7.2.1 { CREATE VIRTUAL TABLE text USING fts3() }
write_test 3.2.2 text_content {
write_test 1.7.2.2 text_content {
INSERT INTO text VALUES('
During 30 Nov-1 Dec, 2-3oC drops. Cool in the upper portion, minimum temperature 14-16oC and cool elsewhere, minimum temperature 17-20oC. Cold to very cold on mountaintops, minimum temperature 6-12oC. Northeasterly winds 15-30 km/hr. After that, temperature increases. Northeasterly winds 15-30 km/hr.
');
@ -410,11 +427,28 @@ write_test 3.2.2 text_content {
read_test 1.7.2.3 {
SELECT snippet(text) FROM text WHERE text MATCH 'cold'
} {{<b>...</b> elsewhere, minimum temperature 17-20oC. <b>Cold</b> to very <b>cold</b> on mountaintops, minimum <b>...</b>}}
} {{<b>...</b>cool elsewhere, minimum temperature 17-20oC. <b>Cold</b> to very <b>cold</b> on mountaintops, minimum temperature 6<b>...</b>}}
read_test 1.7.2.4 {
SELECT snippet(text, '[', ']', '...') FROM text WHERE text MATCH '"min* tem*"'
} {{... 2-3oC drops. Cool in the upper portion, [minimum] [temperature] 14-16oC and cool elsewhere, [minimum] ...}}
} {{...the upper portion, [minimum] [temperature] 14-16oC and cool elsewhere, [minimum] [temperature] 17-20oC. Cold...}}
ddl_test 1.7.3.1 { DROP TABLE IF EXISTS t1 }
ddl_test 1.7.3.2 { CREATE VIRTUAL TABLE t1 USING fts3(a, b) }
write_test 1.7.3.3 t1_content {
INSERT INTO t1 VALUES(
'transaction default models default', 'Non transaction reads');
}
write_test 1.7.3.4 t1_content {
INSERT INTO t1 VALUES('the default transaction', 'these semantics present');
}
write_test 1.7.3.5 t1_content {
INSERT INTO t1 VALUES('single request', 'default data');
}
read_test 1.7.3.6 {
SELECT mit(matchinfo(t1)) FROM t1
WHERE t1 MATCH 'default transaction "these semantics"';
} {{3 2 1 3 2 0 1 1 1 2 2 0 1 1 0 0 0 1 1 1}}
##########################################################################
# Test the example in section 5 (custom tokenizers).
@ -443,6 +477,7 @@ read_test 1.8.2.4 {
# functions are handled correctly.
#
set DO_MALLOC_TEST 0
ddl_test 2.1.0 { DROP TABLE IF EXISTS t1 }
ddl_test 2.1.1 { CREATE VIRTUAL TABLE t1 USING fts3(a, b) }
write_test 2.1.2 t1_content {
INSERT INTO t1 VALUES('one two three', x'A1B2C3D4E5F6');
@ -463,7 +498,208 @@ error_test 2.1.7 {
SELECT snippet() FROM t1 WHERE a MATCH 'one'
} {unable to use function snippet in the requested context}
error_test 2.1.8 {
SELECT snippet(a, b, 'A', 'B', 'C') FROM t1 WHERE a MATCH 'one'
SELECT snippet(a, b, 'A', 'B', 'C', 'D', 'E') FROM t1 WHERE a MATCH 'one'
} {wrong number of arguments to function snippet()}
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Test the effect of an OOM error while installing the FTS3 module (i.e.
# opening a database handle). This case was not tested by the OOM testing
# of the document examples above.
#
do_malloc_test e_fts3-3 -tclbody {
if {[catch {sqlite3 db test.db}]} { error "out of memory" }
}
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Verify the return values of the optimize() function. If no error occurs,
# the returned value should be "Index optimized" if the data structure
# was modified, or "Index already optimal" if it were not.
#
set DO_MALLOC_TEST 0
ddl_test 4.1 { CREATE VIRTUAL TABLE t4 USING fts3(a, b) }
write_test 4.2 t4_content {
INSERT INTO t4 VALUES('In Xanadu', 'did Kubla Khan');
}
write_test 4.3 t4_content {
INSERT INTO t4 VALUES('a stately pleasure', 'dome decree');
}
do_test e_fts3-4.4 {
execsql { SELECT optimize(t4) FROM t4 LIMIT 1 }
} {{Index optimized}}
do_test e_fts3-4.5 {
execsql { SELECT optimize(t4) FROM t4 LIMIT 1 }
} {{Index already optimal}}
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Test that the snippet function appears to work correctly with 1, 2, 3
# or 4 arguments passed to it.
#
set DO_MALLOC_TEST 0
ddl_test 5.1 { CREATE VIRTUAL TABLE t5 USING fts3(x) }
write_test 5.2 t5_content {
INSERT INTO t5 VALUES('In Xanadu did Kubla Khan A stately pleasure-dome decree Where Alph, the sacred river, ran Through caverns measureless to man Down to a sunless sea. So twice five miles of fertile ground With walls and towers were girdled round : And there were gardens bright with sinuous rills, Where blossomed many an incense-bearing tree ; And here were forests ancient as the hills, Enfolding sunny spots of greenery.');
}
read_test 5.3 {
SELECT snippet(t5) FROM t5 WHERE t5 MATCH 'miles'
} {{<b>...</b>to a sunless sea. So twice five <b>miles</b> of fertile ground With walls and towers<b>...</b>}}
read_test 5.4 {
SELECT snippet(t5, '<i>') FROM t5 WHERE t5 MATCH 'miles'
} {{<b>...</b>to a sunless sea. So twice five <i>miles</b> of fertile ground With walls and towers<b>...</b>}}
read_test 5.5 {
SELECT snippet(t5, '<i>', '</i>') FROM t5 WHERE t5 MATCH 'miles'
} {{<b>...</b>to a sunless sea. So twice five <i>miles</i> of fertile ground With walls and towers<b>...</b>}}
read_test 5.6 {
SELECT snippet(t5, '<i>', '</i>', 'XXX') FROM t5 WHERE t5 MATCH 'miles'
} {{XXXto a sunless sea. So twice five <i>miles</i> of fertile ground With walls and towersXXX}}
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Test that an empty MATCH expression returns an empty result set. As
# does passing a NULL value as a MATCH expression.
#
set DO_MALLOC_TEST 0
ddl_test 6.1 { CREATE VIRTUAL TABLE t6 USING fts3(x) }
write_test 6.2 t5_content { INSERT INTO t6 VALUES('a'); }
write_test 6.3 t5_content { INSERT INTO t6 VALUES('b'); }
write_test 6.4 t5_content { INSERT INTO t6 VALUES('c'); }
read_test 6.5 { SELECT * FROM t6 WHERE t6 MATCH '' } {}
read_test 6.6 { SELECT * FROM t6 WHERE x MATCH '' } {}
read_test 6.7 { SELECT * FROM t6 WHERE t6 MATCH NULL } {}
read_test 6.8 { SELECT * FROM t6 WHERE x MATCH NULL } {}
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Test a few facets of the FTS3 xFilter() callback implementation:
#
# 1. That the sqlite3_index_constraint.usable flag is respected.
#
# 2. That it is an error to use the "docid" or "rowid" column of
# an FTS3 table as the LHS of a MATCH operator.
#
# 3. That it is an error to AND together two MATCH expressions in
# that refer to a single FTS3 table in a WHERE clause.
#
#
set DO_MALLOC_TEST 0
ddl_test 7.1.1 { CREATE VIRTUAL TABLE t7 USING fts3(a) }
ddl_test 7.1.2 { CREATE VIRTUAL TABLE t8 USING fts3(b) }
write_test 7.1.3 t7_content { INSERT INTO t7(docid, a) VALUES(4,'number four') }
write_test 7.1.4 t7_content { INSERT INTO t7(docid, a) VALUES(5,'number five') }
write_test 7.1.5 t8_content { INSERT INTO t8(docid, b) VALUES(4,'letter D') }
write_test 7.1.6 t8_content { INSERT INTO t8(docid, b) VALUES(5,'letter E') }
read_test 7.1.7 {
SELECT a || ':' || b FROM t7 JOIN t8 USING(docid)
} {{number four:letter D} {number five:letter E}}
error_test 7.2.1 {
SELECT * FROM t7 WHERE docid MATCH 'number'
} {unable to use function MATCH in the requested context}
error_test 7.2.2 {
SELECT * FROM t7 WHERE rowid MATCH 'number'
} {unable to use function MATCH in the requested context}
error_test 7.3.1 {
SELECT * FROM t7 WHERE a MATCH 'number' AND a MATCH 'four'
} {unable to use function MATCH in the requested context}
error_test 7.3.2 {
SELECT * FROM t7, t8 WHERE a MATCH 'number' AND a MATCH 'four'
} {unable to use function MATCH in the requested context}
error_test 7.3.3 {
SELECT * FROM t7, t8 WHERE b MATCH 'letter' AND b MATCH 'd'
} {unable to use function MATCH in the requested context}
read_test 7.3.4 {
SELECT * FROM t7, t8 WHERE a MATCH 'number' AND b MATCH 'letter'
} {{number four} {letter D} {number four} {letter E} {number five} {letter D} {number five} {letter E}}
read_test 7.3.5 {
SELECT * FROM t7 WHERE a MATCH 'number' AND docid = 4
} {{number four}}
#-------------------------------------------------------------------------
# Test the quoting of FTS3 table column names. Names may be quoted using
# any of "", '', ``` or [].
#
set DO_MALLOC_TEST 0
ddl_test 8.1.1 { CREATE VIRTUAL TABLE t9a USING fts3("c1", [c2]) }
ddl_test 8.1.2 { CREATE VIRTUAL TABLE t9b USING fts3('c1', `c2`) }
read_test 8.1.3 { PRAGMA table_info(t9a) } {0 c1 {} 0 {} 0 1 c2 {} 0 {} 0}
read_test 8.1.4 { PRAGMA table_info(t9b) } {0 c1 {} 0 {} 0 1 c2 {} 0 {} 0}
ddl_test 8.2.1 { CREATE VIRTUAL TABLE t9c USING fts3("c""1", 'c''2') }
read_test 8.2.2 { PRAGMA table_info(t9c) } {0 c\"1 {} 0 {} 0 1 c'2 {} 0 {} 0}
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Test that FTS3 tables can be renamed using the ALTER RENAME command.
# OOM errors are tested during ALTER RENAME commands also.
#
foreach DO_MALLOC_TEST {0 1 2} {
db close
file delete -force test.db test.db-journal
sqlite3 db test.db
if {$DO_MALLOC_TEST} { sqlite3_db_config_lookaside db 0 0 0 }
ddl_test 9.1.1 { CREATE VIRTUAL TABLE t10 USING fts3(x) }
write_test 9.1.2 t10_content { INSERT INTO t10 VALUES('fts3 tables') }
write_test 9.1.3 t10_content { INSERT INTO t10 VALUES('are renameable') }
read_test 9.1.4 {
SELECT * FROM t10 WHERE t10 MATCH 'table*'
} {{fts3 tables}}
read_test 9.1.5 {
SELECT * FROM t10 WHERE x MATCH 'rename*'
} {{are renameable}}
ddl_test 9.1.6 { ALTER TABLE t10 RENAME TO t11 }
read_test 9.1.7 {
SELECT * FROM t11 WHERE t11 MATCH 'table*'
} {{fts3 tables}}
read_test 9.1.8 {
SELECT * FROM t11 WHERE x MATCH 'rename*'
} {{are renameable}}
}
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
# Test a couple of cases involving corrupt data structures:
#
# 1) A case where a document referenced by the full-text index is
# not present in the %_content table.
#
# 2) A badly formatted b-tree segment node.
#
set DO_MALLOC_TEST 0
ddl_test 10.1.1 { CREATE VIRTUAL TABLE ta USING fts3 }
write_test 10.1.2 ta_content {
INSERT INTO ta VALUES('During a summer vacation in 1790') }
write_test 10.1.3 ta_content {
INSERT INTO ta VALUES('Wordsworth went on a walking tour') }
write_test 10.1.4 ta_content { DELETE FROM ta_content WHERE rowid = 2 }
read_test 10.1.5 {
SELECT * FROM ta WHERE ta MATCH 'summer'
} {{During a summer vacation in 1790}}
error_test 10.1.6 {
SELECT * FROM ta WHERE ta MATCH 'walking'
} {database disk image is malformed}
write_test 10.2.1 ta_content { DELETE FROM ta }
write_test 10.2.2 ta_content {
INSERT INTO ta VALUES('debate demonstrated the rising difficulty') }
write_test 10.2.3 ta_content {
INSERT INTO ta VALUES('Google released its browser beta') }
set blob [db one {SELECT root FROM ta_segdir WHERE rowid = 2}]
binary scan $blob "a6 a3 a*" start middle end
set middle "\x0E\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x06\x06"
set blob [binary format "a6 a* a*" $start $middle $end]
write_test 10.2.4 ta_segdir {
UPDATE ta_segdir SET root = $blob WHERE rowid = 2
}
error_test 10.2.5 {
SELECT * FROM ta WHERE ta MATCH 'beta'
} {database disk image is malformed}
finish_test

View File

@ -1003,6 +1003,169 @@ ifcapable altertable {
do_test fkey2-14.2.2.7 {
execsql { INSERT INTO t3 VALUES(1, NULL, 1) }
} {}
# Repeat for TEMP tables
#
drop_all_tables
do_test fkey2-14.1tmp.1 {
# Adding a column with a REFERENCES clause is not supported.
execsql {
CREATE TEMP TABLE t1(a PRIMARY KEY);
CREATE TEMP TABLE t2(a, b);
}
catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 }
} {0 {}}
do_test fkey2-14.1tmp.2 {
catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 }
} {0 {}}
do_test fkey2-14.1tmp.3 {
catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL}
} {0 {}}
do_test fkey2-14.1tmp.4 {
catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'}
} {1 {Cannot add a REFERENCES column with non-NULL default value}}
do_test fkey2-14.1tmp.5 {
catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
} {1 {Cannot add a REFERENCES column with non-NULL default value}}
do_test fkey2-14.1tmp.6 {
execsql {
PRAGMA foreign_keys = off;
ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
PRAGMA foreign_keys = on;
SELECT sql FROM sqlite_temp_master WHERE name='t2';
}
} {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
do_test fkey2-14.2tmp.1.1 {
test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
} {{CREATE TABLE t1(a REFERENCES "t3")}}
do_test fkey2-14.2tmp.1.2 {
test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3
} {{CREATE TABLE t1(a REFERENCES t2)}}
do_test fkey2-14.2tmp.1.3 {
test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
} {{CREATE TABLE t1(a REFERENCES "t3")}}
# Test ALTER TABLE RENAME TABLE a bit.
#
do_test fkey2-14.2tmp.2.1 {
drop_all_tables
execsql {
CREATE TEMP TABLE t1(a PRIMARY KEY, b REFERENCES t1);
CREATE TEMP TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2);
CREATE TEMP TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1);
}
execsql { SELECT sql FROM sqlite_temp_master WHERE type = 'table'}
} [list \
{CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1)} \
{CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)} \
{CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)} \
]
do_test fkey2-14.2tmp.2.2 {
execsql { ALTER TABLE t1 RENAME TO t4 }
execsql { SELECT sql FROM sqlite_temp_master WHERE type = 'table'}
} [list \
{CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4")} \
{CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)} \
{CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
]
do_test fkey2-14.2tmp.2.3 {
catchsql { INSERT INTO t3 VALUES(1, 2, 3) }
} {1 {foreign key constraint failed}}
do_test fkey2-14.2tmp.2.4 {
execsql { INSERT INTO t4 VALUES(1, NULL) }
} {}
do_test fkey2-14.2tmp.2.5 {
catchsql { UPDATE t4 SET b = 5 }
} {1 {foreign key constraint failed}}
do_test fkey2-14.2tmp.2.6 {
catchsql { UPDATE t4 SET b = 1 }
} {0 {}}
do_test fkey2-14.2tmp.2.7 {
execsql { INSERT INTO t3 VALUES(1, NULL, 1) }
} {}
# Repeat for ATTACH-ed tables
#
drop_all_tables
do_test fkey2-14.1aux.1 {
# Adding a column with a REFERENCES clause is not supported.
execsql {
ATTACH ':memory:' AS aux;
CREATE TABLE aux.t1(a PRIMARY KEY);
CREATE TABLE aux.t2(a, b);
}
catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 }
} {0 {}}
do_test fkey2-14.1aux.2 {
catchsql { ALTER TABLE t2 ADD COLUMN d DEFAULT NULL REFERENCES t1 }
} {0 {}}
do_test fkey2-14.1aux.3 {
catchsql { ALTER TABLE t2 ADD COLUMN e REFERENCES t1 DEFAULT NULL}
} {0 {}}
do_test fkey2-14.1aux.4 {
catchsql { ALTER TABLE t2 ADD COLUMN f REFERENCES t1 DEFAULT 'text'}
} {1 {Cannot add a REFERENCES column with non-NULL default value}}
do_test fkey2-14.1aux.5 {
catchsql { ALTER TABLE t2 ADD COLUMN g DEFAULT CURRENT_TIME REFERENCES t1 }
} {1 {Cannot add a REFERENCES column with non-NULL default value}}
do_test fkey2-14.1aux.6 {
execsql {
PRAGMA foreign_keys = off;
ALTER TABLE t2 ADD COLUMN h DEFAULT 'text' REFERENCES t1;
PRAGMA foreign_keys = on;
SELECT sql FROM aux.sqlite_master WHERE name='t2';
}
} {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}}
do_test fkey2-14.2aux.1.1 {
test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3
} {{CREATE TABLE t1(a REFERENCES "t3")}}
do_test fkey2-14.2aux.1.2 {
test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3
} {{CREATE TABLE t1(a REFERENCES t2)}}
do_test fkey2-14.2aux.1.3 {
test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3
} {{CREATE TABLE t1(a REFERENCES "t3")}}
# Test ALTER TABLE RENAME TABLE a bit.
#
do_test fkey2-14.2aux.2.1 {
drop_all_tables
execsql {
CREATE TABLE aux.t1(a PRIMARY KEY, b REFERENCES t1);
CREATE TABLE aux.t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2);
CREATE TABLE aux.t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1);
}
execsql { SELECT sql FROM aux.sqlite_master WHERE type = 'table'}
} [list \
{CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1)} \
{CREATE TABLE t2(a PRIMARY KEY, b REFERENCES t1, c REFERENCES t2)} \
{CREATE TABLE t3(a REFERENCES t1, b REFERENCES t2, c REFERENCES t1)} \
]
do_test fkey2-14.2aux.2.2 {
execsql { ALTER TABLE t1 RENAME TO t4 }
execsql { SELECT sql FROM aux.sqlite_master WHERE type = 'table'}
} [list \
{CREATE TABLE "t4"(a PRIMARY KEY, b REFERENCES "t4")} \
{CREATE TABLE t2(a PRIMARY KEY, b REFERENCES "t4", c REFERENCES t2)} \
{CREATE TABLE t3(a REFERENCES "t4", b REFERENCES t2, c REFERENCES "t4")} \
]
do_test fkey2-14.2aux.2.3 {
catchsql { INSERT INTO t3 VALUES(1, 2, 3) }
} {1 {foreign key constraint failed}}
do_test fkey2-14.2aux.2.4 {
execsql { INSERT INTO t4 VALUES(1, NULL) }
} {}
do_test fkey2-14.2aux.2.5 {
catchsql { UPDATE t4 SET b = 5 }
} {1 {foreign key constraint failed}}
do_test fkey2-14.2aux.2.6 {
catchsql { UPDATE t4 SET b = 1 }
} {0 {}}
do_test fkey2-14.2aux.2.7 {
execsql { INSERT INTO t3 VALUES(1, NULL, 1) }
} {}
}
do_test fkey-2.14.3.1 {

View File

@ -208,7 +208,7 @@ proc fts3_doclist {tbl term where} {
proc gobble_varint {varname} {
upvar $varname blob
set n [read_varint $blob ret]
set n [read_fts3varint $blob ret]
set blob [string range $blob $n end]
return $ret
}
@ -310,36 +310,65 @@ proc fts3_read {tbl where varname} {
# match the expected results passed via parameter $result.
#
proc do_select_test {name sql result} {
doPassiveTest $name $sql [list 0 $result]
uplevel [list doPassiveTest 0 $name $sql [list 0 $result]]
}
proc do_restart_select_test {name sql result} {
uplevel [list doPassiveTest 1 $name $sql [list 0 $result]]
}
proc do_error_test {name sql error} {
doPassiveTest $name $sql [list 1 $error]
uplevel [list doPassiveTest 0 $name $sql [list 1 $error]]
}
proc doPassiveTest {name sql catchres} {
proc doPassiveTest {isRestart name sql catchres} {
if {![info exists ::DO_MALLOC_TEST]} { set ::DO_MALLOC_TEST 1 }
if {$::DO_MALLOC_TEST} {
set answers [list {1 {out of memory}} $catchres]
set modes [list 100000 transient 1 persistent]
} else {
set answers [list $catchres]
set modes [list 0 nofail]
switch $::DO_MALLOC_TEST {
0 { # No malloc failures.
do_test $name [list set {} [uplevel [list catchsql $sql]]] $catchres
return
}
1 { # Simulate transient failures.
set nRepeat 1
set zName "transient"
set nStartLimit 100000
set nBackup 1
}
2 { # Simulate persistent failures.
set nRepeat 1
set zName "persistent"
set nStartLimit 100000
set nBackup 1
}
3 { # Simulate transient failures with extra brute force.
set nRepeat 100000
set zName "ridiculous"
set nStartLimit 1
set nBackup 10
}
}
# The set of acceptable results from running [catchsql $sql].
#
set answers [list {1 {out of memory}} $catchres]
set str [join $answers " OR "]
foreach {nRepeat zName} $modes {
for {set iFail 1} 1 {incr iFail} {
if {$::DO_MALLOC_TEST} {sqlite3_memdebug_fail $iFail -repeat $nRepeat}
set nFail 1
for {set iLimit $nStartLimit} {$nFail} {incr iLimit} {
for {set iFail 1} {$nFail && $iFail<=$iLimit} {incr iFail} {
for {set iTest 0} {$iTest<$nBackup && ($iFail-$iTest)>0} {incr iTest} {
set res [catchsql $sql]
if {[lsearch -exact $answers $res]>=0} {
set res $str
if {$isRestart} { sqlite3 db test.db }
sqlite3_memdebug_fail [expr $iFail-$iTest] -repeat $nRepeat
set res [uplevel [list catchsql $sql]]
if {[lsearch -exact $answers $res]>=0} { set res $str }
set testname "$name.$zName.$iFail"
do_test "$name.$zName.$iLimit.$iFail" [list set {} $res] $str
set nFail [sqlite3_memdebug_fail -1 -benigncnt nBenign]
}
do_test $name.$zName.$iFail [list set {} $res] $str
set nFail [sqlite3_memdebug_fail -1 -benigncnt nBenign]
if {$nFail==0} break
}
}
}

View File

@ -1131,39 +1131,36 @@ do_test fts3ac-4.2 {
SELECT snippet(email) FROM email
WHERE email MATCH 'christmas candlelight'
}
} {{<b>...</b> place.? What do you think about going here <b>Christmas</b>
eve?? They have an 11:00 a.m. service and a <b>candlelight</b> service at 5:00 p.m.,
among others. <b>...</b>}}
} {{<b>...</b>here <b>Christmas</b>
eve?? They have an 11:00 a.m. service and a <b>candlelight</b> service<b>...</b>}}
do_test fts3ac-4.3 {
execsql {
SELECT snippet(email) FROM email
WHERE email MATCH 'deal sheet potential reuse'
}
} {{EOL-Accenture <b>Deal</b> <b>Sheet</b> <b>...</b> intent
Review Enron asset base for <b>potential</b> <b>reuse</b>/ licensing
Contract negotiations <b>...</b>}}
} {{EOL-Accenture <b>Deal</b> <b>Sheet</b><b>...</b>asset base for <b>potential</b> <b>reuse</b>/ licensing
Contract negotiations<b>...</b>}}
do_test fts3ac-4.4 {
execsql {
SELECT snippet(email,'<<<','>>>',' ') FROM email
WHERE email MATCH 'deal sheet potential reuse'
}
} {{EOL-Accenture <<<Deal>>> <<<Sheet>>> intent
Review Enron asset base for <<<potential>>> <<<reuse>>>/ licensing
Contract negotiations }}
} {{EOL-Accenture <<<Deal>>> <<<Sheet>>> asset base for <<<potential>>> <<<reuse>>>/ licensing
Contract negotiations }}
do_test fts3ac-4.5 {
execsql {
SELECT snippet(email,'<<<','>>>',' ') FROM email
WHERE email MATCH 'first things'
}
} {{Re: <<<First>>> Polish Deal! Congrats! <<<Things>>> seem to be building rapidly now on the }}
} {{Re: <<<First>>> Polish Deal! Congrats! <<<Things>>> seem to be building rapidly now }}
do_test fts3ac-4.6 {
execsql {
SELECT snippet(email) FROM email
WHERE email MATCH 'chris is here'
}
} {{<b>chris</b>.germany@enron.com <b>...</b> Sounds good to me. I bet this <b>is</b> next to the Warick?? Hotel. <b>...</b> place.? What do you think about going <b>here</b> Christmas
eve?? They have an 11:00 a.m. <b>...</b>}}
} {{<b>...</b><b>chris</b>.germany@enron.com'" <<b>chris</b><b>...</b>bet this <b>is</b> next to<b>...</b>about going <b>here</b> Christmas
eve<b>...</b>}}
do_test fts3ac-4.7 {
execsql {
SELECT snippet(email) FROM email
@ -1171,19 +1168,15 @@ do_test fts3ac-4.7 {
}
} {{Erin:
<b>Pursuant</b> <b>to</b> your request, attached are the Schedule to <b>...</b>}}
<b>Pursuant</b> <b>to</b> your request, attached are the Schedule to the ISDA Master Agreement, together<b>...</b>}}
do_test fts3ac-4.8 {
execsql {
SELECT snippet(email) FROM email
WHERE email MATCH 'ancillary load davis'
}
} {{pete.<b>davis</b>@enron.com <b>...</b> Start Date: 4/22/01; HourAhead hour: 3; No <b>ancillary</b> schedules awarded.
Variances detected.
Variances detected in <b>Load</b> schedule.
} {{pete.<b>davis</b>@enron.com<b>...</b>3; No <b>ancillary</b> schedules awarded<b>...</b>detected in <b>Load</b> schedule.
LOG MESSAGES:
PARSING <b>...</b>}}
LOG<b>...</b>}}
# Combinations of AND and OR operators:
#
@ -1192,22 +1185,35 @@ do_test fts3ac-5.1 {
SELECT snippet(email) FROM email
WHERE email MATCH 'questar enron OR com'
}
} {{matt.smith@<b>enron</b>.<b>com</b> <b>...</b> six reports:
31 Keystone Receipts
} {{matt.smith@<b>enron</b>.<b>com</b><b>...</b>31 Keystone Receipts
15 <b>Questar</b> Pipeline
40 Rockies Production
22 West_2 <b>...</b>}}
40 Rockies<b>...</b>}}
do_test fts3ac-5.2 {
execsql {
SELECT snippet(email) FROM email
WHERE email MATCH 'enron OR com questar'
}
} {{matt.smith@<b>enron</b>.<b>com</b> <b>...</b> six reports:
31 Keystone Receipts
} {{matt.smith@<b>enron</b>.<b>com</b><b>...</b>31 Keystone Receipts
15 <b>Questar</b> Pipeline
40 Rockies Production
22 West_2 <b>...</b>}}
40 Rockies<b>...</b>}}
#-------------------------------------------------------------------------
# Test a problem reported on the mailing list.
#
do_test fts3ac-6.1 {
execsql {
CREATE VIRTUAL TABLE ft USING fts3(one, two);
INSERT INTO ft VALUES('', 'foo');
INSERT INTO ft VALUES('foo', 'foo');
SELECT offsets(ft) FROM ft WHERE ft MATCH 'foo';
}
} {{1 0 0 3} {0 0 0 3 1 0 0 3}}
do_test fts3ac-6.2 {
execsql {
DELETE FROM ft WHERE one = 'foo';
SELECT offsets(ft) FROM ft WHERE ft MATCH 'foo';
}
} {{1 0 0 3}}
finish_test

View File

@ -73,7 +73,7 @@ do_test fts3ag-1.9 {
# No support for all-except queries.
do_test fts3ag-1.10 {
catchsql {SELECT rowid FROM t1 WHERE t1 MATCH '-this -something'}
} {1 {SQL logic error or missing database}}
} {1 {malformed MATCH expression: [-this -something]}}
# Test that docListOrMerge() correctly handles reaching the end of one
# doclist before it reaches the end of the other.

View File

@ -53,6 +53,10 @@ do_test fts3al-1.3 {
#
# The trailing and leading hi-bit chars help with code which tests for
# isspace() to coalesce multiple spaces.
#
# UPDATE: The above is no longer true; there is no such code in fts3.
# But leave the test in just the same.
#
set word "\x80xxxxx\x80xxxxx\x80xxxxx\x80xxxxx\x80xxxxx\x80xxxxx\x80"
set phrase1 "$word $word $word target $word $word $word"
@ -64,6 +68,6 @@ db eval "INSERT INTO t4 (content) VALUES ('$phrase2')"
do_test fts3al-1.4 {
execsql {SELECT rowid, length(snippet(t4)) FROM t4 WHERE t4 MATCH 'target'}
} {1 111 2 117}
} {1 241 2 247}
finish_test

373
test/fts3cov.test Normal file
View File

@ -0,0 +1,373 @@
# 2009 December 03
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# The tests in this file are structural coverage tests. They are designed
# to complement the tests in fts3rnd.test and fts3doc.test. Between them,
# the three files should provide full coverage of the fts3 extension code.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# If this build does not include FTS3, skip the tests in this file.
#
ifcapable !fts3 { finish_test ; return }
source $testdir/fts3_common.tcl
source $testdir/malloc_common.tcl
set DO_MALLOC_TEST 0
#--------------------------------------------------------------------------
# When it first needs to read a block from the %_segments table, the FTS3
# module compiles an SQL statement for that purpose. The statement is
# stored and reused each subsequent time a block is read. This test case
# tests the effects of an OOM error occuring while compiling the statement.
#
# Similarly, when FTS3 first needs to scan through a set of segment leaves
# to find a set of documents that matches a term, it allocates a string
# containing the text of the required SQL, and compiles one or more
# statements to traverse the leaves. This test case tests that OOM errors
# that occur while allocating this string and statement are handled correctly
# also.
#
do_test fts3cov-1.1 {
execsql {
CREATE VIRTUAL TABLE t1 USING fts3(x);
INSERT INTO t1(t1) VALUES('nodesize=24');
BEGIN;
INSERT INTO t1 VALUES('Is the night chilly and dark?');
INSERT INTO t1 VALUES('The night is chilly, but not dark.');
INSERT INTO t1 VALUES('The thin gray cloud is spread on high,');
INSERT INTO t1 VALUES('It covers but not hides the sky.');
COMMIT;
SELECT count(*)>0 FROM t1_segments;
}
} {1}
set DO_MALLOC_TEST 1
do_restart_select_test fts3cov-1.2 {
SELECT docid FROM t1 WHERE t1 MATCH 'chilly';
} {1 2}
set DO_MALLOC_TEST 0
#--------------------------------------------------------------------------
# When querying the full-text index, if an expected internal node block is
# missing from the %_segments table, or if a NULL value is stored in the
# %_segments table instead of a binary blob, database corruption should be
# reported.
#
# Even with tiny 24 byte nodes, it takes a fair bit of data to produce a
# segment b-tree that uses the %_segments table to store internal nodes.
#
do_test fts3cov-2.1 {
execsql {
INSERT INTO t1(t1) VALUES('nodesize=24');
BEGIN;
INSERT INTO t1 VALUES('The moon is behind, and at the full;');
INSERT INTO t1 VALUES('And yet she looks both small and dull.');
INSERT INTO t1 VALUES('The night is chill, the cloud is gray:');
INSERT INTO t1 VALUES('''T is a month before the month of May,');
INSERT INTO t1 VALUES('And the Spring comes slowly up this way.');
INSERT INTO t1 VALUES('The lovely lady, Christabel,');
INSERT INTO t1 VALUES('Whom her father loves so well,');
INSERT INTO t1 VALUES('What makes her in the wood so late,');
INSERT INTO t1 VALUES('A furlong from the castle gate?');
INSERT INTO t1 VALUES('She had dreams all yesternight');
INSERT INTO t1 VALUES('Of her own betrothed knight;');
INSERT INTO t1 VALUES('And she in the midnight wood will pray');
INSERT INTO t1 VALUES('For the weal of her lover that''s far away.');
COMMIT;
INSERT INTO t1(t1) VALUES('optimize');
SELECT substr(hex(root), 1, 2) FROM t1_segdir;
}
} {03}
# Test the "missing entry" case:
do_test fts3cov-2.1 {
set root [db one {SELECT root FROM t1_segdir}]
read_fts3varint [string range $root 1 end] left_child
execsql { DELETE FROM t1_segments WHERE blockid = $left_child }
} {}
do_error_test fts3cov-2.2 {
SELECT * FROM t1 WHERE t1 MATCH 'c*'
} {database disk image is malformed}
# Test the "replaced with NULL" case:
do_test fts3cov-2.3 {
execsql { INSERT INTO t1_segments VALUES($left_child, NULL) }
} {}
do_error_test fts3cov-2.4 {
SELECT * FROM t1 WHERE t1 MATCH 'cloud'
} {database disk image is malformed}
#--------------------------------------------------------------------------
# The following tests are to test the effects of OOM errors while storing
# terms in the pending-hash table. Specifically, while creating doclist
# blobs to store in the table. More specifically, to test OOM errors while
# appending column numbers to doclists. For example, if a doclist consists
# of:
#
# <docid> <column 0 offset-list> 0x01 <column N> <column N offset-list>
#
# The following tests check that malloc errors encountered while appending
# the "0x01 <column N>" data to the dynamically growable blob used to
# accumulate the doclist in memory are handled correctly.
#
do_test fts3cov-3.1 {
set cols [list]
set vals [list]
for {set i 0} {$i < 120} {incr i} {
lappend cols "col$i"
lappend vals "'word'"
}
execsql "CREATE VIRTUAL TABLE t2 USING fts3([join $cols ,])"
} {}
set DO_MALLOC_TEST 1
do_write_test fts3cov-3.2 t2_content "
INSERT INTO t2(docid, [join $cols ,]) VALUES(1, [join $vals ,])
"
do_write_test fts3cov-3.3 t2_content "
INSERT INTO t2(docid, [join $cols ,]) VALUES(200, [join $vals ,])
"
do_write_test fts3cov-3.4 t2_content "
INSERT INTO t2(docid, [join $cols ,]) VALUES(60000, [join $vals ,])
"
#-------------------------------------------------------------------------
# If too much data accumulates in the pending-terms hash table, it is
# flushed to the database automatically, even if the transaction has not
# finished. The following tests check the effects of encountering an OOM
# while doing this.
#
do_test fts3cov-4.1 {
execsql {
CREATE VIRTUAL TABLE t3 USING fts3(x);
INSERT INTO t3(t3) VALUES('nodesize=24');
INSERT INTO t3(t3) VALUES('maxpending=100');
}
} {}
set DO_MALLOC_TEST 1
do_write_test fts3cov-4.2 t3_content {
INSERT INTO t3(docid, x)
SELECT 1, 'Then Christabel stretched forth her hand,' UNION ALL
SELECT 3, 'And comforted fair Geraldine:' UNION ALL
SELECT 4, '''O well, bright dame, may you command' UNION ALL
SELECT 5, 'The service of Sir Leoline;' UNION ALL
SELECT 2, 'And gladly our stout chivalry' UNION ALL
SELECT 7, 'Will he send forth, and friends withal,' UNION ALL
SELECT 8, 'To guide and guard you safe and free' UNION ALL
SELECT 6, 'Home to your noble father''s hall.'''
}
#-------------------------------------------------------------------------
# When building the internal tree structure for each segment b-tree, FTS3
# assumes that the content of each internal node will be less than
# $nodesize bytes, where $nodesize is the advisory node size. If this turns
# out to be untrue, then an extra buffer must be malloc'd for each term.
# This test case tests these paths and the effects of said mallocs failing
# by inserting insert a document with some fairly large terms into a
# full-text table with a very small node-size.
#
# Test this handling of large terms in three contexts:
#
# 1. When flushing the pending-terms table.
# 2. When optimizing the data structures using the INSERT syntax.
# 2. When optimizing the data structures using the deprecated SELECT syntax.
#
do_test fts3cov-5.1 {
execsql {
CREATE VIRTUAL TABLE t4 USING fts3(x);
INSERT INTO t4(t4) VALUES('nodesize=24');
}
} {}
set DO_MALLOC_TEST 1
# Test when flushing pending-terms table.
do_write_test fts3cov-5.2 t4_content {
INSERT INTO t4
SELECT 'ItisanancientMarinerAndhestoppethoneofthreeAA' UNION ALL
SELECT 'ItisanancientMarinerAndhestoppethoneofthreeBB' UNION ALL
SELECT 'ItisanancientMarinerAndhestoppethoneofthreeCC' UNION ALL
SELECT 'BythylonggreybeardandglitteringeyeNowwhereforestoppstAA' UNION ALL
SELECT 'BythylonggreybeardandglitteringeyeNowwhereforestoppstBB' UNION ALL
SELECT 'BythylonggreybeardandglitteringeyeNowwhereforestoppstCC'
}
# Test when optimizing via INSERT.
do_test fts3cov-5.3 { execsql { INSERT INTO t4 VALUES('extra!') } } {}
do_write_test fts3cov-5.2 t4_segments { INSERT INTO t4(t4) VALUES('optimize') }
# Test when optimizing via SELECT.
do_test fts3cov-5.5 { execsql { INSERT INTO t4 VALUES('more extra!') } } {}
do_write_test fts3cov-5.6 t4_segments {
SELECT * FROM (SELECT optimize(t4) FROM t4 LIMIT 1)
EXCEPT SELECT 'Index optimized'
}
#-------------------------------------------------------------------------
# When merging all segments at a given level to create a single segment
# at level+1, FTS3 runs a query of the form:
#
# SELECT count(*) FROM %_segdir WHERE level = ?
#
# The query is compiled the first time this operation is required and
# reused thereafter. This test aims to test the effects of an OOM while
# preparing and executing this query for the first time.
#
# Then, keep inserting rows into the table so that the effects of an OOM
# while re-executing the same query can also be tested.
#
do_test fts3cov-6.1 {
execsql { CREATE VIRTUAL TABLE t5 USING fts3(x) }
for {set i 0} {$i<16} {incr i} { execsql "INSERT INTO t5 VALUES('term$i')" }
execsql { SELECT count(*) FROM t5_segdir }
} {16}
# First time.
db close
sqlite3 db test.db
do_write_test fts3cov-6.2 t5_content {
INSERT INTO t5 VALUES('segment number 16!');
}
# Second time.
do_test fts3cov-6.3 {
for {set i 1} {$i<16} {incr i} { execsql "INSERT INTO t5 VALUES('term$i')" }
execsql { SELECT count(*) FROM t5_segdir }
} {17}
do_write_test fts3cov-6.4 t5_content {
INSERT INTO t5 VALUES('segment number 16!');
}
#-------------------------------------------------------------------------
# Update the docid of a row. Test this in two scenarios:
#
# 1. When the row being updated is the only row in the table.
# 2. When it is not.
#
# The two cases above take different paths because in case 1 all data
# structures can simply be emptied before inserting the new row record.
# In case 2, the data structures actually have to be updated.
#
do_test fts3cov-7.1 {
execsql {
CREATE VIRTUAL TABLE t7 USING fts3(a, b, c);
INSERT INTO t7 VALUES('A', 'B', 'C');
UPDATE t7 SET docid = 5;
SELECT docid, * FROM t7;
}
} {5 A B C}
do_test fts3cov-7.2 {
execsql {
INSERT INTO t7 VALUES('D', 'E', 'F');
UPDATE t7 SET docid = 1 WHERE docid = 6;
SELECT docid, * FROM t7;
}
} {1 D E F 5 A B C}
#-------------------------------------------------------------------------
# If a set of documents are modified within a transaction, the
# pending-terms table must be flushed each time a document with a docid
# less than or equal to the previous docid is modified.
#
# This test checks the effects of an OOM error occuring when the
# pending-terms table is flushed for this reason as part of a DELETE
# statement.
#
do_malloc_test fts3cov-8 -sqlprep {
BEGIN;
CREATE VIRTUAL TABLE t8 USING fts3;
INSERT INTO t8 VALUES('the output of each batch run');
INSERT INTO t8 VALUES('(possibly a day''s work)');
INSERT INTO t8 VALUES('was written to two separate disks');
COMMIT;
} -sqlbody {
BEGIN;
DELETE FROM t8 WHERE rowid = 3;
DELETE FROM t8 WHERE rowid = 2;
DELETE FROM t8 WHERE rowid = 1;
COMMIT;
}
#-------------------------------------------------------------------------
# Test some branches in the code that handles "special" inserts like:
#
# INSERT INTO t1(t1) VALUES('optimize');
#
# Also test that an optimize (INSERT method) works on an empty table.
#
set DO_MALLOC_TEST 0
do_test fts3cov-9.1 {
execsql { CREATE VIRTUAL TABLE xx USING fts3 }
} {}
do_error_test fts3cov-9.2 {
INSERT INTO xx(xx) VALUES('optimise'); -- British spelling
} {SQL logic error or missing database}
do_error_test fts3cov-9.3 {
INSERT INTO xx(xx) VALUES('short');
} {SQL logic error or missing database}
do_error_test fts3cov-9.4 {
INSERT INTO xx(xx) VALUES('waytoolongtobecorrect');
} {SQL logic error or missing database}
do_test fts3cov-9.5 {
execsql { INSERT INTO xx(xx) VALUES('optimize') }
} {}
#-------------------------------------------------------------------------
# Test that a table can be optimized in the middle of a transaction when
# the pending-terms table is non-empty. This case involves some extra
# branches because data must be read not only from the database, but
# also from the pending-terms table.
#
do_malloc_test fts3cov-10 -sqlprep {
CREATE VIRTUAL TABLE t10 USING fts3;
INSERT INTO t10 VALUES('Optimising images for the web is a tricky business');
BEGIN;
INSERT INTO t10 VALUES('You have to get the right balance between');
} -sqlbody {
INSERT INTO t10(t10) VALUES('optimize');
}
#-------------------------------------------------------------------------
# Test a full-text query for a term that was once in the index, but is
# no longer.
#
do_test fts3cov-11.1 {
execsql {
CREATE VIRTUAL TABLE xx USING fts3;
INSERT INTO xx VALUES('one two three');
INSERT INTO xx VALUES('four five six');
DELETE FROM xx WHERE docid = 1;
}
execsql { SELECT * FROM xx WHERE xx MATCH 'two' }
} {}
do_malloc_test fts3cov-12 -sqlprep {
CREATE VIRTUAL TABLE t12 USING fts3;
INSERT INTO t12 VALUES('is one of the two togther');
BEGIN;
INSERT INTO t12 VALUES('one which was appropriate at the time');
} -sqlbody {
SELECT * FROM t12 WHERE t12 MATCH 'one'
}
do_malloc_test fts3cov-13 -sqlprep {
PRAGMA encoding = 'UTF-16';
CREATE VIRTUAL TABLE t13 USING fts3;
INSERT INTO t13 VALUES('two scalar functions');
INSERT INTO t13 VALUES('scalar two functions');
INSERT INTO t13 VALUES('functions scalar two');
} -sqlbody {
SELECT snippet(t13, '%%', '%%', '#') FROM t13 WHERE t13 MATCH 'two';
SELECT snippet(t13, '%%', '%%') FROM t13 WHERE t13 MATCH 'two';
SELECT snippet(t13, '%%') FROM t13 WHERE t13 MATCH 'two';
}
finish_test

View File

@ -336,53 +336,53 @@ do_test fts3expr-4.1 {
# Mismatched parenthesis:
do_test fts3expr-4.2.1 {
catchsql { SELECT * FROM t1 WHERE t1 MATCH 'example AND (hello OR world))' }
} {1 {SQL logic error or missing database}}
} {1 {malformed MATCH expression: [example AND (hello OR world))]}}
do_test fts3expr-4.2.2 {
catchsql { SELECT * FROM t1 WHERE t1 MATCH 'example AND (hello OR world' }
} {1 {SQL logic error or missing database}}
} {1 {malformed MATCH expression: [example AND (hello OR world]}}
do_test fts3expr-4.2.3 {
catchsql { SELECT * FROM t1 WHERE t1 MATCH '(hello' }
} {1 {SQL logic error or missing database}}
} {1 {malformed MATCH expression: [(hello]}}
do_test fts3expr-4.2.4 {
catchsql { SELECT * FROM t1 WHERE t1 MATCH '(' }
} {1 {SQL logic error or missing database}}
} {1 {malformed MATCH expression: [(]}}
do_test fts3expr-4.2.5 {
catchsql { SELECT * FROM t1 WHERE t1 MATCH ')' }
} {1 {SQL logic error or missing database}}
} {1 {malformed MATCH expression: [)]}}
do_test fts3expr-4.2.6 {
catchsql { SELECT * FROM t1 WHERE t1 MATCH 'example (hello world' }
} {1 {SQL logic error or missing database}}
} {1 {malformed MATCH expression: [example (hello world]}}
# Unterminated quotation marks:
do_test fts3expr-4.3.1 {
catchsql { SELECT * FROM t1 WHERE t1 MATCH 'example OR "hello world' }
} {1 {SQL logic error or missing database}}
} {1 {malformed MATCH expression: [example OR "hello world]}}
do_test fts3expr-4.3.2 {
catchsql { SELECT * FROM t1 WHERE t1 MATCH 'example OR hello world"' }
} {1 {SQL logic error or missing database}}
} {1 {malformed MATCH expression: [example OR hello world"]}}
# Binary operators without the required operands.
do_test fts3expr-4.4.1 {
catchsql { SELECT * FROM t1 WHERE t1 MATCH 'OR hello world' }
} {1 {SQL logic error or missing database}}
} {1 {malformed MATCH expression: [OR hello world]}}
do_test fts3expr-4.4.2 {
catchsql { SELECT * FROM t1 WHERE t1 MATCH 'hello world OR' }
} {1 {SQL logic error or missing database}}
} {1 {malformed MATCH expression: [hello world OR]}}
do_test fts3expr-4.4.3 {
catchsql { SELECT * FROM t1 WHERE t1 MATCH 'one (hello world OR) two' }
} {1 {SQL logic error or missing database}}
} {1 {malformed MATCH expression: [one (hello world OR) two]}}
do_test fts3expr-4.4.4 {
catchsql { SELECT * FROM t1 WHERE t1 MATCH 'one (OR hello world) two' }
} {1 {SQL logic error or missing database}}
} {1 {malformed MATCH expression: [one (OR hello world) two]}}
# NEAR operators with something other than phrases as arguments.
do_test fts3expr-4.5.1 {
catchsql { SELECT * FROM t1 WHERE t1 MATCH '(hello OR world) NEAR one' }
} {1 {SQL logic error or missing database}}
} {1 {malformed MATCH expression: [(hello OR world) NEAR one]}}
do_test fts3expr-4.5.2 {
catchsql { SELECT * FROM t1 WHERE t1 MATCH 'one NEAR (hello OR world)' }
} {1 {SQL logic error or missing database}}
} {1 {malformed MATCH expression: [one NEAR (hello OR world)]}}
#------------------------------------------------------------------------
# The following OOM tests are designed to cover cases in fts3_expr.c.

View File

@ -33,7 +33,8 @@ set DO_MALLOC_TEST 1
# fts3_malloc-2.*: Test OOM during SELECT operations.
# fts3_malloc-3.*: Test OOM during SELECT operations with a larger database.
# fts3_malloc-4.*: Test OOM during database write operations.
#
# fts3_malloc-5.*: Test that a couple of memory leaks that could follow
# OOM in tokenizer code have been fixed.
#
@ -288,6 +289,16 @@ do_test fts3_malloc-4.2 {
execsql { SELECT a FROM ft }
} {two four {two four}}
do_write_test fts3_malloc-5.1 ft_content {
INSERT INTO ft VALUES('short alongertoken reallyquitealotlongerimeanit andthistokenisjustsolongthatonemightbeforgivenforimaginingthatitwasmerelyacontrivedexampleandnotarealtoken', 'cynics!')
}
do_test fts3_malloc-5.2 {
execsql { CREATE VIRTUAL TABLE ft8 USING fts3(x, tokenize porter) }
} {}
do_write_test fts3_malloc-5.3 ft_content {
INSERT INTO ft8 VALUES('short alongertoken reallyquitealotlongerimeanit andthistokenisjustsolongthatonemightbeforgivenforimaginingthatitwasmerelyacontrivedexampleandnotarealtoken')
}
finish_test

View File

@ -76,6 +76,17 @@ do_test fts3near-1.15 {
execsql {SELECT docid FROM t1 WHERE content MATCH 'one NEAR two NEAR one'}
} {3}
do_test fts3near-1.16 {
execsql {
SELECT docid FROM t1 WHERE content MATCH '"one three" NEAR/0 "four five"'
}
} {1}
do_test fts3near-1.17 {
execsql {
SELECT docid FROM t1 WHERE content MATCH '"four five" NEAR/0 "one three"'
}
} {1}
# Output format of the offsets() function:
#
@ -154,6 +165,7 @@ do_test fts3near-3.6 {
SELECT offsets(t1) FROM t1 WHERE content MATCH 'three NEAR/0 "two four"'
}
} {{0 0 8 5 0 1 14 3 0 2 18 4}}
breakpoint
do_test fts3near-3.7 {
execsql {
SELECT offsets(t1) FROM t1 WHERE content MATCH '"two four" NEAR/0 three'}
@ -170,7 +182,7 @@ do_test fts3near-4.1 {
execsql {
SELECT snippet(t1) FROM t1 WHERE content MATCH 'specification NEAR supports'
}
} {{<b>...</b> devices, handheld devices, etc. This <b>specification</b> also <b>supports</b> content positioning, downloadable fonts, <b>...</b>}}
} {{<b>...</b>braille devices, handheld devices, etc. This <b>specification</b> also <b>supports</b> content positioning, downloadable fonts, table layout<b>...</b>}}
do_test fts3near-5.1 {
execsql {

Some files were not shown because too many files have changed in this diff Show More