Merge latest trunk changes with this branch.

FossilOrigin-Name: b5f0e8c5b4bc018d672617ffd342d12b228548b9
This commit is contained in:
dan 2015-05-13 18:12:58 +00:00
commit 5d03b9d365
74 changed files with 2044 additions and 822 deletions

View File

@ -167,7 +167,7 @@ USE_AMALGAMATION = @USE_AMALGAMATION@
#
LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
callback.lo complete.lo ctime.lo date.lo delete.lo \
callback.lo complete.lo ctime.lo date.lo dbstat.lo delete.lo \
expr.lo fault.lo fkey.lo \
fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
@ -213,6 +213,7 @@ SRC = \
$(TOP)/src/complete.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
$(TOP)/src/fault.c \
@ -389,7 +390,6 @@ TESTSRC = \
$(TOP)/src/test_server.c \
$(TOP)/src/test_superlock.c \
$(TOP)/src/test_syscall.c \
$(TOP)/src/test_stat.c \
$(TOP)/src/test_tclvar.c \
$(TOP)/src/test_thread.c \
$(TOP)/src/test_vfs.c \
@ -423,6 +423,7 @@ TESTSRC2 = \
$(TOP)/src/build.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/expr.c \
$(TOP)/src/func.c \
$(TOP)/src/insert.c \
@ -509,6 +510,15 @@ EXTHDR += \
EXTHDR += \
$(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
# are what get build when you type just "make" with no arguments.
#
@ -536,19 +546,19 @@ sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h
-o $@ $(TOP)/src/shell.c libsqlite3.la \
$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"
sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS)
fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS)
mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
mptester$(TEXE): sqlite3.c $(TOP)/mptest/mptest.c
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
$(TLIBS) -rpath "$(libdir)"
MPTEST1=./mptester$(EXE) mptest.db $(TOP)/mptest/crash01.test --repeat 20
MPTEST2=./mptester$(EXE) mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20
mptest: mptester$(EXE)
MPTEST1=./mptester$(TEXE) mptest.db $(TOP)/mptest/crash01.test --repeat 20
MPTEST2=./mptester$(TEXE) mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20
mptest: mptester$(TEXE)
rm -f mptest.db
$(MPTEST1) --journalmode DELETE
$(MPTEST2) --journalmode WAL
@ -652,6 +662,9 @@ ctime.lo: $(TOP)/src/ctime.c $(HDR)
date.lo: $(TOP)/src/date.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/date.c
dbstat.lo: $(TOP)/src/dbstat.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/dbstat.c
delete.lo: $(TOP)/src/delete.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/delete.c
@ -951,31 +964,34 @@ testfixture$(TEXE): $(TESTFIXTURE_SRC)
-o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)
# 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
# Really really long testing
soaktest: testfixture$(TEXE) sqlite3$(TEXE)
soaktest: $(TESTPROGS) fuzzoomtest
./testfixture$(TEXE) $(TOP)/test/all.test -soak=1
# Do extra testing but not aeverything.
fulltestonly: testfixture$(TEXE) sqlite3$(TEXE)
# Do extra testing but not everything.
fulltestonly: $(TESTPROGS)
./testfixture$(TEXE) $(TOP)/test/full.test
# Fuzz testing
fuzztest: fuzzershell$(TEXE)
./fuzzershell$(TEXE) -f $(TOP)/test/fuzzdata1.txt
./fuzzershell$(TEXE) $(TOP)/test/fuzzdata1.txt $(TOP)/test/fuzzdata2.txt
fuzzoomtest: fuzzershell$(TEXE)
./fuzzershell$(TEXE) -f $(TOP)/test/fuzzdata1.txt --oom
# This is the common case. Run many tests but not those that take
# a really long time.
#
test: testfixture$(TEXE) sqlite3$(TEXE) fuzztest
test: $(TESTPROGS) fuzztest
./testfixture$(TEXE) $(TOP)/test/veryquick.test
# Run a test using valgrind. This can take a really long time
# 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
OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind
@ -983,12 +999,13 @@ valgrindtest: testfixture$(TEXE) sqlite3$(TEXE) fuzzershell$(TEXE)
# the 60s-era electronics testing: "Turn it on and see if smoke
# comes out."
#
smoketest: testfixture$(TEXE) fuzzershell$(TEXE)
smoketest: $(TESTPROGS) fuzzershell$(TEXE)
./testfixture$(TEXE) $(TOP)/test/main.test
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/test_stat.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" > $@
cat sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c >> $@
echo "#define SQLITE_ENABLE_DBSTAT_VTAB 1" >> $@
cat sqlite3.c $(TOP)/src/tclsqlite.c >> $@
echo "static const char *tclsh_main_loop(void){" >> $@
echo "static const char *zMainloop = " >> $@
$(NAWK) -f $(TOP)/tool/tostr.awk $(TOP)/tool/spaceanal.tcl >> $@
@ -1098,6 +1115,8 @@ clean:
rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c
rm -f sqlite-*-output.vsix
rm -f mptester mptester.exe
rm -f fuzzershell fuzzershell.exe
rm -f sqldiff sqldiff.exe
distclean: clean
rm -f config.log config.status libtool Makefile sqlite3.pc

View File

@ -36,6 +36,13 @@ USE_STDCALL = 0
DYNAMIC_SHELL = 0
!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
# compiling the various tools. For the SQLite source code itself, warnings,
# if any, will be disabled from within it.
@ -148,6 +155,13 @@ MEMDEBUG = 0
WIN32HEAP = 0
!ENDIF
# Set this to non-0 to enable OSTRACE() macros, which can be useful when
# debugging.
#
!IFNDEF OSTRACE
OSTRACE = 0
!ENDIF
# Set this to one of the following values to enable various debugging
# features. Each level includes the debugging options from the previous
# levels. Currently, the recognized values for DEBUG are:
@ -484,24 +498,24 @@ BCC = $(BCC) -DNDEBUG
RCC = $(RCC) -DNDEBUG
!ENDIF
!IF $(DEBUG)>0
TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR
RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR
!IF $(DEBUG)>0 || $(API_ARMOR)!=0
TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR=1
RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
!ENDIF
!IF $(DEBUG)>2
TCC = $(TCC) -DSQLITE_DEBUG
RCC = $(RCC) -DSQLITE_DEBUG
TCC = $(TCC) -DSQLITE_DEBUG=1
RCC = $(RCC) -DSQLITE_DEBUG=1
!ENDIF
!IF $(DEBUG)>4
TCC = $(TCC) -DSQLITE_DEBUG_OS_TRACE=1
RCC = $(RCC) -DSQLITE_DEBUG_OS_TRACE=1
!IF $(DEBUG)>4 || $(OSTRACE)!=0
TCC = $(TCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1
RCC = $(RCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1
!ENDIF
!IF $(DEBUG)>5
TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE
RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE
TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE=1
RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE=1
!ENDIF
# Prevent warnings about "insecure" MSVC runtime library functions
@ -808,7 +822,7 @@ NAWK = gawk.exe
#
LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
callback.lo complete.lo ctime.lo date.lo delete.lo \
callback.lo complete.lo ctime.lo date.lo dbstat.lo delete.lo \
expr.lo fault.lo fkey.lo \
fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
@ -864,6 +878,7 @@ SRC1 = \
$(TOP)\src\complete.c \
$(TOP)\src\ctime.c \
$(TOP)\src\date.c \
$(TOP)\src\dbstat.c \
$(TOP)\src\delete.c \
$(TOP)\src\expr.c \
$(TOP)\src\fault.c \
@ -1041,7 +1056,6 @@ TESTSRC = \
$(TOP)\src\test_server.c \
$(TOP)\src\test_superlock.c \
$(TOP)\src\test_syscall.c \
$(TOP)\src\test_stat.c \
$(TOP)\src\test_tclvar.c \
$(TOP)\src\test_thread.c \
$(TOP)\src\test_vfs.c \
@ -1076,6 +1090,7 @@ TESTSRC2 = \
$(TOP)\src\build.c \
$(TOP)\src\ctime.c \
$(TOP)\src\date.c \
$(TOP)\src\dbstat.c \
$(TOP)\src\expr.c \
$(TOP)\src\func.c \
$(TOP)\src\insert.c \
@ -1164,6 +1179,15 @@ EXTHDR = $(EXTHDR) \
EXTHDR = $(EXTHDR) \
$(TOP)\ext\rtree\sqlite3rtree.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
# are what get build when you type just "make" with no arguments.
#
@ -1319,6 +1343,9 @@ ctime.lo: $(TOP)\src\ctime.c $(HDR)
date.lo: $(TOP)\src\date.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\date.c
dbstat.lo: $(TOP)\src\date.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\dbstat.c
delete.lo: $(TOP)\src\delete.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\delete.c
@ -1624,36 +1651,41 @@ testfixture.exe: $(TESTFIXTURE_SRC) $(LIBRESOBJS) $(HDR)
extensiontest: testfixture.exe testloadext.dll
.\testfixture.exe $(TOP)\test\loadext.test
fulltest: testfixture.exe sqlite3.exe fuzztest
fulltest: $(TESTPROGS) fuzztest
.\testfixture.exe $(TOP)\test\all.test
soaktest: testfixture.exe sqlite3.exe
soaktest: $(TESTPROGS) fuzzoomtest
.\testfixture.exe $(TOP)\test\all.test -soak=1
fulltestonly: testfixture.exe sqlite3.exe fuzztest
fulltestonly: $(TESTPROGS) fuzztest
.\testfixture.exe $(TOP)\test\full.test
queryplantest: testfixture.exe sqlite3.exe
.\testfixture.exe $(TOP)\test\permutations.test queryplanner
fuzztest: fuzzershell.exe
.\fuzzershell.exe -f $(TOP)\test\fuzzdata1.txt
.\fuzzershell.exe $(TOP)\test\fuzzdata1.txt $(TOP)\test\fuzzdata2.txt
test: testfixture.exe sqlite3.exe fuzztest
fuzzoomtest: fuzzershell.exe
.\fuzzershell.exe -f $(TOP)\test\fuzzdata1.txt --oom
test: $(TESTPROGS) fuzztest
.\testfixture.exe $(TOP)\test\veryquick.test
smoketest: testfixture.exe
smoketest: $(TESTPROGS) fuzzershell.exe
.\testfixture.exe $(TOP)\test\main.test
sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\test_stat.c $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
copy $(SQLITE3C) + $(TOP)\src\test_stat.c + $(TOP)\src\tclsqlite.c $@
sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
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 *zMainloop = >> $@
$(NAWK) -f $(TOP)\tool\tostr.awk $(TOP)\tool\spaceanal.tcl >> $@
echo ; return zMainloop; } >> $@
sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
testloadext.lo: $(TOP)\src\test_loadext.c
@ -1723,6 +1755,7 @@ clean:
del /Q shell.c sqlite3ext.h 2>NUL
del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL
del /Q sqlite-*-output.vsix 2>NUL
del /Q fuzzershell.exe sqldiff.exe 2>NUL
# Dynamic link library section.
#

View File

@ -1 +1 @@
3.8.10
3.8.10.1

View File

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

18
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.62 for sqlite 3.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,
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.8.10'
PACKAGE_STRING='sqlite 3.8.10'
PACKAGE_VERSION='3.8.10.1'
PACKAGE_STRING='sqlite 3.8.10.1'
PACKAGE_BUGREPORT=''
# 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.
# This message is too long to be a string in the A/UX 3.1 sh.
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]...
@ -1546,7 +1546,7 @@ fi
if test -n "$ac_init_help"; then
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
cat <<\_ACEOF
@ -1660,7 +1660,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.8.10
sqlite configure 3.8.10.1
generated by GNU Autoconf 2.62
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
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
$ $0 $@
@ -13953,7 +13953,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.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
CONFIG_FILES = $CONFIG_FILES
@ -14006,7 +14006,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
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,
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"

View File

@ -508,6 +508,17 @@ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){
return SQLITE_OK;
}
/*
** Write an error message into *pzErr
*/
void sqlite3Fts3ErrMsg(char **pzErr, const char *zFormat, ...){
va_list ap;
sqlite3_free(*pzErr);
va_start(ap, zFormat);
*pzErr = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
}
/*
** Construct one or more SQL statements from the format string given
** and then evaluate those statements. The success code is written
@ -1039,7 +1050,7 @@ static int fts3ContentColumns(
}else{
rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
if( rc!=SQLITE_OK ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
sqlite3Fts3ErrMsg(pzErr, "%s", sqlite3_errmsg(db));
}
}
sqlite3_free(zSql);
@ -1207,13 +1218,13 @@ static int fts3InitVtab(
}
}
if( iOpt==SizeofArray(aFts4Opt) ){
*pzErr = sqlite3_mprintf("unrecognized parameter: %s", z);
sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z);
rc = SQLITE_ERROR;
}else{
switch( iOpt ){
case 0: /* MATCHINFO */
if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
*pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal);
sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal);
rc = SQLITE_ERROR;
}
bNoDocsize = 1;
@ -1241,7 +1252,7 @@ static int fts3InitVtab(
if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
&& (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
){
*pzErr = sqlite3_mprintf("unrecognized order: %s", zVal);
sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal);
rc = SQLITE_ERROR;
}
bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
@ -1327,7 +1338,7 @@ static int fts3InitVtab(
rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex);
if( rc==SQLITE_ERROR ){
assert( zPrefix );
*pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
sqlite3Fts3ErrMsg(pzErr, "error parsing prefix parameter: %s", zPrefix);
}
if( rc!=SQLITE_OK ) goto fts3_init_out;
@ -1409,7 +1420,7 @@ static int fts3InitVtab(
}
for(i=0; i<nNotindexed; i++){
if( azNotindexed[i] ){
*pzErr = sqlite3_mprintf("no such column: %s", azNotindexed[i]);
sqlite3Fts3ErrMsg(pzErr, "no such column: %s", azNotindexed[i]);
rc = SQLITE_ERROR;
}
}
@ -1417,7 +1428,7 @@ static int fts3InitVtab(
if( rc==SQLITE_OK && (zCompress==0)!=(zUncompress==0) ){
char const *zMiss = (zCompress==0 ? "compress" : "uncompress");
rc = SQLITE_ERROR;
*pzErr = sqlite3_mprintf("missing %s parameter in fts4 constructor", zMiss);
sqlite3Fts3ErrMsg(pzErr, "missing %s parameter in fts4 constructor", zMiss);
}
p->zReadExprlist = fts3ReadExprList(p, zUncompress, &rc);
p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc);
@ -1664,7 +1675,7 @@ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
sqlite3Fts3ExprFree(pCsr->pExpr);
sqlite3Fts3FreeDeferredTokens(pCsr);
sqlite3_free(pCsr->aDoclist);
sqlite3_free(pCsr->aMatchinfo);
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
sqlite3_free(pCsr);
return SQLITE_OK;
@ -3165,7 +3176,7 @@ static int fts3FilterMethod(
/* In case the cursor has been used before, clear it now. */
sqlite3_finalize(pCsr->pStmt);
sqlite3_free(pCsr->aDoclist);
sqlite3_free(pCsr->aMatchinfo);
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
sqlite3Fts3ExprFree(pCsr->pExpr);
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 Fts3MultiSegReader Fts3MultiSegReader;
typedef struct MatchinfoBuffer MatchinfoBuffer;
/*
** A connection to a fulltext index is an instance of the following
** structure. The xCreate and xConnect methods create an instance
@ -306,9 +308,7 @@ struct Fts3Cursor {
i64 iMinDocid; /* Minimum docid to return */
i64 iMaxDocid; /* Maximum docid to return */
int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
u32 *aMatchinfo; /* Information about most recent match */
int nMatchinfo; /* Number of elements in aMatchinfo[] */
char *zMatchinfo; /* Matchinfo specification */
MatchinfoBuffer *pMIBuffer; /* Buffer for matchinfo data */
};
#define FTS3_EVAL_FILTER 0
@ -428,7 +428,9 @@ struct Fts3Expr {
u8 bStart; /* True if iDocid is valid */
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 */
};
/*
@ -539,6 +541,7 @@ int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
)
/* fts3.c */
void sqlite3Fts3ErrMsg(char**,const char*,...);
int sqlite3Fts3PutVarint(char *, sqlite3_int64);
int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
int sqlite3Fts3GetVarint32(const char *, int *);
@ -563,6 +566,7 @@ void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *,
const char *, const char *, int, int
);
void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *);
void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p);
/* fts3_expr.c */
int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int,

View File

@ -116,7 +116,7 @@ static int fts3auxConnectMethod(
return SQLITE_OK;
bad_args:
*pzErr = sqlite3_mprintf("invalid arguments to fts4aux constructor");
sqlite3Fts3ErrMsg(pzErr, "invalid arguments to fts4aux constructor");
return SQLITE_ERROR;
}

View File

@ -1022,13 +1022,13 @@ int sqlite3Fts3ExprParse(
sqlite3Fts3ExprFree(*ppExpr);
*ppExpr = 0;
if( rc==SQLITE_TOOBIG ){
*pzErr = sqlite3_mprintf(
sqlite3Fts3ErrMsg(pzErr,
"FTS expression tree is too large (maximum depth %d)",
SQLITE_FTS3_MAX_EXPR_DEPTH
);
rc = SQLITE_ERROR;
}else if( rc==SQLITE_ERROR ){
*pzErr = sqlite3_mprintf("malformed MATCH expression: [%s]", z);
sqlite3Fts3ErrMsg(pzErr, "malformed MATCH expression: [%s]", z);
}
}

View File

@ -27,6 +27,8 @@
#define FTS3_MATCHINFO_LENGTH 'l' /* nCol values */
#define FTS3_MATCHINFO_LCS 's' /* nCol values */
#define FTS3_MATCHINFO_HITS 'x' /* 3*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().
@ -88,9 +90,22 @@ struct MatchInfo {
int nCol; /* Number of columns in table */
int nPhrase; /* Number of matchable phrases in query */
sqlite3_int64 nDoc; /* Number of docs in database */
char flag;
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];
};
/*
@ -106,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
** list is a list of unique integers, sorted from smallest to largest. Each
@ -142,7 +248,7 @@ static int fts3ExprIterate2(
void *pCtx /* Second argument to pass to callback */
){
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 ){
assert( pExpr->pLeft && pExpr->pRight );
@ -176,6 +282,7 @@ static int fts3ExprIterate(
return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx);
}
/*
** This is an fts3ExprIterate() callback used while loading the doclists
** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also
@ -220,8 +327,7 @@ static int fts3ExprLoadDoclists(
static int fts3ExprPhraseCountCb(Fts3Expr *pExpr, int iPhrase, void *ctx){
(*(int *)ctx)++;
UNUSED_PARAMETER(pExpr);
UNUSED_PARAMETER(iPhrase);
pExpr->iPhrase = iPhrase;
return SQLITE_OK;
}
static int fts3ExprPhraseCount(Fts3Expr *pExpr){
@ -442,7 +548,7 @@ static int fts3BestSnippet(
sIter.nSnippet = nSnippet;
sIter.nPhrase = nList;
sIter.iCurrent = -1;
rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter);
rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void*)&sIter);
if( rc==SQLITE_OK ){
/* Set the *pmSeen output variable. */
@ -743,6 +849,60 @@ static int fts3ColumnlistCount(char **ppCollist){
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
** for a single query.
@ -821,10 +981,12 @@ static int fts3MatchinfoCheck(
|| (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize)
|| (cArg==FTS3_MATCHINFO_LCS)
|| (cArg==FTS3_MATCHINFO_HITS)
|| (cArg==FTS3_MATCHINFO_LHITS)
|| (cArg==FTS3_MATCHINFO_LHITS_BM)
){
return SQLITE_OK;
}
*pzErr = sqlite3_mprintf("unrecognized matchinfo request: %c", cArg);
sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo request: %c", cArg);
return SQLITE_ERROR;
}
@ -844,6 +1006,14 @@ static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
nVal = pInfo->nCol;
break;
case FTS3_MATCHINFO_LHITS:
nVal = pInfo->nCol * pInfo->nPhrase;
break;
case FTS3_MATCHINFO_LHITS_BM:
nVal = pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
break;
default:
assert( cArg==FTS3_MATCHINFO_HITS );
nVal = pInfo->nCol * pInfo->nPhrase * 3;
@ -1038,7 +1208,7 @@ static int fts3MatchinfoValues(
sqlite3_stmt *pSelect = 0;
for(i=0; rc==SQLITE_OK && zArg[i]; i++){
pInfo->flag = zArg[i];
switch( zArg[i] ){
case FTS3_MATCHINFO_NPHRASE:
if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nPhrase;
@ -1098,6 +1268,14 @@ static int fts3MatchinfoValues(
}
break;
case FTS3_MATCHINFO_LHITS_BM:
case FTS3_MATCHINFO_LHITS: {
int nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
memset(pInfo->aMatchinfo, 0, nZero);
fts3ExprLHitGather(pCsr->pExpr, pInfo);
break;
}
default: {
Fts3Expr *pExpr;
assert( zArg[i]==FTS3_MATCHINFO_HITS );
@ -1129,7 +1307,8 @@ static int fts3MatchinfoValues(
** Populate pCsr->aMatchinfo[] with data for the current row. The
** '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 */
const char *zArg /* Second argument to matchinfo() function */
){
@ -1138,6 +1317,9 @@ static int fts3GetMatchinfo(
int rc = SQLITE_OK;
int bGlobal = 0; /* Collect 'global' stats as well as local */
u32 *aOut = 0;
void (*xDestroyOut)(void*) = 0;
memset(&sInfo, 0, sizeof(MatchInfo));
sInfo.pCursor = pCsr;
sInfo.nCol = pTab->nColumn;
@ -1145,21 +1327,18 @@ static int fts3GetMatchinfo(
/* If there is cached matchinfo() data, but the format string for the
** cache does not match the format string for this request, discard
** the cached data. */
if( pCsr->zMatchinfo && strcmp(pCsr->zMatchinfo, zArg) ){
assert( pCsr->aMatchinfo );
sqlite3_free(pCsr->aMatchinfo);
pCsr->zMatchinfo = 0;
pCsr->aMatchinfo = 0;
if( pCsr->pMIBuffer && strcmp(pCsr->pMIBuffer->zMatchinfo, zArg) ){
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
pCsr->pMIBuffer = 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
** allocate the array used to accumulate the matchinfo data and
** 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 nArg; /* Bytes in zArg */
int i; /* Used to iterate through zArg */
/* Determine the number of phrases in the query */
@ -1168,30 +1347,46 @@ static int fts3GetMatchinfo(
/* Determine the number of integers in the buffer returned by this call. */
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]);
}
/* Allocate space for Fts3Cursor.aMatchinfo[] and Fts3Cursor.zMatchinfo. */
nArg = (int)strlen(zArg);
pCsr->aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo + nArg + 1);
if( !pCsr->aMatchinfo ) return SQLITE_NOMEM;
pCsr->pMIBuffer = fts3MIBufferNew(nMatchinfo, zArg);
if( !pCsr->pMIBuffer ) rc = 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;
bGlobal = 1;
}
sInfo.aMatchinfo = pCsr->aMatchinfo;
sInfo.nPhrase = pCsr->nPhrase;
if( pCsr->isMatchinfoNeeded ){
rc = fts3MatchinfoValues(pCsr, bGlobal, &sInfo, zArg);
pCsr->isMatchinfoNeeded = 0;
if( rc==SQLITE_OK ){
xDestroyOut = fts3MIBufferAlloc(pCsr->pMIBuffer, &aOut);
if( xDestroyOut==0 ){
rc = SQLITE_NOMEM;
}
}
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);
}
}
/*
@ -1397,7 +1592,7 @@ void sqlite3Fts3Offsets(
*/
sCtx.iCol = iCol;
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
** in column iCol, jump immediately to the next iteration of the loop.
@ -1489,19 +1684,9 @@ void sqlite3Fts3Matchinfo(
const char *zArg /* Second arg to matchinfo() function */
){
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
int rc;
int i;
const char *zFormat;
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;
}else{
zFormat = FTS3_MATCHINFO_DEFAULT;
@ -1510,17 +1695,10 @@ void sqlite3Fts3Matchinfo(
if( !pCsr->pExpr ){
sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC);
return;
}
/* Retrieve matchinfo() data. */
rc = fts3GetMatchinfo(pCsr, zFormat);
sqlite3Fts3SegmentsClose(pTab);
if( rc!=SQLITE_OK ){
sqlite3_result_error_code(pContext, rc);
}else{
int n = pCsr->nMatchinfo * sizeof(u32);
sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT);
/* Retrieve matchinfo() data. */
fts3GetMatchinfo(pContext, pCsr, zFormat);
sqlite3Fts3SegmentsClose(pTab);
}
}

View File

@ -81,7 +81,7 @@ static int fts3termConnectMethod(
/* The user should specify a single argument - the name of an fts3 table. */
if( argc!=4 ){
*pzErr = sqlite3_mprintf(
sqlite3Fts3ErrMsg(pzErr,
"wrong number of arguments to fts4term constructor"
);
return SQLITE_ERROR;

View File

@ -85,7 +85,7 @@ static int fts3tokQueryTokenizer(
p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
if( !p ){
*pzErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", zName);
return SQLITE_ERROR;
}

View File

@ -172,7 +172,7 @@ int sqlite3Fts3InitTokenizer(
m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash,z,(int)strlen(z)+1);
if( !m ){
*pzErr = sqlite3_mprintf("unknown tokenizer: %s", z);
sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", z);
rc = SQLITE_ERROR;
}else{
char const **aArg = 0;
@ -195,7 +195,7 @@ int sqlite3Fts3InitTokenizer(
rc = m->xCreate(iArg, aArg, ppTok);
assert( rc!=SQLITE_OK || *ppTok );
if( rc!=SQLITE_OK ){
*pzErr = sqlite3_mprintf("unknown tokenizer");
sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer");
}else{
(*ppTok)->pModule = m;
}

View File

@ -2820,11 +2820,19 @@ static int rtreeUpdate(
if( nData>1 ){
int ii;
/* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */
assert( nData==(pRtree->nDim*2 + 3) );
/* Populate the cell.aCoord[] array. The first coordinate is azData[3].
**
** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared
** with "column" that are interpreted as table constraints.
** Example: CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5));
** This problem was discovered after years of use, so we silently ignore
** these kinds of misdeclared tables to avoid breaking any legacy.
*/
assert( nData<=(pRtree->nDim*2 + 3) );
#ifndef SQLITE_RTREE_INT_ONLY
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
for(ii=0; ii<(pRtree->nDim*2); ii+=2){
for(ii=0; ii<nData-4; ii+=2){
cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]);
cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]);
if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
@ -2835,7 +2843,7 @@ static int rtreeUpdate(
}else
#endif
{
for(ii=0; ii<(pRtree->nDim*2); ii+=2){
for(ii=0; ii<nData-4; ii+=2){
cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]);
cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]);
if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){

View File

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

42
main.mk
View File

@ -54,7 +54,7 @@ TCCX += -I$(TOP)/ext/fts5
LIBOBJ+= vdbe.o parse.o \
alter.o analyze.o attach.o auth.o \
backup.o bitvec.o btmutex.o btree.o build.o \
callback.o complete.o ctime.o date.o delete.o expr.o fault.o fkey.o \
callback.o complete.o ctime.o date.o dbstat.o delete.o expr.o fault.o fkey.o \
fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \
fts3_tokenize_vtab.o \
@ -105,6 +105,7 @@ SRC = \
$(TOP)/src/complete.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
$(TOP)/src/fault.c \
@ -300,7 +301,6 @@ TESTSRC = \
$(TOP)/src/test_rtree.c \
$(TOP)/src/test_schema.c \
$(TOP)/src/test_server.c \
$(TOP)/src/test_stat.c \
$(TOP)/src/test_sqllog.c \
$(TOP)/src/test_superlock.c \
$(TOP)/src/test_syscall.c \
@ -337,6 +337,7 @@ TESTSRC2 = \
$(TOP)/src/btree.c \
$(TOP)/src/build.c \
$(TOP)/src/date.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/expr.c \
$(TOP)/src/func.c \
$(TOP)/src/insert.c \
@ -425,6 +426,14 @@ EXTHDR += \
EXTHDR += \
$(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
# are what get build when you type just "make" with no arguments.
#
@ -684,9 +693,10 @@ tclsqlite3: $(TOP)/src/tclsqlite.c libsqlite3.a
$(TCCX) $(TCL_FLAGS) -DTCLSH=1 -o tclsqlite3 \
$(TOP)/src/tclsqlite.c libsqlite3.a $(LIBTCL) $(THREADLIB)
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/test_stat.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" > $@
cat sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c >> $@
echo "#define SQLITE_ENABLE_DBSTAT_VTAB 1" >> $@
cat sqlite3.c $(TOP)/src/tclsqlite.c >> $@
echo "static const char *tclsh_main_loop(void){" >> $@
echo "static const char *zMainloop = " >> $@
$(NAWK) -f $(TOP)/tool/tostr.awk $(TOP)/tool/spaceanal.tcl >> $@
@ -716,31 +726,41 @@ fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c
$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c \
-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
fulltest: testfixture$(EXE) sqlite3$(EXE) fuzztest
fulltest: $(TESTPROGS) fuzztest
./testfixture$(EXE) $(TOP)/test/all.test
soaktest: testfixture$(EXE) sqlite3$(EXE)
soaktest: $(TESTPROGS) fuzzoomtest
./testfixture$(EXE) $(TOP)/test/all.test -soak=1
fulltestonly: testfixture$(EXE) sqlite3$(EXE) fuzztest
fulltestonly: $(TESTPROGS) fuzztest
./testfixture$(EXE) $(TOP)/test/full.test
queryplantest: testfixture$(EXE) sqlite3$(EXE)
./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner
fuzztest: fuzzershell$(EXE)
./fuzzershell$(EXE) -f $(TOP)/test/fuzzdata1.txt
./fuzzershell$(EXE) $(TOP)/test/fuzzdata1.txt $(TOP)/test/fuzzdata2.txt
test: testfixture$(EXE) sqlite3$(EXE) fuzztest
fuzzoomtest: fuzzershell$(EXE)
./fuzzershell$(EXE) -f $(TOP)/test/fuzzdata1.txt --oom
test: $(TESTPROGS) fuzztest
./testfixture$(EXE) $(TOP)/test/veryquick.test
# Run a test using valgrind. This can take a really long time
# 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
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
# threadtest runs a few thread-safety tests that are implemented in C. This
# target is invoked by the releasetest.tcl script.
@ -850,3 +870,5 @@ clean:
rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c
rm -f sqlite-*-output.vsix
rm -f mptester mptester.exe
rm -f fuzzershell fuzzershell.exe
rm -f sqldiff sqldiff.exe

149
manifest
View File

@ -1,19 +1,19 @@
C Change\sfts5\sdoclist-index\sstructures\sto\sbe\strees\sinstead\sof\sflat\slists.\sThis\sonly\smakes\sa\sdifference\sfor\sdatabases\sthat\scontain\smillions\sof\sinstances\sof\sthe\ssame\stoken.
D 2015-05-13T17:15:32.981
C Merge\slatest\strunk\schanges\swith\sthis\sbranch.
D 2015-05-13T18:12:58.028
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 31b38b9da2e4b36f54a013bd71a5c3f6e45ca78f
F Makefile.in edfc69769e613a6359c42c06ea1d42c3bece1736
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc 4a546e42ecfd0fe53c31e05c2a965e17fb591637
F Makefile.msc a9fd7fd02265aa5b3b2522f5e39d975972ff906d
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866
F VERSION 2e244662b71e6e68a5c29b014ebc5b7564f4cc5a
F VERSION 8af05c43e00f7de32be74ff9984d792c96cdb0de
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am 8fc2972d92769cf20ab8e4a73ea901b84d69bf44
F autoconf/Makefile.am 27de1af382c82e81f1fe36a7f38528fba004eb1a
F autoconf/README 14458f1046c118efa721aadec5f227e876d3cd38
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/config.guess 94cc57e2a3fdb9c235b362ace86d77e89d188cad x
@ -38,7 +38,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure 2ea5f5b58dd106da449ab598ab6e515339d7fa2a x
F configure dae9f0ec4df32a9e300befbcdbc4ff8874731357 x
F configure.ac 0b775d383c536bbaafc1e46dd3cbb81a7ea11aeb
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
@ -78,20 +78,20 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c 81f9ed55ad58614828ad9d8b1e0525ad78fede1b
F ext/fts3/fts3.c 341e9d9a3c7615bac8e815a8937d576265b22f78
F ext/fts3/fts3.h 62a77d880cf06a2865052726f8325c8fabcecad7
F ext/fts3/fts3Int.h 3626655d6ba903a3919bb44e1c38e5f0f9d6be82
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
F ext/fts3/fts3_expr.c 40123785eaa3ebd4c45c9b23407cc44ac0c49905
F ext/fts3/fts3Int.h 142837a7544dff49121b67091a71c4f7a4546b0f
F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
F ext/fts3/fts3_expr.c 71c063da9c2a4167fb54aec089dd5ef33a58c9cb
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5
F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
F ext/fts3/fts3_snippet.c 52c2dcf410b1f9af5a44d81a2cf8c68ed1cb5283
F ext/fts3/fts3_term.c a521f75132f9a495bdca1bdd45949b3191c52763
F ext/fts3/fts3_snippet.c b7aaa8698096b26e1c6eb563e317409323398142
F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7
F ext/fts3/fts3_test.c 8a3a78c4458b2d7c631fcf4b152a5cd656fa7038
F ext/fts3/fts3_tokenize_vtab.c becc661223db7898b213f9e8a23d75bac02408c9
F ext/fts3/fts3_tokenizer.c 9afd223b07740b14dd589edd3116acacf951fd78
F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860
F ext/fts3/fts3_tokenizer.c 50e7a69a549ac5882cc1971ee43f66aaabc11395
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145
@ -189,7 +189,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 14e6239434d4e3f65d3e90320713f26aa24e167f
F ext/rtree/rtree.c 0c207fd8b814a35537d96681cbf57436e200b75e
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
F ext/rtree/rtree1.test 541bbcab74613907fea08b2ecdcdd5b7aa724cc9
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
@ -199,7 +199,7 @@ F ext/rtree/rtree5.test 6a510494f12454bf57ef28f45bc7764ea279431e
F ext/rtree/rtree6.test 773a90db2dce6a8353dd0d5b64bca69b29761196
F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971
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/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e
F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06
@ -217,7 +217,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk 063cdc009247a9b543875ea12f4e27b8f3bcca54
F main.mk a17ff4be35788f0a007b80af5e2a4f3036f03882
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk d5e22023b5238985bb54a72d33e0ac71fe4f8a32
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@ -231,26 +231,27 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c d23d6b6991f66b383934f137fd4384d93fb98c81
F src/alter.c 8f6dc4a6ddc1ebc0ed5cc470c4e57ff0d1605e90
F src/analyze.c d23790787f80ebed58df7774744b4cf96401498b
F src/attach.c c38ac5a520a231d5d0308fd7f2ad95191c867bae
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/bitvec.c 5eb7958c3bf65210211cbcfc44eff86d0ded7c9d
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
F src/btree.c 127aceb71ba93f59bc9c6ba810e992a04299e98a
F src/btree.c 30a80340481098d699398cba3536c895373b2e2c
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4
F src/build.c e246c2cea69c8f6fc825a156ea2de9dd4a17f18b
F src/build.c 61b47073f79f31e80a05db9ce13c5ca81bf8f74e
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575
F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a w src/test_stat.c
F src/delete.c 37964e6c1d73ff49cbea9ff690c9605fb15f600e
F src/expr.c 4c05a28eebe63b288fda1db0e8de556a82ca2ec6
F src/expr.c 3fb2ab3ab69d15b4b75ae53fceb4e317f64cb306
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c c9b63a217d86582c22121699a47f22f524608869
F src/func.c 1414c24c873c48796ad45942257a179a423ba42f
F src/func.c 5b8b8e77a0fb644eaf8947d413804622e32692b6
F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
@ -259,9 +260,9 @@ F src/insert.c 8176ba5bad8fcef643558ca5708f33ed05a4035a
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
F src/loadext.c 86bd4e2fccd520b748cba52492ab60c4a770f660
F src/main.c 43cb916046dc9dfde761380a764190a4a4223bc6
F src/malloc.c 6a370b83d54e4bbf6f94021221c2a311cff26a18
F src/loadext.c 29255bbe1cfb2ce9bbff2526a5ecfddcb49b9271
F src/main.c 35fe70009ee313c5535194695ca4182bda15a2de
F src/malloc.c 5bc15d525811d387b37c29f2e368143460e41e96
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
@ -277,12 +278,12 @@ F src/mutex_w32.c 61660ada28d8308ad190f444c2170c4f2a590c2f
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c 5ed7e2e453c2980909a6b2c80dc55764b50819a8
F src/os_win.c 03d27be3a20048ef52a648d5f0a15f5edda9f2a3
F src/os_unix.c 23eb5f56fac54d8fe0cb204291f3b3b2d94f23fc
F src/os_win.c 97f7828a9554d753665b6fcf7540e31c2b3d6a6e
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
F src/pager.c 5283581c8ce8950ff483a0b3a3cab9cb4d25a21e
F src/pager.c 97110085b1321298412f1e5c37bddb95b36d9208
F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77
F src/parse.y c4e0387bc88c8e21e5ba653e2578959a1f3cdbc7
F src/pcache.c 10539fb959849ad6efff80050541cab3d25089d4
@ -291,21 +292,21 @@ F src/pcache1.c 69d137620a305f814398bd29a0c998038c0695e9
F src/pragma.c c1f4d012ea9f6b1ce52d341b2cd0ad72d560afd7
F src/pragma.h 09c89bca58e9a44de2116cc8272b8d454657129f
F src/prepare.c 1fffbdcd6f8a0173a8f70d71f22528f4c0e1e3d3
F src/printf.c 08fa675c200aac29e561c6153f91f909ed17612f
F src/printf.c 54dd6dce95454fadffa3ebf7717c5f6c06250d1d
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 13109bc3b5ab404446296efa17039640de5bc35d
F src/resolve.c 99eabf7eff0bfa65b75939b46caa82e2b2133f28
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c 35433ea8894ac42594ddc31eb0165a6d6401cfe5
F src/shell.c 78eabce4c16c45e36fea2368f95118116399ba8a
F src/sqlite.h.in ca27603a36fcacdaac5a19d8ee35aaff8ce8516f
F src/select.c 1b0bfc7d59e48c26b895a6b719157111a617d9e3
F src/shell.c 07dda7cd692911d2f22269953418d049f2e2c0ee
F src/sqlite.h.in bf3fe5eba3a5142477b8dae3cfce627c3e971455
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
F src/sqliteInt.h 8abcea1295138f10ef8f7ed38db5f1b573b93ece
F src/sqliteInt.h c9f77bd02f419dcc8c644c5032c42eb29069a545
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
F src/table.c e7a09215315a978057fb42c640f890160dbcc45e
F src/tclsqlite.c 3d89752d9a58039c2e82412a85387fe49eec6f72
F src/test1.c 90fbedce75330d48d99eadb7d5f4223e86969585
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
F src/tclsqlite.c 47f303d6572a3c01700d5e57ea04f8833bd8059b
F src/test1.c a8e09b811f70184ce65012f27f30cfee7e54f268
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
@ -317,7 +318,7 @@ F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803
F src/test_blob.c 1f2e3e25255b731c4fcf15ee7990d06347cb6c09
F src/test_blob.c e5a7a81d61a780da79101aeb1e60d300af169e07
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
F src/test_config.c ca734889a4ece295d3ed129dc532f7fefc63711d
F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852
@ -326,12 +327,12 @@ F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
F src/test_func.c f1ac201465472e76a73e2f3695c3553c63e7322a
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
F src/test_intarray.c 6c610a21ab8edde85a3a2c7f2b069244ecf4d834
F src/test_intarray.c 870124b95ec4c645d4eb84f15efb7133528fb1a5
F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202
F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa
F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4
F src/test_malloc.c 208f09a4e21defa496bc1094fcfadea19385a112
F src/test_multiplex.c 4dfb159e5c280c0ebdbf8b5ab9d95bf2765061f9
F src/test_multiplex.c 9fefd23f6cc3fa9bf0748a5e453167e7b9f193ce
F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3
F src/test_mutex.c 293042d623ebba969160f471a82aa1551626454f
F src/test_onefile.c 38f7cbe79d5bafe95bde683cc3a53b8ca16daf10
@ -343,7 +344,6 @@ F src/test_rtree.c bfe6f4386517f70054311109f3528adffec34485
F src/test_schema.c 2bdba21b82f601da69793e1f1d11bf481a79b091
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
F src/test_sqllog.c b690c12933f50ff46491e0d56a251f84ae16e914
F src/test_stat.c ffc8177f6e69de32a8a89fa6bca73facb6c5face
F src/test_superlock.c 06797157176eb7085027d9dd278c0d7a105e3ec9
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
@ -352,34 +352,34 @@ F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
F src/tokenize.c b7fb584c2be5ec39b6fdf04b185e7c6f33f8dc15
F src/tokenize.c b15511a2396641792f386ceb440d1d922972a78e
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c a6431c92803b975b7322724a7b433e538d243539
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
F src/vdbe.c f0cf3cf527d5a40b8d5d2324fdbb31da6c90cd8b
F src/vdbe.c d437887d02d13d79dc69ac018f788aefac3b3972
F src/vdbe.h 7e538ecf47dccb307ea2d087c3ddc2dd8d70e79d
F src/vdbeInt.h 9cbaa84f53ddd2d09a0cf61a94337a3a035d08a0
F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75
F src/vdbeaux.c 03591cca98ec50e1493043f0ff7abbece0b9c83d
F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90
F src/vdbemem.c b5256445b318b0f2b3bc429028469cfbb08f19a5
F src/vdbesort.c 2e7f683464fd5db3be4beaa1ff2d39e24fcb64b8
F src/vdbetrace.c f95c2dff9041fcf07f871789c22ebb0648ea0b7c
F src/vtab.c fcbf338e0e8a91906aaf24bda8120e9f00cb4576
F src/vdbemem.c 7bfbeef0978a2e1a05d979641fdbf7c189b7ddf4
F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
F src/vtab.c 082b35a25a26e3d36f365ca8cd73c1922532f05e
F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
F src/wal.c 753995db83247f20361a8e8a874990b21a75abd9
F src/wal.c ce2cb2d06faab54d1bce3e739bec79e063dd9113
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
F src/where.c 32fe265e3dc74ef3b27deb9e6eb5fc3c71409612
F src/where.c 85fff9c40569ccb79c3177419b339e7d7df566cb
F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783
F test/alter.test 547dc2d292644301ac9a7dda22b319b74f9c08d2
F test/alter.test 2facdddf08d0d48e75dc6cc312cd2b030f4835dd
F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
F test/alter4.test c461150723ac957f3b2214aa0b11552cd72023ec
@ -399,6 +399,7 @@ F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
F test/analyzeD.test 08f9d0bee4e118a66fff3a32d02dbe0ee0a2b594
F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
F test/analyzeF.test 7ccd7a04f7d3061bde1a8a4dacc4792edccf6bf2
F test/analyzer1.test e3bccac3be49382050464952998a631bf51e3ce1
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
@ -658,11 +659,11 @@ F test/fts3fault2.test f953bb3cf903988172270a9a0aafd5a890b0f98f
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
F test/fts3join.test 53e66a0c21eb568580674a43b21c059acb26f499
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
F test/fts3matchinfo.test 58544fa4d254000fa4e7f494b0a832f7ba61d45e
F test/fts3matchinfo.test 07009313ad6c082f94d8c9c3228eb8940c93ac71
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
F test/fts3query.test c838b18f2b859e15fd31c64be3d79ef1556803ca
F test/fts3query.test f33eb71a1fe1084ea585eeb7ee76b390729f5170
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
F test/fts3snippet.test 63dbd687d5bf5191f1b8e6a0977aa9c1e28a7004
@ -696,7 +697,8 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
F test/fuzz3.test efd384b896c647b61a2c1848ba70d42aad60a7b3
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
F test/fuzzdata1.txt c7929942f6820873fdd9ae6bb542651fefea40f7
F test/fuzzdata1.txt 9fceb50868e0b798160e83742bd7e44e457176a0
F test/fuzzdata2.txt ba9b4467d7ec46cc85d32c0d031540cd727ae6ad
F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
@ -755,7 +757,7 @@ F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577
F test/journal2.test ae06f566c28552c313ded3fee79a6c69e6d049b1
F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307
F test/jrnlmode.test 9ee3a78f53d52cca737db69293d15dc41c0cbd36
F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
@ -778,7 +780,7 @@ F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035
F test/lookaside.test 93f07bac140c5bb1d49f3892d2684decafdc7af2
F test/main.test 16131264ea0c2b93b95201f0c92958e85f2ba11a
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
F test/malloc.test 96939d2d1a6f39667bbebe5bc27c6525f2ab614e
F test/malloc.test 21c213365f2cca95ab2d7dc078dc8525f96065f8
F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
F test/malloc5.test 79182b8bffd6d62f77b1a5a8ba8e6bf0e5053b8e
@ -819,6 +821,7 @@ F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2
F test/misc8.test fc2754d38892f7dac30c22db3616c2764f117d66
F test/misuse.test 3c34719944ba045cc6c188a4852ba04680728912
F test/mkfuzzdata1.tcl 5f9c33fadc64b078bb4a2c04c18b6dd3da075bec
F test/mmap1.test 1bfd611b9841eafb44f7d83c0788e146d84a33c9
F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
F test/mmap3.test c92273e16eb8d23c1d55c9815b446bb72ef0512e
@ -856,7 +859,7 @@ F test/pagerfault.test ae9ee0db5a30aecda9db8290ce3dd12e5f7bbaa1
F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6
F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
@ -879,7 +882,7 @@ F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.tcl f649253610c8b0b0d63ad85b0d2961867d4f0ac0
F test/releasetest.tcl 7ad4fd49ae50c41ec7781815bdda8a8b278781d4
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
@ -906,7 +909,7 @@ F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
F test/select1.test be62204d2bd9a5a8a149e9974cfddce893d8f686
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
F test/select4.test 48e14766d98b744b2202cca6d4679bf7ef3784c8
F test/select4.test 824342f382f16b4afe42d0887ef82b3d6abb6075
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
@ -932,7 +935,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test ca88b14a8fc8b1f3543a24e519d019585ac9c903
F test/shell1.test ce5e744870387164703bf2dee2cc9753e4a71513
F test/shell2.test 12b8bf901b0e3a8ac58cf5c0c63a0a388d4d1862
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
F test/shell4.test ddf0a99044e2245a87fc17423e3aaa1445b3243b
@ -964,8 +967,10 @@ F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 2b416dca3a155fcaa849540b2e7fc1df12896c23
F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49
F test/sqldiff1.test e5ecfe95b3a2ff6380f0db6ea8bec246b675e122
F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68
F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de
F test/stat.test 8de91498c99f5298b303f70f1d1f3b9557af91bf
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
F test/subquery2.test 438f8a7da1457277b22e4176510f7659b286995f
@ -982,7 +987,7 @@ F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
F test/tester.tcl ed77454e6c7b40eb501db7e79d1c6fbfd3eebbff
F test/tester.tcl 51211254f2ee2340d3e4fa0a83bd5381b9e1a227
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@ -1270,7 +1275,7 @@ F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
F tool/fuzzershell.c a13c48cb83bbea8966442d777e14595b87023701
F tool/fuzzershell.c e8be9a8bd8e0e7814592c5e3e38de99ad7beee83
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
@ -1284,7 +1289,7 @@ F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl 94f196c9961e0ca3513e29f57125a3197808be2d
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl 69bae8ce4aa52d2ff82d4a8a856bf283ec035b2e
F tool/mksqlite3c.tcl eea6aa21d76f47c7932af2baa9291517ec72f5ce
F tool/mksqlite3c.tcl ddd1ab091b2b42cf5cef07db5003b4c88272754e
F tool/mksqlite3h.tcl 44730d586c9031638cdd2eb443b801c0d2dbd9f8
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
F tool/mkvsix.tcl 3b58b9398f91c7dbf18d49eb87cefeee9efdbce1
@ -1301,14 +1306,14 @@ F tool/showstat4.c 9515faa8ec176599d4a8288293ba8ec61f7b728a
F tool/showwal.c 85cb36d4fe3e93e2fbd63e786e0d1ce42d0c4fad
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b
F tool/spaceanal.tcl d5a09620c66a6c144576cb9d2bdfa9a6fbe362a5
F tool/spaceanal.tcl 713c587a057334de42c41ad9566f10e255d3ad27
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
F tool/sqldiff.c 393b0f5b17ef29341664563a90d40ee63a0a18f7
F tool/sqldiff.c 0748c0daed08f31e5a8eab6de98ca57500e61ecf
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f
@ -1319,7 +1324,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 3922276135a7825d0ede8d9c757e9cfe492f803a
R 80fc221c857ceeffac4c1ca1e8e3c4c0
P aa34bf666c384cf32a8d8166ab6d9afbca26a256 59e3e9e764440b7feaafadff74f422535d21bca2
R 7fb50d1391be18153fa78235920902bf
U dan
Z ea2587087e805cefd8e74a1d1357bdd2
Z 5ed330406879741f67800dc0f7082030

View File

@ -1 +1 @@
aa34bf666c384cf32a8d8166ab6d9afbca26a256
b5f0e8c5b4bc018d672617ffd342d12b228548b9

View File

@ -126,6 +126,7 @@ static void renameParentFunc(
n = sqlite3GetToken(z, &token);
}while( token==TK_SPACE );
if( token==TK_ILLEGAL ) break;
zParent = sqlite3DbStrNDup(db, (const char *)z, n);
if( zParent==0 ) break;
sqlite3Dequote(zParent);

View File

@ -341,7 +341,7 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){
** bits to act as the reference */
pBitvec = sqlite3BitvecCreate( sz );
pV = sqlite3MallocZero( (sz+7)/8 + 1 );
pTmpSpace = sqlite3_malloc(BITVEC_SZ);
pTmpSpace = sqlite3_malloc64(BITVEC_SZ);
if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
/* NULL pBitvec tests */

View File

@ -2429,7 +2429,7 @@ int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
((pageSize-1)&pageSize)==0 ){
assert( (pageSize & 7)==0 );
assert( !pBt->pPage1 && !pBt->pCursor );
assert( !pBt->pCursor );
pBt->pageSize = (u32)pageSize;
freeTempSpace(pBt);
}
@ -8537,12 +8537,12 @@ static void checkList(
**
** The heap property is this: Every node is less than or equal to both
** of its daughter nodes. A consequence of the heap property is that the
** root node aHeap[1] is always the minimum value current in the heap.
** root node aHeap[1] is always the minimum value currently in the heap.
**
** The btreeHeapInsert() routine inserts an unsigned 32-bit number onto
** the heap, preserving the heap property. The btreeHeapPull() routine
** removes the root element from the heap (the minimum value in the heap)
** and then move other nodes around as necessary to preserve the heap
** and then moves other nodes around as necessary to preserve the heap
** property.
**
** This heap is used for cell overlap and coverage testing. Each u32
@ -8899,8 +8899,7 @@ char *sqlite3BtreeIntegrityCheck(
}
i = PENDING_BYTE_PAGE(pBt);
if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
sCheck.errMsg.useMalloc = 2;
sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
/* Check the integrity of the freelist
*/

View File

@ -4024,8 +4024,7 @@ void sqlite3UniqueConstraint(
StrAccum errMsg;
Table *pTab = pIdx->pTable;
sqlite3StrAccumInit(&errMsg, 0, 0, 200);
errMsg.db = pParse->db;
sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200);
for(j=0; j<pIdx->nKeyCol; j++){
char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2);

View File

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

View File

@ -18,11 +18,9 @@
** for an example implementation.
*/
#ifndef SQLITE_AMALGAMATION
# include "sqliteInt.h"
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h" /* Requires access to internal data structures */
#if (defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)) \
&& !defined(SQLITE_OMIT_VIRTUALTABLE)
/*
** Page paths:
@ -124,6 +122,7 @@ struct StatCursor {
struct StatTable {
sqlite3_vtab base;
sqlite3 *db;
int iDb; /* Index of database to analyze */
};
#ifndef get2byte
@ -140,15 +139,34 @@ static int statConnect(
sqlite3_vtab **ppVtab,
char **pzErr
){
StatTable *pTab;
StatTable *pTab = 0;
int rc = SQLITE_OK;
int iDb;
pTab = (StatTable *)sqlite3_malloc(sizeof(StatTable));
memset(pTab, 0, sizeof(StatTable));
pTab->db = db;
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);
if( rc==SQLITE_OK ){
pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable));
if( pTab==0 ) rc = SQLITE_NOMEM;
}
sqlite3_declare_vtab(db, VTAB_SCHEMA);
*ppVtab = &pTab->base;
return SQLITE_OK;
assert( rc==SQLITE_OK || pTab==0 );
if( rc==SQLITE_OK ){
memset(pTab, 0, sizeof(StatTable));
pTab->db = db;
pTab->iDb = iDb;
}
*ppVtab = (sqlite3_vtab*)pTab;
return rc;
}
/*
@ -195,33 +213,45 @@ static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
StatCursor *pCsr;
int rc;
pCsr = (StatCursor *)sqlite3_malloc(sizeof(StatCursor));
memset(pCsr, 0, sizeof(StatCursor));
pCsr->base.pVtab = pVTab;
pCsr = (StatCursor *)sqlite3_malloc64(sizeof(StatCursor));
if( pCsr==0 ){
rc = SQLITE_NOMEM;
}else{
char *zSql;
memset(pCsr, 0, sizeof(StatCursor));
pCsr->base.pVtab = pVTab;
rc = sqlite3_prepare_v2(pTab->db,
"SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
" UNION ALL "
"SELECT name, rootpage, type FROM sqlite_master WHERE rootpage!=0"
" ORDER BY name", -1,
&pCsr->pStmt, 0
);
if( rc!=SQLITE_OK ){
sqlite3_free(pCsr);
return rc;
zSql = sqlite3_mprintf(
"SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
" UNION ALL "
"SELECT name, rootpage, type"
" FROM \"%w\".sqlite_master WHERE rootpage!=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 ){
sqlite3_free(pCsr);
pCsr = 0;
}
}
*ppCursor = (sqlite3_vtab_cursor *)pCsr;
return SQLITE_OK;
return rc;
}
static void statClearPage(StatPage *p){
int i;
for(i=0; i<p->nCell; i++){
sqlite3_free(p->aCell[i].aOvfl);
if( p->aCell ){
for(i=0; i<p->nCell; i++){
sqlite3_free(p->aCell[i].aOvfl);
}
sqlite3_free(p->aCell);
}
sqlite3PagerUnref(p->pPg);
sqlite3_free(p->aCell);
sqlite3_free(p->zPath);
memset(p, 0, sizeof(StatPage));
}
@ -306,7 +336,8 @@ static int statDecodePage(Btree *pBt, StatPage *p){
sqlite3BtreeEnter(pBt);
nUsable = szPage - sqlite3BtreeGetReserveNoMutex(pBt);
sqlite3BtreeLeave(pBt);
p->aCell = sqlite3_malloc((p->nCell+1) * sizeof(StatCell));
p->aCell = sqlite3_malloc64((p->nCell+1) * sizeof(StatCell));
if( p->aCell==0 ) return SQLITE_NOMEM;
memset(p->aCell, 0, (p->nCell+1) * sizeof(StatCell));
for(i=0; i<p->nCell; i++){
@ -338,7 +369,8 @@ static int statDecodePage(Btree *pBt, StatPage *p){
int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4);
pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4);
pCell->nOvfl = nOvfl;
pCell->aOvfl = sqlite3_malloc(sizeof(u32)*nOvfl);
pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl);
if( pCell->aOvfl==0 ) return SQLITE_NOMEM;
pCell->aOvfl[0] = sqlite3Get4byte(&aData[iOff+nLocal]);
for(j=1; j<nOvfl; j++){
int rc;
@ -366,7 +398,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
*/
static void statSizeAndOffset(StatCursor *pCsr){
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);
sqlite3_file *fd;
sqlite3_int64 x[2];
@ -380,7 +412,7 @@ static void statSizeAndOffset(StatCursor *pCsr){
*/
fd = sqlite3PagerFile(pPager);
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->szPage = (int)x[1];
}
@ -392,9 +424,10 @@ static void statSizeAndOffset(StatCursor *pCsr){
static int statNext(sqlite3_vtab_cursor *pCursor){
int rc;
int nPayload;
char *z;
StatCursor *pCsr = (StatCursor *)pCursor;
StatTable *pTab = (StatTable *)pCursor->pVtab;
Btree *pBt = pTab->db->aDb[0].pBt;
Btree *pBt = pTab->db->aDb[pTab->iDb].pBt;
Pager *pPager = sqlite3BtreePager(pBt);
sqlite3_free(pCsr->zPath);
@ -414,8 +447,9 @@ statNextRestart:
rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg);
pCsr->aPage[0].iPgno = iRoot;
pCsr->aPage[0].iCell = 0;
pCsr->aPage[0].zPath = sqlite3_mprintf("/");
pCsr->aPage[0].zPath = z = sqlite3_mprintf("/");
pCsr->iPage = 0;
if( z==0 ) rc = SQLITE_NOMEM;
}else{
pCsr->isEof = 1;
return sqlite3_reset(pCsr->pStmt);
@ -438,7 +472,7 @@ statNextRestart:
pCsr->zPagetype = "overflow";
pCsr->nCell = 0;
pCsr->nMxPayload = 0;
pCsr->zPath = sqlite3_mprintf(
pCsr->zPath = z = sqlite3_mprintf(
"%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl
);
if( pCell->iOvfl<pCell->nOvfl-1 ){
@ -450,7 +484,7 @@ statNextRestart:
}
pCell->iOvfl++;
statSizeAndOffset(pCsr);
return SQLITE_OK;
return z==0 ? SQLITE_NOMEM : SQLITE_OK;
}
if( p->iRightChildPg ) break;
p->iCell++;
@ -472,8 +506,9 @@ statNextRestart:
}
rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg);
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++;
if( z==0 ) rc = SQLITE_NOMEM;
}
@ -486,31 +521,34 @@ statNextRestart:
pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0);
pCsr->iPageno = p->iPgno;
statDecodePage(pBt, p);
statSizeAndOffset(pCsr);
rc = statDecodePage(pBt, p);
if( rc==SQLITE_OK ){
statSizeAndOffset(pCsr);
switch( p->flags ){
case 0x05: /* table internal */
case 0x02: /* index internal */
pCsr->zPagetype = "internal";
break;
case 0x0D: /* table leaf */
case 0x0A: /* index leaf */
pCsr->zPagetype = "leaf";
break;
default:
pCsr->zPagetype = "corrupted";
break;
switch( p->flags ){
case 0x05: /* table internal */
case 0x02: /* index internal */
pCsr->zPagetype = "internal";
break;
case 0x0D: /* table leaf */
case 0x0A: /* index leaf */
pCsr->zPagetype = "leaf";
break;
default:
pCsr->zPagetype = "corrupted";
break;
}
pCsr->nCell = p->nCell;
pCsr->nUnused = p->nUnused;
pCsr->nMxPayload = p->nMxPayload;
pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath);
if( z==0 ) rc = SQLITE_NOMEM;
nPayload = 0;
for(i=0; i<p->nCell; i++){
nPayload += p->aCell[i].nLocal;
}
pCsr->nPayload = nPayload;
}
pCsr->nCell = p->nCell;
pCsr->nUnused = p->nUnused;
pCsr->nMxPayload = p->nMxPayload;
pCsr->zPath = sqlite3_mprintf("%s", p->zPath);
nPayload = 0;
for(i=0; i<p->nCell; i++){
nPayload += p->aCell[i].nLocal;
}
pCsr->nPayload = nPayload;
}
return rc;
@ -540,7 +578,7 @@ static int statColumn(
StatCursor *pCsr = (StatCursor *)pCursor;
switch( i ){
case 0: /* name */
sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_STATIC);
sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_TRANSIENT);
break;
case 1: /* path */
sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT);
@ -566,7 +604,8 @@ static int statColumn(
case 8: /* pgoffset */
sqlite3_result_int64(ctx, pCsr->iOffset);
break;
case 9: /* pgsize */
default: /* pgsize */
assert( i==9 );
sqlite3_result_int(ctx, pCsr->szPage);
break;
}
@ -579,7 +618,10 @@ static int statRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
return SQLITE_OK;
}
int sqlite3_dbstat_register(sqlite3 *db){
/*
** Invoke this routine to register the "dbstat" virtual table module
*/
int sqlite3DbstatRegister(sqlite3 *db){
static sqlite3_module dbstat_module = {
0, /* iVersion */
statConnect, /* xCreate */
@ -602,46 +644,8 @@ int sqlite3_dbstat_register(sqlite3 *db){
0, /* xFindMethod */
0, /* xRename */
};
sqlite3_create_module(db, "dbstat", &dbstat_module, 0);
return SQLITE_OK;
return sqlite3_create_module(db, "dbstat", &dbstat_module, 0);
}
#endif
#if defined(SQLITE_TEST) || TCLSH==2
#include <tcl.h>
static int test_dbstat(
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;
sqlite3_dbstat_register(db);
}
return TCL_OK;
#endif
}
int SqlitetestStat_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(interp, "register_dbstat_vtab", test_dbstat, 0, 0);
return TCL_OK;
}
#endif /* if defined(SQLITE_TEST) || TCLSH==2 */
#elif defined(SQLITE_ENABLE_DBSTAT_VTAB)
int sqlite3DbstatRegister(sqlite3 *db){ return SQLITE_OK; }
#endif /* SQLITE_ENABLE_DBSTAT_VTAB */

View File

@ -1252,7 +1252,7 @@ u32 sqlite3ExprListFlags(const ExprList *pList){
if( pList ){
for(i=0; i<pList->nExpr; i++){
Expr *pExpr = pList->a[i].pExpr;
if( ALWAYS(pExpr) ) m |= pList->a[i].pExpr->flags;
if( ALWAYS(pExpr) ) m |= pExpr->flags;
}
}
return m;

View File

@ -232,13 +232,13 @@ static void printfFunc(
StrAccum str;
const char *zFormat;
int n;
sqlite3 *db = sqlite3_context_db_handle(context);
if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){
x.nArg = argc-1;
x.nUsed = 0;
x.apArg = argv+1;
sqlite3StrAccumInit(&str, 0, 0, SQLITE_MAX_LENGTH);
str.db = sqlite3_context_db_handle(context);
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x);
n = str.nChar;
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
@ -388,7 +388,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
#endif
/*
** Allocate nByte bytes of space using sqlite3_malloc(). If the
** Allocate nByte bytes of space using sqlite3Malloc(). If the
** allocation fails, call sqlite3_result_error_nomem() to notify
** the database handle that malloc() has failed and return NULL.
** If nByte is larger than the maximum string or blob length, then
@ -1057,7 +1057,7 @@ static void charFunc(
){
unsigned char *z, *zOut;
int i;
zOut = z = sqlite3_malloc( argc*4+1 );
zOut = z = sqlite3_malloc64( argc*4+1 );
if( z==0 ){
sqlite3_result_error_nomem(context);
return;
@ -1205,7 +1205,7 @@ static void replaceFunc(
return;
}
zOld = zOut;
zOut = sqlite3_realloc(zOut, (int)nOut);
zOut = sqlite3_realloc64(zOut, (int)nOut);
if( zOut==0 ){
sqlite3_result_error_nomem(context);
sqlite3_free(zOld);
@ -1567,8 +1567,7 @@ static void groupConcatStep(
if( pAccum ){
sqlite3 *db = sqlite3_context_db_handle(context);
int firstTerm = pAccum->useMalloc==0;
pAccum->useMalloc = 2;
int firstTerm = pAccum->mxAlloc==0;
pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
if( !firstTerm ){
if( argc==2 ){

View File

@ -430,7 +430,7 @@ static int sqlite3LoadExtension(
const char *zEntry;
char *zAltEntry = 0;
void **aHandle;
int nMsg = 300 + sqlite3Strlen30(zFile);
u64 nMsg = 300 + sqlite3Strlen30(zFile);
int ii;
/* Shared library endings to try if zFile cannot be loaded as written */
@ -473,7 +473,7 @@ static int sqlite3LoadExtension(
#endif
if( handle==0 ){
if( pzErrMsg ){
*pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
*pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
if( zErrmsg ){
sqlite3_snprintf(nMsg, zErrmsg,
"unable to open shared library [%s]", zFile);
@ -499,7 +499,7 @@ static int sqlite3LoadExtension(
if( xInit==0 && zProc==0 ){
int iFile, iEntry, c;
int ncFile = sqlite3Strlen30(zFile);
zAltEntry = sqlite3_malloc(ncFile+30);
zAltEntry = sqlite3_malloc64(ncFile+30);
if( zAltEntry==0 ){
sqlite3OsDlClose(pVfs, handle);
return SQLITE_NOMEM;
@ -521,7 +521,7 @@ static int sqlite3LoadExtension(
if( xInit==0 ){
if( pzErrMsg ){
nMsg += sqlite3Strlen30(zEntry);
*pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
*pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
if( zErrmsg ){
sqlite3_snprintf(nMsg, zErrmsg,
"no entry point [%s] in shared library [%s]", zEntry, zFile);
@ -620,7 +620,7 @@ static const sqlite3_api_routines sqlite3Apis = { 0 };
*/
typedef struct sqlite3AutoExtList sqlite3AutoExtList;
static SQLITE_WSD struct sqlite3AutoExtList {
int nExt; /* Number of entries in aExt[] */
u32 nExt; /* Number of entries in aExt[] */
void (**aExt)(void); /* Pointers to the extension init functions */
} sqlite3Autoext = { 0, 0 };
@ -653,7 +653,7 @@ int sqlite3_auto_extension(void (*xInit)(void)){
}else
#endif
{
int i;
u32 i;
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
@ -663,9 +663,9 @@ int sqlite3_auto_extension(void (*xInit)(void)){
if( wsdAutoext.aExt[i]==xInit ) break;
}
if( i==wsdAutoext.nExt ){
int nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]);
u64 nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]);
void (**aNew)(void);
aNew = sqlite3_realloc(wsdAutoext.aExt, nByte);
aNew = sqlite3_realloc64(wsdAutoext.aExt, nByte);
if( aNew==0 ){
rc = SQLITE_NOMEM;
}else{
@ -697,7 +697,7 @@ int sqlite3_cancel_auto_extension(void (*xInit)(void)){
int n = 0;
wsdAutoextInit;
sqlite3_mutex_enter(mutex);
for(i=wsdAutoext.nExt-1; i>=0; i--){
for(i=(int)wsdAutoext.nExt-1; i>=0; i--){
if( wsdAutoext.aExt[i]==xInit ){
wsdAutoext.nExt--;
wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt];
@ -735,7 +735,7 @@ void sqlite3_reset_auto_extension(void){
** If anything goes wrong, set an error in the database connection.
*/
void sqlite3AutoLoadExtensions(sqlite3 *db){
int i;
u32 i;
int go = 1;
int rc;
int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);

View File

@ -58,6 +58,18 @@ int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; }
*/
int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }
/*
** When compiling the test fixture or with debugging enabled (on Win32),
** this variable being set to non-zero will cause OSTRACE macros to emit
** extra diagnostic information.
*/
#ifdef SQLITE_HAVE_OS_TRACE
# ifndef SQLITE_DEBUG_OS_TRACE
# define SQLITE_DEBUG_OS_TRACE 0
# endif
int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
#endif
#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
/*
** If the following function pointer is not NULL and if
@ -1197,7 +1209,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
** Return a static string containing the name corresponding to the error code
** specified in the argument.
*/
#if (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) || defined(SQLITE_TEST)
#if defined(SQLITE_NEED_ERR_NAME)
const char *sqlite3ErrName(int rc){
const char *zName = 0;
int i, origRc = rc;
@ -2422,14 +2434,14 @@ int sqlite3ParseUri(
int eState; /* Parser state when parsing URI */
int iIn; /* Input character index */
int iOut = 0; /* Output character index */
int nByte = nUri+2; /* Bytes of space to allocate */
u64 nByte = nUri+2; /* Bytes of space to allocate */
/* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
** method that there may be extra parameters following the file-name. */
flags |= SQLITE_OPEN_URI;
for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
zFile = sqlite3_malloc(nByte);
zFile = sqlite3_malloc64(nByte);
if( !zFile ) return SQLITE_NOMEM;
iIn = 5;
@ -2595,7 +2607,7 @@ int sqlite3ParseUri(
}
}else{
zFile = sqlite3_malloc(nUri+2);
zFile = sqlite3_malloc64(nUri+2);
if( !zFile ) return SQLITE_NOMEM;
memcpy(zFile, zUri, nUri);
zFile[nUri] = '\0';
@ -2873,6 +2885,12 @@ static int openDatabase(
}
#endif
#ifdef SQLITE_ENABLE_DBSTAT_VTAB
if( !db->mallocFailed && rc==SQLITE_OK){
rc = sqlite3DbstatRegister(db);
}
#endif
/* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking
** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking
** mode. Doing nothing at all also makes NORMAL the default.

View File

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

View File

@ -29,16 +29,6 @@
# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
#endif
#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
# ifndef SQLITE_DEBUG_OS_TRACE
# define SQLITE_DEBUG_OS_TRACE 0
# endif
int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
#else
# define OSTRACE(X)
#endif
/*
** Macros for performance tracing. Normally turned off. Only works
** on i486 hardware.

View File

@ -641,7 +641,7 @@ static int unixMutexHeld(void) {
#endif
#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
#ifdef SQLITE_HAVE_OS_TRACE
/*
** Helper function for printing out trace information from debugging
** binaries. This returns the string representation of the supplied
@ -904,7 +904,7 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
assert( zAbsoluteName[0]=='/' );
n = (int)strlen(zAbsoluteName);
pNew = sqlite3_malloc( sizeof(*pNew) + (n+1) );
pNew = sqlite3_malloc64( sizeof(*pNew) + (n+1) );
if( pNew==0 ) return 0;
pNew->zCanonicalName = (char*)&pNew[1];
memcpy(pNew->zCanonicalName, zAbsoluteName, n+1);
@ -1308,7 +1308,7 @@ static int findInodeInfo(
pInode = pInode->pNext;
}
if( pInode==0 ){
pInode = sqlite3_malloc( sizeof(*pInode) );
pInode = sqlite3_malloc64( sizeof(*pInode) );
if( pInode==0 ){
return SQLITE_NOMEM;
}
@ -3829,7 +3829,7 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
return SQLITE_OK;
}
case SQLITE_FCNTL_TEMPFILENAME: {
char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
char *zTFile = sqlite3_malloc64( pFile->pVfs->mxPathname );
if( zTFile ){
unixGetTempname(pFile->pVfs->mxPathname, zTFile);
*(char**)pArg = zTFile;
@ -4270,7 +4270,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
int nShmFilename; /* Size of the SHM filename in bytes */
/* Allocate space for the new unixShm object. */
p = sqlite3_malloc( sizeof(*p) );
p = sqlite3_malloc64( sizeof(*p) );
if( p==0 ) return SQLITE_NOMEM;
memset(p, 0, sizeof(*p));
assert( pDbFd->pShm==0 );
@ -4301,7 +4301,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
#else
nShmFilename = 6 + (int)strlen(zBasePath);
#endif
pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nShmFilename );
pShmNode = sqlite3_malloc64( sizeof(*pShmNode) + nShmFilename );
if( pShmNode==0 ){
rc = SQLITE_NOMEM;
goto shm_open_err;
@ -4511,7 +4511,7 @@ static int unixShmMap(
goto shmpage_out;
}
}else{
pMem = sqlite3_malloc(szRegion);
pMem = sqlite3_malloc64(szRegion);
if( pMem==0 ){
rc = SQLITE_NOMEM;
goto shmpage_out;
@ -5348,7 +5348,7 @@ static int fillInUnixFile(
** the afpLockingContext.
*/
afpLockingContext *pCtx;
pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
pNew->lockingContext = pCtx = sqlite3_malloc64( sizeof(*pCtx) );
if( pCtx==0 ){
rc = SQLITE_NOMEM;
}else{
@ -5378,7 +5378,7 @@ static int fillInUnixFile(
int nFilename;
assert( zFilename!=0 );
nFilename = (int)strlen(zFilename) + 6;
zLockFile = (char *)sqlite3_malloc(nFilename);
zLockFile = (char *)sqlite3_malloc64(nFilename);
if( zLockFile==0 ){
rc = SQLITE_NOMEM;
}else{
@ -5755,7 +5755,7 @@ static int unixOpen(
if( pUnused ){
fd = pUnused->fd;
}else{
pUnused = sqlite3_malloc(sizeof(*pUnused));
pUnused = sqlite3_malloc64(sizeof(*pUnused));
if( !pUnused ){
return SQLITE_NOMEM;
}
@ -6135,7 +6135,7 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
*/
memset(zBuf, 0, nBuf);
randomnessPid = osGetpid(0);
#if !defined(SQLITE_TEST)
#if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS)
{
int fd, got;
fd = robust_open("/dev/urandom", O_RDONLY, 0);
@ -6547,7 +6547,7 @@ static int proxyCreateUnixFile(
if( pUnused ){
fd = pUnused->fd;
}else{
pUnused = sqlite3_malloc(sizeof(*pUnused));
pUnused = sqlite3_malloc64(sizeof(*pUnused));
if( !pUnused ){
return SQLITE_NOMEM;
}
@ -6580,7 +6580,7 @@ static int proxyCreateUnixFile(
}
}
pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew));
pNew = (unixFile *)sqlite3_malloc64(sizeof(*pNew));
if( pNew==NULL ){
rc = SQLITE_NOMEM;
goto end_create_proxy;
@ -7042,7 +7042,7 @@ static int proxyReleaseConch(unixFile *pFile){
/*
** Given the name of a database file, compute the name of its conch file.
** Store the conch filename in memory obtained from sqlite3_malloc().
** Store the conch filename in memory obtained from sqlite3_malloc64().
** Make *pConchPath point to the new name. Return SQLITE_OK on success
** or SQLITE_NOMEM if unable to obtain memory.
**
@ -7058,7 +7058,7 @@ static int proxyCreateConchPathname(char *dbPath, char **pConchPath){
/* Allocate space for the conch filename and initialize the name to
** the name of the original database file. */
*pConchPath = conchPath = (char *)sqlite3_malloc(len + 8);
*pConchPath = conchPath = (char *)sqlite3_malloc64(len + 8);
if( conchPath==0 ){
return SQLITE_NOMEM;
}
@ -7174,7 +7174,7 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h,
(lockPath ? lockPath : ":auto:"), osGetpid(0)));
pCtx = sqlite3_malloc( sizeof(*pCtx) );
pCtx = sqlite3_malloc64( sizeof(*pCtx) );
if( pCtx==0 ){
return SQLITE_NOMEM;
}

View File

@ -2757,7 +2757,7 @@ static int winSync(sqlite3_file *id, int flags){
BOOL rc;
#endif
#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
(defined(SQLITE_TEST) && defined(SQLITE_DEBUG))
defined(SQLITE_HAVE_OS_TRACE)
/*
** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
** OSTRACE() macros.
@ -3434,7 +3434,7 @@ struct winShmNode {
int nRef; /* Number of winShm objects pointing to this */
winShm *pFirst; /* All winShm objects pointing to this */
winShmNode *pNext; /* Next in list of all winShmNode objects */
#ifdef SQLITE_DEBUG
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
u8 nextShmId; /* Next available winShm.id value */
#endif
};
@ -3465,7 +3465,7 @@ struct winShm {
u8 hasMutex; /* True if holding the winShmNode mutex */
u16 sharedMask; /* Mask of shared locks held */
u16 exclMask; /* Mask of exclusive locks held */
#ifdef SQLITE_DEBUG
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
u8 id; /* Id of this connection with its winShmNode */
#endif
};
@ -3656,7 +3656,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
/* Make the new connection a child of the winShmNode */
p->pShmNode = pShmNode;
#ifdef SQLITE_DEBUG
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
p->id = pShmNode->nextShmId++;
#endif
pShmNode->nRef++;
@ -3925,7 +3925,7 @@ static int winShmMap(
}
/* Map the requested memory region into this processes address space. */
apNew = (struct ShmRegion *)sqlite3_realloc(
apNew = (struct ShmRegion *)sqlite3_realloc64(
pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
);
if( !apNew ){
@ -5372,7 +5372,7 @@ static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
int n = 0;
UNUSED_PARAMETER(pVfs);
#if defined(SQLITE_TEST)
#if defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS)
n = nBuf;
memset(zBuf, 0, nBuf);
#else
@ -5406,23 +5406,23 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
memcpy(&zBuf[n], &i, sizeof(i));
n += sizeof(i);
}
#endif
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
if( sizeof(UUID)<=nBuf-n ){
UUID id;
memset(&id, 0, sizeof(UUID));
osUuidCreate(&id);
memcpy(zBuf, &id, sizeof(UUID));
memcpy(&zBuf[n], &id, sizeof(UUID));
n += sizeof(UUID);
}
if( sizeof(UUID)<=nBuf-n ){
UUID id;
memset(&id, 0, sizeof(UUID));
osUuidCreateSequential(&id);
memcpy(zBuf, &id, sizeof(UUID));
memcpy(&zBuf[n], &id, sizeof(UUID));
n += sizeof(UUID);
}
#endif
#endif /* defined(SQLITE_TEST) || defined(SQLITE_ZERO_PRNG_SEED) */
return n;
}

View File

@ -7010,6 +7010,8 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
}
assert( state==pPager->eState );
}
}else if( eMode==PAGER_JOURNALMODE_OFF ){
sqlite3OsClose(pPager->jfd);
}
}

View File

@ -138,6 +138,7 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
** Set the StrAccum object to an error mode.
*/
static void setStrAccumError(StrAccum *p, u8 eError){
assert( eError==STRACCUM_NOMEM || eError==STRACCUM_TOOBIG );
p->accError = eError;
p->nAlloc = 0;
}
@ -252,7 +253,6 @@ void sqlite3VXPrintf(
}
}while( !done && (c=(*++fmt))!=0 );
/* Get the field width */
width = 0;
if( c=='*' ){
if( bArgList ){
width = (int)getIntArg(pArgList);
@ -276,7 +276,6 @@ void sqlite3VXPrintf(
/* Get the precision */
if( c=='.' ){
precision = 0;
c = *++fmt;
if( c=='*' ){
if( bArgList ){
@ -755,7 +754,7 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
testcase(p->accError==STRACCUM_NOMEM);
return 0;
}
if( !p->useMalloc ){
if( p->mxAlloc==0 ){
N = p->nAlloc - p->nChar - 1;
setStrAccumError(p, STRACCUM_TOOBIG);
return N;
@ -775,10 +774,10 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
}else{
p->nAlloc = (int)szNew;
}
if( p->useMalloc==1 ){
if( p->db ){
zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
}else{
zNew = sqlite3_realloc(zOld, p->nAlloc);
zNew = sqlite3_realloc64(zOld, p->nAlloc);
}
if( zNew ){
assert( p->zText!=0 || p->nChar==0 );
@ -855,12 +854,8 @@ void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){
char *sqlite3StrAccumFinish(StrAccum *p){
if( p->zText ){
p->zText[p->nChar] = 0;
if( p->useMalloc && p->zText==p->zBase ){
if( p->useMalloc==1 ){
p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
}else{
p->zText = sqlite3_malloc(p->nChar+1);
}
if( p->mxAlloc>0 && p->zText==p->zBase ){
p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
if( p->zText ){
memcpy(p->zText, p->zBase, p->nChar+1);
}else{
@ -876,25 +871,31 @@ char *sqlite3StrAccumFinish(StrAccum *p){
*/
void sqlite3StrAccumReset(StrAccum *p){
if( p->zText!=p->zBase ){
if( p->useMalloc==1 ){
sqlite3DbFree(p->db, p->zText);
}else{
sqlite3_free(p->zText);
}
sqlite3DbFree(p->db, p->zText);
}
p->zText = 0;
}
/*
** Initialize a string accumulator
** Initialize a string accumulator.
**
** p: The accumulator to be initialized.
** db: Pointer to a database connection. May be NULL. Lookaside
** memory is used if not NULL. db->mallocFailed is set appropriately
** when not NULL.
** zBase: An initial buffer. May be NULL in which case the initial buffer
** is malloced.
** n: Size of zBase in bytes. If total space requirements never exceed
** n then no memory allocations ever occur.
** mx: Maximum number of bytes to accumulate. If mx==0 then no memory
** allocations will ever occur.
*/
void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){
void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){
p->zText = p->zBase = zBase;
p->db = 0;
p->db = db;
p->nChar = 0;
p->nAlloc = n;
p->mxAlloc = mx;
p->useMalloc = 1;
p->accError = 0;
}
@ -907,9 +908,8 @@ char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
char zBase[SQLITE_PRINT_BUF_SIZE];
StrAccum acc;
assert( db!=0 );
sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase),
db->aLimit[SQLITE_LIMIT_LENGTH]);
acc.db = db;
sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
if( acc.accError==STRACCUM_NOMEM ){
@ -967,8 +967,7 @@ char *sqlite3_vmprintf(const char *zFormat, va_list ap){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
acc.useMalloc = 2;
sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
return z;
@ -1013,8 +1012,7 @@ char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){
return zBuf;
}
#endif
sqlite3StrAccumInit(&acc, zBuf, n, 0);
acc.useMalloc = 0;
sqlite3StrAccumInit(&acc, 0, zBuf, n, 0);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
return sqlite3StrAccumFinish(&acc);
}
@ -1040,8 +1038,7 @@ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
StrAccum acc; /* String accumulator */
char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
acc.useMalloc = 0;
sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
sqlite3StrAccumFinish(&acc));
@ -1059,7 +1056,7 @@ void sqlite3_log(int iErrCode, const char *zFormat, ...){
}
}
#if defined(SQLITE_DEBUG)
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
/*
** A version of printf() that understands %lld. Used for debugging.
** The printf() built into some versions of windows does not understand %lld
@ -1069,8 +1066,7 @@ void sqlite3DebugPrintf(const char *zFormat, ...){
va_list ap;
StrAccum acc;
char zBuf[500];
sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
acc.useMalloc = 0;
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
va_start(ap,zFormat);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
va_end(ap);
@ -1097,7 +1093,7 @@ void sqlite3DebugPrintf(const char *zFormat, ...){
** is not the last item in the tree. */
TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
if( p==0 ){
p = sqlite3_malloc( sizeof(*p) );
p = sqlite3_malloc64( sizeof(*p) );
if( p==0 ) return 0;
memset(p, 0, sizeof(*p));
}else{
@ -1120,8 +1116,7 @@ void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
int i;
StrAccum acc;
char zBuf[500];
sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
acc.useMalloc = 0;
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
if( p ){
for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4);

View File

@ -99,7 +99,6 @@ static void resolveAlias(
assert( iCol>=0 && iCol<pEList->nExpr );
pOrig = pEList->a[iCol].pExpr;
assert( pOrig!=0 );
assert( (pOrig->flags & EP_Resolved)!=0 || zType[0]==0 );
db = pParse->db;
pDup = sqlite3ExprDup(db, pOrig, 0);
if( pDup==0 ) return;

View File

@ -2603,7 +2603,7 @@ static int generateOutputSubroutine(
*/
case SRT_Set: {
int r1;
assert( pIn->nSdst==1 );
assert( pIn->nSdst==1 || pParse->nErr>0 );
pDest->affSdst =
sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst);
r1 = sqlite3GetTempReg(pParse);
@ -5539,8 +5539,7 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
struct SrcList_item *pItem = &p->pSrc->a[i];
StrAccum x;
char zLine[100];
sqlite3StrAccumInit(&x, zLine, sizeof(zLine), 0);
x.useMalloc = 0;
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor);
if( pItem->zDatabase ){
sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName);

View File

@ -990,7 +990,16 @@ static int shell_callback(
case MODE_Insert: {
p->cnt++;
if( azArg==0 ) break;
fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable);
fprintf(p->out,"INSERT INTO %s",p->zDestTable);
if( p->showHeader ){
fprintf(p->out,"(");
for(i=0; i<nArg; i++){
char *zSep = i>0 ? ",": "";
fprintf(p->out, "%s%s", zSep, azCol[i]);
}
fprintf(p->out,")");
}
fprintf(p->out," VALUES(");
for(i=0; i<nArg; i++){
char *zSep = i>0 ? ",": "";
if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
@ -1191,7 +1200,7 @@ static char *save_err_msg(
sqlite3 *db /* Database to query */
){
int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
char *zErrMsg = sqlite3_malloc(nErrMsg);
char *zErrMsg = sqlite3_malloc64(nErrMsg);
if( zErrMsg ){
memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
}
@ -1428,8 +1437,8 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
/* Grow the p->aiIndent array as required */
if( iOp>=nAlloc ){
nAlloc += 100;
p->aiIndent = (int*)sqlite3_realloc(p->aiIndent, nAlloc*sizeof(int));
abYield = (int*)sqlite3_realloc(abYield, nAlloc*sizeof(int));
p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
}
abYield[iOp] = str_in_array(zOp, azYield);
p->aiIndent[iOp] = 0;
@ -1546,7 +1555,7 @@ static int shell_exec(
if( xCallback ){
/* allocate space for col name ptr, value ptr, and type */
int nCol = sqlite3_column_count(pStmt);
void *pData = sqlite3_malloc(3*nCol*sizeof(const char*) + 1);
void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
if( !pData ){
rc = SQLITE_NOMEM;
}else{
@ -1772,6 +1781,7 @@ static int run_schema_dump_query(
static char zHelp[] =
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
".bail on|off Stop after hitting an error. Default OFF\n"
".binary on|off Turn binary output on or off. Default OFF\n"
".clone NEWDB Clone data into NEWDB from the existing database\n"
".databases List names and files of attached databases\n"
".dbinfo ?DB? Show status information about the database\n"
@ -1793,6 +1803,7 @@ static char zHelp[] =
#ifdef SQLITE_ENABLE_IOTRACE
".iotrace FILE Enable I/O diagnostic logging to FILE\n"
#endif
".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n"
#ifndef SQLITE_OMIT_LOAD_EXTENSION
".load FILE ?ENTRY? Load an extension library\n"
#endif
@ -1862,7 +1873,7 @@ static void readfileFunc(
fseek(in, 0, SEEK_END);
nIn = ftell(in);
rewind(in);
pBuf = sqlite3_malloc( nIn );
pBuf = sqlite3_malloc64( nIn );
if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);
}else{
@ -1933,12 +1944,18 @@ static void open_db(ShellState *p, int keepAlive){
/*
** Do C-language style dequoting.
**
** \a -> alarm
** \b -> backspace
** \t -> tab
** \n -> newline
** \v -> vertical tab
** \f -> form feed
** \r -> carriage return
** \s -> space
** \" -> "
** \NNN -> ascii character NNN in octal
** \' -> '
** \\ -> backslash
** \NNN -> ascii character NNN in octal
*/
static void resolve_backslashes(char *z){
int i, j;
@ -1947,12 +1964,24 @@ static void resolve_backslashes(char *z){
for(i=j=0; (c = z[i])!=0; i++, j++){
if( c=='\\' && z[i+1]!=0 ){
c = z[++i];
if( c=='n' ){
c = '\n';
if( c=='a' ){
c = '\a';
}else if( c=='b' ){
c = '\b';
}else if( c=='t' ){
c = '\t';
}else if( c=='n' ){
c = '\n';
}else if( c=='v' ){
c = '\v';
}else if( c=='f' ){
c = '\f';
}else if( c=='r' ){
c = '\r';
}else if( c=='"' ){
c = '"';
}else if( c=='\'' ){
c = '\'';
}else if( c=='\\' ){
c = '\\';
}else if( c>='0' && c<='7' ){
@ -2122,7 +2151,7 @@ struct ImportCtx {
static void import_append_char(ImportCtx *p, int c){
if( p->n+1>=p->nAlloc ){
p->nAlloc += p->nAlloc + 100;
p->z = sqlite3_realloc(p->z, p->nAlloc);
p->z = sqlite3_realloc64(p->z, p->nAlloc);
if( p->z==0 ){
fprintf(stderr, "out of memory\n");
exit(1);
@ -2136,7 +2165,7 @@ static void import_append_char(ImportCtx *p, int c){
**
** + Input comes from p->in.
** + Store results in p->z of length p->n. Space to hold p->z comes
** from sqlite3_malloc().
** from sqlite3_malloc64().
** + Use p->cSep as the column separator. The default is ",".
** + Use p->rSep as the row separator. The default is "\n".
** + Keep track of the line number in p->nLine.
@ -2210,7 +2239,7 @@ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
**
** + Input comes from p->in.
** + Store results in p->z of length p->n. Space to hold p->z comes
** from sqlite3_malloc().
** from sqlite3_malloc64().
** + Use p->cSep as the column separator. The default is "\x1F".
** + Use p->rSep as the row separator. The default is "\x1E".
** + Keep track of the row number in p->nLine.
@ -2270,7 +2299,7 @@ static void tryToCloneData(
goto end_data_xfer;
}
n = sqlite3_column_count(pQuery);
zInsert = sqlite3_malloc(200 + nTable + n*3);
zInsert = sqlite3_malloc64(200 + nTable + n*3);
if( zInsert==0 ){
fprintf(stderr, "out of memory\n");
goto end_data_xfer;
@ -2686,6 +2715,19 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
if( nArg==2 ){
if( booleanValue(azArg[1]) ){
setBinaryMode(p->out);
}else{
setTextMode(p->out);
}
}else{
fprintf(stderr, "Usage: .binary on|off\n");
rc = 1;
}
}else
/* The undocumented ".breakpoint" command causes a call to the no-op
** routine named test_breakpoint().
*/
@ -3025,7 +3067,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_finalize(pStmt);
pStmt = 0;
if( nCol==0 ) return 0; /* no columns, no error */
zSql = sqlite3_malloc( nByte*2 + 20 + nCol*2 );
zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
if( zSql==0 ){
fprintf(stderr, "Error: out of memory\n");
xCloser(sCtx.in);
@ -3165,6 +3207,64 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
#endif
if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
static const struct {
const char *zLimitName; /* Name of a limit */
int limitCode; /* Integer code for that limit */
} aLimit[] = {
{ "length", SQLITE_LIMIT_LENGTH },
{ "sql_length", SQLITE_LIMIT_SQL_LENGTH },
{ "column", SQLITE_LIMIT_COLUMN },
{ "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
{ "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
{ "vdbe_op", SQLITE_LIMIT_VDBE_OP },
{ "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
{ "attached", SQLITE_LIMIT_ATTACHED },
{ "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
{ "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
{ "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
{ "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
};
int i, n2;
open_db(p, 0);
if( nArg==1 ){
for(i=0; i<sizeof(aLimit)/sizeof(aLimit[0]); i++){
printf("%20s %d\n", aLimit[i].zLimitName,
sqlite3_limit(p->db, aLimit[i].limitCode, -1));
}
}else if( nArg>3 ){
fprintf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
rc = 1;
goto meta_command_exit;
}else{
int iLimit = -1;
n2 = strlen30(azArg[1]);
for(i=0; i<sizeof(aLimit)/sizeof(aLimit[0]); i++){
if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
if( iLimit<0 ){
iLimit = i;
}else{
fprintf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
rc = 1;
goto meta_command_exit;
}
}
}
if( iLimit<0 ){
fprintf(stderr, "unknown limit: \"%s\"\n"
"enter \".limits\" with no arguments for a list.\n",
azArg[1]);
rc = 1;
goto meta_command_exit;
}
if( nArg==3 ){
sqlite3_limit(p->db, aLimit[iLimit].limitCode,
(int)integerValue(azArg[2]));
}
printf("%20s %d\n", aLimit[iLimit].zLimitName,
sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
}
}else
#ifndef SQLITE_OMIT_LOAD_EXTENSION
if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
@ -3650,7 +3750,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( nRow>=nAlloc ){
char **azNew;
int n2 = nAlloc*2 + 10;
azNew = sqlite3_realloc(azResult, sizeof(azResult[0])*n2);
azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
if( azNew==0 ){
fprintf(stderr, "Error: out of memory\n");
break;

View File

@ -3893,8 +3893,6 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** KEYWORDS: {column access functions}
** METHOD: sqlite3_stmt
**
** These routines form the "result set" interface.
**
** ^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
** 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
** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
**
** ^The object returned by [sqlite3_column_value()] is an
** [unprotected sqlite3_value] object. An unprotected sqlite3_value object
** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()].
** <b>Warning:</b> ^The object returned by [sqlite3_column_value()] is an
** [unprotected sqlite3_value] object. In a multithreaded environment,
** 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
** [sqlite3_column_value()] is used in any other way, including calls
** 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
** example, if the internal representation is FLOAT and a text result
@ -3991,12 +3990,6 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** </table>
** </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
** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or
** 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
** 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:
**
** <ul>
@ -4041,7 +4034,7 @@ int sqlite3_data_count(sqlite3_stmt *pStmt);
** ^The pointers returned are valid until a type conversion occurs as
** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
** [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
** [sqlite3_free()].
**

View File

@ -362,6 +362,32 @@
# define NEVER(X) (X)
#endif
/*
** Declarations used for tracing the operating system interfaces.
*/
#if defined(SQLITE_FORCE_OS_TRACE) || defined(SQLITE_TEST) || \
(defined(SQLITE_DEBUG) && SQLITE_OS_WIN)
extern int sqlite3OSTrace;
# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
# define SQLITE_HAVE_OS_TRACE
#else
# define OSTRACE(X)
# undef SQLITE_HAVE_OS_TRACE
#endif
/*
** Is the sqlite3ErrName() function needed in the build? Currently,
** it is needed by "mutex_w32.c" (when debugging), "os_win.c" (when
** OSTRACE is enabled), and by several "test*.c" files (which are
** compiled using SQLITE_TEST).
*/
#if defined(SQLITE_HAVE_OS_TRACE) || defined(SQLITE_TEST) || \
(defined(SQLITE_DEBUG) && SQLITE_OS_WIN)
# define SQLITE_NEED_ERR_NAME
#else
# undef SQLITE_NEED_ERR_NAME
#endif
/*
** Return true (non-zero) if the input is an integer that is too large
** to fit in 32-bits. This macro is used inside of various testcase()
@ -1557,34 +1583,8 @@ struct VTable {
};
/*
** Each SQL table is represented in memory by an instance of the
** following structure.
**
** Table.zName is the name of the table. The case of the original
** CREATE TABLE statement is stored, but case is not significant for
** comparisons.
**
** Table.nCol is the number of columns in this table. Table.aCol is a
** pointer to an array of Column structures, one for each column.
**
** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of
** the column that is that key. Otherwise Table.iPKey is negative. Note
** that the datatype of the PRIMARY KEY must be INTEGER for this field to
** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of
** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid
** is generated for each row of the table. TF_HasPrimaryKey is set if
** the table has any PRIMARY KEY, INTEGER or otherwise.
**
** Table.tnum is the page number for the root BTree page of the table in the
** database file. If Table.iDb is the index of the database table backend
** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that
** holds temporary tables and indices. If TF_Ephemeral is set
** then the table is stored in a file that is automatically deleted
** when the VDBE cursor to the table is closed. In this case Table.tnum
** refers VDBE cursor number that holds the table open, not to the root
** page number. Transient tables are used to hold the results of a
** sub-query that appears instead of a real table name in the FROM clause
** of a SELECT statement.
** The schema for each SQL table and view is represented in memory
** by an instance of the following structure.
*/
struct Table {
char *zName; /* Name of the table or view */
@ -1596,11 +1596,11 @@ struct Table {
#ifndef SQLITE_OMIT_CHECK
ExprList *pCheck; /* All CHECK constraints */
#endif
LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
int tnum; /* Root BTree node for this table (see note above) */
i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
int tnum; /* Root BTree page for this table */
i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */
i16 nCol; /* Number of columns in this table */
u16 nRef; /* Number of pointers to this Table */
LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
LogEst szTabRow; /* Estimated size of each table row in bytes */
#ifdef SQLITE_ENABLE_COSTMULT
LogEst costMult; /* Cost multiplier for using this table */
@ -2835,8 +2835,7 @@ struct StrAccum {
char *zText; /* The string collected so far */
int nChar; /* Length of the string so far */
int nAlloc; /* Amount of space allocated in zText */
int mxAlloc; /* Maximum allowed string length */
u8 useMalloc; /* 0: none, 1: sqlite3DbMalloc, 2: sqlite3_malloc */
int mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */
u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
};
#define STRACCUM_NOMEM 1
@ -3153,7 +3152,7 @@ void sqlite3XPrintf(StrAccum*, u32, const char*, ...);
char *sqlite3MPrintf(sqlite3*,const char*, ...);
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
void sqlite3DebugPrintf(const char*, ...);
#endif
#if defined(SQLITE_TEST)
@ -3500,7 +3499,7 @@ void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
u8 sqlite3HexToInt(int h);
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
#if defined(SQLITE_TEST)
#if defined(SQLITE_NEED_ERR_NAME)
const char *sqlite3ErrName(int);
#endif
@ -3594,7 +3593,7 @@ int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
int sqlite3ApiExit(sqlite3 *db, int);
int sqlite3OpenTempDatabase(Parse *);
void sqlite3StrAccumInit(StrAccum*, char*, int, int);
void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int);
void sqlite3StrAccumAppend(StrAccum*,const char*,int);
void sqlite3StrAccumAppendAll(StrAccum*,const char*);
void sqlite3AppendChar(StrAccum*,int,char);
@ -3868,4 +3867,8 @@ int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*);
int sqlite3ThreadJoin(SQLiteThread*, void**);
#endif
#if defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)
int sqlite3DbstatRegister(sqlite3*);
#endif
#endif /* _SQLITEINT_H_ */

View File

@ -90,7 +90,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
z = 0;
}else{
int n = sqlite3Strlen30(argv[i])+1;
z = sqlite3_malloc( n );
z = sqlite3_malloc64( n );
if( z==0 ) goto malloc_failed;
memcpy(z, argv[i], n);
}
@ -139,7 +139,7 @@ int sqlite3_get_table(
res.nData = 1;
res.nAlloc = 20;
res.rc = SQLITE_OK;
res.azResult = sqlite3_malloc(sizeof(char*)*res.nAlloc );
res.azResult = sqlite3_malloc64(sizeof(char*)*res.nAlloc );
if( res.azResult==0 ){
db->errCode = SQLITE_NOMEM;
return SQLITE_NOMEM;
@ -167,7 +167,7 @@ int sqlite3_get_table(
}
if( res.nAlloc>res.nData ){
char **azNew;
azNew = sqlite3_realloc( res.azResult, sizeof(char*)*res.nData );
azNew = sqlite3_realloc64( res.azResult, sizeof(char*)*res.nData );
if( azNew==0 ){
sqlite3_free_table(&res.azResult[1]);
db->errCode = SQLITE_NOMEM;

View File

@ -3704,7 +3704,7 @@ static int db_last_stmt_ptr(
return TCL_OK;
}
#endif
#endif /* SQLITE_TEST */
/*
** Configure the interpreter passed as the first argument to have access
@ -3724,17 +3724,6 @@ static void init_all(Tcl_Interp *interp){
Md5_Init(interp);
#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) || TCLSH==2
{
extern int SqlitetestStat_Init(Tcl_Interp*);
SqlitetestStat_Init(interp);
}
#endif
#ifdef SQLITE_TEST
{
extern int Sqliteconfig_Init(Tcl_Interp*);

View File

@ -6680,7 +6680,40 @@ static int test_bad_behavior(
}
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.
@ -6752,6 +6785,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
void *clientData;
} aObjCmd[] = {
{ "bad_behavior", test_bad_behavior, (void*)&iZero },
{ "register_dbstat_vtab", test_register_dbstat_vtab },
{ "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
{ "sqlite3_bind_int", test_bind_int, 0 },
{ "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 },

View File

@ -16,6 +16,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifndef SQLITE_OMIT_INCRBLOB
/* These functions are implemented in main.c. */
extern const char *sqlite3ErrName(int);
@ -295,12 +296,13 @@ static int test_blob_write(
return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
}
#endif /* SQLITE_OMIT_INCRBLOB */
/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest_blob_Init(Tcl_Interp *interp){
#ifndef SQLITE_OMIT_INCRBLOB
static struct {
char *zName;
Tcl_ObjCmdProc *xProc;
@ -315,5 +317,6 @@ int Sqlitetest_blob_Init(Tcl_Interp *interp){
for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
}
#endif /* SQLITE_OMIT_INCRBLOB */
return TCL_OK;
}

View File

@ -85,7 +85,7 @@ static int intarrayCreate(
char **pzErr /* Put error message text here */
){
int rc = SQLITE_NOMEM;
intarray_vtab *pVtab = sqlite3_malloc(sizeof(intarray_vtab));
intarray_vtab *pVtab = sqlite3_malloc64(sizeof(intarray_vtab));
if( pVtab ){
memset(pVtab, 0, sizeof(intarray_vtab));
@ -102,7 +102,7 @@ static int intarrayCreate(
static int intarrayOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
int rc = SQLITE_NOMEM;
intarray_cursor *pCur;
pCur = sqlite3_malloc(sizeof(intarray_cursor));
pCur = sqlite3_malloc64(sizeof(intarray_cursor));
if( pCur ){
memset(pCur, 0, sizeof(intarray_cursor));
*ppCursor = (sqlite3_vtab_cursor *)pCur;
@ -225,7 +225,7 @@ SQLITE_API int sqlite3_intarray_create(
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3_intarray *p;
*ppReturn = p = sqlite3_malloc( sizeof(*p) );
*ppReturn = p = sqlite3_malloc64( sizeof(*p) );
if( p==0 ){
return SQLITE_NOMEM;
}
@ -340,7 +340,7 @@ static int test_intarray_bind(
pArray = (sqlite3_intarray*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
n = objc - 2;
#ifndef SQLITE_OMIT_VIRTUALTABLE
a = sqlite3_malloc( sizeof(a[0])*n );
a = sqlite3_malloc64( sizeof(a[0])*n );
if( a==0 ){
Tcl_AppendResult(interp, "SQLITE_NOMEM", (char*)0);
return TCL_ERROR;

View File

@ -286,7 +286,7 @@ static void multiplexFilename(
static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
if( iChunk>=pGroup->nReal ){
struct multiplexReal *p;
p = sqlite3_realloc(pGroup->aReal, (iChunk+1)*sizeof(*p));
p = sqlite3_realloc64(pGroup->aReal, (iChunk+1)*sizeof(*p));
if( p==0 ){
return SQLITE_NOMEM;
}
@ -297,7 +297,7 @@ static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){
char *z;
int n = pGroup->nName;
pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+5 );
pGroup->aReal[iChunk].z = z = sqlite3_malloc64( n+5 );
if( z==0 ){
return SQLITE_NOMEM;
}
@ -357,7 +357,7 @@ static sqlite3_file *multiplexSubOpen(
}
flags &= ~SQLITE_OPEN_CREATE;
}
pSubOpen = sqlite3_malloc( pOrigVfs->szOsFile );
pSubOpen = sqlite3_malloc64( pOrigVfs->szOsFile );
if( pSubOpen==0 ){
*rc = SQLITE_IOERR_NOMEM;
return 0;
@ -524,7 +524,7 @@ static int multiplexOpen(
nName = zName ? multiplexStrlen30(zName) : 0;
sz = sizeof(multiplexGroup) /* multiplexGroup */
+ nName + 1; /* zName */
pGroup = sqlite3_malloc( sz );
pGroup = sqlite3_malloc64( sz );
if( pGroup==0 ){
rc = SQLITE_NOMEM;
}
@ -655,7 +655,7 @@ static int multiplexDelete(
*/
int nName = (int)strlen(zName);
char *z;
z = sqlite3_malloc(nName + 5);
z = sqlite3_malloc64(nName + 5);
if( z==0 ){
rc = SQLITE_IOERR_NOMEM;
}else{

View File

@ -450,12 +450,14 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
}
abort_parse:
assert( nErr==0 );
if( zSql[i]==0 && pParse->rc==SQLITE_OK ){
if( zSql[i]==0 && pParse->rc==SQLITE_OK && db->mallocFailed==0 ){
if( lastTokenParsed!=TK_SEMI ){
sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
pParse->zTail = &zSql[i];
}
sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){
sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
}
}
#ifdef YYTRACKMAXSTACKDEPTH
sqlite3_mutex_enter(sqlite3MallocMutex());

View File

@ -985,7 +985,6 @@ case OP_Halt: {
assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 );
rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
}
pOp = &aOp[pcx];
goto vdbe_return;
}
@ -1205,10 +1204,11 @@ case OP_Move: {
memAboutToChange(p, pOut);
sqlite3VdbeMemMove(pOut, pIn1);
#ifdef SQLITE_DEBUG
if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){
pOut->pScopyFrom += p1 - pOp->p2;
if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<pOut ){
pOut->pScopyFrom += pOp->p2 - p1;
}
#endif
Deephemeralize(pOut);
REGISTER_TRACE(p2++, pOut);
pIn1++;
pOut++;
@ -2477,7 +2477,7 @@ case OP_Column: {
}
}
/* If after trying to extra new entries from the header, nHdrParsed is
/* If after trying to extract new entries from the header, nHdrParsed is
** still not up to p2, that means that the record has fewer than p2
** columns. So the result will be either the default value or a NULL.
*/
@ -5912,7 +5912,6 @@ case OP_JournalMode: { /* out2 */
}
eNew = sqlite3PagerSetJournalMode(pPager, eNew);
pOut = &aMem[pOp->p2];
pOut->flags = MEM_Str|MEM_Static|MEM_Term;
pOut->z = (char *)sqlite3JournalModename(eNew);
pOut->n = sqlite3Strlen30(pOut->z);
@ -6107,8 +6106,9 @@ case OP_VOpen: {
pCur->pVtabCursor = pVtabCursor;
pVtab->nRef++;
}else{
db->mallocFailed = 1;
assert( db->mallocFailed );
pModule->xClose(pVtabCursor);
goto no_mem;
}
}
break;

View File

@ -200,10 +200,11 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){
pMem->z[pMem->n] = 0;
pMem->z[pMem->n+1] = 0;
pMem->flags |= MEM_Term;
#ifdef SQLITE_DEBUG
pMem->pScopyFrom = 0;
#endif
}
pMem->flags &= ~MEM_Ephem;
#ifdef SQLITE_DEBUG
pMem->pScopyFrom = 0;
#endif
return SQLITE_OK;
}

View File

@ -2063,11 +2063,12 @@ static void vdbeMergeEngineCompare(
#define INCRINIT_TASK 1
#define INCRINIT_ROOT 2
/* Forward reference.
** The vdbeIncrMergeInit() and vdbePmaReaderIncrMergeInit() routines call each
** other (when building a merge tree).
/*
** Forward reference required as the vdbeIncrMergeInit() and
** vdbePmaReaderIncrInit() routines are called mutually recursively when
** building a merge tree.
*/
static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode);
static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode);
/*
** Initialize the MergeEngine object passed as the second argument. Once this
@ -2114,7 +2115,7 @@ static int vdbeMergeEngineInit(
** better advantage of multi-processor hardware. */
rc = vdbePmaReaderNext(&pMerger->aReadr[nTree-i-1]);
}else{
rc = vdbePmaReaderIncrMergeInit(&pMerger->aReadr[i], INCRINIT_NORMAL);
rc = vdbePmaReaderIncrInit(&pMerger->aReadr[i], INCRINIT_NORMAL);
}
if( rc!=SQLITE_OK ) return rc;
}
@ -2126,17 +2127,15 @@ static int vdbeMergeEngineInit(
}
/*
** Initialize the IncrMerge field of a PmaReader.
**
** If the PmaReader passed as the first argument is not an incremental-reader
** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it serves
** to open and/or initialize the temp file related fields of the IncrMerge
** The PmaReader passed as the first argument is guaranteed to be an
** incremental-reader (pReadr->pIncr!=0). This function serves to open
** and/or initialize the temp file related fields of the IncrMerge
** object at (pReadr->pIncr).
**
** If argument eMode is set to INCRINIT_NORMAL, then all PmaReaders
** in the sub-tree headed by pReadr are also initialized. Data is then loaded
** into the buffers belonging to pReadr and it is set to
** point to the first key in its range.
** in the sub-tree headed by pReadr are also initialized. Data is then
** loaded into the buffers belonging to pReadr and it is set to point to
** the first key in its range.
**
** If argument eMode is set to INCRINIT_TASK, then pReadr is guaranteed
** to be a multi-threaded PmaReader and this function is being called in a
@ -2163,59 +2162,62 @@ static int vdbeMergeEngineInit(
static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){
int rc = SQLITE_OK;
IncrMerger *pIncr = pReadr->pIncr;
SortSubtask *pTask = pIncr->pTask;
sqlite3 *db = pTask->pSorter->db;
/* eMode is always INCRINIT_NORMAL in single-threaded mode */
assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL );
if( pIncr ){
SortSubtask *pTask = pIncr->pTask;
sqlite3 *db = pTask->pSorter->db;
rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode);
rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode);
/* Set up the required files for pIncr. A multi-theaded IncrMerge object
** requires two temp files to itself, whereas a single-threaded object
** only requires a region of pTask->file2. */
if( rc==SQLITE_OK ){
int mxSz = pIncr->mxSz;
/* Set up the required files for pIncr. A multi-theaded IncrMerge object
** requires two temp files to itself, whereas a single-threaded object
** only requires a region of pTask->file2. */
if( rc==SQLITE_OK ){
int mxSz = pIncr->mxSz;
#if SQLITE_MAX_WORKER_THREADS>0
if( pIncr->bUseThread ){
rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[0].pFd);
if( rc==SQLITE_OK ){
rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[1].pFd);
}
}else
if( pIncr->bUseThread ){
rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[0].pFd);
if( rc==SQLITE_OK ){
rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[1].pFd);
}
}else
#endif
/*if( !pIncr->bUseThread )*/{
if( pTask->file2.pFd==0 ){
assert( pTask->file2.iEof>0 );
rc = vdbeSorterOpenTempFile(db, pTask->file2.iEof, &pTask->file2.pFd);
pTask->file2.iEof = 0;
}
if( rc==SQLITE_OK ){
pIncr->aFile[1].pFd = pTask->file2.pFd;
pIncr->iStartOff = pTask->file2.iEof;
pTask->file2.iEof += mxSz;
}
/*if( !pIncr->bUseThread )*/{
if( pTask->file2.pFd==0 ){
assert( pTask->file2.iEof>0 );
rc = vdbeSorterOpenTempFile(db, pTask->file2.iEof, &pTask->file2.pFd);
pTask->file2.iEof = 0;
}
if( rc==SQLITE_OK ){
pIncr->aFile[1].pFd = pTask->file2.pFd;
pIncr->iStartOff = pTask->file2.iEof;
pTask->file2.iEof += mxSz;
}
}
}
#if SQLITE_MAX_WORKER_THREADS>0
if( rc==SQLITE_OK && pIncr->bUseThread ){
/* Use the current thread to populate aFile[1], even though this
** PmaReader is multi-threaded. The reason being that this function
** is already running in background thread pIncr->pTask->thread. */
assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK );
rc = vdbeIncrPopulate(pIncr);
}
if( rc==SQLITE_OK && pIncr->bUseThread ){
/* Use the current thread to populate aFile[1], even though this
** PmaReader is multi-threaded. If this is an INCRINIT_TASK object,
** then this function is already running in background thread
** pIncr->pTask->thread.
**
** If this is the INCRINIT_ROOT object, then it is running in the
** main VDBE thread. But that is Ok, as that thread cannot return
** control to the VDBE or proceed with anything useful until the
** first results are ready from this merger object anyway.
*/
assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK );
rc = vdbeIncrPopulate(pIncr);
}
#endif
if( rc==SQLITE_OK
&& (SQLITE_MAX_WORKER_THREADS==0 || eMode!=INCRINIT_TASK)
){
rc = vdbePmaReaderNext(pReadr);
}
if( rc==SQLITE_OK && (SQLITE_MAX_WORKER_THREADS==0 || eMode!=INCRINIT_TASK) ){
rc = vdbePmaReaderNext(pReadr);
}
return rc;
}
@ -2224,7 +2226,7 @@ static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){
** The main routine for vdbePmaReaderIncrMergeInit() operations run in
** background threads.
*/
static void *vdbePmaReaderBgInit(void *pCtx){
static void *vdbePmaReaderBgIncrInit(void *pCtx){
PmaReader *pReader = (PmaReader*)pCtx;
void *pRet = SQLITE_INT_TO_PTR(
vdbePmaReaderIncrMergeInit(pReader,INCRINIT_TASK)
@ -2232,20 +2234,36 @@ static void *vdbePmaReaderBgInit(void *pCtx){
pReader->pIncr->pTask->bDone = 1;
return pRet;
}
#endif
/*
** Use a background thread to invoke vdbePmaReaderIncrMergeInit(INCRINIT_TASK)
** on the PmaReader object passed as the first argument.
**
** This call will initialize the various fields of the pReadr->pIncr
** structure and, if it is a multi-threaded IncrMerger, launch a
** background thread to populate aFile[1].
** If the PmaReader passed as the first argument is not an incremental-reader
** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it invokes
** the vdbePmaReaderIncrMergeInit() function with the parameters passed to
** this routine to initialize the incremental merge.
**
** If the IncrMerger object is multi-threaded (IncrMerger.bUseThread==1),
** then a background thread is launched to call vdbePmaReaderIncrMergeInit().
** Or, if the IncrMerger is single threaded, the same function is called
** using the current thread.
*/
static int vdbePmaReaderBgIncrInit(PmaReader *pReadr){
void *pCtx = (void*)pReadr;
return vdbeSorterCreateThread(pReadr->pIncr->pTask, vdbePmaReaderBgInit, pCtx);
}
static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode){
IncrMerger *pIncr = pReadr->pIncr; /* Incremental merger */
int rc = SQLITE_OK; /* Return code */
if( pIncr ){
#if SQLITE_MAX_WORKER_THREADS>0
assert( pIncr->bUseThread==0 || eMode==INCRINIT_TASK );
if( pIncr->bUseThread ){
void *pCtx = (void*)pReadr;
rc = vdbeSorterCreateThread(pIncr->pTask, vdbePmaReaderBgIncrInit, pCtx);
}else
#endif
{
rc = vdbePmaReaderIncrMergeInit(pReadr, eMode);
}
}
return rc;
}
/*
** Allocate a new MergeEngine object to merge the contents of nPMA level-0
@ -2490,15 +2508,21 @@ static int vdbeSorterSetupMerge(VdbeSorter *pSorter){
}
}
for(iTask=0; rc==SQLITE_OK && iTask<pSorter->nTask; iTask++){
/* Check that:
**
** a) The incremental merge object is configured to use the
** right task, and
** b) If it is using task (nTask-1), it is configured to run
** in single-threaded mode. This is important, as the
** root merge (INCRINIT_ROOT) will be using the same task
** object.
*/
PmaReader *p = &pMain->aReadr[iTask];
assert( p->pIncr==0 || p->pIncr->pTask==&pSorter->aTask[iTask] );
if( p->pIncr ){
if( iTask==pSorter->nTask-1 ){
rc = vdbePmaReaderIncrMergeInit(p, INCRINIT_TASK);
}else{
rc = vdbePmaReaderBgIncrInit(p);
}
}
assert( p->pIncr==0 || (
(p->pIncr->pTask==&pSorter->aTask[iTask]) /* a */
&& (iTask!=pSorter->nTask-1 || p->pIncr->bUseThread==0) /* b */
));
rc = vdbePmaReaderIncrInit(p, INCRINIT_TASK);
}
}
pMain = 0;

View File

@ -84,9 +84,8 @@ char *sqlite3VdbeExpandSql(
char zBase[100]; /* Initial working space */
db = p->db;
sqlite3StrAccumInit(&out, zBase, sizeof(zBase),
sqlite3StrAccumInit(&out, db, zBase, sizeof(zBase),
db->aLimit[SQLITE_LIMIT_LENGTH]);
out.db = db;
if( db->nVdbeExec>1 ){
while( *zRawSql ){
const char *zStart = zRawSql;

View File

@ -1083,7 +1083,7 @@ void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){
if( pTab==pToplevel->apVtabLock[i] ) return;
}
n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]);
apVtabLock = sqlite3_realloc(pToplevel->apVtabLock, n);
apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n);
if( apVtabLock ){
pToplevel->apVtabLock = apVtabLock;
pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;

View File

@ -522,7 +522,7 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
if( pWal->nWiData<=iPage ){
int nByte = sizeof(u32*)*(iPage+1);
volatile u32 **apNew;
apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte);
apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte);
if( !apNew ){
*ppPage = 0;
return SQLITE_NOMEM;
@ -1147,7 +1147,7 @@ static int walIndexRecover(Wal *pWal){
/* Malloc a buffer to read frames into. */
szFrame = szPage + WAL_FRAME_HDRSIZE;
aFrame = (u8 *)sqlite3_malloc(szFrame);
aFrame = (u8 *)sqlite3_malloc64(szFrame);
if( !aFrame ){
rc = SQLITE_NOMEM;
goto recovery_error;
@ -1540,7 +1540,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
nByte = sizeof(WalIterator)
+ (nSegment-1)*sizeof(struct WalSegment)
+ iLast*sizeof(ht_slot);
p = (WalIterator *)sqlite3_malloc(nByte);
p = (WalIterator *)sqlite3_malloc64(nByte);
if( !p ){
return SQLITE_NOMEM;
}
@ -1550,7 +1550,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
/* Allocate temporary space used by the merge-sort routine. This block
** of memory will be freed before this function returns.
*/
aTmp = (ht_slot *)sqlite3_malloc(
aTmp = (ht_slot *)sqlite3_malloc64(
sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
);
if( !aTmp ){

View File

@ -3103,8 +3103,7 @@ static int explainOneScan(
|| ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
|| (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
sqlite3StrAccumInit(&str, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
str.db = db;
sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN");
if( pItem->pSelect ){
sqlite3XPrintf(&str, 0, " SUBQUERY %d", pItem->iSelectId);
@ -4303,6 +4302,13 @@ static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
*/
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
if( ALWAYS(pWInfo) ){
int i;
for(i=0; i<pWInfo->nLevel; i++){
WhereLevel *pLevel = &pWInfo->a[i];
if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){
sqlite3DbFree(db, pLevel->u.in.aInLoop);
}
}
whereClauseClear(&pWInfo->sWC);
while( pWInfo->pLoops ){
WhereLoop *p = pWInfo->pLoops;
@ -6899,7 +6905,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen);
sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
}
sqlite3DbFree(db, pLevel->u.in.aInLoop);
}
sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
if( pLevel->addrSkip ){

View File

@ -912,5 +912,14 @@ do_execsql_test alter-17.9 {
do_execsql_test alter-17.10 {
SELECT sqlite_rename_parent(NULL,'abc','xyz');
} {{}}
do_execsql_test alter-17.11 {
SELECT sqlite_rename_parent('create references ''','abc','xyz');
} {{create references '}}
do_execsql_test alter-17.12 {
SELECT sqlite_rename_parent('create references "abc"123" ','abc','xyz');
} {{create references "xyz"123" }}
do_execsql_test alter-17.13 {
SELECT sqlite_rename_parent("references '''",'abc','xyz');
} {{references '''}}
finish_test

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

@ -449,5 +449,107 @@ do_execsql_test 10.1 {
ORDER BY 1;
} {1 1 one 2 2 two 3 3 three}
#---------------------------------------------------------------------------
# Test the 'y' matchinfo flag
#
set sqlite_fts3_enable_parentheses 1
reset_db
do_execsql_test 11.0 {
CREATE VIRTUAL TABLE tt USING fts3(x, y);
INSERT INTO tt VALUES('c d a c d d', 'e a g b d a'); -- 1
INSERT INTO tt VALUES('c c g a e b', 'c g d g e c'); -- 2
INSERT INTO tt VALUES('b e f d e g', 'b a c b c g'); -- 3
INSERT INTO tt VALUES('a c f f g d', 'd b f d e g'); -- 4
INSERT INTO tt VALUES('g a c f c f', 'd g g b c c'); -- 5
INSERT INTO tt VALUES('g a c e b b', 'd b f b g g'); -- 6
INSERT INTO tt VALUES('f d a a f c', 'e e a d c f'); -- 7
INSERT INTO tt VALUES('a c b b g f', 'a b a e d f'); -- 8
INSERT INTO tt VALUES('b a f e c c', 'f d b b a b'); -- 9
INSERT INTO tt VALUES('f d c e a c', 'f a f a a f'); -- 10
}
db func mit mit
foreach {tn expr res} {
1 "a" {
1 {1 2} 2 {1 0} 3 {0 1} 4 {1 0} 5 {1 0}
6 {1 0} 7 {2 1} 8 {1 2} 9 {1 1} 10 {1 3}
}
2 "b" {
1 {0 1} 2 {1 0} 3 {1 2} 4 {0 1} 5 {0 1}
6 {2 2} 8 {2 1} 9 {1 3}
}
3 "y:a" {
1 {0 2} 3 {0 1}
7 {0 1} 8 {0 2} 9 {0 1} 10 {0 3}
}
4 "x:a" {
1 {1 0} 2 {1 0} 4 {1 0} 5 {1 0}
6 {1 0} 7 {2 0} 8 {1 0} 9 {1 0} 10 {1 0}
}
5 "a OR b" {
1 {1 2 0 1} 2 {1 0 1 0} 3 {0 1 1 2} 4 {1 0 0 1} 5 {1 0 0 1}
6 {1 0 2 2} 7 {2 1 0 0} 8 {1 2 2 1} 9 {1 1 1 3} 10 {1 3 0 0}
}
6 "a AND b" {
1 {1 2 0 1} 2 {1 0 1 0} 3 {0 1 1 2} 4 {1 0 0 1} 5 {1 0 0 1}
6 {1 0 2 2} 8 {1 2 2 1} 9 {1 1 1 3}
}
7 "a OR (a AND b)" {
1 {1 2 1 2 0 1} 2 {1 0 1 0 1 0} 3 {0 1 0 1 1 2} 4 {1 0 1 0 0 1}
5 {1 0 1 0 0 1} 6 {1 0 1 0 2 2} 7 {2 1 0 0 0 0} 8 {1 2 1 2 2 1}
9 {1 1 1 1 1 3} 10 {1 3 0 0 0 0}
}
} {
do_execsql_test 11.1.$tn.1 {
SELECT rowid, mit(matchinfo(tt, 'y')) FROM tt WHERE tt MATCH $expr
} $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
#---------------------------------------------------------------------------
# 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

View File

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

Binary file not shown.

BIN
test/fuzzdata2.txt Normal file

Binary file not shown.

View File

@ -555,4 +555,18 @@ do_execsql_test jrnlmode-8.28 { PRAGMA journal_mode=DELETE } {delete}
do_execsql_test jrnlmode-8.29 { COMMIT } {}
do_execsql_test jrnlmode-8.30 { PRAGMA journal_mode=DELETE } {delete}
# Assertion fault on 2015-05-01
do_test jrnlmode-9.1 {
forcedelete test2.db
sqlite3 db2 test2.db
db2 eval {CREATE TEMP TABLE t(l); PRAGMA journal_mode=off;}
db2 close
} {}
do_execsql_test jrnlmode-9.2 {
PRAGMA locking_mode = exclusive;
CREATE TABLE tx(a);
PRAGMA journal_mode = off;
} {exclusive off}
finish_test

View File

@ -923,6 +923,27 @@ do_faultsim_test 41.2 -faults oom* -body {
faultsim_integrity_check
}
reset_db
do_execsql_test 42.0 {
CREATE TABLE t1(x INTEGER PRIMARY KEY, y, z);
CREATE TABLE t2(a, b);
CREATE VIEW a002 AS SELECT *, sum(b) AS m FROM t2 GROUP BY a;
}
faultsim_save_and_close
do_faultsim_test 42 -faults oom-tran* -prep {
faultsim_restore_and_reopen
execsql { SELECT * FROM sqlite_master }
} -body {
execsql {
SELECT t1.z, a002.m
FROM t1 JOIN a002 ON t1.y=a002.m
WHERE t1.x IN (1,2,3);
}
} -test {
faultsim_test_result {0 {}}
}
# Ensure that no file descriptors were leaked.
do_test malloc-99.X {
catch {db close}

113
test/mkfuzzdata1.tcl Normal file
View File

@ -0,0 +1,113 @@
#!/usr/bin/tclsh
#
# Run this script in order to rebuild the fuzzdata1.txt file containing
# fuzzer data for the fuzzershell utility that is create by afl-fuzz.
#
# This script gathers all of the test cases identified by afl-fuzz and
# runs afl-cmin and afl-tmin over them all to try to generate a mimimum
# set of tests that cover all observed behavior.
#
# Options:
#
# --afl-bin DIR1 DIR1 contains the AFL binaries
# --fuzzershell PATH Full pathname of instrumented fuzzershell
# --afl-data DIR3 DIR3 is the "-o" directory from afl-fuzz
# -o FILE Write results into FILE
#
set AFLBIN {}
set FUZZERSHELL {}
set AFLDATA {}
set OUTFILE {}
proc usage {} {
puts stderr "Usage: $::argv0 --afl-bin DIR --fuzzershell PATH\
--afl-data DIR -o FILE"
exit 1
}
proc cmdlineerr {msg} {
puts stderr $msg
usage
}
for {set i 0} {$i<[llength $argv]} {incr i} {
set x [lindex $argv $i]
if {[string index $x 0]!="-"} {cmdlineerr "illegal argument: $x"}
set x [string trimleft $x -]
incr i
if {$i>=[llength $argv]} {cmdlineerr "no argument on --$x"}
set a [lindex $argv $i]
switch -- $x {
afl-bin {set AFLBIN $a}
afl-data {set AFLDATA $a}
fuzzershell {set FUZZERSHELL $a}
o {set OUTFILE $a}
default {cmdlineerr "unknown option: --$x"}
}
}
proc checkarg {varname option} {
set val [set ::$varname]
if {$val==""} {cmdlineerr "required option missing: --$option"}
}
checkarg AFLBIN afl-bin
checkarg AFLDATA afl-data
checkarg FUZZERSHELL fuzzershell
checkarg OUTFILE o
proc checkexec {x} {
if {![file exec $x]} {cmdlineerr "cannot find $x"}
}
checkexec $AFLBIN/afl-cmin
checkexec $AFLBIN/afl-tmin
checkexec $FUZZERSHELL
proc checkdir {x} {
if {![file isdir $x]} {cmdlineerr "no such directory: $x"}
}
checkdir $AFLDATA/queue
proc progress {msg} {
puts "******** $msg"
flush stdout
}
progress "mkdir tmp1 tmp2"
file mkdir tmp1 tmp2
progress "copying test cases from $AFLDATA into tmp1..."
set n 0
foreach file [glob -nocomplain $AFLDATA/queue/id:*] {
incr n
file copy $file tmp1/$n
}
foreach file [glob -nocomplain $AFLDATA/crash*/id:*] {
incr n
file copy $file tmp1/$n
}
progress "total $n files copied."
progress "running: $AFLBIN/afl-cmin -i tmp1 -o tmp2 $FUZZERSHELL"
exec $AFLBIN/afl-cmin -i tmp1 -o tmp2 $FUZZERSHELL >&@ stdout
progress "afl-cmin complete."
#
# Experiments show that running afl-tmin is too slow for this application.
# And it doesn't really make the test cases that much smaller. So let's
# just skip it.
#
# foreach file [glob tmp2/*] {
# progress "$AFLBIN/afl-tmin -i $file -o tmp3/[file tail $file] $FUZZERSHELL"
# exec $AFLBIN/afl-tmin -i $file -o tmp3/[file tail $file] \
# $FUZZERSHELL >&@ stdout
# }
progress "generating final output into $OUTFILE"
set out [open $OUTFILE wb]
puts $out "# Test data for use with fuzzershell. Automatically
# generated using $argv0. This file contains binary data
#"
set n 0
foreach file [glob tmp2/*] {
incr n
puts -nonewline $out "/****<$n>****/"
set in [open $file rb]
puts -nonewline $out [read $in]
close $in
}
close $out
progress "done. $n test cases written to $OUTFILE"
progress "clean-up..."
file delete -force tmp1
progress "culled test cases left in the tmp2 directory"

View File

@ -216,4 +216,22 @@ foreach PGSZ {512 2048 4096 8192} {
} [list $PGSZ $PGSZ]
}
reset_db
do_execsql_test pagesize-3.1 {
BEGIN;
SELECT * FROM sqlite_master;
PRAGMA page_size=2048;
PRAGMA main.page_size;
} {1024}
do_execsql_test pagesize-3.2 {
CREATE TABLE t1(x);
COMMIT;
}
do_execsql_test pagesize-3.3 {
BEGIN;
PRAGMA page_size = 2048;
COMMIT;
PRAGMA main.page_size;
} {1024}
finish_test

View File

@ -111,6 +111,13 @@ array set ::Configs [strip_comments {
-DSQLITE_ENABLE_STAT4
-DSQLITE_MAX_ATTACHED=125
}
"Fast-One" {
-O6
-DSQLITE_ENABLE_FTS4=1
-DSQLITE_ENABLE_RTREE=1
-DSQLITE_ENABLE_STAT4
-DSQLITE_MAX_ATTACHED=125
}
"Device-One" {
-O2
-DSQLITE_DEBUG=1
@ -217,6 +224,7 @@ array set ::Platforms [strip_comments {
"No-lookaside" test
"Devkit" test
"Sanitize" {QUICKTEST_OMIT=func4.test,nan.test test}
"Fast-One" fuzzoomtest
"Valgrind" valgrindtest
"Default" "threadtest fulltest"
"Device-One" fulltest
@ -653,10 +661,11 @@ proc main {argv} {
# it and run veryquick.test. If it did not include the SQLITE_DEBUG option
# add it and run veryquick.test.
if {$target!="checksymbols" && $target!="valgrindtest"
&& !$::BUILDONLY && $::QUICK<2} {
&& $target!="fuzzoomtest" && !$::BUILDONLY && $::QUICK<2} {
set debug_idx [lsearch -glob $config_options -DSQLITE_DEBUG*]
set xtarget $target
regsub -all {fulltest[a-z]*} $xtarget test xtarget
regsub -all {fuzzoomtest} $xtarget fuzztest xtarget
if {$debug_idx < 0} {
incr NTEST
append config_options " -DSQLITE_DEBUG=1"

View File

@ -158,6 +158,9 @@ do_test select4-2.4 {
}} msg]
lappend v $msg
} {1 {ORDER BY clause should come after UNION not before}}
do_execsql_test select4-2.5 {
SELECT 123 AS x ORDER BY (SELECT x ORDER BY 1);
} {123}
# Except operator
#
@ -274,6 +277,16 @@ do_test select4-4.3 {
}} msg]
lappend v $msg
} {1 {ORDER BY clause should come after INTERSECT not before}}
do_catchsql_test select4-4.4 {
SELECT 3 IN (
SELECT 0 ORDER BY 1
INTERSECT
SELECT 1
INTERSECT
SELECT 2
ORDER BY 1
);
} {1 {ORDER BY clause should come after INTERSECT not before}}
# Various error messages while processing UNION or INTERSECT
#

View File

@ -738,6 +738,9 @@ do_test shell1-4.1 {
PRAGMA encoding=UTF16;
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(null), (''), (1), (2.25), ('hello'), (x'807f');
CREATE TABLE t3(x,y);
INSERT INTO t3 VALUES(1,null), (2,''), (3,1),
(4,2.25), (5,'hello'), (6,x'807f');
}
catchcmd test.db {.dump}
} {0 {PRAGMA foreign_keys=OFF;
@ -749,11 +752,18 @@ INSERT INTO "t1" VALUES(1);
INSERT INTO "t1" VALUES(2.25);
INSERT INTO "t1" VALUES('hello');
INSERT INTO "t1" VALUES(X'807F');
CREATE TABLE t3(x,y);
INSERT INTO "t3" VALUES(1,NULL);
INSERT INTO "t3" VALUES(2,'');
INSERT INTO "t3" VALUES(3,1);
INSERT INTO "t3" VALUES(4,2.25);
INSERT INTO "t3" VALUES(5,'hello');
INSERT INTO "t3" VALUES(6,X'807F');
COMMIT;}}
# Test the output of ".mode insert"
#
do_test shell1-4.2 {
do_test shell1-4.2.1 {
catchcmd test.db ".mode insert t1\nselect * from t1;"
} {0 {INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES('');
@ -762,6 +772,39 @@ INSERT INTO t1 VALUES(2.25);
INSERT INTO t1 VALUES('hello');
INSERT INTO t1 VALUES(X'807f');}}
# Test the output of ".mode insert" with headers
#
do_test shell1-4.2.2 {
catchcmd test.db ".mode insert t1\n.headers on\nselect * from t1;"
} {0 {INSERT INTO t1(x) VALUES(NULL);
INSERT INTO t1(x) VALUES('');
INSERT INTO t1(x) VALUES(1);
INSERT INTO t1(x) VALUES(2.25);
INSERT INTO t1(x) VALUES('hello');
INSERT INTO t1(x) VALUES(X'807f');}}
# Test the output of ".mode insert"
#
do_test shell1-4.2.3 {
catchcmd test.db ".mode insert t3\nselect * from t3;"
} {0 {INSERT INTO t3 VALUES(1,NULL);
INSERT INTO t3 VALUES(2,'');
INSERT INTO t3 VALUES(3,1);
INSERT INTO t3 VALUES(4,2.25);
INSERT INTO t3 VALUES(5,'hello');
INSERT INTO t3 VALUES(6,X'807f');}}
# Test the output of ".mode insert" with headers
#
do_test shell1-4.2.4 {
catchcmd test.db ".mode insert t3\n.headers on\nselect * from t3;"
} {0 {INSERT INTO t3(x,y) VALUES(1,NULL);
INSERT INTO t3(x,y) VALUES(2,'');
INSERT INTO t3(x,y) VALUES(3,1);
INSERT INTO t3(x,y) VALUES(4,2.25);
INSERT INTO t3(x,y) VALUES(5,'hello');
INSERT INTO t3(x,y) VALUES(6,X'807f');}}
# Test the output of ".mode tcl"
#
do_test shell1-4.3 {
@ -818,4 +861,61 @@ do_test shell1-4.6 {
";"
"$"} 7}
# Test using arbitrary byte data with the shell via standard input/output.
#
do_test shell1-5.0 {
#
# NOTE: Skip NUL byte because it appears to be incompatible with command
# shell argument parsing.
#
for {set i 1} {$i < 256} {incr i} {
#
# NOTE: Due to how the Tcl [exec] command works (i.e. where it treats
# command channels opened for it as textual ones), the carriage
# return character (and on Windows, the end-of-file character)
# cannot be used here.
#
if {$i==0x0D || ($tcl_platform(platform)=="windows" && $i==0x1A)} {
continue
}
set hex [format %02X $i]
set char [subst \\x$hex]; set oldChar $char
set escapes [list]
if {$tcl_platform(platform)=="windows"} {
#
# NOTE: On Windows, we need to escape all the whitespace characters,
# the alarm (\a) character, and those with special meaning to
# the SQLite shell itself.
#
set escapes [list \
\a \\a \b \\b \t \\t \n \\n \v \\v \f \\f \r \\r \
" " "\" \"" \" \\\" ' \"'\" \\ \\\\]
} else {
#
# NOTE: On Unix, we need to escape most of the whitespace characters
# and those with special meaning to the SQLite shell itself.
# The alarm (\a), backspace (\b), and carriage-return (\r)
# characters do not appear to require escaping on Unix. For
# the alarm and backspace characters, this is probably due to
# differences in the command shell. For the carriage-return,
# it is probably due to differences in how Tcl handles command
# channel end-of-line translations.
#
set escapes [list \
\t \\t \n \\n \v \\v \f \\f \
" " "\" \"" \" \\\" ' \"'\" \\ \\\\]
}
set char [string map $escapes $char]
set x [catchcmdex test.db ".print $char\n"]
set code [lindex $x 0]
set res [lindex $x 1]
if {$code ne "0"} {
error "failed with error: $res"
}
if {$res ne "$oldChar\n"} {
error "failed with byte $hex mismatch"
}
}
} {}
finish_test

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
do_execsql_test stat-5.1 {
PRAGMA auto_vacuum = OFF;
CREATE VIRTUAL TABLE temp.stat USING dbstat;
CREATE TABLE t1(x);
CREATE TABLE tx(y);
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(1514));
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 \
]
do_catchsql_test stat-6.1 {
CREATE VIRTUAL TABLE temp.s2 USING dbstat(mainx);
} {1 {no such database: mainx}}
finish_test

45
test/statfault.test Normal file
View File

@ -0,0 +1,45 @@
# 2015 April 28
#
# 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.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
set testprefix statfault
ifcapable !vtab||!compound {
finish_test
return
}
register_dbstat_vtab db
do_execsql_test statfault-1 {
CREATE TABLE t1(a, b UNIQUE);
INSERT INTO t1 VALUES(1, randomblob(500));
INSERT INTO t1 VALUES(randomblob(500), 1);
INSERT INTO t1 VALUES(2, randomblob(250));
INSERT INTO t1 VALUES(randomblob(250), 2);
CREATE VIRTUAL TABLE sss USING dbstat;
} {}
faultsim_save_and_close
do_faultsim_test 1 -faults * -prep {
faultsim_restore_and_reopen
register_dbstat_vtab db
execsql { SELECT 1 FROM sqlite_master LIMIT 1 }
} -body {
execsql { SELECT count(*) FROM sss }
} -test {
faultsim_test_result {0 8}
}
finish_test

View File

@ -666,6 +666,15 @@ proc do_test {name cmd expected} {
flush stdout
}
proc dumpbytes {s} {
set r ""
for {set i 0} {$i < [string length $s]} {incr i} {
if {$i > 0} {append r " "}
append r [format %02X [scan [string index $s $i] %c]]
}
return $r
}
proc catchcmd {db {cmd ""}} {
global CLI
set out [open cmds.txt w]
@ -676,6 +685,30 @@ proc catchcmd {db {cmd ""}} {
list $rc $msg
}
proc catchcmdex {db {cmd ""}} {
global CLI
set out [open cmds.txt w]
fconfigure $out -encoding binary -translation binary
puts -nonewline $out $cmd
close $out
set line "exec -keepnewline -- $CLI $db < cmds.txt"
set chans [list stdin stdout stderr]
foreach chan $chans {
catch {
set modes($chan) [fconfigure $chan]
fconfigure $chan -encoding binary -translation binary -buffering none
}
}
set rc [catch { eval $line } msg]
foreach chan $chans {
catch {
eval fconfigure [list $chan] $modes($chan)
}
}
# puts [dumpbytes $msg]
list $rc $msg
}
proc filepath_normalize {p} {
# test cases should be written to assume "unix"-like file paths
if {$::tcl_platform(platform)!="unix"} {

View File

@ -32,14 +32,16 @@
** (4) The eval() SQL function is added, allowing the fuzzer to do
** interesting recursive operations.
**
** 2015-04-20: The input text can be divided into separate SQL chunks using
** lines of the form:
** (5) An error is raised if there is a memory leak.
**
** The input text can be divided into separate test cases using comments
** of the form:
**
** |****<...>****|
**
** where the "..." is arbitrary text, except the "|" should really be "/".
** ("|" is used here to avoid compiler warnings about nested comments.)
** A separate in-memory SQLite database is created to run each chunk of SQL.
** where the "..." is arbitrary text. (Except the "|" should really be "/".
** "|" is used here to avoid compiler errors about nested comments.)
** A separate in-memory SQLite database is created to run each test case.
** This feature allows the "queue" of AFL to be captured into a single big
** file using a command like this:
**
@ -54,11 +56,10 @@
** program aborts if the close fails or if there is any unfreed memory after
** the close.
**
** New cases can be appended to all-queue.txt at any time. If redundant cases
** are added, that can be eliminated by running:
** New test cases can be appended to all-queue.txt at any time. If redundant
** test cases are added, they can be eliminated by running:
**
** fuzzershell -f ~/all-queue.txt --unique-cases ~/unique-cases.txt
**
*/
#include <stdio.h>
#include <stdlib.h>
@ -71,10 +72,58 @@
** All global variables are gathered into the "g" singleton.
*/
struct GlobalVars {
const char *zArgv0; /* Name of program */
const char *zArgv0; /* Name of program */
sqlite3_mem_methods sOrigMem; /* Original memory methods */
sqlite3_mem_methods sOomMem; /* Memory methods with OOM simulator */
int iOomCntdown; /* Memory fails on 1 to 0 transition */
int nOomFault; /* Increments for each OOM fault */
int bOomOnce; /* Fail just once if true */
int bOomEnable; /* True to enable OOM simulation */
int nOomBrkpt; /* Number of calls to oomFault() */
char zTestName[100]; /* Name of current test */
} g;
/*
** Maximum number of iterations for an OOM test
*/
#ifndef OOM_MAX
# define OOM_MAX 625
#endif
/*
** This routine is called when a simulated OOM occurs. It exists as a
** convenient place to set a debugger breakpoint.
*/
static void oomFault(void){
g.nOomBrkpt++; /* Prevent oomFault() from being optimized out */
}
/* Versions of malloc() and realloc() that simulate OOM conditions */
static void *oomMalloc(int nByte){
if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){
g.iOomCntdown--;
if( g.iOomCntdown==0 ){
if( g.nOomFault==0 ) oomFault();
g.nOomFault++;
if( !g.bOomOnce ) g.iOomCntdown = 1;
return 0;
}
}
return g.sOrigMem.xMalloc(nByte);
}
static void *oomRealloc(void *pOld, int nByte){
if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){
g.iOomCntdown--;
if( g.iOomCntdown==0 ){
if( g.nOomFault==0 ) oomFault();
g.nOomFault++;
if( !g.bOomOnce ) g.iOomCntdown = 1;
return 0;
}
}
return g.sOrigMem.xRealloc(pOld, nByte);
}
/*
** Print an error message and abort in such a way to indicate to the
@ -82,7 +131,11 @@ struct GlobalVars {
*/
static void abendError(const char *zFormat, ...){
va_list ap;
fprintf(stderr, "%s: ", g.zArgv0);
if( g.zTestName[0] ){
fprintf(stderr, "%s (%s): ", g.zArgv0, g.zTestName);
}else{
fprintf(stderr, "%s: ", g.zArgv0);
}
va_start(ap, zFormat);
vfprintf(stderr, zFormat, ap);
va_end(ap);
@ -95,7 +148,11 @@ static void abendError(const char *zFormat, ...){
*/
static void fatalError(const char *zFormat, ...){
va_list ap;
fprintf(stderr, "%s: ", g.zArgv0);
if( g.zTestName[0] ){
fprintf(stderr, "%s (%s): ", g.zArgv0, g.zTestName);
}else{
fprintf(stderr, "%s: ", g.zArgv0);
}
va_start(ap, zFormat);
vfprintf(stderr, zFormat, ap);
va_end(ap);
@ -124,6 +181,10 @@ static void sqlexec(sqlite3 *db, const char *zFormat, ...){
*/
static void shellLog(void *pNotUsed, int iErrCode, const char *zMsg){
printf("LOG: (%d) %s\n", iErrCode, zMsg);
fflush(stdout);
}
static void shellLogNoop(void *pNotUsed, int iErrCode, const char *zMsg){
return;
}
/*
@ -141,6 +202,7 @@ static int execCallback(void *NotUsed, int argc, char **argv, char **colv){
printf("NULL\n");
}
}
fflush(stdout);
return 0;
}
static int execNoop(void *NotUsed, int argc, char **argv, char **colv){
@ -154,6 +216,10 @@ static int execNoop(void *NotUsed, int argc, char **argv, char **colv){
*/
static void traceCallback(void *NotUsed, const char *zMsg){
printf("TRACE: %s\n", zMsg);
fflush(stdout);
}
static void traceNoop(void *NotUsed, const char *zMsg){
return;
}
#endif
@ -249,16 +315,16 @@ static void sqlEvalFunc(
** Print sketchy documentation for this utility program
*/
static void showHelp(void){
printf("Usage: %s [options]\n", g.zArgv0);
printf("Usage: %s [options] ?FILE...?\n", g.zArgv0);
printf(
"Read SQL text from standard input and evaluate it.\n"
"Read SQL text from FILE... (or from standard input if FILE... is omitted)\n"
"and then evaluate each block of SQL contained therein.\n"
"Options:\n"
" --autovacuum Enable AUTOVACUUM mode\n"
" -f FILE Read SQL text from FILE instead of standard input\n"
" --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n"
" --help Show this help text\n"
" --initdb DBFILE Initialize the in-memory database using template DBFILE\n"
" --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n"
" --oom Run each test multiple times in a simulated OOM loop\n"
" --pagesize N Set the page size to N\n"
" --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n"
" -q Reduced output\n"
@ -330,28 +396,31 @@ static int integerValue(const char *zArg){
return (int)(isNeg? -v : v);
}
/*
** Various operating modes
*/
#define FZMODE_Generic 1
#define FZMODE_Strftime 2
#define FZMODE_Printf 3
#define FZMODE_Glob 4
/* Return the current wall-clock time */
static sqlite3_int64 timeOfDay(void){
static sqlite3_vfs *clockVfs = 0;
sqlite3_int64 t;
if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){
clockVfs->xCurrentTimeInt64(clockVfs, &t);
}else{
double r;
clockVfs->xCurrentTime(clockVfs, &r);
t = (sqlite3_int64)(r*86400000.0);
}
return t;
}
int main(int argc, char **argv){
char *zIn = 0; /* Input text */
int nAlloc = 0; /* Number of bytes allocated for zIn[] */
int nIn = 0; /* Number of bytes of zIn[] used */
size_t got; /* Bytes read from input */
FILE *in = stdin; /* Where to read SQL text from */
int rc = SQLITE_OK; /* Result codes from API functions */
int i; /* Loop counter */
int iNext; /* Next block of SQL */
sqlite3 *db; /* Open database */
sqlite3 *dbInit = 0; /* On-disk database used to initialize the in-memory db */
const char *zInitDb = 0;/* Name of the initialization database file */
char *zErrMsg = 0; /* Error message returned from sqlite3_exec() */
char *zIn = 0; /* Input text */
int nAlloc = 0; /* Number of bytes allocated for zIn[] */
int nIn = 0; /* Number of bytes of zIn[] used */
size_t got; /* Bytes read from input */
int rc = SQLITE_OK; /* Result codes from API functions */
int i; /* Loop counter */
int iNext; /* Next block of SQL */
sqlite3 *db; /* Open database */
char *zErrMsg = 0; /* Error message returned from sqlite3_exec() */
const char *zEncoding = 0; /* --utf16be or --utf16le */
int nHeap = 0, mnHeap = 0; /* Heap size from --heap */
int nLook = 0, szLook = 0; /* --lookaside configuration */
@ -365,8 +434,6 @@ int main(int argc, char **argv){
int doAutovac = 0; /* True for --autovacuum */
char *zSql; /* SQL to run */
char *zToFree = 0; /* Call sqlite3_free() on this afte running zSql */
int iMode = FZMODE_Generic; /* Operating mode */
const char *zCkGlob = 0; /* Inputs must match this glob */
int verboseFlag = 0; /* --verbose or -v flag */
int quietFlag = 0; /* --quiet or -q flag */
int nTest = 0; /* Number of test cases run */
@ -376,9 +443,21 @@ int main(int argc, char **argv){
sqlite3_stmt *pStmt = 0; /* Statement to insert testcase into dataDb */
const char *zDataOut = 0; /* Write compacted data to this output file */
int nHeader = 0; /* Bytes of header comment text on input file */
int oomFlag = 0; /* --oom */
int oomCnt = 0; /* Counter for the OOM loop */
char zErrBuf[200]; /* Space for the error message */
const char *zFailCode; /* Value of the TEST_FAILURE environment var */
const char *zPrompt; /* Initial prompt when large-file fuzzing */
int nInFile = 0; /* Number of input files to read */
char **azInFile = 0; /* Array of input file names */
int jj; /* Loop counter for azInFile[] */
sqlite3_int64 iBegin; /* Start time for the whole program */
sqlite3_int64 iStart, iEnd; /* Start and end-times for a test case */
iBegin = timeOfDay();
zFailCode = getenv("TEST_FAILURE");
g.zArgv0 = argv[0];
zPrompt = "<stdin>";
for(i=1; i<argc; i++){
const char *z = argv[i];
if( z[0]=='-' ){
@ -388,9 +467,8 @@ int main(int argc, char **argv){
doAutovac = 1;
}else
if( strcmp(z, "f")==0 && i+1<argc ){
if( in!=stdin ) abendError("only one -f allowed");
in = fopen(argv[++i],"rb");
if( in==0 ) abendError("cannot open input file \"%s\"", argv[i]);
i++;
goto addNewInFile;
}else
if( strcmp(z,"heap")==0 ){
if( i>=argc-2 ) abendError("missing arguments on %s\n", argv[i]);
@ -402,34 +480,14 @@ int main(int argc, char **argv){
showHelp();
return 0;
}else
if( strcmp(z, "initdb")==0 && i+1<argc ){
if( zInitDb!=0 ) abendError("only one --initdb allowed");
zInitDb = argv[++i];
}else
if( strcmp(z,"lookaside")==0 ){
if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
nLook = integerValue(argv[i+1]);
szLook = integerValue(argv[i+2]);
i += 2;
}else
if( strcmp(z,"mode")==0 ){
if( i>=argc-1 ) abendError("missing argument on %s", argv[i]);
z = argv[++i];
if( strcmp(z,"generic")==0 ){
iMode = FZMODE_Printf;
zCkGlob = 0;
}else if( strcmp(z, "glob")==0 ){
iMode = FZMODE_Glob;
zCkGlob = "'*','*'";
}else if( strcmp(z, "printf")==0 ){
iMode = FZMODE_Printf;
zCkGlob = "'*',*";
}else if( strcmp(z, "strftime")==0 ){
iMode = FZMODE_Strftime;
zCkGlob = "'*',*";
}else{
abendError("unknown --mode: %s", z);
}
if( strcmp(z,"oom")==0 ){
oomFlag = 1;
}else
if( strcmp(z,"pagesize")==0 ){
if( i>=argc-1 ) abendError("missing argument on %s", argv[i]);
@ -470,16 +528,29 @@ int main(int argc, char **argv){
abendError("unknown option: %s", argv[i]);
}
}else{
abendError("unknown argument: %s", argv[i]);
addNewInFile:
nInFile++;
azInFile = realloc(azInFile, sizeof(azInFile[0])*nInFile);
if( azInFile==0 ) abendError("out of memory");
azInFile[nInFile-1] = argv[i];
}
}
if( verboseFlag ) sqlite3_config(SQLITE_CONFIG_LOG, shellLog, 0);
/* Do global SQLite initialization */
sqlite3_config(SQLITE_CONFIG_LOG, verboseFlag ? shellLog : shellLogNoop, 0);
if( nHeap>0 ){
pHeap = malloc( nHeap );
if( pHeap==0 ) fatalError("cannot allocate %d-byte heap\n", nHeap);
rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
if( rc ) abendError("heap configuration failed: %d\n", rc);
}
if( oomFlag ){
sqlite3_config(SQLITE_CONFIG_GETMALLOC, &g.sOrigMem);
g.sOomMem = g.sOrigMem;
g.sOomMem.xMalloc = oomMalloc;
g.sOomMem.xRealloc = oomRealloc;
sqlite3_config(SQLITE_CONFIG_MALLOC, &g.sOomMem);
}
if( nLook>0 ){
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
if( szLook>0 ){
@ -501,140 +572,225 @@ int main(int argc, char **argv){
rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache);
if( rc ) abendError("pcache configuration failed: %d", rc);
}
while( !feof(in) ){
nAlloc += nAlloc+1000;
zIn = realloc(zIn, nAlloc);
if( zIn==0 ) fatalError("out of memory");
got = fread(zIn+nIn, 1, nAlloc-nIn-1, in);
nIn += (int)got;
zIn[nIn] = 0;
if( got==0 ) break;
}
if( in!=stdin ) fclose(in);
/* If the --unique-cases option was supplied, open the database that will
** be used to gather unique test cases.
*/
if( zDataOut ){
rc = sqlite3_open(":memory:", &dataDb);
if( rc ) abendError("cannot open :memory: database");
rc = sqlite3_exec(dataDb,
"CREATE TABLE testcase(sql BLOB PRIMARY KEY) WITHOUT ROWID;",0,0,0);
"CREATE TABLE testcase(sql BLOB PRIMARY KEY, tm) WITHOUT ROWID;",0,0,0);
if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
rc = sqlite3_prepare_v2(dataDb, "INSERT OR IGNORE INTO testcase(sql)VALUES(?1)",
-1, &pStmt, 0);
rc = sqlite3_prepare_v2(dataDb,
"INSERT OR IGNORE INTO testcase(sql,tm)VALUES(?1,?2)",
-1, &pStmt, 0);
if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
}
if( zInitDb ){
rc = sqlite3_open_v2(zInitDb, &dbInit, SQLITE_OPEN_READONLY, 0);
if( rc!=SQLITE_OK ){
abendError("unable to open initialization database \"%s\"", zInitDb);
/* Initialize the input buffer used to hold SQL text */
if( nInFile==0 ) nInFile = 1;
nAlloc = 1000;
zIn = malloc(nAlloc);
if( zIn==0 ) fatalError("out of memory");
/* Loop over all input files */
for(jj=0; jj<nInFile; jj++){
/* Read the complete content of the next input file into zIn[] */
FILE *in;
if( azInFile ){
int j, k;
in = fopen(azInFile[jj],"rb");
if( in==0 ){
abendError("cannot open %s for reading", azInFile[jj]);
}
zPrompt = azInFile[jj];
for(j=k=0; zPrompt[j]; j++) if( zPrompt[j]=='/' ) k = j+1;
zPrompt += k;
}else{
in = stdin;
zPrompt = "<stdin>";
}
}
for(i=0; i<nIn; i=iNext+1){ /* Skip initial lines beginning with '#' */
if( zIn[i]!='#' ) break;
for(iNext=i+1; iNext<nIn && zIn[iNext]!='\n'; iNext++){}
}
nHeader = i;
for(nTest=0; i<nIn; i=iNext, nTest++){
char cSaved;
if( strncmp(&zIn[i], "/****<",6)==0 ){
char *z = strstr(&zIn[i], ">****/");
if( z ){
z += 6;
if( verboseFlag ) printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
i += (int)(z-&zIn[i]);
multiTest = 1;
while( !feof(in) ){
got = fread(zIn+nIn, 1, nAlloc-nIn-1, in);
nIn += (int)got;
zIn[nIn] = 0;
if( got==0 ) break;
if( nAlloc - nIn - 1 < 100 ){
nAlloc += nAlloc+1000;
zIn = realloc(zIn, nAlloc);
if( zIn==0 ) fatalError("out of memory");
}
}
for(iNext=i; iNext<nIn && strncmp(&zIn[iNext],"/****<",6)!=0; iNext++){}
if( zDataOut ){
sqlite3_bind_blob(pStmt, 1, &zIn[i], iNext-i, SQLITE_STATIC);
rc = sqlite3_step(pStmt);
if( rc!=SQLITE_DONE ) abendError("%s", sqlite3_errmsg(dataDb));
sqlite3_reset(pStmt);
continue;
if( in!=stdin ) fclose(in);
lastPct = -1;
/* Skip initial lines of the input file that begin with "#" */
for(i=0; i<nIn; i=iNext+1){
if( zIn[i]!='#' ) break;
for(iNext=i+1; iNext<nIn && zIn[iNext]!='\n'; iNext++){}
}
cSaved = zIn[iNext];
zIn[iNext] = 0;
if( zCkGlob && sqlite3_strglob(zCkGlob,&zIn[i])!=0 ){
nHeader = i;
/* Process all test cases contained within the input file.
*/
for(; i<nIn; i=iNext, nTest++, g.zTestName[0]=0){
char cSaved;
if( strncmp(&zIn[i], "/****<",6)==0 ){
char *z = strstr(&zIn[i], ">****/");
if( z ){
z += 6;
sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "%.*s",
(int)(z-&zIn[i]) - 12, &zIn[i+6]);
if( verboseFlag ){
printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
fflush(stdout);
}
i += (int)(z-&zIn[i]);
multiTest = 1;
}
}
for(iNext=i; iNext<nIn && strncmp(&zIn[iNext],"/****<",6)!=0; iNext++){}
cSaved = zIn[iNext];
zIn[iNext] = 0;
/* Print out the SQL of the next test case is --verbose is enabled
*/
zSql = &zIn[i];
if( verboseFlag ){
printf("INPUT (offset: %d, size: %d): [%s]\n",
i, (int)strlen(&zIn[i]), &zIn[i]);
}else if( multiTest && !quietFlag ){
if( oomFlag ){
printf("%s\n", g.zTestName);
}else{
int pct = (10*iNext)/nIn;
if( pct!=lastPct ){
if( lastPct<0 ) printf("%s:", zPrompt);
printf(" %d%%", pct*10);
lastPct = pct;
}
}
}else if( nInFile>1 ){
printf("%s\n", zPrompt);
}
fflush(stdout);
/* Run the next test case. Run it multiple times in --oom mode
*/
if( oomFlag ){
oomCnt = g.iOomCntdown = 1;
g.nOomFault = 0;
g.bOomOnce = 1;
if( verboseFlag ){
printf("Once.%d\n", oomCnt);
fflush(stdout);
}
}else{
oomCnt = 0;
}
do{
rc = sqlite3_open_v2(
"main.db", &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY,
0);
if( rc!=SQLITE_OK ){
abendError("Unable to open the in-memory database");
}
if( pLook ){
rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE,pLook,szLook,nLook);
if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc);
}
#ifndef SQLITE_OMIT_TRACE
sqlite3_trace(db, verboseFlag ? traceCallback : traceNoop, 0);
#endif
sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000);
if( zEncoding ) sqlexec(db, "PRAGMA encoding=%s", zEncoding);
if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize);
if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL");
iStart = timeOfDay();
g.bOomEnable = 1;
if( verboseFlag ){
zErrMsg = 0;
rc = sqlite3_exec(db, zSql, execCallback, 0, &zErrMsg);
if( zErrMsg ){
sqlite3_snprintf(sizeof(zErrBuf),zErrBuf,"%z", zErrMsg);
zErrMsg = 0;
}
}else {
rc = sqlite3_exec(db, zSql, execNoop, 0, 0);
}
g.bOomEnable = 0;
iEnd = timeOfDay();
rc = sqlite3_close(db);
if( rc ){
abendError("sqlite3_close() failed with rc=%d", rc);
}
if( !zDataOut && sqlite3_memory_used()>0 ){
abendError("memory in use after close: %lld bytes",sqlite3_memory_used());
}
if( oomFlag ){
/* Limit the number of iterations of the OOM loop to OOM_MAX. If the
** first pass (single failure) exceeds 2/3rds of OOM_MAX this skip the
** second pass (continuous failure after first) completely. */
if( g.nOomFault==0 || oomCnt>OOM_MAX ){
if( g.bOomOnce && oomCnt<=(OOM_MAX*2/3) ){
oomCnt = g.iOomCntdown = 1;
g.bOomOnce = 0;
}else{
oomCnt = 0;
}
}else{
g.iOomCntdown = ++oomCnt;
g.nOomFault = 0;
}
if( oomCnt ){
if( verboseFlag ){
printf("%s.%d\n", g.bOomOnce ? "Once" : "Multi", oomCnt);
fflush(stdout);
}
nTest++;
}
}
}while( oomCnt>0 );
/* Store unique test cases in the in the dataDb database if the
** --unique-cases flag is present
*/
if( zDataOut ){
sqlite3_bind_blob(pStmt, 1, &zIn[i], iNext-i, SQLITE_STATIC);
sqlite3_bind_int64(pStmt, 2, iEnd - iStart);
rc = sqlite3_step(pStmt);
if( rc!=SQLITE_DONE ) abendError("%s", sqlite3_errmsg(dataDb));
sqlite3_reset(pStmt);
}
/* Free the SQL from the current test case
*/
if( zToFree ){
sqlite3_free(zToFree);
zToFree = 0;
}
zIn[iNext] = cSaved;
continue;
}
rc = sqlite3_open_v2(
"main.db", &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY,
0);
if( rc!=SQLITE_OK ){
abendError("Unable to open the in-memory database");
}
if( pLook ){
rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, pLook, szLook, nLook);
if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc);
}
if( zInitDb ){
sqlite3_backup *pBackup;
pBackup = sqlite3_backup_init(db, "main", dbInit, "main");
rc = sqlite3_backup_step(pBackup, -1);
if( rc!=SQLITE_DONE ){
abendError("attempt to initialize the in-memory database failed (rc=%d)",
rc);
}
sqlite3_backup_finish(pBackup);
}
#ifndef SQLITE_OMIT_TRACE
if( verboseFlag ) sqlite3_trace(db, traceCallback, 0);
#endif
sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000);
if( zEncoding ) sqlexec(db, "PRAGMA encoding=%s", zEncoding);
if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize);
if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL");
zSql = &zIn[i];
if( verboseFlag ){
printf("INPUT (offset: %d, size: %d): [%s]\n",
i, (int)strlen(&zIn[i]), &zIn[i]);
}else if( multiTest && !quietFlag ){
int pct = 10*iNext/nIn;
if( pct!=lastPct ){
if( lastPct<0 ) printf("fuzz test:");
printf(" %d%%", pct*10);
/* Show test-case results in --verbose mode
*/
if( verboseFlag ){
printf("RESULT-CODE: %d\n", rc);
if( zErrMsg ){
printf("ERROR-MSG: [%s]\n", zErrBuf);
}
fflush(stdout);
lastPct = pct;
}
}
switch( iMode ){
case FZMODE_Glob:
zSql = zToFree = sqlite3_mprintf("SELECT glob(%s);", zSql);
break;
case FZMODE_Printf:
zSql = zToFree = sqlite3_mprintf("SELECT printf(%s);", zSql);
break;
case FZMODE_Strftime:
zSql = zToFree = sqlite3_mprintf("SELECT strftime(%s);", zSql);
break;
}
zErrMsg = 0;
rc = sqlite3_exec(db, zSql, verboseFlag ? execCallback : execNoop, 0, &zErrMsg);
if( zToFree ){
sqlite3_free(zToFree);
zToFree = 0;
}
zIn[iNext] = cSaved;
if( verboseFlag ){
printf("RESULT-CODE: %d\n", rc);
if( zErrMsg ){
printf("ERROR-MSG: [%s]\n", zErrMsg);
}
}
sqlite3_free(zErrMsg);
rc = sqlite3_close(db);
if( rc ){
abendError("sqlite3_close() failed with rc=%d", rc);
}
if( sqlite3_memory_used()>0 ){
abendError("memory in use after close: %lld bytes", sqlite3_memory_used());
}
if( nTest==1 ){
/* Simulate an error if the TEST_FAILURE environment variable is "5" */
char *zFailCode = getenv("TEST_FAILURE");
/* Simulate an error if the TEST_FAILURE environment variable is "5".
** This is used to verify that automated test script really do spot
** errors that occur in this test program.
*/
if( zFailCode ){
if( zFailCode[0]=='5' && zFailCode[1]==0 ){
abendError("simulated failure");
@ -646,28 +802,41 @@ int main(int argc, char **argv){
}
}
}
if( !verboseFlag && multiTest && !quietFlag && !oomFlag ) printf("\n");
}
if( !verboseFlag && multiTest && !quietFlag ) printf("\n");
/* Report total number of tests run
*/
if( nTest>1 && !quietFlag ){
printf("%d fuzz tests with no errors\nSQLite %s %s\n",
nTest, sqlite3_libversion(), sqlite3_sourceid());
sqlite3_int64 iElapse = timeOfDay() - iBegin;
printf("%s: 0 errors out of %d tests in %d.%03d seconds\nSQLite %s %s\n",
g.zArgv0, nTest, (int)(iElapse/1000), (int)(iElapse%1000),
sqlite3_libversion(), sqlite3_sourceid());
}
/* Write the unique test cases if the --unique-cases flag was used
*/
if( zDataOut ){
int n = 0;
FILE *out = fopen(zDataOut, "wb");
if( out==0 ) abendError("cannot open %s for writing", zDataOut);
if( nHeader>0 ) fwrite(zIn, nHeader, 1, out);
sqlite3_finalize(pStmt);
rc = sqlite3_prepare_v2(dataDb, "SELECT sql FROM testcase", -1, &pStmt, 0);
rc = sqlite3_prepare_v2(dataDb, "SELECT sql, tm FROM testcase ORDER BY tm, sql",
-1, &pStmt, 0);
if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
while( sqlite3_step(pStmt)==SQLITE_ROW ){
fprintf(out,"/****<%d>****/", ++n);
fprintf(out,"/****<%d:%dms>****/", ++n, sqlite3_column_int(pStmt,1));
fwrite(sqlite3_column_blob(pStmt,0),sqlite3_column_bytes(pStmt,0),1,out);
}
fclose(out);
sqlite3_finalize(pStmt);
sqlite3_close(dataDb);
}
/* Clean up and exit.
*/
free(azInFile);
free(zIn);
free(pHeap);
free(pLook);

View File

@ -17,7 +17,7 @@
# After the "tsrc" directory has been created and populated, run
# this script:
#
# tclsh mksqlite3c.tcl
# tclsh mksqlite3c.tcl --srcdir $SRC
#
# The amalgamated SQLite code will be written into sqlite3.c
#
@ -26,15 +26,17 @@
# from in this file. The version number is needed to generate the header
# comment of the amalgamation.
#
if {[lsearch $argv --nostatic]>=0} {
set addstatic 0
} else {
set addstatic 1
}
if {[lsearch $argv --linemacros]>=0} {
set linemacros 1
} else {
set linemacros 0
set addstatic 1
set linemacros 0
for {set i 0} {$i<[llength $argv]} {incr i} {
set x [lindex $argv $i]
if {[regexp {^-+nostatic$} $x]} {
set addstatic 0
} elseif {[regexp {^-+linemacros} $x]} {
set linemacros 1
} else {
error "unknown command-line option: $x"
}
}
set in [open tsrc/sqlite3.h]
set cnt 0
@ -382,6 +384,7 @@ foreach file {
rtree.c
icu.c
fts3_icu.c
dbstat.c
} {
copy_file tsrc/$file
}

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"
exit 1
}
register_dbstat_vtab db
db eval {SELECT count(*) FROM sqlite_master}
set pageSize [expr {wide([db one {PRAGMA page_size}])}]

View File

@ -497,7 +497,7 @@ static void diff_one_table(const char *zTab, FILE *out){
char **az2 = 0; /* Columns in aux */
int nPk; /* Primary key columns in main */
int nPk2; /* Primary key columns in aux */
int n; /* Number of columns in main */
int n = 0; /* Number of columns in main */
int n2; /* Number of columns in aux */
int nQ; /* Number of output columns in the diff query */
int i; /* Loop counter */
@ -734,7 +734,7 @@ static void summarize_one_table(const char *zTab, FILE *out){
char **az2 = 0; /* Columns in aux */
int nPk; /* Primary key columns in main */
int nPk2; /* Primary key columns in aux */
int n; /* Number of columns in main */
int n = 0; /* Number of columns in main */
int n2; /* Number of columns in aux */
int i; /* Loop counter */
const char *zSep; /* Separator string */
@ -897,19 +897,19 @@ static void putValue(FILE *out, sqlite3_value *pVal){
for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out);
break;
case SQLITE_FLOAT:
rX = sqlite3_value_int64(pVal);
rX = sqlite3_value_double(pVal);
memcpy(&uX, &rX, 8);
for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out);
break;
case SQLITE_TEXT:
iX = sqlite3_value_bytes(pVal);
putsVarint(out, (sqlite3_uint64)iX);
fwrite(sqlite3_value_text(pVal),1,iX,out);
fwrite(sqlite3_value_text(pVal),1,(size_t)iX,out);
break;
case SQLITE_BLOB:
iX = sqlite3_value_bytes(pVal);
putsVarint(out, (sqlite3_uint64)iX);
fwrite(sqlite3_value_blob(pVal),1,iX,out);
fwrite(sqlite3_value_blob(pVal),1,(size_t)iX,out);
break;
case SQLITE_NULL:
break;
@ -1116,6 +1116,7 @@ static void showHelp(void){
"Output SQL text that would transform DB1 into DB2.\n"
"Options:\n"
" --changeset FILE Write a CHANGESET into FILE\n"
" -L|--lib LIBRARY Load an SQLite extension library\n"
" --primarykey Use schema-defined PRIMARY KEYs\n"
" --schema Show only differences in the schema\n"
" --summary Show only a summary of the differences\n"
@ -1134,25 +1135,38 @@ int main(int argc, char **argv){
char *zTab = 0;
FILE *out = stdout;
void (*xDiff)(const char*,FILE*) = diff_one_table;
int nExt = 0;
char **azExt = 0;
g.zArgv0 = argv[0];
sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
for(i=1; i<argc; i++){
const char *z = argv[i];
if( z[0]=='-' ){
z++;
if( z[0]=='-' ) z++;
if( strcmp(z,"changeset")==0 ){
if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
out = fopen(argv[++i], "wb");
if( out==0 ) cmdlineError("cannot open: %s", argv[i]);
xDiff = changeset_one_table;
}else
if( strcmp(z,"debug")==0 ){
if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
g.fDebug = strtol(argv[++i], 0, 0);
}else
if( strcmp(z,"help")==0 ){
showHelp();
return 0;
}else
#ifndef SQLITE_OMIT_LOAD_EXTENSION
if( strcmp(z,"lib")==0 || strcmp(z,"L")==0 ){
if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
azExt = realloc(azExt, sizeof(azExt[0])*(nExt+1));
if( azExt==0 ) cmdlineError("out of memory");
azExt[nExt++] = argv[++i];
}else
#endif
if( strcmp(z,"primarykey")==0 ){
g.bSchemaPK = 1;
}else
@ -1163,6 +1177,7 @@ int main(int argc, char **argv){
xDiff = summarize_one_table;
}else
if( strcmp(z,"table")==0 ){
if( i==argc-1 ) cmdlineError("missing argument to %s", argv[i]);
zTab = argv[++i];
}else
{
@ -1187,6 +1202,16 @@ int main(int argc, char **argv){
if( rc || zErrMsg ){
cmdlineError("\"%s\" does not appear to be a valid SQLite database", zDb1);
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
sqlite3_enable_load_extension(g.db, 1);
for(i=0; i<nExt; i++){
rc = sqlite3_load_extension(g.db, azExt[i], 0, &zErrMsg);
if( rc || zErrMsg ){
cmdlineError("error loading %s: %s", azExt[i], zErrMsg);
}
}
#endif
free(azExt);
zSql = sqlite3_mprintf("ATTACH %Q as aux;", zDb2);
rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);
if( rc || zErrMsg ){