1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Merge in the IS-operator enhancements and other recent changes from trunk.

FossilOrigin-Name: 4f9229445c293b39c80b2a662901f608c85b36ef
This commit is contained in:
drh
2015-05-14 15:17:20 +00:00
39 changed files with 766 additions and 324 deletions

View File

@ -519,6 +519,15 @@ EXTHDR += \
EXTHDR += \ EXTHDR += \
$(TOP)/ext/rtree/sqlite3rtree.h $(TOP)/ext/rtree/sqlite3rtree.h
# executables needed for testing
#
TESTPROGS = \
testfixture$(TEXE) \
sqlite3$(TEXE) \
sqlite3_analyzer$(TEXE) \
sqldiff$(TEXE)
# This is the default Makefile target. The objects listed here # This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments. # are what get build when you type just "make" with no arguments.
# #
@ -968,15 +977,15 @@ testfixture$(TEXE): $(TESTFIXTURE_SRC)
-o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS) -o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)
# A very detailed test running most or all test cases # A very detailed test running most or all test cases
fulltest: testfixture$(TEXE) sqlite3$(TEXE) fuzztest fulltest: $(TESTPROGS) fuzztest
./testfixture$(TEXE) $(TOP)/test/all.test ./testfixture$(TEXE) $(TOP)/test/all.test
# Really really long testing # Really really long testing
soaktest: testfixture$(TEXE) sqlite3$(TEXE) fuzzoomtest soaktest: $(TESTPROGS) fuzzoomtest
./testfixture$(TEXE) $(TOP)/test/all.test -soak=1 ./testfixture$(TEXE) $(TOP)/test/all.test -soak=1
# Do extra testing but not aeverything. # Do extra testing but not everything.
fulltestonly: testfixture$(TEXE) sqlite3$(TEXE) fulltestonly: $(TESTPROGS)
./testfixture$(TEXE) $(TOP)/test/full.test ./testfixture$(TEXE) $(TOP)/test/full.test
# Fuzz testing # Fuzz testing
@ -989,13 +998,13 @@ fuzzoomtest: fuzzershell$(TEXE)
# This is the common case. Run many tests but not those that take # This is the common case. Run many tests but not those that take
# a really long time. # a really long time.
# #
test: testfixture$(TEXE) sqlite3$(TEXE) fuzztest test: $(TESTPROGS) fuzztest
./testfixture$(TEXE) $(TOP)/test/veryquick.test ./testfixture$(TEXE) $(TOP)/test/veryquick.test
# Run a test using valgrind. This can take a really long time # Run a test using valgrind. This can take a really long time
# because valgrind is so much slower than a native machine. # because valgrind is so much slower than a native machine.
# #
valgrindtest: testfixture$(TEXE) sqlite3$(TEXE) fuzzershell$(TEXE) valgrindtest: $(TESTPROGS) fuzzershell$(TEXE)
valgrind -v ./fuzzershell$(TEXE) -f $(TOP)/test/fuzzdata1.txt valgrind -v ./fuzzershell$(TEXE) -f $(TOP)/test/fuzzdata1.txt
OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind
@ -1003,12 +1012,12 @@ valgrindtest: testfixture$(TEXE) sqlite3$(TEXE) fuzzershell$(TEXE)
# the 60s-era electronics testing: "Turn it on and see if smoke # the 60s-era electronics testing: "Turn it on and see if smoke
# comes out." # comes out."
# #
smoketest: testfixture$(TEXE) fuzzershell$(TEXE) smoketest: $(TESTPROGS) fuzzershell$(TEXE)
./testfixture$(TEXE) $(TOP)/test/main.test ./testfixture$(TEXE) $(TOP)/test/main.test
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
echo "#define TCLSH 2" > $@ echo "#define TCLSH 2" > $@
echo "#define SQLITE_ENABLE_DBSTAT_VTAB" >> $@ echo "#define SQLITE_ENABLE_DBSTAT_VTAB 1" >> $@
cat sqlite3.c $(TOP)/src/tclsqlite.c >> $@ cat sqlite3.c $(TOP)/src/tclsqlite.c >> $@
echo "static const char *tclsh_main_loop(void){" >> $@ echo "static const char *tclsh_main_loop(void){" >> $@
echo "static const char *zMainloop = " >> $@ echo "static const char *zMainloop = " >> $@
@ -1122,6 +1131,8 @@ clean:
rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c
rm -f sqlite-*-output.vsix rm -f sqlite-*-output.vsix
rm -f mptester mptester.exe rm -f mptester mptester.exe
rm -f fuzzershell fuzzershell.exe
rm -f sqldiff sqldiff.exe
distclean: clean distclean: clean
rm -f config.log config.status libtool Makefile sqlite3.pc rm -f config.log config.status libtool Makefile sqlite3.pc

View File

@ -36,6 +36,13 @@ USE_STDCALL = 0
DYNAMIC_SHELL = 0 DYNAMIC_SHELL = 0
!ENDIF !ENDIF
# Set this non-0 to enable extra code that attempts to detect misuse of the
# SQLite API.
#
!IFNDEF API_ARMOR
API_ARMOR = 0
!ENDIF
# If necessary, create a list of harmless compiler warnings to disable when # If necessary, create a list of harmless compiler warnings to disable when
# compiling the various tools. For the SQLite source code itself, warnings, # compiling the various tools. For the SQLite source code itself, warnings,
# if any, will be disabled from within it. # if any, will be disabled from within it.
@ -493,14 +500,14 @@ BCC = $(BCC) -DNDEBUG
RCC = $(RCC) -DNDEBUG RCC = $(RCC) -DNDEBUG
!ENDIF !ENDIF
!IF $(DEBUG)>0 !IF $(DEBUG)>0 || $(API_ARMOR)!=0
TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR=1
RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
!ENDIF !ENDIF
!IF $(DEBUG)>2 !IF $(DEBUG)>2
TCC = $(TCC) -DSQLITE_DEBUG TCC = $(TCC) -DSQLITE_DEBUG=1
RCC = $(RCC) -DSQLITE_DEBUG RCC = $(RCC) -DSQLITE_DEBUG=1
!ENDIF !ENDIF
!IF $(DEBUG)>4 || $(OSTRACE)!=0 !IF $(DEBUG)>4 || $(OSTRACE)!=0
@ -509,8 +516,8 @@ RCC = $(RCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1
!ENDIF !ENDIF
!IF $(DEBUG)>5 !IF $(DEBUG)>5
TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE=1
RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE=1
!ENDIF !ENDIF
# Prevent warnings about "insecure" MSVC runtime library functions # Prevent warnings about "insecure" MSVC runtime library functions
@ -1196,6 +1203,15 @@ EXTHDR = $(EXTHDR) \
EXTHDR = $(EXTHDR) \ EXTHDR = $(EXTHDR) \
$(TOP)\ext\session\sqlite3session.h $(TOP)\ext\session\sqlite3session.h
# executables needed for testing
#
TESTPROGS = \
testfixture.exe \
sqlite3.exe \
sqlite3_analyzer.exe \
sqldiff.exe
# This is the default Makefile target. The objects listed here # This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments. # are what get build when you type just "make" with no arguments.
# #
@ -1663,13 +1679,13 @@ testfixture.exe: $(TESTFIXTURE_SRC) $(LIBRESOBJS) $(HDR)
extensiontest: testfixture.exe testloadext.dll extensiontest: testfixture.exe testloadext.dll
.\testfixture.exe $(TOP)\test\loadext.test .\testfixture.exe $(TOP)\test\loadext.test
fulltest: testfixture.exe sqlite3.exe fuzztest fulltest: $(TESTPROGS) fuzztest
.\testfixture.exe $(TOP)\test\all.test .\testfixture.exe $(TOP)\test\all.test
soaktest: testfixture.exe sqlite3.exe fuzzoomtest soaktest: $(TESTPROGS) fuzzoomtest
.\testfixture.exe $(TOP)\test\all.test -soak=1 .\testfixture.exe $(TOP)\test\all.test -soak=1
fulltestonly: testfixture.exe sqlite3.exe fuzztest fulltestonly: $(TESTPROGS) fuzztest
.\testfixture.exe $(TOP)\test\full.test .\testfixture.exe $(TOP)\test\full.test
queryplantest: testfixture.exe sqlite3.exe queryplantest: testfixture.exe sqlite3.exe
@ -1681,21 +1697,23 @@ fuzztest: fuzzershell.exe
fuzzoomtest: fuzzershell.exe fuzzoomtest: fuzzershell.exe
.\fuzzershell.exe -f $(TOP)\test\fuzzdata1.txt --oom .\fuzzershell.exe -f $(TOP)\test\fuzzdata1.txt --oom
test: testfixture.exe sqlite3.exe fuzztest test: $(TESTPROGS) fuzztest
.\testfixture.exe $(TOP)\test\veryquick.test .\testfixture.exe $(TOP)\test\veryquick.test
smoketest: testfixture.exe smoketest: $(TESTPROGS) fuzzershell.exe
.\testfixture.exe $(TOP)\test\main.test .\testfixture.exe $(TOP)\test\main.test
sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
copy $(SQLITE3C) + $(TOP)\src\tclsqlite.c $@ echo #define TCLSH 2 > $@
echo #define SQLITE_ENABLE_DBSTAT_VTAB 1 >> $@
copy $@ + $(SQLITE3C) + $(TOP)\src\tclsqlite.c $@
echo static const char *tclsh_main_loop(void){ >> $@ echo static const char *tclsh_main_loop(void){ >> $@
echo static const char *zMainloop = >> $@ echo static const char *zMainloop = >> $@
$(NAWK) -f $(TOP)\tool\tostr.awk $(TOP)\tool\spaceanal.tcl >> $@ $(NAWK) -f $(TOP)\tool\tostr.awk $(TOP)\tool\spaceanal.tcl >> $@
echo ; return zMainloop; } >> $@ echo ; return zMainloop; } >> $@
sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS) sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -DSQLITE_ENABLE_DBSTAT_VTAB -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \ $(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) /link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
testloadext.lo: $(TOP)\src\test_loadext.c testloadext.lo: $(TOP)\src\test_loadext.c
@ -1770,6 +1788,7 @@ clean:
del /Q shell.c sqlite3ext.h 2>NUL del /Q shell.c sqlite3ext.h 2>NUL
del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL
del /Q sqlite-*-output.vsix 2>NUL del /Q sqlite-*-output.vsix 2>NUL
del /Q fuzzershell.exe sqldiff.exe 2>NUL
# Dynamic link library section. # Dynamic link library section.
# #

View File

@ -1 +1 @@
3.8.10 3.8.10.1

View File

@ -6,8 +6,9 @@ libsqlite3_la_SOURCES = sqlite3.c
libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8 libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8
bin_PROGRAMS = sqlite3 bin_PROGRAMS = sqlite3
sqlite3_SOURCES = shell.c sqlite3.h sqlite3_SOURCES = shell.c sqlite3.c sqlite3.h
sqlite3_LDADD = sqlite3.$(OBJEXT) @READLINE_LIBS@ sqlite3_LDADD = @READLINE_LIBS@
sqlite3_CFLAGS = $(AM_CFLAGS)
include_HEADERS = sqlite3.h sqlite3ext.h include_HEADERS = sqlite3.h sqlite3ext.h

18
configure vendored
View File

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

View File

@ -1675,7 +1675,7 @@ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
sqlite3Fts3ExprFree(pCsr->pExpr); sqlite3Fts3ExprFree(pCsr->pExpr);
sqlite3Fts3FreeDeferredTokens(pCsr); sqlite3Fts3FreeDeferredTokens(pCsr);
sqlite3_free(pCsr->aDoclist); sqlite3_free(pCsr->aDoclist);
sqlite3_free(pCsr->aMatchinfo); sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
sqlite3_free(pCsr); sqlite3_free(pCsr);
return SQLITE_OK; return SQLITE_OK;
@ -3176,7 +3176,7 @@ static int fts3FilterMethod(
/* In case the cursor has been used before, clear it now. */ /* In case the cursor has been used before, clear it now. */
sqlite3_finalize(pCsr->pStmt); sqlite3_finalize(pCsr->pStmt);
sqlite3_free(pCsr->aDoclist); sqlite3_free(pCsr->aDoclist);
sqlite3_free(pCsr->aMatchinfo); sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
sqlite3Fts3ExprFree(pCsr->pExpr); sqlite3Fts3ExprFree(pCsr->pExpr);
memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));

View File

@ -197,6 +197,8 @@ typedef struct Fts3DeferredToken Fts3DeferredToken;
typedef struct Fts3SegReader Fts3SegReader; typedef struct Fts3SegReader Fts3SegReader;
typedef struct Fts3MultiSegReader Fts3MultiSegReader; typedef struct Fts3MultiSegReader Fts3MultiSegReader;
typedef struct MatchinfoBuffer MatchinfoBuffer;
/* /*
** A connection to a fulltext index is an instance of the following ** A connection to a fulltext index is an instance of the following
** structure. The xCreate and xConnect methods create an instance ** structure. The xCreate and xConnect methods create an instance
@ -306,9 +308,7 @@ struct Fts3Cursor {
i64 iMinDocid; /* Minimum docid to return */ i64 iMinDocid; /* Minimum docid to return */
i64 iMaxDocid; /* Maximum docid to return */ i64 iMaxDocid; /* Maximum docid to return */
int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */ int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
u32 *aMatchinfo; /* Information about most recent match */ MatchinfoBuffer *pMIBuffer; /* Buffer for matchinfo data */
int nMatchinfo; /* Number of elements in aMatchinfo[] */
char *zMatchinfo; /* Matchinfo specification */
}; };
#define FTS3_EVAL_FILTER 0 #define FTS3_EVAL_FILTER 0
@ -428,7 +428,9 @@ struct Fts3Expr {
u8 bStart; /* True if iDocid is valid */ u8 bStart; /* True if iDocid is valid */
u8 bDeferred; /* True if this expression is entirely deferred */ u8 bDeferred; /* True if this expression is entirely deferred */
u32 *aMI; /* The following are used by the fts3_snippet.c module. */
int iPhrase; /* Index of this phrase in matchinfo() results */
u32 *aMI; /* See above */
}; };
/* /*
@ -564,6 +566,7 @@ void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *,
const char *, const char *, int, int const char *, const char *, int, int
); );
void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *); void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *);
void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p);
/* fts3_expr.c */ /* fts3_expr.c */
int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int, int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int,

View File

@ -28,6 +28,7 @@
#define FTS3_MATCHINFO_LCS 's' /* nCol values */ #define FTS3_MATCHINFO_LCS 's' /* nCol values */
#define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */ #define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */
#define FTS3_MATCHINFO_LHITS 'y' /* nCol*nPhrase values */ #define FTS3_MATCHINFO_LHITS 'y' /* nCol*nPhrase values */
#define FTS3_MATCHINFO_LHITS_BM 'b' /* nCol*nPhrase values */
/* /*
** The default value for the second argument to matchinfo(). ** The default value for the second argument to matchinfo().
@ -89,9 +90,22 @@ struct MatchInfo {
int nCol; /* Number of columns in table */ int nCol; /* Number of columns in table */
int nPhrase; /* Number of matchable phrases in query */ int nPhrase; /* Number of matchable phrases in query */
sqlite3_int64 nDoc; /* Number of docs in database */ sqlite3_int64 nDoc; /* Number of docs in database */
char flag;
u32 *aMatchinfo; /* Pre-allocated buffer */ u32 *aMatchinfo; /* Pre-allocated buffer */
}; };
/*
** An instance of this structure is used to manage a pair of buffers, each
** (nElem * sizeof(u32)) bytes in size. See the MatchinfoBuffer code below
** for details.
*/
struct MatchinfoBuffer {
u8 aRef[3];
int nElem;
int bGlobal; /* Set if global data is loaded */
char *zMatchinfo;
u32 aMatchinfo[0];
};
/* /*
@ -107,6 +121,97 @@ struct StrBuffer {
}; };
/*************************************************************************
** Start of MatchinfoBuffer code.
*/
/*
** Allocate a two-slot MatchinfoBuffer object.
*/
static MatchinfoBuffer *fts3MIBufferNew(int nElem, const char *zMatchinfo){
MatchinfoBuffer *pRet;
int nByte = sizeof(u32) * (2*nElem + 2) + sizeof(MatchinfoBuffer);
int nStr = strlen(zMatchinfo);
pRet = sqlite3_malloc(nByte + nStr+1);
if( pRet ){
memset(pRet, 0, nByte);
pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet;
pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0] + sizeof(u32)*(nElem+1);
pRet->nElem = nElem;
pRet->zMatchinfo = ((char*)pRet) + nByte;
memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1);
pRet->aRef[0] = 1;
}
return pRet;
}
static void fts3MIBufferFree(void *p){
MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]);
assert( (u32*)p==&pBuf->aMatchinfo[1]
|| (u32*)p==&pBuf->aMatchinfo[pBuf->nElem+2]
);
if( (u32*)p==&pBuf->aMatchinfo[1] ){
pBuf->aRef[1] = 0;
}else{
pBuf->aRef[2] = 0;
}
if( pBuf->aRef[0]==0 && pBuf->aRef[1]==0 && pBuf->aRef[2]==0 ){
sqlite3_free(pBuf);
}
}
static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){
void (*xRet)(void*) = 0;
u32 *aOut = 0;
if( p->aRef[1]==0 ){
p->aRef[1] = 1;
aOut = &p->aMatchinfo[1];
xRet = fts3MIBufferFree;
}
else if( p->aRef[2]==0 ){
p->aRef[2] = 1;
aOut = &p->aMatchinfo[p->nElem+2];
xRet = fts3MIBufferFree;
}else{
aOut = (u32*)sqlite3_malloc(p->nElem * sizeof(u32));
if( aOut ){
xRet = sqlite3_free;
if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32));
}
}
*paOut = aOut;
return xRet;
}
static void fts3MIBufferSetGlobal(MatchinfoBuffer *p){
p->bGlobal = 1;
memcpy(&p->aMatchinfo[2+p->nElem], &p->aMatchinfo[1], p->nElem*sizeof(u32));
}
/*
** Free a MatchinfoBuffer object allocated using fts3MIBufferNew()
*/
void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p){
if( p ){
assert( p->aRef[0]==1 );
p->aRef[0] = 0;
if( p->aRef[0]==0 && p->aRef[1]==0 && p->aRef[2]==0 ){
sqlite3_free(p);
}
}
}
/*
** End of MatchinfoBuffer code.
*************************************************************************/
/* /*
** This function is used to help iterate through a position-list. A position ** This function is used to help iterate through a position-list. A position
** list is a list of unique integers, sorted from smallest to largest. Each ** list is a list of unique integers, sorted from smallest to largest. Each
@ -143,7 +248,7 @@ static int fts3ExprIterate2(
void *pCtx /* Second argument to pass to callback */ void *pCtx /* Second argument to pass to callback */
){ ){
int rc; /* Return code */ int rc; /* Return code */
int eType = pExpr->eType; /* Type of expression node pExpr */ int eType = pExpr->eType; /* Type of expression node pExpr */
if( eType!=FTSQUERY_PHRASE ){ if( eType!=FTSQUERY_PHRASE ){
assert( pExpr->pLeft && pExpr->pRight ); assert( pExpr->pLeft && pExpr->pRight );
@ -177,6 +282,7 @@ static int fts3ExprIterate(
return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx); return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx);
} }
/* /*
** This is an fts3ExprIterate() callback used while loading the doclists ** This is an fts3ExprIterate() callback used while loading the doclists
** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also ** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
@ -221,8 +327,7 @@ static int fts3ExprLoadDoclists(
static int fts3ExprPhraseCountCb(Fts3Expr *pExpr, int iPhrase, void *ctx){ static int fts3ExprPhraseCountCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
(*(int *)ctx)++; (*(int *)ctx)++;
UNUSED_PARAMETER(pExpr); pExpr->iPhrase = iPhrase;
UNUSED_PARAMETER(iPhrase);
return SQLITE_OK; return SQLITE_OK;
} }
static int fts3ExprPhraseCount(Fts3Expr *pExpr){ static int fts3ExprPhraseCount(Fts3Expr *pExpr){
@ -443,7 +548,7 @@ static int fts3BestSnippet(
sIter.nSnippet = nSnippet; sIter.nSnippet = nSnippet;
sIter.nPhrase = nList; sIter.nPhrase = nList;
sIter.iCurrent = -1; sIter.iCurrent = -1;
rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter); rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void*)&sIter);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
/* Set the *pmSeen output variable. */ /* Set the *pmSeen output variable. */
@ -744,6 +849,60 @@ static int fts3ColumnlistCount(char **ppCollist){
return nEntry; return nEntry;
} }
/*
** This function gathers 'y' or 'b' data for a single phrase.
*/
static void fts3ExprLHits(
Fts3Expr *pExpr, /* Phrase expression node */
MatchInfo *p /* Matchinfo context */
){
Fts3Table *pTab = (Fts3Table *)p->pCursor->base.pVtab;
int iStart;
Fts3Phrase *pPhrase = pExpr->pPhrase;
char *pIter = pPhrase->doclist.pList;
int iCol = 0;
assert( p->flag==FTS3_MATCHINFO_LHITS_BM || p->flag==FTS3_MATCHINFO_LHITS );
if( p->flag==FTS3_MATCHINFO_LHITS ){
iStart = pExpr->iPhrase * p->nCol;
}else{
iStart = pExpr->iPhrase * ((p->nCol + 31) / 32);
}
while( 1 ){
int nHit = fts3ColumnlistCount(&pIter);
if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){
if( p->flag==FTS3_MATCHINFO_LHITS ){
p->aMatchinfo[iStart + iCol] = (u32)nHit;
}else if( nHit ){
p->aMatchinfo[iStart + (iCol+1)/32] |= (1 << (iCol&0x1F));
}
}
assert( *pIter==0x00 || *pIter==0x01 );
if( *pIter!=0x01 ) break;
pIter++;
pIter += fts3GetVarint32(pIter, &iCol);
}
}
/*
** Gather the results for matchinfo directives 'y' and 'b'.
*/
static void fts3ExprLHitGather(
Fts3Expr *pExpr,
MatchInfo *p
){
assert( (pExpr->pLeft==0)==(pExpr->pRight==0) );
if( pExpr->bEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){
if( pExpr->pLeft ){
fts3ExprLHitGather(pExpr->pLeft, p);
fts3ExprLHitGather(pExpr->pRight, p);
}else{
fts3ExprLHits(pExpr, p);
}
}
}
/* /*
** fts3ExprIterate() callback used to collect the "global" matchinfo stats ** fts3ExprIterate() callback used to collect the "global" matchinfo stats
** for a single query. ** for a single query.
@ -810,51 +969,6 @@ static int fts3ExprLocalHitsCb(
return rc; return rc;
} }
/*
** fts3ExprIterate() callback used to gather information for the matchinfo
** directive 'y'.
*/
static int fts3ExprLHitsCb(
Fts3Expr *pExpr, /* Phrase expression node */
int iPhrase, /* Phrase number */
void *pCtx /* Pointer to MatchInfo structure */
){
MatchInfo *p = (MatchInfo *)pCtx;
Fts3Table *pTab = (Fts3Table *)p->pCursor->base.pVtab;
int rc = SQLITE_OK;
int iStart = iPhrase * p->nCol;
Fts3Expr *pEof; /* Ancestor node already at EOF */
/* This must be a phrase */
assert( pExpr->pPhrase );
/* Initialize all output integers to zero. */
memset(&p->aMatchinfo[iStart], 0, sizeof(u32) * p->nCol);
/* Check if this or any parent node is at EOF. If so, then all output
** values are zero. */
for(pEof=pExpr; pEof && pEof->bEof==0; pEof=pEof->pParent);
if( pEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){
Fts3Phrase *pPhrase = pExpr->pPhrase;
char *pIter = pPhrase->doclist.pList;
int iCol = 0;
while( 1 ){
int nHit = fts3ColumnlistCount(&pIter);
if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){
p->aMatchinfo[iStart + iCol] = (u32)nHit;
}
assert( *pIter==0x00 || *pIter==0x01 );
if( *pIter!=0x01 ) break;
pIter++;
pIter += fts3GetVarint32(pIter, &iCol);
}
}
return rc;
}
static int fts3MatchinfoCheck( static int fts3MatchinfoCheck(
Fts3Table *pTab, Fts3Table *pTab,
char cArg, char cArg,
@ -868,6 +982,7 @@ static int fts3MatchinfoCheck(
|| (cArg==FTS3_MATCHINFO_LCS) || (cArg==FTS3_MATCHINFO_LCS)
|| (cArg==FTS3_MATCHINFO_HITS) || (cArg==FTS3_MATCHINFO_HITS)
|| (cArg==FTS3_MATCHINFO_LHITS) || (cArg==FTS3_MATCHINFO_LHITS)
|| (cArg==FTS3_MATCHINFO_LHITS_BM)
){ ){
return SQLITE_OK; return SQLITE_OK;
} }
@ -895,6 +1010,10 @@ static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
nVal = pInfo->nCol * pInfo->nPhrase; nVal = pInfo->nCol * pInfo->nPhrase;
break; break;
case FTS3_MATCHINFO_LHITS_BM:
nVal = pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
break;
default: default:
assert( cArg==FTS3_MATCHINFO_HITS ); assert( cArg==FTS3_MATCHINFO_HITS );
nVal = pInfo->nCol * pInfo->nPhrase * 3; nVal = pInfo->nCol * pInfo->nPhrase * 3;
@ -1089,7 +1208,7 @@ static int fts3MatchinfoValues(
sqlite3_stmt *pSelect = 0; sqlite3_stmt *pSelect = 0;
for(i=0; rc==SQLITE_OK && zArg[i]; i++){ for(i=0; rc==SQLITE_OK && zArg[i]; i++){
pInfo->flag = zArg[i];
switch( zArg[i] ){ switch( zArg[i] ){
case FTS3_MATCHINFO_NPHRASE: case FTS3_MATCHINFO_NPHRASE:
if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nPhrase; if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nPhrase;
@ -1149,9 +1268,13 @@ static int fts3MatchinfoValues(
} }
break; break;
case FTS3_MATCHINFO_LHITS: case FTS3_MATCHINFO_LHITS_BM:
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprLHitsCb, (void*)pInfo); case FTS3_MATCHINFO_LHITS: {
int nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
memset(pInfo->aMatchinfo, 0, nZero);
fts3ExprLHitGather(pCsr->pExpr, pInfo);
break; break;
}
default: { default: {
Fts3Expr *pExpr; Fts3Expr *pExpr;
@ -1184,7 +1307,8 @@ static int fts3MatchinfoValues(
** Populate pCsr->aMatchinfo[] with data for the current row. The ** Populate pCsr->aMatchinfo[] with data for the current row. The
** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32). ** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32).
*/ */
static int fts3GetMatchinfo( static void fts3GetMatchinfo(
sqlite3_context *pCtx, /* Return results here */
Fts3Cursor *pCsr, /* FTS3 Cursor object */ Fts3Cursor *pCsr, /* FTS3 Cursor object */
const char *zArg /* Second argument to matchinfo() function */ const char *zArg /* Second argument to matchinfo() function */
){ ){
@ -1193,6 +1317,9 @@ static int fts3GetMatchinfo(
int rc = SQLITE_OK; int rc = SQLITE_OK;
int bGlobal = 0; /* Collect 'global' stats as well as local */ int bGlobal = 0; /* Collect 'global' stats as well as local */
u32 *aOut = 0;
void (*xDestroyOut)(void*) = 0;
memset(&sInfo, 0, sizeof(MatchInfo)); memset(&sInfo, 0, sizeof(MatchInfo));
sInfo.pCursor = pCsr; sInfo.pCursor = pCsr;
sInfo.nCol = pTab->nColumn; sInfo.nCol = pTab->nColumn;
@ -1200,21 +1327,18 @@ static int fts3GetMatchinfo(
/* If there is cached matchinfo() data, but the format string for the /* If there is cached matchinfo() data, but the format string for the
** cache does not match the format string for this request, discard ** cache does not match the format string for this request, discard
** the cached data. */ ** the cached data. */
if( pCsr->zMatchinfo && strcmp(pCsr->zMatchinfo, zArg) ){ if( pCsr->pMIBuffer && strcmp(pCsr->pMIBuffer->zMatchinfo, zArg) ){
assert( pCsr->aMatchinfo ); sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
sqlite3_free(pCsr->aMatchinfo); pCsr->pMIBuffer = 0;
pCsr->zMatchinfo = 0;
pCsr->aMatchinfo = 0;
} }
/* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the /* If Fts3Cursor.pMIBuffer is NULL, then this is the first time the
** matchinfo function has been called for this query. In this case ** matchinfo function has been called for this query. In this case
** allocate the array used to accumulate the matchinfo data and ** allocate the array used to accumulate the matchinfo data and
** initialize those elements that are constant for every row. ** initialize those elements that are constant for every row.
*/ */
if( pCsr->aMatchinfo==0 ){ if( pCsr->pMIBuffer==0 ){
int nMatchinfo = 0; /* Number of u32 elements in match-info */ int nMatchinfo = 0; /* Number of u32 elements in match-info */
int nArg; /* Bytes in zArg */
int i; /* Used to iterate through zArg */ int i; /* Used to iterate through zArg */
/* Determine the number of phrases in the query */ /* Determine the number of phrases in the query */
@ -1223,30 +1347,46 @@ static int fts3GetMatchinfo(
/* Determine the number of integers in the buffer returned by this call. */ /* Determine the number of integers in the buffer returned by this call. */
for(i=0; zArg[i]; i++){ for(i=0; zArg[i]; i++){
char *zErr = 0;
if( fts3MatchinfoCheck(pTab, zArg[i], &zErr) ){
sqlite3_result_error(pCtx, zErr, -1);
sqlite3_free(zErr);
return;
}
nMatchinfo += fts3MatchinfoSize(&sInfo, zArg[i]); nMatchinfo += fts3MatchinfoSize(&sInfo, zArg[i]);
} }
/* Allocate space for Fts3Cursor.aMatchinfo[] and Fts3Cursor.zMatchinfo. */ /* Allocate space for Fts3Cursor.aMatchinfo[] and Fts3Cursor.zMatchinfo. */
nArg = (int)strlen(zArg); pCsr->pMIBuffer = fts3MIBufferNew(nMatchinfo, zArg);
pCsr->aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo + nArg + 1); if( !pCsr->pMIBuffer ) rc = SQLITE_NOMEM;
if( !pCsr->aMatchinfo ) return SQLITE_NOMEM;
pCsr->zMatchinfo = (char *)&pCsr->aMatchinfo[nMatchinfo];
pCsr->nMatchinfo = nMatchinfo;
memcpy(pCsr->zMatchinfo, zArg, nArg+1);
memset(pCsr->aMatchinfo, 0, sizeof(u32)*nMatchinfo);
pCsr->isMatchinfoNeeded = 1; pCsr->isMatchinfoNeeded = 1;
bGlobal = 1; bGlobal = 1;
} }
sInfo.aMatchinfo = pCsr->aMatchinfo; if( rc==SQLITE_OK ){
sInfo.nPhrase = pCsr->nPhrase; xDestroyOut = fts3MIBufferAlloc(pCsr->pMIBuffer, &aOut);
if( pCsr->isMatchinfoNeeded ){ if( xDestroyOut==0 ){
rc = fts3MatchinfoValues(pCsr, bGlobal, &sInfo, zArg); rc = SQLITE_NOMEM;
pCsr->isMatchinfoNeeded = 0; }
} }
return rc; if( rc==SQLITE_OK ){
sInfo.aMatchinfo = aOut;
sInfo.nPhrase = pCsr->nPhrase;
rc = fts3MatchinfoValues(pCsr, bGlobal, &sInfo, zArg);
if( bGlobal ){
fts3MIBufferSetGlobal(pCsr->pMIBuffer);
}
}
if( rc!=SQLITE_OK ){
sqlite3_result_error_code(pCtx, rc);
if( xDestroyOut ) xDestroyOut(aOut);
}else{
int n = pCsr->pMIBuffer->nElem * sizeof(u32);
sqlite3_result_blob(pCtx, aOut, n, xDestroyOut);
}
} }
/* /*
@ -1452,7 +1592,7 @@ void sqlite3Fts3Offsets(
*/ */
sCtx.iCol = iCol; sCtx.iCol = iCol;
sCtx.iTerm = 0; sCtx.iTerm = 0;
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void *)&sCtx); (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx);
/* Retreive the text stored in column iCol. If an SQL NULL is stored /* Retreive the text stored in column iCol. If an SQL NULL is stored
** in column iCol, jump immediately to the next iteration of the loop. ** in column iCol, jump immediately to the next iteration of the loop.
@ -1544,19 +1684,9 @@ void sqlite3Fts3Matchinfo(
const char *zArg /* Second arg to matchinfo() function */ const char *zArg /* Second arg to matchinfo() function */
){ ){
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
int rc;
int i;
const char *zFormat; const char *zFormat;
if( zArg ){ if( zArg ){
for(i=0; zArg[i]; i++){
char *zErr = 0;
if( fts3MatchinfoCheck(pTab, zArg[i], &zErr) ){
sqlite3_result_error(pContext, zErr, -1);
sqlite3_free(zErr);
return;
}
}
zFormat = zArg; zFormat = zArg;
}else{ }else{
zFormat = FTS3_MATCHINFO_DEFAULT; zFormat = FTS3_MATCHINFO_DEFAULT;
@ -1565,17 +1695,10 @@ void sqlite3Fts3Matchinfo(
if( !pCsr->pExpr ){ if( !pCsr->pExpr ){
sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC); sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC);
return; return;
}
/* Retrieve matchinfo() data. */
rc = fts3GetMatchinfo(pCsr, zFormat);
sqlite3Fts3SegmentsClose(pTab);
if( rc!=SQLITE_OK ){
sqlite3_result_error_code(pContext, rc);
}else{ }else{
int n = pCsr->nMatchinfo * sizeof(u32); /* Retrieve matchinfo() data. */
sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT); fts3GetMatchinfo(pContext, pCsr, zFormat);
sqlite3Fts3SegmentsClose(pTab);
} }
} }

View File

@ -87,7 +87,6 @@ do_catchsql_test rtree9-4.3 {
# #
register_circle_geom db register_circle_geom db
breakpoint
do_execsql_test rtree9-5.1 { do_execsql_test rtree9-5.1 {
CREATE VIRTUAL TABLE rt2 USING rtree(id, xmin, xmax, ymin, ymax); CREATE VIRTUAL TABLE rt2 USING rtree(id, xmin, xmax, ymin, ymax);

27
main.mk
View File

@ -399,6 +399,14 @@ EXTHDR += \
EXTHDR += \ EXTHDR += \
$(TOP)/ext/userauth/sqlite3userauth.h $(TOP)/ext/userauth/sqlite3userauth.h
# executables needed for testing
#
TESTPROGS = \
testfixture$(EXE) \
sqlite3$(EXE) \
sqlite3_analyzer$(EXE) \
sqldiff$(EXE)
# This is the default Makefile target. The objects listed here # This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments. # are what get build when you type just "make" with no arguments.
# #
@ -649,13 +657,13 @@ fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c
$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c \ $(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c \
-o testfixture$(EXE) $(LIBTCL) $(THREADLIB) -o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
fulltest: testfixture$(EXE) sqlite3$(EXE) fuzztest fulltest: $(TESTPROGS) fuzztest
./testfixture$(EXE) $(TOP)/test/all.test ./testfixture$(EXE) $(TOP)/test/all.test
soaktest: testfixture$(EXE) sqlite3$(EXE) fuzzoomtest soaktest: $(TESTPROGS) fuzzoomtest
./testfixture$(EXE) $(TOP)/test/all.test -soak=1 ./testfixture$(EXE) $(TOP)/test/all.test -soak=1
fulltestonly: testfixture$(EXE) sqlite3$(EXE) fuzztest fulltestonly: $(TESTPROGS) fuzztest
./testfixture$(EXE) $(TOP)/test/full.test ./testfixture$(EXE) $(TOP)/test/full.test
queryplantest: testfixture$(EXE) sqlite3$(EXE) queryplantest: testfixture$(EXE) sqlite3$(EXE)
@ -667,16 +675,23 @@ fuzztest: fuzzershell$(EXE)
fuzzoomtest: fuzzershell$(EXE) fuzzoomtest: fuzzershell$(EXE)
./fuzzershell$(EXE) -f $(TOP)/test/fuzzdata1.txt --oom ./fuzzershell$(EXE) -f $(TOP)/test/fuzzdata1.txt --oom
test: testfixture$(EXE) sqlite3$(EXE) fuzztest test: $(TESTPROGS) fuzztest
./testfixture$(EXE) $(TOP)/test/veryquick.test ./testfixture$(EXE) $(TOP)/test/veryquick.test
# Run a test using valgrind. This can take a really long time # Run a test using valgrind. This can take a really long time
# because valgrind is so much slower than a native machine. # because valgrind is so much slower than a native machine.
# #
valgrindtest: testfixture$(EXE) sqlite3$(EXE) fuzzershell$(EXE) valgrindtest: $(TESTPROGS) fuzzershell$(EXE)
valgrind -v ./fuzzershell$(EXE) -f $(TOP)/test/fuzzdata1.txt valgrind -v ./fuzzershell$(EXE) -f $(TOP)/test/fuzzdata1.txt
OMIT_MISUSE=1 valgrind -v ./testfixture$(EXE) $(TOP)/test/permutations.test valgrind OMIT_MISUSE=1 valgrind -v ./testfixture$(EXE) $(TOP)/test/permutations.test valgrind
# A very fast test that checks basic sanity. The name comes from
# the 60s-era electronics testing: "Turn it on and see if smoke
# comes out."
#
smoketest: $(TESTPROGS) fuzzershell$(EXE)
./testfixture$(EXE) $(TOP)/test/main.test
# The next two rules are used to support the "threadtest" target. Building # The next two rules are used to support the "threadtest" target. Building
# threadtest runs a few thread-safety tests that are implemented in C. This # threadtest runs a few thread-safety tests that are implemented in C. This
# target is invoked by the releasetest.tcl script. # target is invoked by the releasetest.tcl script.
@ -788,3 +803,5 @@ clean:
rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c
rm -f sqlite-*-output.vsix rm -f sqlite-*-output.vsix
rm -f mptester mptester.exe rm -f mptester mptester.exe
rm -f fuzzershell fuzzershell.exe
rm -f sqldiff sqldiff.exe

View File

@ -1,19 +1,19 @@
C Merge\sin\sthe\s3.8.10\srelease\schanges. C Merge\sin\sthe\sIS-operator\senhancements\sand\sother\srecent\schanges\sfrom\strunk.
D 2015-05-07T12:29:54.271 D 2015-05-14T15:17:20.176
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 114f5809eeff63855cfda99551addf1e00ef7730 F Makefile.in 73b64617bc169971c12be153e3ad9ef76e662fe4
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc 6b0b04b6037ef272e8c1f2a24ccc0f99663dde14 F Makefile.msc 35200c2f470516f178392b0135375f656fdeac02
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858 F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866 F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866
F VERSION 2e244662b71e6e68a5c29b014ebc5b7564f4cc5a F VERSION 8af05c43e00f7de32be74ff9984d792c96cdb0de
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811 F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am 4012e106208c7b86ba54d06e9ed400b59a4dee6b F autoconf/Makefile.am 27de1af382c82e81f1fe36a7f38528fba004eb1a
F autoconf/README 14458f1046c118efa721aadec5f227e876d3cd38 F autoconf/README 14458f1046c118efa721aadec5f227e876d3cd38
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/config.guess 94cc57e2a3fdb9c235b362ace86d77e89d188cad x F autoconf/config.guess 94cc57e2a3fdb9c235b362ace86d77e89d188cad x
@ -38,7 +38,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0 F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure 2ea5f5b58dd106da449ab598ab6e515339d7fa2a x F configure dae9f0ec4df32a9e300befbcdbc4ff8874731357 x
F configure.ac 0b775d383c536bbaafc1e46dd3cbb81a7ea11aeb F configure.ac 0b775d383c536bbaafc1e46dd3cbb81a7ea11aeb
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1 F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
@ -78,16 +78,16 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314 F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c 2fb98467f4b670c8934cdd97d1ba3ffa7382764c F ext/fts3/fts3.c 341e9d9a3c7615bac8e815a8937d576265b22f78
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 59ecaa2d7af0da44c70b6aeaebdcfc070d14abab F ext/fts3/fts3Int.h 142837a7544dff49121b67091a71c4f7a4546b0f
F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1 F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
F ext/fts3/fts3_expr.c 71c063da9c2a4167fb54aec089dd5ef33a58c9cb F ext/fts3/fts3_expr.c 71c063da9c2a4167fb54aec089dd5ef33a58c9cb
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60 F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5 F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5
F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009 F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
F ext/fts3/fts3_snippet.c 40a96ba78e90aba7d7d6d014a18049bb218060fd F ext/fts3/fts3_snippet.c b7aaa8698096b26e1c6eb563e317409323398142
F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7 F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7
F ext/fts3/fts3_test.c 8a3a78c4458b2d7c631fcf4b152a5cd656fa7038 F ext/fts3/fts3_test.c 8a3a78c4458b2d7c631fcf4b152a5cd656fa7038
F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860 F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860
@ -134,7 +134,7 @@ F ext/rtree/rtree5.test 6a510494f12454bf57ef28f45bc7764ea279431e
F ext/rtree/rtree6.test 773a90db2dce6a8353dd0d5b64bca69b29761196 F ext/rtree/rtree6.test 773a90db2dce6a8353dd0d5b64bca69b29761196
F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971 F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971
F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a
F ext/rtree/rtree9.test d86ebf08ff6328895613ed577dd8a2a37c472c34 F ext/rtree/rtree9.test b5eb13849545dfd271a54ff16784cb00d8792aea
F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf
F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e
F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06 F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06
@ -170,7 +170,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk d8b3e198082720785408b7d99c2f45f749d1da7b F main.mk a76e778116586db55895d3cc9796bde70bd9db08
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk d5e22023b5238985bb54a72d33e0ac71fe4f8a32 F mkopcodeh.awk d5e22023b5238985bb54a72d33e0ac71fe4f8a32
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@ -197,9 +197,9 @@ F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4
F src/build.c 61b47073f79f31e80a05db9ce13c5ca81bf8f74e F src/build.c 61b47073f79f31e80a05db9ce13c5ca81bf8f74e
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575 F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575
F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887 F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
F src/dbstat.c 1eacd310212b5ae59b7be645a06de8f8bbe0b5d6 F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
F src/delete.c 5075d88557eb4e2a7fdb2b61a96142830d8589b8 F src/delete.c 5075d88557eb4e2a7fdb2b61a96142830d8589b8
F src/expr.c 3fb2ab3ab69d15b4b75ae53fceb4e317f64cb306 F src/expr.c 3fb2ab3ab69d15b4b75ae53fceb4e317f64cb306
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
@ -214,8 +214,8 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770 F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
F src/loadext.c 29255bbe1cfb2ce9bbff2526a5ecfddcb49b9271 F src/loadext.c 29255bbe1cfb2ce9bbff2526a5ecfddcb49b9271
F src/main.c 6b9b7976bd63b04b795f0eff6e07dcb019f56e97 F src/main.c 3fd7ec2399ce67b7dda1b155925d95b8afe2b9ea
F src/malloc.c 6a370b83d54e4bbf6f94021221c2a311cff26a18 F src/malloc.c 5bc15d525811d387b37c29f2e368143460e41e96
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987 F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
@ -234,7 +234,7 @@ F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c 23eb5f56fac54d8fe0cb204291f3b3b2d94f23fc F src/os_unix.c 23eb5f56fac54d8fe0cb204291f3b3b2d94f23fc
F src/os_win.c 2da99cf07da7db6bcb1974013abfd89ec74749b3 F src/os_win.c 97f7828a9554d753665b6fcf7540e31c2b3d6a6e
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
F src/pager.c 97110085b1321298412f1e5c37bddb95b36d9208 F src/pager.c 97110085b1321298412f1e5c37bddb95b36d9208
F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77 F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77
@ -250,16 +250,16 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 99eabf7eff0bfa65b75939b46caa82e2b2133f28 F src/resolve.c 99eabf7eff0bfa65b75939b46caa82e2b2133f28
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c 1b0bfc7d59e48c26b895a6b719157111a617d9e3 F src/select.c 1b0bfc7d59e48c26b895a6b719157111a617d9e3
F src/shell.c a781037a81ac801495e06855605b444a8c5bd19b F src/shell.c f26cca96f7dadab5efb5e655edf548f4b91695c5
F src/sqlite.h.in 679a3abfef9c13a989728fd27f308a3e3f00e232 F src/sqlite.h.in 0d711b199290c187b6013bc6b519ddc8ec36d4d8
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
F src/sqliteInt.h 15960c3f5f682abb9ac1664c6bd9146d18d3f21d F src/sqliteInt.h 5f7643182e9da425d16a9ea4ad2264adf77c2c4e
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
F src/tclsqlite.c d6952e9d739357ffe9bbfbda3832f6315f6271a2 F src/tclsqlite.c 3e98ca80d7c0b66c2e89721ee263d1f396fad816
F src/test1.c 90fbedce75330d48d99eadb7d5f4223e86969585 F src/test1.c a8e09b811f70184ce65012f27f30cfee7e54f268
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622 F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
@ -325,8 +325,8 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
F src/wal.c ce2cb2d06faab54d1bce3e739bec79e063dd9113 F src/wal.c ce2cb2d06faab54d1bce3e739bec79e063dd9113
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
F src/where.c 85fff9c40569ccb79c3177419b339e7d7df566cb F src/where.c 08fadd0d211699348349be5449f3a1e391adf20e
F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c F src/whereInt.h a6f5a762bc1b4b1c76e1cea79976b437ac35a435
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7 F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
@ -352,6 +352,7 @@ F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
F test/analyzeD.test 08f9d0bee4e118a66fff3a32d02dbe0ee0a2b594 F test/analyzeD.test 08f9d0bee4e118a66fff3a32d02dbe0ee0a2b594
F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
F test/analyzeF.test 7ccd7a04f7d3061bde1a8a4dacc4792edccf6bf2 F test/analyzeF.test 7ccd7a04f7d3061bde1a8a4dacc4792edccf6bf2
F test/analyzer1.test e3bccac3be49382050464952998a631bf51e3ce1
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7 F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
@ -611,11 +612,11 @@ F test/fts3fault2.test f953bb3cf903988172270a9a0aafd5a890b0f98f
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641 F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
F test/fts3join.test 53e66a0c21eb568580674a43b21c059acb26f499 F test/fts3join.test 53e66a0c21eb568580674a43b21c059acb26f499
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6 F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
F test/fts3matchinfo.test 3e5f5ac2e0a8ba42eafd4c685f803ca48b4c3a83 F test/fts3matchinfo.test 07009313ad6c082f94d8c9c3228eb8940c93ac71
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905 F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2 F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
F test/fts3query.test c838b18f2b859e15fd31c64be3d79ef1556803ca F test/fts3query.test f33eb71a1fe1084ea585eeb7ee76b390729f5170
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0 F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
F test/fts3snippet.test 63dbd687d5bf5191f1b8e6a0977aa9c1e28a7004 F test/fts3snippet.test 63dbd687d5bf5191f1b8e6a0977aa9c1e28a7004
@ -709,7 +710,7 @@ F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577 F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577
F test/journal2.test ae06f566c28552c313ded3fee79a6c69e6d049b1 F test/journal2.test ae06f566c28552c313ded3fee79a6c69e6d049b1
F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307 F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307
F test/jrnlmode.test 6014ba5c11d66ff8bc7d87a7a2abc5c54be73b2e F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
@ -920,8 +921,9 @@ F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 2b416dca3a155fcaa849540b2e7fc1df12896c23 F test/speedtest1.c 2b416dca3a155fcaa849540b2e7fc1df12896c23
F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49 F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49
F test/sqldiff1.test e5ecfe95b3a2ff6380f0db6ea8bec246b675e122
F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68 F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68
F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de F test/stat.test 8de91498c99f5298b303f70f1d1f3b9557af91bf
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1 F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9 F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
@ -1099,7 +1101,7 @@ F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983
F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6 F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76 F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94 F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
F test/transitive1.test 03f532954f46cdf5608f7766bff0b0c52bf2a7cd F test/transitive1.test 875a9f0097a15b30a62431d183f989364d5accac
F test/trigger1.test dc47573ac79ffe0ee3eecaa517d70d8dacbccd03 F test/trigger1.test dc47573ac79ffe0ee3eecaa517d70d8dacbccd03
F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6 F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945 F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
@ -1137,12 +1139,12 @@ F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102 F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test f311691d696a5cc27e3c1b875cec1b0866b4ccd9 F test/view.test f311691d696a5cc27e3c1b875cec1b0866b4ccd9
F test/vtab1.test d1e5ec7a818f1d3f0402382b6a1d0c06071b770f F test/vtab1.test dbe0e9e121102d0ba365f20d126a72676aa2343f
F test/vtab2.test 3644649aa8d1daac57fd541f6a5f914cac59203e F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275 F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391 F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391
F test/vtab6.test 5f5380c425e52993560ab4763db4f826d2ba7b09 F test/vtab6.test d2986cf418dc51e7fb81d12366bea2caa8b812df
F test/vtab7.test ae560ebea870ed04e9aa4177cc302f910faaabb5 F test/vtab7.test ae560ebea870ed04e9aa4177cc302f910faaabb5
F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583 F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583
F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b
@ -1182,10 +1184,10 @@ F test/walro.test 34422d1d95aaff0388f0791ec20edb34e2a3ed57
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a
F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e
F test/where.test 28b64e93428961b07b0d486778d63fd672948f6b F test/where.test 1ff3d9f8da0a6c0dc5ccfd38d9225b2cdb5b6afb
F test/where2.test 23fdb5d8e756554aad4ca7ae03de9dd8367a2c6e F test/where2.test 23fdb5d8e756554aad4ca7ae03de9dd8367a2c6e
F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e
F test/where4.test d8420ceeb8323a41ceff1f1841fc528e824e1ecf F test/where4.test a4603fa0d018bd4b9430dac840c9c522af421dd5
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2 F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8 F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8
@ -1194,7 +1196,7 @@ F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739
F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2 F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2
F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5 F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
F test/whereD.test 9eba1f9b18e5b19a0b0bcaae5e8c037260195f2b F test/whereD.test 9eba1f9b18e5b19a0b0bcaae5e8c037260195f2b
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7 F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
@ -1257,14 +1259,14 @@ F tool/showstat4.c 9515faa8ec176599d4a8288293ba8ec61f7b728a
F tool/showwal.c 85cb36d4fe3e93e2fbd63e786e0d1ce42d0c4fad F tool/showwal.c 85cb36d4fe3e93e2fbd63e786e0d1ce42d0c4fad
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b
F tool/spaceanal.tcl d5a09620c66a6c144576cb9d2bdfa9a6fbe362a5 F tool/spaceanal.tcl 713c587a057334de42c41ad9566f10e255d3ad27
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355 F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
F tool/sqldiff.c 10e3c01111f97b99627adf0954cf5ffbfba0723c F tool/sqldiff.c 0748c0daed08f31e5a8eab6de98ca57500e61ecf
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
F tool/symbols.sh c5a617b8c61a0926747a56c65f5671ef8ac0e148 F tool/symbols.sh c5a617b8c61a0926747a56c65f5671ef8ac0e148
@ -1275,7 +1277,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P de7083cfe2bb00b689bec6bcc75e994f564ceda6 cf975957b9ae671f34bb65f049acf351e650d437 P 0404ef885e47f0df1daa04feb28452beb4d32a35 3428043cd00294457548bb07ada2ad526b6532d6
R 2f55d0a58047aedd7e79d4671acd0f99 R 25710cfb819c9f25a12055b84606adbc
U drh U drh
Z 12d4e95f1926699d9a88cac43c727452 Z 9620c8120a371d7867c988796203e7a5

View File

@ -1 +1 @@
0404ef885e47f0df1daa04feb28452beb4d32a35 4f9229445c293b39c80b2a662901f608c85b36ef

View File

@ -75,6 +75,9 @@ static const char * const azCompileOpt[] = {
#if SQLITE_ENABLE_COLUMN_METADATA #if SQLITE_ENABLE_COLUMN_METADATA
"ENABLE_COLUMN_METADATA", "ENABLE_COLUMN_METADATA",
#endif #endif
#if SQLITE_ENABLE_DBSTAT_VTAB
"ENABLE_DBSTAT_VTAB",
#endif
#if SQLITE_ENABLE_EXPENSIVE_ASSERT #if SQLITE_ENABLE_EXPENSIVE_ASSERT
"ENABLE_EXPENSIVE_ASSERT", "ENABLE_EXPENSIVE_ASSERT",
#endif #endif

View File

@ -18,9 +18,9 @@
** for an example implementation. ** for an example implementation.
*/ */
#include "sqliteInt.h" /* Requires access to internal data structures */
#if (defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)) \ #if (defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)) \
&& !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_VIRTUALTABLE)
#include "sqliteInt.h" /* Requires access to internal data structures */
/* /*
** Page paths: ** Page paths:
@ -122,6 +122,7 @@ struct StatCursor {
struct StatTable { struct StatTable {
sqlite3_vtab base; sqlite3_vtab base;
sqlite3 *db; sqlite3 *db;
int iDb; /* Index of database to analyze */
}; };
#ifndef get2byte #ifndef get2byte
@ -140,7 +141,17 @@ static int statConnect(
){ ){
StatTable *pTab = 0; StatTable *pTab = 0;
int rc = SQLITE_OK; int rc = SQLITE_OK;
int iDb;
if( argc>=4 ){
iDb = sqlite3FindDbName(db, argv[3]);
if( iDb<0 ){
*pzErr = sqlite3_mprintf("no such database: %s", argv[3]);
return SQLITE_ERROR;
}
}else{
iDb = 0;
}
rc = sqlite3_declare_vtab(db, VTAB_SCHEMA); rc = sqlite3_declare_vtab(db, VTAB_SCHEMA);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable)); pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable));
@ -151,6 +162,7 @@ static int statConnect(
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
memset(pTab, 0, sizeof(StatTable)); memset(pTab, 0, sizeof(StatTable));
pTab->db = db; pTab->db = db;
pTab->iDb = iDb;
} }
*ppVtab = (sqlite3_vtab*)pTab; *ppVtab = (sqlite3_vtab*)pTab;
@ -205,16 +217,22 @@ static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
if( pCsr==0 ){ if( pCsr==0 ){
rc = SQLITE_NOMEM; rc = SQLITE_NOMEM;
}else{ }else{
char *zSql;
memset(pCsr, 0, sizeof(StatCursor)); memset(pCsr, 0, sizeof(StatCursor));
pCsr->base.pVtab = pVTab; pCsr->base.pVtab = pVTab;
rc = sqlite3_prepare_v2(pTab->db, zSql = sqlite3_mprintf(
"SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type" "SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
" UNION ALL " " UNION ALL "
"SELECT name, rootpage, type FROM sqlite_master WHERE rootpage!=0" "SELECT name, rootpage, type"
" ORDER BY name", -1, " FROM \"%w\".sqlite_master WHERE rootpage!=0"
&pCsr->pStmt, 0 " ORDER BY name", pTab->db->aDb[pTab->iDb].zName);
); if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
}
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
sqlite3_free(pCsr); sqlite3_free(pCsr);
pCsr = 0; pCsr = 0;
@ -380,7 +398,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
*/ */
static void statSizeAndOffset(StatCursor *pCsr){ static void statSizeAndOffset(StatCursor *pCsr){
StatTable *pTab = (StatTable *)((sqlite3_vtab_cursor *)pCsr)->pVtab; StatTable *pTab = (StatTable *)((sqlite3_vtab_cursor *)pCsr)->pVtab;
Btree *pBt = pTab->db->aDb[0].pBt; Btree *pBt = pTab->db->aDb[pTab->iDb].pBt;
Pager *pPager = sqlite3BtreePager(pBt); Pager *pPager = sqlite3BtreePager(pBt);
sqlite3_file *fd; sqlite3_file *fd;
sqlite3_int64 x[2]; sqlite3_int64 x[2];
@ -394,7 +412,7 @@ static void statSizeAndOffset(StatCursor *pCsr){
*/ */
fd = sqlite3PagerFile(pPager); fd = sqlite3PagerFile(pPager);
x[0] = pCsr->iPageno; x[0] = pCsr->iPageno;
if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ if( fd->pMethods!=0 && sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){
pCsr->iOffset = x[0]; pCsr->iOffset = x[0];
pCsr->szPage = (int)x[1]; pCsr->szPage = (int)x[1];
} }
@ -406,9 +424,10 @@ static void statSizeAndOffset(StatCursor *pCsr){
static int statNext(sqlite3_vtab_cursor *pCursor){ static int statNext(sqlite3_vtab_cursor *pCursor){
int rc; int rc;
int nPayload; int nPayload;
char *z;
StatCursor *pCsr = (StatCursor *)pCursor; StatCursor *pCsr = (StatCursor *)pCursor;
StatTable *pTab = (StatTable *)pCursor->pVtab; StatTable *pTab = (StatTable *)pCursor->pVtab;
Btree *pBt = pTab->db->aDb[0].pBt; Btree *pBt = pTab->db->aDb[pTab->iDb].pBt;
Pager *pPager = sqlite3BtreePager(pBt); Pager *pPager = sqlite3BtreePager(pBt);
sqlite3_free(pCsr->zPath); sqlite3_free(pCsr->zPath);
@ -428,8 +447,9 @@ statNextRestart:
rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg); rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg);
pCsr->aPage[0].iPgno = iRoot; pCsr->aPage[0].iPgno = iRoot;
pCsr->aPage[0].iCell = 0; pCsr->aPage[0].iCell = 0;
pCsr->aPage[0].zPath = sqlite3_mprintf("/"); pCsr->aPage[0].zPath = z = sqlite3_mprintf("/");
pCsr->iPage = 0; pCsr->iPage = 0;
if( z==0 ) rc = SQLITE_NOMEM;
}else{ }else{
pCsr->isEof = 1; pCsr->isEof = 1;
return sqlite3_reset(pCsr->pStmt); return sqlite3_reset(pCsr->pStmt);
@ -452,7 +472,7 @@ statNextRestart:
pCsr->zPagetype = "overflow"; pCsr->zPagetype = "overflow";
pCsr->nCell = 0; pCsr->nCell = 0;
pCsr->nMxPayload = 0; pCsr->nMxPayload = 0;
pCsr->zPath = sqlite3_mprintf( pCsr->zPath = z = sqlite3_mprintf(
"%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl "%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl
); );
if( pCell->iOvfl<pCell->nOvfl-1 ){ if( pCell->iOvfl<pCell->nOvfl-1 ){
@ -464,7 +484,7 @@ statNextRestart:
} }
pCell->iOvfl++; pCell->iOvfl++;
statSizeAndOffset(pCsr); statSizeAndOffset(pCsr);
return SQLITE_OK; return z==0 ? SQLITE_NOMEM : SQLITE_OK;
} }
if( p->iRightChildPg ) break; if( p->iRightChildPg ) break;
p->iCell++; p->iCell++;
@ -486,8 +506,9 @@ statNextRestart:
} }
rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg); rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg);
p[1].iCell = 0; p[1].iCell = 0;
p[1].zPath = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell); p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell);
p->iCell++; p->iCell++;
if( z==0 ) rc = SQLITE_NOMEM;
} }
@ -520,7 +541,8 @@ statNextRestart:
pCsr->nCell = p->nCell; pCsr->nCell = p->nCell;
pCsr->nUnused = p->nUnused; pCsr->nUnused = p->nUnused;
pCsr->nMxPayload = p->nMxPayload; pCsr->nMxPayload = p->nMxPayload;
pCsr->zPath = sqlite3_mprintf("%s", p->zPath); pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath);
if( z==0 ) rc = SQLITE_NOMEM;
nPayload = 0; nPayload = 0;
for(i=0; i<p->nCell; i++){ for(i=0; i<p->nCell; i++){
nPayload += p->aCell[i].nLocal; nPayload += p->aCell[i].nLocal;
@ -556,7 +578,7 @@ static int statColumn(
StatCursor *pCsr = (StatCursor *)pCursor; StatCursor *pCsr = (StatCursor *)pCursor;
switch( i ){ switch( i ){
case 0: /* name */ case 0: /* name */
sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_STATIC); sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_TRANSIENT);
break; break;
case 1: /* path */ case 1: /* path */
sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT); sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT);
@ -582,7 +604,8 @@ static int statColumn(
case 8: /* pgoffset */ case 8: /* pgoffset */
sqlite3_result_int64(ctx, pCsr->iOffset); sqlite3_result_int64(ctx, pCsr->iOffset);
break; break;
case 9: /* pgsize */ default: /* pgsize */
assert( i==9 );
sqlite3_result_int(ctx, pCsr->szPage); sqlite3_result_int(ctx, pCsr->szPage);
break; break;
} }
@ -598,7 +621,7 @@ static int statRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
/* /*
** Invoke this routine to register the "dbstat" virtual table module ** Invoke this routine to register the "dbstat" virtual table module
*/ */
int sqlite3_dbstat_register(sqlite3 *db){ int sqlite3DbstatRegister(sqlite3 *db){
static sqlite3_module dbstat_module = { static sqlite3_module dbstat_module = {
0, /* iVersion */ 0, /* iVersion */
statConnect, /* xCreate */ statConnect, /* xCreate */
@ -623,4 +646,6 @@ int sqlite3_dbstat_register(sqlite3 *db){
}; };
return sqlite3_create_module(db, "dbstat", &dbstat_module, 0); return sqlite3_create_module(db, "dbstat", &dbstat_module, 0);
} }
#elif defined(SQLITE_ENABLE_DBSTAT_VTAB)
int sqlite3DbstatRegister(sqlite3 *db){ return SQLITE_OK; }
#endif /* SQLITE_ENABLE_DBSTAT_VTAB */ #endif /* SQLITE_ENABLE_DBSTAT_VTAB */

View File

@ -2899,8 +2899,7 @@ static int openDatabase(
#ifdef SQLITE_ENABLE_DBSTAT_VTAB #ifdef SQLITE_ENABLE_DBSTAT_VTAB
if( !db->mallocFailed && rc==SQLITE_OK){ if( !db->mallocFailed && rc==SQLITE_OK){
int sqlite3_dbstat_register(sqlite3*); rc = sqlite3DbstatRegister(db);
rc = sqlite3_dbstat_register(db);
} }
#endif #endif

View File

@ -226,10 +226,8 @@ void sqlite3MallocEnd(void){
** Return the amount of memory currently checked out. ** Return the amount of memory currently checked out.
*/ */
sqlite3_int64 sqlite3_memory_used(void){ sqlite3_int64 sqlite3_memory_used(void){
int n, mx; sqlite3_int64 res, mx;
sqlite3_int64 res; sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, 0);
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, 0);
res = (sqlite3_int64)n; /* Work around bug in Borland C. Ticket #3216 */
return res; return res;
} }
@ -239,11 +237,9 @@ sqlite3_int64 sqlite3_memory_used(void){
** or since the most recent reset. ** or since the most recent reset.
*/ */
sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
int n, mx; sqlite3_int64 res, mx;
sqlite3_int64 res; sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, resetFlag);
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, resetFlag); return mx;
res = (sqlite3_int64)mx; /* Work around bug in Borland C. Ticket #3216 */
return res;
} }
/* /*

View File

@ -5411,14 +5411,14 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
UUID id; UUID id;
memset(&id, 0, sizeof(UUID)); memset(&id, 0, sizeof(UUID));
osUuidCreate(&id); osUuidCreate(&id);
memcpy(zBuf, &id, sizeof(UUID)); memcpy(&zBuf[n], &id, sizeof(UUID));
n += sizeof(UUID); n += sizeof(UUID);
} }
if( sizeof(UUID)<=nBuf-n ){ if( sizeof(UUID)<=nBuf-n ){
UUID id; UUID id;
memset(&id, 0, sizeof(UUID)); memset(&id, 0, sizeof(UUID));
osUuidCreateSequential(&id); osUuidCreateSequential(&id);
memcpy(zBuf, &id, sizeof(UUID)); memcpy(&zBuf[n], &id, sizeof(UUID));
n += sizeof(UUID); n += sizeof(UUID);
} }
#endif #endif

View File

@ -3347,7 +3347,8 @@ static int do_meta_command(char *zLine, ShellState *p){
goto meta_command_exit; goto meta_command_exit;
} }
if( nArg==3 ){ if( nArg==3 ){
sqlite3_limit(p->db, aLimit[iLimit].limitCode, integerValue(azArg[2])); sqlite3_limit(p->db, aLimit[iLimit].limitCode,
(int)integerValue(azArg[2]));
} }
printf("%20s %d\n", aLimit[iLimit].zLimitName, printf("%20s %d\n", aLimit[iLimit].zLimitName,
sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));

View File

@ -3893,8 +3893,6 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** KEYWORDS: {column access functions} ** KEYWORDS: {column access functions}
** METHOD: sqlite3_stmt ** METHOD: sqlite3_stmt
** **
** These routines form the "result set" interface.
**
** ^These routines return information about a single column of the current ** ^These routines return information about a single column of the current
** result row of a query. ^In every case the first argument is a pointer ** result row of a query. ^In every case the first argument is a pointer
** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*] ** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*]
@ -3954,13 +3952,14 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** even empty strings, are always zero-terminated. ^The return ** even empty strings, are always zero-terminated. ^The return
** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer. ** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
** **
** ^The object returned by [sqlite3_column_value()] is an ** <b>Warning:</b> ^The object returned by [sqlite3_column_value()] is an
** [unprotected sqlite3_value] object. An unprotected sqlite3_value object ** [unprotected sqlite3_value] object. In a multithreaded environment,
** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()]. ** an unprotected sqlite3_value object may only be used safely with
** [sqlite3_bind_value()] and [sqlite3_result_value()].
** If the [unprotected sqlite3_value] object returned by ** If the [unprotected sqlite3_value] object returned by
** [sqlite3_column_value()] is used in any other way, including calls ** [sqlite3_column_value()] is used in any other way, including calls
** to routines like [sqlite3_value_int()], [sqlite3_value_text()], ** to routines like [sqlite3_value_int()], [sqlite3_value_text()],
** or [sqlite3_value_bytes()], then the behavior is undefined. ** or [sqlite3_value_bytes()], the behavior is not threadsafe.
** **
** These routines attempt to convert the value where appropriate. ^For ** These routines attempt to convert the value where appropriate. ^For
** example, if the internal representation is FLOAT and a text result ** example, if the internal representation is FLOAT and a text result
@ -3991,12 +3990,6 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** </table> ** </table>
** </blockquote>)^ ** </blockquote>)^
** **
** The table above makes reference to standard C library functions atoi()
** and atof(). SQLite does not really use these functions. It has its
** own equivalent internal routines. The atoi() and atof() names are
** used in the table for brevity and because they are familiar to most
** C programmers.
**
** Note that when type conversions occur, pointers returned by prior ** Note that when type conversions occur, pointers returned by prior
** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or ** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or
** sqlite3_column_text16() may be invalidated. ** sqlite3_column_text16() may be invalidated.
@ -4021,7 +4014,7 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** of conversion are done in place when it is possible, but sometimes they ** of conversion are done in place when it is possible, but sometimes they
** are not possible and in those cases prior pointers are invalidated. ** are not possible and in those cases prior pointers are invalidated.
** **
** The safest and easiest to remember policy is to invoke these routines ** The safest policy is to invoke these routines
** in one of the following ways: ** in one of the following ways:
** **
** <ul> ** <ul>
@ -4041,7 +4034,7 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** ^The pointers returned are valid until a type conversion occurs as ** ^The pointers returned are valid until a type conversion occurs as
** described above, or until [sqlite3_step()] or [sqlite3_reset()] or ** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
** [sqlite3_finalize()] is called. ^The memory space used to hold strings ** [sqlite3_finalize()] is called. ^The memory space used to hold strings
** and BLOBs is freed automatically. Do <b>not</b> pass the pointers returned ** and BLOBs is freed automatically. Do <em>not</em> pass the pointers returned
** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into ** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
** [sqlite3_free()]. ** [sqlite3_free()].
** **

View File

@ -3879,4 +3879,8 @@ int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*);
int sqlite3ThreadJoin(SQLiteThread*, void**); int sqlite3ThreadJoin(SQLiteThread*, void**);
#endif #endif
#if defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)
int sqlite3DbstatRegister(sqlite3*);
#endif
#endif /* _SQLITEINT_H_ */ #endif /* _SQLITEINT_H_ */

View File

@ -3852,43 +3852,6 @@ static int db_last_stmt_ptr(
} }
#endif /* SQLITE_TEST */ #endif /* SQLITE_TEST */
#if defined(SQLITE_TEST) || defined(SQLITE_ENABLE_DBSTAT_VTAB)
/*
** tclcmd: register_dbstat_vtab DB
**
** Cause the dbstat virtual table to be available on the connection DB
*/
static int sqlite3RegisterDbstatCmd(
void *clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
#ifdef SQLITE_OMIT_VIRTUALTABLE
Tcl_AppendResult(interp, "dbstat not available because of "
"SQLITE_OMIT_VIRTUALTABLE", (void*)0);
return TCL_ERROR;
#else
struct SqliteDb { sqlite3 *db; };
char *zDb;
Tcl_CmdInfo cmdInfo;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB");
return TCL_ERROR;
}
zDb = Tcl_GetString(objv[1]);
if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
int sqlite3_dbstat_register(sqlite3*);
sqlite3* db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
sqlite3_dbstat_register(db);
}
return TCL_OK;
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}
#endif /* defined(SQLITE_TEST) || defined(SQLITE_ENABLE_DBSTAT_VTAB) */
/* /*
** Configure the interpreter passed as the first argument to have access ** Configure the interpreter passed as the first argument to have access
** to the commands and linked variables that make up: ** to the commands and linked variables that make up:
@ -3907,16 +3870,6 @@ static void init_all(Tcl_Interp *interp){
Md5_Init(interp); Md5_Init(interp);
#endif #endif
/* Install the [register_dbstat_vtab] command to access the implementation
** of virtual table dbstat (source file test_stat.c). This command is
** required for testfixture and sqlite3_analyzer, but not by the production
** Tcl extension. */
#if defined(SQLITE_TEST) || defined(SQLITE_ENABLE_DBSTAT_VTAB)
Tcl_CreateObjCommand(
interp, "register_dbstat_vtab", sqlite3RegisterDbstatCmd, 0, 0
);
#endif
#ifdef SQLITE_TEST #ifdef SQLITE_TEST
{ {
extern int Sqliteconfig_Init(Tcl_Interp*); extern int Sqliteconfig_Init(Tcl_Interp*);

View File

@ -6680,7 +6680,40 @@ static int test_bad_behavior(
} }
return TCL_OK; return TCL_OK;
} }
/*
** tclcmd: register_dbstat_vtab DB
**
** Cause the dbstat virtual table to be available on the connection DB
*/
static int test_register_dbstat_vtab(
void *clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
#ifdef SQLITE_OMIT_VIRTUALTABLE
Tcl_AppendResult(interp, "dbstat not available because of "
"SQLITE_OMIT_VIRTUALTABLE", (void*)0);
return TCL_ERROR;
#else
struct SqliteDb { sqlite3 *db; };
char *zDb;
Tcl_CmdInfo cmdInfo;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB");
return TCL_ERROR;
}
zDb = Tcl_GetString(objv[1]);
if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
sqlite3* db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
sqlite3DbstatRegister(db);
}
return TCL_OK;
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}
/* /*
** Register commands with the TCL interpreter. ** Register commands with the TCL interpreter.
@ -6752,6 +6785,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
void *clientData; void *clientData;
} aObjCmd[] = { } aObjCmd[] = {
{ "bad_behavior", test_bad_behavior, (void*)&iZero }, { "bad_behavior", test_bad_behavior, (void*)&iZero },
{ "register_dbstat_vtab", test_register_dbstat_vtab },
{ "sqlite3_connection_pointer", get_sqlite_pointer, 0 }, { "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
{ "sqlite3_bind_int", test_bind_int, 0 }, { "sqlite3_bind_int", test_bind_int, 0 },
{ "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 }, { "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 },

View File

@ -363,7 +363,7 @@ static int allowedOp(int op){
assert( TK_LT>TK_EQ && TK_LT<TK_GE ); assert( TK_LT>TK_EQ && TK_LT<TK_GE );
assert( TK_LE>TK_EQ && TK_LE<TK_GE ); assert( TK_LE>TK_EQ && TK_LE<TK_GE );
assert( TK_GE==TK_EQ+4 ); assert( TK_GE==TK_EQ+4 );
return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL; return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL || op==TK_IS;
} }
/* /*
@ -416,6 +416,8 @@ static u16 operatorMask(int op){
c = WO_IN; c = WO_IN;
}else if( op==TK_ISNULL ){ }else if( op==TK_ISNULL ){
c = WO_ISNULL; c = WO_ISNULL;
}else if( op==TK_IS ){
c = WO_IS;
}else{ }else{
assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff ); assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
c = (u16)(WO_EQ<<(op-TK_EQ)); c = (u16)(WO_EQ<<(op-TK_EQ));
@ -427,6 +429,7 @@ static u16 operatorMask(int op){
assert( op!=TK_LE || c==WO_LE ); assert( op!=TK_LE || c==WO_LE );
assert( op!=TK_GT || c==WO_GT ); assert( op!=TK_GT || c==WO_GT );
assert( op!=TK_GE || c==WO_GE ); assert( op!=TK_GE || c==WO_GE );
assert( op!=TK_IS || c==WO_IS );
return c; return c;
} }
@ -487,11 +490,12 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
continue; continue;
} }
} }
if( (pTerm->eOperator & WO_EQ)!=0 if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0
&& (pX = pTerm->pExpr->pRight)->op==TK_COLUMN && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN
&& pX->iTable==pScan->aEquiv[0] && pX->iTable==pScan->aEquiv[0]
&& pX->iColumn==pScan->aEquiv[1] && pX->iColumn==pScan->aEquiv[1]
){ ){
testcase( pTerm->eOperator & WO_IS );
continue; continue;
} }
pScan->k = k+1; pScan->k = k+1;
@ -593,9 +597,11 @@ static WhereTerm *findTerm(
WhereScan scan; WhereScan scan;
p = whereScanInit(&scan, pWC, iCur, iColumn, op, pIdx); p = whereScanInit(&scan, pWC, iCur, iColumn, op, pIdx);
op &= WO_EQ|WO_IS;
while( p ){ while( p ){
if( (p->prereqRight & notReady)==0 ){ if( (p->prereqRight & notReady)==0 ){
if( p->prereqRight==0 && (p->eOperator&WO_EQ)!=0 ){ if( p->prereqRight==0 && (p->eOperator&op)!=0 ){
testcase( p->eOperator & WO_IS );
return p; return p;
} }
if( pResult==0 ) pResult = p; if( pResult==0 ) pResult = p;
@ -1254,6 +1260,7 @@ static void exprAnalyze(
pTerm->u.leftColumn = pLeft->iColumn; pTerm->u.leftColumn = pLeft->iColumn;
pTerm->eOperator = operatorMask(op) & opMask; pTerm->eOperator = operatorMask(op) & opMask;
} }
if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
if( pRight && pRight->op==TK_COLUMN ){ if( pRight && pRight->op==TK_COLUMN ){
WhereTerm *pNew; WhereTerm *pNew;
Expr *pDup; Expr *pDup;
@ -1271,13 +1278,14 @@ static void exprAnalyze(
markTermAsChild(pWC, idxNew, idxTerm); markTermAsChild(pWC, idxNew, idxTerm);
pTerm = &pWC->a[idxTerm]; pTerm = &pWC->a[idxTerm];
pTerm->wtFlags |= TERM_COPIED; pTerm->wtFlags |= TERM_COPIED;
if( pExpr->op==TK_EQ if( (op==TK_EQ || op==TK_IS)
&& !ExprHasProperty(pExpr, EP_FromJoin) && !ExprHasProperty(pExpr, EP_FromJoin)
&& OptimizationEnabled(db, SQLITE_Transitive) && OptimizationEnabled(db, SQLITE_Transitive)
){ ){
pTerm->eOperator |= WO_EQUIV; pTerm->eOperator |= WO_EQUIV;
eExtraOp = WO_EQUIV; eExtraOp = WO_EQUIV;
} }
if( op==TK_IS ) pNew->wtFlags |= TERM_IS;
}else{ }else{
pDup = pExpr; pDup = pExpr;
pNew = pTerm; pNew = pTerm;
@ -1468,10 +1476,7 @@ static void exprAnalyze(
** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a ** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
** virtual term of that form. ** virtual term of that form.
** **
** Note that the virtual term must be tagged with TERM_VNULL. This ** Note that the virtual term must be tagged with TERM_VNULL.
** TERM_VNULL tag will suppress the not-null check at the beginning
** of the loop. Without the TERM_VNULL flag, the not-null check at
** the start of the loop will prevent any results from being returned.
*/ */
if( pExpr->op==TK_NOTNULL if( pExpr->op==TK_NOTNULL
&& pExpr->pLeft->op==TK_COLUMN && pExpr->pLeft->op==TK_COLUMN
@ -1675,11 +1680,12 @@ static int termCanDriveIndex(
){ ){
char aff; char aff;
if( pTerm->leftCursor!=pSrc->iCursor ) return 0; if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
if( (pTerm->eOperator & WO_EQ)==0 ) return 0; if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
if( (pTerm->prereqRight & notReady)!=0 ) return 0; if( (pTerm->prereqRight & notReady)!=0 ) return 0;
if( pTerm->u.leftColumn<0 ) return 0; if( pTerm->u.leftColumn<0 ) return 0;
aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity; aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0; if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
testcase( pTerm->pExpr->op==TK_IS );
return 1; return 1;
} }
#endif #endif
@ -1896,8 +1902,9 @@ static sqlite3_index_info *allocateIndexInfo(
assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
testcase( pTerm->eOperator & WO_IN ); testcase( pTerm->eOperator & WO_IN );
testcase( pTerm->eOperator & WO_ISNULL ); testcase( pTerm->eOperator & WO_ISNULL );
testcase( pTerm->eOperator & WO_IS );
testcase( pTerm->eOperator & WO_ALL ); testcase( pTerm->eOperator & WO_ALL );
if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV))==0 ) continue; if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV|WO_IS))==0 ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue;
nTerm++; nTerm++;
} }
@ -1948,9 +1955,10 @@ static sqlite3_index_info *allocateIndexInfo(
if( pTerm->leftCursor != pSrc->iCursor ) continue; if( pTerm->leftCursor != pSrc->iCursor ) continue;
assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
testcase( pTerm->eOperator & WO_IN ); testcase( pTerm->eOperator & WO_IN );
testcase( pTerm->eOperator & WO_IS );
testcase( pTerm->eOperator & WO_ISNULL ); testcase( pTerm->eOperator & WO_ISNULL );
testcase( pTerm->eOperator & WO_ALL ); testcase( pTerm->eOperator & WO_ALL );
if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV))==0 ) continue; if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV|WO_IS))==0 ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue;
pIdxCons[j].iColumn = pTerm->u.leftColumn; pIdxCons[j].iColumn = pTerm->u.leftColumn;
pIdxCons[j].iTermOffset = i; pIdxCons[j].iTermOffset = i;
@ -2792,7 +2800,7 @@ static int codeEqualityTerm(
int iReg; /* Register holding results */ int iReg; /* Register holding results */
assert( iTarget>0 ); assert( iTarget>0 );
if( pX->op==TK_EQ ){ if( pX->op==TK_EQ || pX->op==TK_IS ){
iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget); iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
}else if( pX->op==TK_ISNULL ){ }else if( pX->op==TK_ISNULL ){
iReg = iTarget; iReg = iTarget;
@ -2977,7 +2985,7 @@ static int codeAllEqualityTerms(
testcase( pTerm->eOperator & WO_IN ); testcase( pTerm->eOperator & WO_IN );
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){ if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
Expr *pRight = pTerm->pExpr->pRight; Expr *pRight = pTerm->pExpr->pRight;
if( sqlite3ExprCanBeNull(pRight) ){ if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk); sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
VdbeCoverage(v); VdbeCoverage(v);
} }
@ -4099,16 +4107,19 @@ static Bitmask codeOneLoopStart(
Expr *pE, *pEAlt; Expr *pE, *pEAlt;
WhereTerm *pAlt; WhereTerm *pAlt;
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( pTerm->eOperator!=(WO_EQUIV|WO_EQ) ) continue; if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue;
if( (pTerm->eOperator & WO_EQUIV)==0 ) continue;
if( pTerm->leftCursor!=iCur ) continue; if( pTerm->leftCursor!=iCur ) continue;
if( pLevel->iLeftJoin ) continue; if( pLevel->iLeftJoin ) continue;
pE = pTerm->pExpr; pE = pTerm->pExpr;
assert( !ExprHasProperty(pE, EP_FromJoin) ); assert( !ExprHasProperty(pE, EP_FromJoin) );
assert( (pTerm->prereqRight & pLevel->notReady)!=0 ); assert( (pTerm->prereqRight & pLevel->notReady)!=0 );
pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0); pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady,
WO_EQ|WO_IN|WO_IS, 0);
if( pAlt==0 ) continue; if( pAlt==0 ) continue;
if( pAlt->wtFlags & (TERM_CODED) ) continue; if( pAlt->wtFlags & (TERM_CODED) ) continue;
testcase( pAlt->eOperator & WO_EQ ); testcase( pAlt->eOperator & WO_EQ );
testcase( pAlt->eOperator & WO_IS );
testcase( pAlt->eOperator & WO_IN ); testcase( pAlt->eOperator & WO_IN );
VdbeModuleComment((v, "begin transitive constraint")); VdbeModuleComment((v, "begin transitive constraint"));
pEAlt = sqlite3StackAllocRaw(db, sizeof(*pEAlt)); pEAlt = sqlite3StackAllocRaw(db, sizeof(*pEAlt));
@ -4158,9 +4169,10 @@ static void whereTermPrint(WhereTerm *pTerm, int iTerm){
if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V'; if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E'; if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E';
if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L'; if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
sqlite3DebugPrintf("TERM-%-3d %p %s cursor=%-3d prob=%-3d op=0x%03x\n", sqlite3DebugPrintf(
iTerm, pTerm, zType, pTerm->leftCursor, pTerm->truthProb, "TERM-%-3d %p %s cursor=%-3d prob=%-3d op=0x%03x wtFlags=0x%04x\n",
pTerm->eOperator); iTerm, pTerm, zType, pTerm->leftCursor, pTerm->truthProb,
pTerm->eOperator, pTerm->wtFlags);
sqlite3TreeViewExpr(0, pTerm->pExpr, 0); sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
} }
} }
@ -4650,8 +4662,9 @@ static void whereLoopOutputAdjust(
/* In the absence of explicit truth probabilities, use heuristics to /* In the absence of explicit truth probabilities, use heuristics to
** guess a reasonable truth probability. */ ** guess a reasonable truth probability. */
pLoop->nOut--; pLoop->nOut--;
if( pTerm->eOperator&WO_EQ ){ if( pTerm->eOperator&(WO_EQ|WO_IS) ){
Expr *pRight = pTerm->pExpr->pRight; Expr *pRight = pTerm->pExpr->pRight;
testcase( pTerm->pExpr->op==TK_IS );
if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){ if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
k = 10; k = 10;
}else{ }else{
@ -4719,10 +4732,10 @@ static int whereLoopAddBtreeIndex(
assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
if( pNew->wsFlags & WHERE_BTM_LIMIT ){ if( pNew->wsFlags & WHERE_BTM_LIMIT ){
opMask = WO_LT|WO_LE; opMask = WO_LT|WO_LE;
}else if( pProbe->tnum<=0 || (pSrc->jointype & JT_LEFT)!=0 ){ }else if( /*pProbe->tnum<=0 ||*/ (pSrc->jointype & JT_LEFT)!=0 ){
opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE; opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE;
}else{ }else{
opMask = WO_EQ|WO_IN|WO_ISNULL|WO_GT|WO_GE|WO_LT|WO_LE; opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
} }
if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
@ -4785,7 +4798,7 @@ static int whereLoopAddBtreeIndex(
assert( nIn>0 ); /* RHS always has 2 or more terms... The parser assert( nIn>0 ); /* RHS always has 2 or more terms... The parser
** changes "x IN (?)" into "x=?". */ ** changes "x IN (?)" into "x=?". */
}else if( eOp & (WO_EQ) ){ }else if( eOp & (WO_EQ|WO_IS) ){
pNew->wsFlags |= WHERE_COLUMN_EQ; pNew->wsFlags |= WHERE_COLUMN_EQ;
if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1) ){ if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1) ){
if( iCol>=0 && pProbe->uniqNotNull==0 ){ if( iCol>=0 && pProbe->uniqNotNull==0 ){
@ -4835,7 +4848,7 @@ static int whereLoopAddBtreeIndex(
whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew); whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew);
}else{ }else{
int nEq = ++pNew->u.btree.nEq; int nEq = ++pNew->u.btree.nEq;
assert( eOp & (WO_ISNULL|WO_EQ|WO_IN) ); assert( eOp & (WO_ISNULL|WO_EQ|WO_IN|WO_IS) );
assert( pNew->nOut==saved_nOut ); assert( pNew->nOut==saved_nOut );
if( pTerm->truthProb<=0 && iCol>=0 ){ if( pTerm->truthProb<=0 && iCol>=0 ){
@ -4852,8 +4865,9 @@ static int whereLoopAddBtreeIndex(
&& ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)) && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
){ ){
Expr *pExpr = pTerm->pExpr; Expr *pExpr = pTerm->pExpr;
if( (eOp & (WO_EQ|WO_ISNULL))!=0 ){ if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){
testcase( eOp & WO_EQ ); testcase( eOp & WO_EQ );
testcase( eOp & WO_IS );
testcase( eOp & WO_ISNULL ); testcase( eOp & WO_ISNULL );
rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut); rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut);
}else{ }else{
@ -5690,9 +5704,9 @@ static i8 wherePathSatisfiesOrderBy(
if( pOBExpr->op!=TK_COLUMN ) continue; if( pOBExpr->op!=TK_COLUMN ) continue;
if( pOBExpr->iTable!=iCur ) continue; if( pOBExpr->iTable!=iCur ) continue;
pTerm = findTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn, pTerm = findTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
~ready, WO_EQ|WO_ISNULL, 0); ~ready, WO_EQ|WO_ISNULL|WO_IS, 0);
if( pTerm==0 ) continue; if( pTerm==0 ) continue;
if( (pTerm->eOperator&WO_EQ)!=0 && pOBExpr->iColumn>=0 ){ if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){
const char *z1, *z2; const char *z1, *z2;
pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
if( !pColl ) pColl = db->pDfltColl; if( !pColl ) pColl = db->pDfltColl;
@ -5701,6 +5715,7 @@ static i8 wherePathSatisfiesOrderBy(
if( !pColl ) pColl = db->pDfltColl; if( !pColl ) pColl = db->pDfltColl;
z2 = pColl->zName; z2 = pColl->zName;
if( sqlite3StrICmp(z1, z2)!=0 ) continue; if( sqlite3StrICmp(z1, z2)!=0 ) continue;
testcase( pTerm->pExpr->op==TK_IS );
} }
obSat |= MASKBIT(i); obSat |= MASKBIT(i);
} }
@ -5731,7 +5746,7 @@ static i8 wherePathSatisfiesOrderBy(
/* Skip over == and IS NULL terms */ /* Skip over == and IS NULL terms */
if( j<pLoop->u.btree.nEq if( j<pLoop->u.btree.nEq
&& pLoop->nSkip==0 && pLoop->nSkip==0
&& ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL))!=0 && ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL|WO_IS))!=0
){ ){
if( i & WO_ISNULL ){ if( i & WO_ISNULL ){
testcase( isOrderDistinct ); testcase( isOrderDistinct );
@ -6304,8 +6319,9 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
pLoop = pBuilder->pNew; pLoop = pBuilder->pNew;
pLoop->wsFlags = 0; pLoop->wsFlags = 0;
pLoop->nSkip = 0; pLoop->nSkip = 0;
pTerm = findTerm(pWC, iCur, -1, 0, WO_EQ, 0); pTerm = findTerm(pWC, iCur, -1, 0, WO_EQ|WO_IS, 0);
if( pTerm ){ if( pTerm ){
testcase( pTerm->eOperator & WO_IS );
pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW; pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
pLoop->aLTerm[0] = pTerm; pLoop->aLTerm[0] = pTerm;
pLoop->nLTerm = 1; pLoop->nLTerm = 1;
@ -6320,8 +6336,9 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
|| pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace) || pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace)
) continue; ) continue;
for(j=0; j<pIdx->nKeyCol; j++){ for(j=0; j<pIdx->nKeyCol; j++){
pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx); pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ|WO_IS, pIdx);
if( pTerm==0 ) break; if( pTerm==0 ) break;
testcase( pTerm->eOperator & WO_IS );
pLoop->aLTerm[j] = pTerm; pLoop->aLTerm[j] = pTerm;
} }
if( j!=pIdx->nKeyCol ) continue; if( j!=pIdx->nKeyCol ) continue;

View File

@ -280,6 +280,7 @@ struct WhereTerm {
#define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */ #define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */
#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */ #define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */
#define TERM_LIKE 0x400 /* The original LIKE operator */ #define TERM_LIKE 0x400 /* The original LIKE operator */
#define TERM_IS 0x800 /* Term.pExpr is an IS operator */
/* /*
** An instance of the WhereScan object is used as an iterator for locating ** An instance of the WhereScan object is used as an iterator for locating
@ -428,21 +429,22 @@ struct WhereInfo {
** OR-ed combination of these values can be used when searching for ** OR-ed combination of these values can be used when searching for
** particular WhereTerms within a WhereClause. ** particular WhereTerms within a WhereClause.
*/ */
#define WO_IN 0x001 #define WO_IN 0x0001
#define WO_EQ 0x002 #define WO_EQ 0x0002
#define WO_LT (WO_EQ<<(TK_LT-TK_EQ)) #define WO_LT (WO_EQ<<(TK_LT-TK_EQ))
#define WO_LE (WO_EQ<<(TK_LE-TK_EQ)) #define WO_LE (WO_EQ<<(TK_LE-TK_EQ))
#define WO_GT (WO_EQ<<(TK_GT-TK_EQ)) #define WO_GT (WO_EQ<<(TK_GT-TK_EQ))
#define WO_GE (WO_EQ<<(TK_GE-TK_EQ)) #define WO_GE (WO_EQ<<(TK_GE-TK_EQ))
#define WO_MATCH 0x040 #define WO_MATCH 0x0040
#define WO_ISNULL 0x080 #define WO_IS 0x0080
#define WO_OR 0x100 /* Two or more OR-connected terms */ #define WO_ISNULL 0x0100
#define WO_AND 0x200 /* Two or more AND-connected terms */ #define WO_OR 0x0200 /* Two or more OR-connected terms */
#define WO_EQUIV 0x400 /* Of the form A==B, both columns */ #define WO_AND 0x0400 /* Two or more AND-connected terms */
#define WO_NOOP 0x800 /* This term does not restrict search space */ #define WO_EQUIV 0x0800 /* Of the form A==B, both columns */
#define WO_NOOP 0x1000 /* This term does not restrict search space */
#define WO_ALL 0xfff /* Mask of all possible WO_* values */ #define WO_ALL 0x1fff /* Mask of all possible WO_* values */
#define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */ #define WO_SINGLE 0x01ff /* Mask of all non-compound WO_* values */
/* /*
** These are definitions of bits in the WhereLoop.wsFlags field. ** These are definitions of bits in the WhereLoop.wsFlags field.

47
test/analyzer1.test Normal file
View File

@ -0,0 +1,47 @@
# 2015-05-11
#
# 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.
#
#***********************************************************************
#
# Quick tests for the sqlite3_analyzer tool
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !vtab {
finish_test
return
}
if {$tcl_platform(platform)=="windows"} {
set PROG "sqlite3_analyzer.exe"
} else {
set PROG "./sqlite3_analyzer"
}
db close
forcedelete test.db test.db-journal test.db-wal
sqlite3 db test.db
do_test analyzer1-1.0 {
db eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE TABLE t2(a INT PRIMARY KEY, b) WITHOUT ROWID;
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<250)
INSERT INTO t1(a,b) SELECT x, randomblob(200) FROM c;
INSERT INTO t2(a,b) SELECT a, b FROM t1;
}
set line "exec $PROG test.db"
unset -nocomplain ::MSG
catch {eval $line} ::MSG
} {0}
do_test analyzer1-1.1 {
regexp {^/\*\* Disk-Space Utilization.*COMMIT;\W*$} $::MSG
} {1}
finish_test

View File

@ -507,10 +507,49 @@ foreach {tn expr res} {
} }
} { } {
do_execsql_test 11.1.$tn { do_execsql_test 11.1.$tn.1 {
SELECT rowid, mit(matchinfo(tt, 'y')) FROM tt WHERE tt MATCH $expr SELECT rowid, mit(matchinfo(tt, 'y')) FROM tt WHERE tt MATCH $expr
} $res } $res
set r2 [list]
foreach {rowid L} $res {
lappend r2 $rowid
set M [list]
foreach {a b} $L {
lappend M [expr ($a ? 1 : 0) + ($b ? 2 : 0)]
}
lappend r2 $M
}
do_execsql_test 11.1.$tn.2 {
SELECT rowid, mit(matchinfo(tt, 'b')) FROM tt WHERE tt MATCH $expr
} $r2
breakpoint
do_execsql_test 11.1.$tn.2 {
SELECT rowid, mit(matchinfo(tt, 'b')) FROM tt WHERE tt MATCH $expr
} $r2
} }
set sqlite_fts3_enable_parentheses 0 set sqlite_fts3_enable_parentheses 0
#---------------------------------------------------------------------------
# Test the 'b' matchinfo flag
#
set sqlite_fts3_enable_parentheses 1
reset_db
db func mit mit
do_test 12.0 {
set cols [list]
for {set i 0} {$i < 50} {incr i} { lappend cols "c$i" }
execsql "CREATE VIRTUAL TABLE tt USING fts3([join $cols ,])"
} {}
do_execsql_test 12.1 {
INSERT INTO tt (rowid, c4, c45) VALUES(1, 'abc', 'abc');
SELECT mit(matchinfo(tt, 'b')) FROM tt WHERE tt MATCH 'abc';
} [list [list [expr 1<<4] [expr 1<<(45-32)]]]
set sqlite_fts3_enable_parentheses 0
finish_test finish_test

View File

@ -173,8 +173,8 @@ do_select_tests 5.4 -errorformat {
4 "SELECT optimize(content) FROM t2 WHERE t2 MATCH 'history'" optimize 4 "SELECT optimize(content) FROM t2 WHERE t2 MATCH 'history'" optimize
} }
do_catchsql_test 5.5.1 { do_catchsql_test 5.5.1 {
SELECT matchinfo(t2, 'abc') FROM t2 WHERE t2 MATCH 'history' SELECT matchinfo(t2, 'abcd') FROM t2 WHERE t2 MATCH 'history'
} {1 {unrecognized matchinfo request: b}} } {1 {unrecognized matchinfo request: d}}
do_execsql_test 5.5 { DROP TABLE t2 } do_execsql_test 5.5 { DROP TABLE t2 }

View File

@ -559,7 +559,6 @@ do_execsql_test jrnlmode-8.30 { PRAGMA journal_mode=DELETE } {delete}
do_test jrnlmode-9.1 { do_test jrnlmode-9.1 {
forcedelete test2.db forcedelete test2.db
sqlite3 db2 test2.db sqlite3 db2 test2.db
breakpoint
db2 eval {CREATE TEMP TABLE t(l); PRAGMA journal_mode=off;} db2 eval {CREATE TEMP TABLE t(l); PRAGMA journal_mode=off;}
db2 close db2 close
} {} } {}

60
test/sqldiff1.test Normal file
View File

@ -0,0 +1,60 @@
# 2015-05-11
#
# 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.
#
#***********************************************************************
#
# Quick tests for the sqldiff tool
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
if {$tcl_platform(platform)=="windows"} {
set PROG "sqldiff.exe"
} else {
set PROG "./sqldiff"
}
db close
forcedelete test.db test2.db
sqlite3 db test.db
do_test sqldiff-1.0 {
db eval {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE TABLE t2(a INT PRIMARY KEY, b) WITHOUT ROWID;
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
INSERT INTO t1(a,b) SELECT x, printf('abc-%d-xyz',x) FROM c;
INSERT INTO t2(a,b) SELECT a, b FROM t1;
}
db backup test2.db
db eval {
ATTACH 'test2.db' AS x2;
DELETE FROM x2.t1 WHERE a=49;
DELETE FROM x2.t2 WHERE a=48;
INSERT INTO x2.t1(a,b) VALUES(1234,'hello');
INSERT INTO x2.t2(a,b) VALUES(50.5,'xyzzy');
CREATE TABLE x2.t3(a,b,c);
INSERT INTO x2.t3 VALUES(111,222,333);
CREATE TABLE main.t4(x,y,z);
INSERT INTO t4 SELECT * FROM t3;
}
set line "exec $PROG test.db test2.db"
unset -nocomplain ::MSG
catch {eval $line} ::MSG
} {0}
do_test sqldiff-1.1 {
set ::MSG
} {DELETE FROM t1 WHERE a=49;
INSERT INTO t1(a,b) VALUES(1234,'hello');
DELETE FROM t2 WHERE a=48;
INSERT INTO t2(a,b) VALUES(50.5,'xyzzy');
CREATE TABLE t3(a,b,c);
INSERT INTO t3(rowid,a,b,c) VALUES(1,111,222,333);
DROP TABLE t4;}
finish_test

View File

@ -166,8 +166,10 @@ sqlite3 db test.db
register_dbstat_vtab db register_dbstat_vtab db
do_execsql_test stat-5.1 { do_execsql_test stat-5.1 {
PRAGMA auto_vacuum = OFF; PRAGMA auto_vacuum = OFF;
CREATE VIRTUAL TABLE temp.stat USING dbstat; CREATE TABLE tx(y);
CREATE TABLE t1(x); ATTACH ':memory:' AS aux1;
CREATE VIRTUAL TABLE temp.stat USING dbstat(aux1);
CREATE TABLE aux1.t1(x);
INSERT INTO t1 VALUES(zeroblob(1513)); INSERT INTO t1 VALUES(zeroblob(1513));
INSERT INTO t1 VALUES(zeroblob(1514)); INSERT INTO t1 VALUES(zeroblob(1514));
SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload
@ -178,4 +180,8 @@ do_execsql_test stat-5.1 {
t1 /001+000000 4 overflow 0 1020 0 0 \ t1 /001+000000 4 overflow 0 1020 0 0 \
] ]
do_catchsql_test stat-6.1 {
CREATE VIRTUAL TABLE temp.s2 USING dbstat(mainx);
} {1 {no such database: mainx}}
finish_test finish_test

View File

@ -66,6 +66,12 @@ do_execsql_test transitive1-301 {
WHERE w=y AND y IS NOT NULL WHERE w=y AND y IS NOT NULL
ORDER BY w; ORDER BY w;
} {1 2 1 3 3 4 3 6 5 6 5 7} } {1 2 1 3 3 4 3 6 5 6 5 7}
do_execsql_test transitive1-302 {
SELECT *
FROM t301 CROSS JOIN t302
WHERE w IS y AND y IS NOT NULL
ORDER BY w;
} {1 2 1 3 3 4 3 6 5 6 5 7}
do_execsql_test transitive1-310 { do_execsql_test transitive1-310 {
SELECT * SELECT *
FROM t301 CROSS JOIN t302 ON w=y FROM t301 CROSS JOIN t302 ON w=y
@ -103,7 +109,7 @@ do_execsql_test transitive1-332 {
} {3 4 3 6 1 2 1 3} } {3 4 3 6 1 2 1 3}
# Ticket [c620261b5b5dc] circa 2013-10-28. # Ticket [c620261b5b5dc] circa 2013-10-28.
# Make sureconstraints are not used with LEFT JOINs. # Make sure constraints are not used with LEFT JOINs.
# #
# The next case is from the ticket report. It outputs no rows in 3.8.1 # The next case is from the ticket report. It outputs no rows in 3.8.1
# prior to the bug-fix. # prior to the bug-fix.
@ -116,6 +122,16 @@ do_execsql_test transitive1-400 {
INSERT INTO t403 VALUES(1); INSERT INTO t403 VALUES(1);
SELECT '1-row' FROM t401 LEFT JOIN t402 ON b=a JOIN t403 ON c=a; SELECT '1-row' FROM t401 LEFT JOIN t402 ON b=a JOIN t403 ON c=a;
} {1-row} } {1-row}
do_execsql_test transitive1-401 {
SELECT '1-row' FROM t401 LEFT JOIN t402 ON b IS a JOIN t403 ON c=a;
} {1-row}
do_execsql_test transitive1-402 {
SELECT '1-row' FROM t401 LEFT JOIN t402 ON b=a JOIN t403 ON c IS a;
} {1-row}
do_execsql_test transitive1-403 {
SELECT '1-row' FROM t401 LEFT JOIN t402 ON b IS a JOIN t403 ON c IS a;
} {1-row}
# The following is a script distilled from the XBMC project where the # The following is a script distilled from the XBMC project where the
# bug was originally encountered. The correct answer is a single row # bug was originally encountered. The correct answer is a single row

View File

@ -1085,11 +1085,22 @@ do_test vtab1.13-3 {
SELECT * FROM echo_c WHERE b IS NULL SELECT * FROM echo_c WHERE b IS NULL
} }
} {15 {} 16} } {15 {} 16}
do_test vtab1.13-3 { do_test vtab1.13-4 {
unset -nocomplain null
execsql {
SELECT * FROM echo_c WHERE b IS $null
}
} {15 {} 16}
do_test vtab1.13-5 {
execsql { execsql {
SELECT * FROM echo_c WHERE b IS NULL AND a = 15; SELECT * FROM echo_c WHERE b IS NULL AND a = 15;
} }
} {15 {} 16} } {15 {} 16}
do_test vtab1.13-6 {
execsql {
SELECT * FROM echo_c WHERE NULL IS b AND a IS 15;
}
} {15 {} 16}
do_test vtab1-14.001 { do_test vtab1-14.001 {

View File

@ -104,6 +104,14 @@ do_test vtab2-3.2 {
WHERE a.rowid=1 WHERE a.rowid=1
} }
} {main schema 0 database {} 0 {} 0 {} {} {} {} {} {} {} {} {}} } {main schema 0 database {} 0 {} 0 {} {} {} {} {} {} {} {} {}}
do_test vtab2-3.3 {
execsql {
SELECT *, b.rowid
FROM schema a LEFT JOIN schema b ON a.dflt_value IS b.dflt_value
AND a.dflt_value IS NOT NULL
WHERE a.rowid=1
}
} {main schema 0 database {} 0 {} 0 {} {} {} {} {} {} {} {} {}}
do_test vtab2-4.1 { do_test vtab2-4.1 {
execsql { execsql {
@ -153,4 +161,3 @@ ifcapable fts3 {
finish_test finish_test

View File

@ -233,6 +233,11 @@ do_test vtab6-2.4 {
SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d
} }
} {1 2 3 {} {} {} 2 3 4 {} {} {} 3 4 5 1 2 3} } {1 2 3 {} {} {} 2 3 4 {} {} {} 3 4 5 1 2 3}
do_test vtab6-2.4.1 {
execsql {
SELECT * FROM t1 LEFT JOIN t2 ON t1.a IS t2.d
}
} {1 2 3 {} {} {} 2 3 4 {} {} {} 3 4 5 1 2 3}
do_test vtab6-2.5 { do_test vtab6-2.5 {
execsql { execsql {
SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d WHERE t1.a>1 SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d WHERE t1.a>1

View File

@ -65,9 +65,15 @@ proc count sql {
do_test where-1.1.1 { do_test where-1.1.1 {
count {SELECT x, y, w FROM t1 WHERE w=10} count {SELECT x, y, w FROM t1 WHERE w=10}
} {3 121 10 3} } {3 121 10 3}
do_test where-1.1.1b {
count {SELECT x, y, w FROM t1 WHERE w IS 10}
} {3 121 10 3}
do_eqp_test where-1.1.2 { do_eqp_test where-1.1.2 {
SELECT x, y, w FROM t1 WHERE w=10 SELECT x, y, w FROM t1 WHERE w=10
} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*} } {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
do_eqp_test where-1.1.2b {
SELECT x, y, w FROM t1 WHERE w IS 10
} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
do_test where-1.1.3 { do_test where-1.1.3 {
db status step db status step
} {0} } {0}
@ -101,12 +107,21 @@ do_test where-1.3.1 {
do_test where-1.3.2 { do_test where-1.3.2 {
count {SELECT x, y, w AS abc FROM t1 WHERE 11=abc} count {SELECT x, y, w AS abc FROM t1 WHERE 11=abc}
} {3 144 11 3} } {3 144 11 3}
do_test where-1.3.3 {
count {SELECT x, y, w AS abc FROM t1 WHERE 11 IS abc}
} {3 144 11 3}
do_test where-1.4.1 { do_test where-1.4.1 {
count {SELECT w, x, y FROM t1 WHERE 11=w AND x>2} count {SELECT w, x, y FROM t1 WHERE 11=w AND x>2}
} {11 3 144 3} } {11 3 144 3}
do_test where-1.4.1b {
count {SELECT w, x, y FROM t1 WHERE 11 IS w AND x>2}
} {11 3 144 3}
do_eqp_test where-1.4.2 { do_eqp_test where-1.4.2 {
SELECT w, x, y FROM t1 WHERE 11=w AND x>2 SELECT w, x, y FROM t1 WHERE 11=w AND x>2
} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*} } {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
do_eqp_test where-1.4.2b {
SELECT w, x, y FROM t1 WHERE 11 IS w AND x>2
} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
do_test where-1.4.3 { do_test where-1.4.3 {
count {SELECT w AS a, x AS b, y FROM t1 WHERE 11=a AND b>2} count {SELECT w AS a, x AS b, y FROM t1 WHERE 11=a AND b>2}
} {11 3 144 3} } {11 3 144 3}
@ -143,6 +158,9 @@ do_test where-1.10 {
do_test where-1.11 { do_test where-1.11 {
count {SELECT x, y FROM t1 WHERE x=3 AND y=100 AND w<10} count {SELECT x, y FROM t1 WHERE x=3 AND y=100 AND w<10}
} {3 100 3} } {3 100 3}
do_test where-1.11b {
count {SELECT x, y FROM t1 WHERE x IS 3 AND y IS 100 AND w<10}
} {3 100 3}
# New for SQLite version 2.1: Verify that that inequality constraints # New for SQLite version 2.1: Verify that that inequality constraints
# are used correctly. # are used correctly.
@ -150,12 +168,18 @@ do_test where-1.11 {
do_test where-1.12 { do_test where-1.12 {
count {SELECT w FROM t1 WHERE x=3 AND y<100} count {SELECT w FROM t1 WHERE x=3 AND y<100}
} {8 3} } {8 3}
do_test where-1.12b {
count {SELECT w FROM t1 WHERE x IS 3 AND y<100}
} {8 3}
do_test where-1.13 { do_test where-1.13 {
count {SELECT w FROM t1 WHERE x=3 AND 100>y} count {SELECT w FROM t1 WHERE x=3 AND 100>y}
} {8 3} } {8 3}
do_test where-1.14 { do_test where-1.14 {
count {SELECT w FROM t1 WHERE 3=x AND y<100} count {SELECT w FROM t1 WHERE 3=x AND y<100}
} {8 3} } {8 3}
do_test where-1.14b {
count {SELECT w FROM t1 WHERE 3 IS x AND y<100}
} {8 3}
do_test where-1.15 { do_test where-1.15 {
count {SELECT w FROM t1 WHERE 3=x AND 100>y} count {SELECT w FROM t1 WHERE 3=x AND 100>y}
} {8 3} } {8 3}
@ -168,6 +192,9 @@ do_test where-1.17 {
do_test where-1.18 { do_test where-1.18 {
count {SELECT w FROM t1 WHERE x=3 AND y>225} count {SELECT w FROM t1 WHERE x=3 AND y>225}
} {15 3} } {15 3}
do_test where-1.18b {
count {SELECT w FROM t1 WHERE x IS 3 AND y>225}
} {15 3}
do_test where-1.19 { do_test where-1.19 {
count {SELECT w FROM t1 WHERE x=3 AND 225<y} count {SELECT w FROM t1 WHERE x=3 AND 225<y}
} {15 3} } {15 3}
@ -180,6 +207,9 @@ do_test where-1.21 {
do_test where-1.22 { do_test where-1.22 {
count {SELECT w FROM t1 WHERE x=3 AND y>121 AND y<196} count {SELECT w FROM t1 WHERE x=3 AND y>121 AND y<196}
} {11 12 5} } {11 12 5}
do_test where-1.22b {
count {SELECT w FROM t1 WHERE x IS 3 AND y>121 AND y<196}
} {11 12 5}
do_test where-1.23 { do_test where-1.23 {
count {SELECT w FROM t1 WHERE x=3 AND y>=121 AND y<=196} count {SELECT w FROM t1 WHERE x=3 AND y>=121 AND y<=196}
} {10 11 12 13 9} } {10 11 12 13 9}

View File

@ -57,6 +57,10 @@ proc count sql {
do_test where4-1.1 { do_test where4-1.1 {
count {SELECT rowid FROM t1 WHERE w IS NULL} count {SELECT rowid FROM t1 WHERE w IS NULL}
} {7 2} } {7 2}
do_test where4-1.1b {
unset -nocomplain null
count {SELECT rowid FROM t1 WHERE w IS $null}
} {7 2}
do_test where4-1.2 { do_test where4-1.2 {
count {SELECT rowid FROM t1 WHERE +w IS NULL} count {SELECT rowid FROM t1 WHERE +w IS NULL}
} {7 6} } {7 6}
@ -143,6 +147,17 @@ do_test where4-3.2 {
SELECT * FROM t2 LEFT JOIN t3 ON a=x WHERE y IS NULL; SELECT * FROM t2 LEFT JOIN t3 ON a=x WHERE y IS NULL;
} }
} {2 2 {} 3 {} {}} } {2 2 {} 3 {} {}}
do_test where4-3.3 {
execsql {
SELECT * FROM t2 LEFT JOIN t3 ON a=x WHERE NULL is y;
}
} {2 2 {} 3 {} {}}
do_test where4-3.4 {
unset -nocomplain null
execsql {
SELECT * FROM t2 LEFT JOIN t3 ON a=x WHERE y IS $null;
}
} {2 2 {} 3 {} {}}
# Ticket #2189. Probably the same bug as #2177. # Ticket #2189. Probably the same bug as #2177.
# #

View File

@ -59,6 +59,7 @@ foreach {tn sql res} {
12 "SELECT i FROM t1 WHERE a=2 AND b=2 AND i<NULL" {} 12 "SELECT i FROM t1 WHERE a=2 AND b=2 AND i<NULL" {}
13 "SELECT i FROM t1 WHERE a=2 AND b=2 AND i>=NULL" {} 13 "SELECT i FROM t1 WHERE a=2 AND b=2 AND i>=NULL" {}
14 "SELECT i FROM t1 WHERE a=1 AND b='2' AND i<4.5" {3 4} 14 "SELECT i FROM t1 WHERE a=1 AND b='2' AND i<4.5" {3 4}
15 "SELECT i FROM t1 WHERE rowid IS '12'" {12}
} { } {
do_execsql_test 1.$tn.1 $sql $res do_execsql_test 1.$tn.1 $sql $res
do_execsql_test 1.$tn.2 "$sql ORDER BY i ASC" [lsort -integer -inc $res] do_execsql_test 1.$tn.2 "$sql ORDER BY i ASC" [lsort -integer -inc $res]

View File

@ -88,7 +88,6 @@ if {[catch {sqlite3 db $file_to_analyze -uri 1} msg]} {
puts stderr "error trying to open $file_to_analyze: $msg" puts stderr "error trying to open $file_to_analyze: $msg"
exit 1 exit 1
} }
register_dbstat_vtab db
db eval {SELECT count(*) FROM sqlite_master} db eval {SELECT count(*) FROM sqlite_master}
set pageSize [expr {wide([db one {PRAGMA page_size}])}] set pageSize [expr {wide([db one {PRAGMA page_size}])}]

View File

@ -1139,6 +1139,7 @@ int main(int argc, char **argv){
char **azExt = 0; char **azExt = 0;
g.zArgv0 = argv[0]; g.zArgv0 = argv[0];
sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
for(i=1; i<argc; i++){ for(i=1; i<argc; i++){
const char *z = argv[i]; const char *z = argv[i];
if( z[0]=='-' ){ if( z[0]=='-' ){
@ -1158,12 +1159,14 @@ int main(int argc, char **argv){
showHelp(); showHelp();
return 0; return 0;
}else }else
#ifndef SQLITE_OMIT_LOAD_EXTENSION
if( strcmp(z,"lib")==0 || strcmp(z,"L")==0 ){ if( strcmp(z,"lib")==0 || strcmp(z,"L")==0 ){
if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]); if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
azExt = realloc(azExt, sizeof(azExt[0])*(nExt+1)); azExt = realloc(azExt, sizeof(azExt[0])*(nExt+1));
if( azExt==0 ) cmdlineError("out of memory"); if( azExt==0 ) cmdlineError("out of memory");
azExt[nExt++] = argv[++i]; azExt[nExt++] = argv[++i];
}else }else
#endif
if( strcmp(z,"primarykey")==0 ){ if( strcmp(z,"primarykey")==0 ){
g.bSchemaPK = 1; g.bSchemaPK = 1;
}else }else
@ -1199,6 +1202,7 @@ int main(int argc, char **argv){
if( rc || zErrMsg ){ if( rc || zErrMsg ){
cmdlineError("\"%s\" does not appear to be a valid SQLite database", zDb1); cmdlineError("\"%s\" does not appear to be a valid SQLite database", zDb1);
} }
#ifndef SQLITE_OMIT_LOAD_EXTENSION
sqlite3_enable_load_extension(g.db, 1); sqlite3_enable_load_extension(g.db, 1);
for(i=0; i<nExt; i++){ for(i=0; i<nExt; i++){
rc = sqlite3_load_extension(g.db, azExt[i], 0, &zErrMsg); rc = sqlite3_load_extension(g.db, azExt[i], 0, &zErrMsg);
@ -1206,6 +1210,7 @@ int main(int argc, char **argv){
cmdlineError("error loading %s: %s", azExt[i], zErrMsg); cmdlineError("error loading %s: %s", azExt[i], zErrMsg);
} }
} }
#endif
free(azExt); free(azExt);
zSql = sqlite3_mprintf("ATTACH %Q as aux;", zDb2); zSql = sqlite3_mprintf("ATTACH %Q as aux;", zDb2);
rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg); rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);