Compare commits

..

1 Commits

Author SHA1 Message Date
drh 4b973dfd11 Experiments with an OP_Unpack opcode that extracts multiple columns from
a record without caching.

FossilOrigin-Name: 39ae92f5c63de4b95502f438dc7e9f2669efdf91
2015-10-15 20:17:15 +00:00
119 changed files with 2046 additions and 4355 deletions
+3 -4
View File
@@ -54,7 +54,6 @@ LIBTCL = @TCL_LIB_SPEC@
# Compiler options needed for programs that use the readline() library.
#
READLINE_FLAGS = -DHAVE_READLINE=@TARGET_HAVE_READLINE@ @TARGET_READLINE_INC@
READLINE_FLAGS += -DHAVE_EDITLINE=@TARGET_HAVE_EDITLINE@
# The library that programs using readline() must link against.
#
@@ -645,9 +644,9 @@ sqlite3.lo: sqlite3.c
# Rules to build the LEMON compiler generator
#
lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/src/lempar.c
$(BCC) -o $@ $(TOP)/tool/lemon.c
cp $(TOP)/tool/lempar.c .
cp $(TOP)/src/lempar.c .
# Rules to build individual *.o files from generated *.c files. This
# applies to:
@@ -1068,7 +1067,7 @@ fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA)
./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA)
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA)
valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M $(FUZZDATA)
# Minimal testing that runs in less than 3 minutes
#
+10 -10
View File
@@ -292,9 +292,9 @@ NSDKLIBPATH = $(NSDKLIBPATH:\\=\)
# will run on the platform that is doing the build.
#
!IF $(USE_FULLWARN)!=0
BCC = $(NCC) -nologo -W4 $(CCOPTS) $(BCCOPTS)
BCC = $(NCC) -nologo -W4
!ELSE
BCC = $(NCC) -nologo -W3 $(CCOPTS) $(BCCOPTS)
BCC = $(NCC) -nologo -W3
!ENDIF
# Check if assembly code listings should be generated for the source
@@ -322,13 +322,13 @@ NLTLIBPATHS = $(NLTLIBPATHS) "/LIBPATH:$(NUCRTLIBPATH)"
# same unless your are cross-compiling.)
#
!IF $(USE_FULLWARN)!=0
TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS)
TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1
!ELSE
TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS)
TCC = $(CC) -nologo -W3
!ENDIF
TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise
RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS)
RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src
# Check if we want to use the "stdcall" calling convention when compiling.
# This is not supported by the compilers for non-x86 platforms. It should
@@ -800,9 +800,7 @@ LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(PSDKLIBPATH)"
# If either debugging or symbols are enabled, enable PDBs.
#
!IF $(DEBUG)>1 || $(SYMBOLS)!=0
LDFLAGS = /DEBUG $(LDOPTS)
!ELSE
LDFLAGS = $(LDOPTS)
LDFLAGS = /DEBUG
!ENDIF
# Start with the Tcl related linker options.
@@ -1084,9 +1082,11 @@ TESTEXT = \
$(TOP)\ext\misc\eval.c \
$(TOP)\ext\misc\fileio.c \
$(TOP)\ext\misc\fuzzer.c \
fts5.c \
$(TOP)\ext\fts5\fts5_tcl.c \
$(TOP)\ext\fts5\fts5_test_mi.c \
$(TOP)\ext\misc\ieee754.c \
$(TOP)\ext\misc\json1.c \
$(TOP)\ext\misc\nextchar.c \
$(TOP)\ext\misc\percentile.c \
$(TOP)\ext\misc\regexp.c \
@@ -1310,8 +1310,8 @@ sqlite3.lo: $(SQLITE3C)
# Rules to build the LEMON compiler generator
#
lempar.c: $(TOP)\tool\lempar.c
copy $(TOP)\tool\lempar.c .
lempar.c: $(TOP)\src\lempar.c
copy $(TOP)\src\lempar.c .
lemon.exe: $(TOP)\tool\lemon.c lempar.c
$(BCC) $(NO_WARN) -Daccess=_access \
+1 -1
View File
@@ -1 +1 @@
3.10.0
3.9.0
+3 -17
View File
@@ -18,6 +18,7 @@ AC_SYS_LARGEFILE
# Check for required programs.
AC_PROG_CC
AC_PROG_RANLIB
AC_PROG_LIBTOOL
AC_PROG_MKDIR_P
@@ -29,27 +30,12 @@ AC_CONFIG_FILES([Makefile sqlite3.pc])
AC_SUBST(BUILD_CFLAGS)
#-----------------------------------------------------------------------
# --enable-editline
# --enable-readline
#
AC_ARG_ENABLE(editline, [AS_HELP_STRING(
[--enable-editline],
[use BSD libedit])],
[], [enable_editline=yes])
AC_ARG_ENABLE(readline, [AS_HELP_STRING(
[--enable-readline],
[use readline])],
[], [enable_readline=no])
if test x"$enable_editline" != xno ; then
sLIBS=$LIBS
LIBS=""
AC_SEARCH_LIBS([readline],[edit],[enable_readline=no],[enable_editline=no])
READLINE_LIBS=$LIBS
if test x"$LIBS" != "x"; then
AC_DEFINE([HAVE_EDITLINE],1,Define to use BSD editline)
fi
LIBS=$sLIBS
fi
[use readline in shell tool (yes, no) [default=yes]])],
[], [enable_readline=yes])
if test x"$enable_readline" != xno ; then
sLIBS=$LIBS
LIBS=""
+3 -3
View File
@@ -603,8 +603,8 @@ SubstituteFile(
sp = fopen(substitutions, "rt");
if (sp != NULL) {
while (fgets(szBuffer, cbBuffer, sp) != NULL) {
unsigned char *ks, *ke, *vs, *ve;
ks = (unsigned char*)szBuffer;
char *ks, *ke, *vs, *ve;
ks = szBuffer;
while (ks && *ks && isspace(*ks)) ++ks;
ke = ks;
while (ke && *ke && !isspace(*ke)) ++ke;
@@ -613,7 +613,7 @@ SubstituteFile(
ve = vs;
while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve;
*ke = 0, *ve = 0;
list_insert(&substPtr, (char*)ks, (char*)vs);
list_insert(&substPtr, ks, vs);
}
fclose(sp);
}
Vendored
+24 -101
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.10.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.9.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.10.0'
PACKAGE_STRING='sqlite 3.10.0'
PACKAGE_VERSION='3.9.0'
PACKAGE_STRING='sqlite 3.9.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -774,7 +774,6 @@ USE_GCOV
OPT_FEATURE_FLAGS
USE_AMALGAMATION
TARGET_DEBUG
TARGET_HAVE_EDITLINE
TARGET_HAVE_READLINE
TARGET_READLINE_INC
TARGET_READLINE_LIBS
@@ -896,7 +895,6 @@ enable_releasemode
enable_tempstore
enable_tcl
with_tcl
enable_editline
enable_readline
with_readline_lib
with_readline_inc
@@ -1460,7 +1458,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.10.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.9.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1525,7 +1523,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.10.0:";;
short | recursive ) echo "Configuration of sqlite 3.9.0:";;
esac
cat <<\_ACEOF
@@ -1544,8 +1542,7 @@ Optional Features:
--enable-tempstore Use an in-ram database for temporary tables
(never,no,yes,always)
--disable-tcl do not build TCL extension
--enable-editline enable BSD editline support
--disable-readline disable readline support
--disable-readline disable readline support [default=detect]
--enable-debug enable debugging & verbose explain
--disable-amalgamation Disable the amalgamation and instead build all files
separately
@@ -1646,7 +1643,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.10.0
sqlite configure 3.9.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2065,7 +2062,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.10.0, which was
It was created by sqlite $as_me 3.9.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3923,13 +3920,13 @@ if ${lt_cv_nm_interface+:} false; then :
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
(eval echo "\"\$as_me:3926: $ac_compile\"" >&5)
(eval echo "\"\$as_me:3923: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
(eval echo "\"\$as_me:3929: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval echo "\"\$as_me:3926: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
(eval echo "\"\$as_me:3932: output\"" >&5)
(eval echo "\"\$as_me:3929: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -5135,7 +5132,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
echo '#line 5138 "configure"' > conftest.$ac_ext
echo '#line 5135 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6660,11 +6657,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:6663: $lt_compile\"" >&5)
(eval echo "\"\$as_me:6660: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:6667: \$? = $ac_status" >&5
echo "$as_me:6664: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -6999,11 +6996,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7002: $lt_compile\"" >&5)
(eval echo "\"\$as_me:6999: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:7006: \$? = $ac_status" >&5
echo "$as_me:7003: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7104,11 +7101,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7107: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7104: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7111: \$? = $ac_status" >&5
echo "$as_me:7108: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -7159,11 +7156,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7162: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7159: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7166: \$? = $ac_status" >&5
echo "$as_me:7163: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -9539,7 +9536,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9542 "configure"
#line 9539 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -9635,7 +9632,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9638 "configure"
#line 9635 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10835,14 +10832,6 @@ fi
TARGET_READLINE_LIBS=""
TARGET_READLINE_INC=""
TARGET_HAVE_READLINE=0
TARGET_HAVE_EDITLINE=0
# Check whether --enable-editline was given.
if test "${enable_editline+set}" = set; then :
enableval=$enable_editline; with_editline=$enableval
else
with_editline=auto
fi
# Check whether --enable-readline was given.
if test "${enable_readline+set}" = set; then :
enableval=$enable_readline; with_readline=$enableval
@@ -10851,71 +10840,6 @@ else
fi
if test x"$with_editline" != xno; then
sLIBS=$LIBS
LIBS=""
TARGET_HAVE_EDITLINE=1
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing readline" >&5
$as_echo_n "checking for library containing readline... " >&6; }
if ${ac_cv_search_readline+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char readline ();
int
main ()
{
return readline ();
;
return 0;
}
_ACEOF
for ac_lib in '' edit; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_readline=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_readline+:} false; then :
break
fi
done
if ${ac_cv_search_readline+:} false; then :
else
ac_cv_search_readline=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_readline" >&5
$as_echo "$ac_cv_search_readline" >&6; }
ac_res=$ac_cv_search_readline
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
with_readline=no
else
TARGET_HAVE_EDITLINE=0
fi
TARGET_READLINE_LIBS=$LIBS
LIBS=$sLIBS
fi
if test x"$with_readline" != xno; then
found="yes"
@@ -11104,7 +11028,6 @@ fi
##########
# Figure out what C libraries are required to compile programs
# that use "fdatasync()" function.
@@ -12023,7 +11946,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=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.10.0, which was
This file was extended by sqlite $as_me 3.9.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12089,7 +12012,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.10.0
sqlite config.status 3.9.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+1 -15
View File
@@ -460,24 +460,11 @@ AC_SUBST(HAVE_TCL)
TARGET_READLINE_LIBS=""
TARGET_READLINE_INC=""
TARGET_HAVE_READLINE=0
TARGET_HAVE_EDITLINE=0
AC_ARG_ENABLE([editline],
[AC_HELP_STRING([--enable-editline],[enable BSD editline support])],
[with_editline=$enableval],
[with_editline=auto])
AC_ARG_ENABLE([readline],
[AC_HELP_STRING([--disable-readline],[disable readline support])],
[AC_HELP_STRING([--disable-readline],[disable readline support [default=detect]])],
[with_readline=$enableval],
[with_readline=auto])
if test x"$with_editline" != xno; then
sLIBS=$LIBS
LIBS=""
TARGET_HAVE_EDITLINE=1
AC_SEARCH_LIBS(readline,edit,[with_readline=no],[TARGET_HAVE_EDITLINE=0])
TARGET_READLINE_LIBS=$LIBS
LIBS=$sLIBS
fi
if test x"$with_readline" != xno; then
found="yes"
@@ -532,7 +519,6 @@ fi
AC_SUBST(TARGET_READLINE_LIBS)
AC_SUBST(TARGET_READLINE_INC)
AC_SUBST(TARGET_HAVE_READLINE)
AC_SUBST(TARGET_HAVE_EDITLINE)
##########
# Figure out what C libraries are required to compile programs
+3 -3
View File
@@ -205,13 +205,13 @@ static int getVarint32(const char *p, int *pi){
*/
/* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */
static int safe_isspace(char c){
return (c&0x80)==0 ? isspace((unsigned char)c) : 0;
return (c&0x80)==0 ? isspace(c) : 0;
}
static int safe_tolower(char c){
return (c&0x80)==0 ? tolower((unsigned char)c) : c;
return (c&0x80)==0 ? tolower(c) : c;
}
static int safe_isalnum(char c){
return (c&0x80)==0 ? isalnum((unsigned char)c) : 0;
return (c&0x80)==0 ? isalnum(c) : 0;
}
typedef enum DocListType {
+1 -1
View File
@@ -138,7 +138,7 @@ static int simpleNext(
** case-insensitivity.
*/
char ch = c->pCurrent[ii];
c->zToken[ii] = (unsigned char)ch<0x80 ? tolower((unsigned char)ch):ch;
c->zToken[ii] = (unsigned char)ch<0x80 ? tolower(ch) : ch;
}
c->zToken[n] = '\0';
*ppToken = c->zToken;
+5 -8
View File
@@ -160,7 +160,6 @@ struct Fts5Config {
int pgsz; /* Approximate page size used in %_data */
int nAutomerge; /* 'automerge' setting */
int nCrisisMerge; /* Maximum allowed segments per level */
int nHashSize; /* Bytes of memory for in-memory hash */
char *zRank; /* Name of rank function */
char *zRankArgs; /* Arguments to rank function */
@@ -225,7 +224,7 @@ struct Fts5Buffer {
int nSpace;
};
int sqlite3Fts5BufferSize(int*, Fts5Buffer*, int);
int sqlite3Fts5BufferGrow(int*, Fts5Buffer*, int);
void sqlite3Fts5BufferAppendVarint(int*, Fts5Buffer*, i64);
void sqlite3Fts5BufferAppendBlob(int*, Fts5Buffer*, int, const u8*);
void sqlite3Fts5BufferAppendString(int *, Fts5Buffer*, const char*);
@@ -233,19 +232,17 @@ void sqlite3Fts5BufferFree(Fts5Buffer*);
void sqlite3Fts5BufferZero(Fts5Buffer*);
void sqlite3Fts5BufferSet(int*, Fts5Buffer*, int, const u8*);
void sqlite3Fts5BufferAppendPrintf(int *, Fts5Buffer*, char *zFmt, ...);
void sqlite3Fts5BufferAppend32(int*, Fts5Buffer*, int);
char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...);
#define fts5BufferZero(x) sqlite3Fts5BufferZero(x)
#define fts5BufferGrow(a,b,c) sqlite3Fts5BufferGrow(a,b,c)
#define fts5BufferAppendVarint(a,b,c) sqlite3Fts5BufferAppendVarint(a,b,c)
#define fts5BufferFree(a) sqlite3Fts5BufferFree(a)
#define fts5BufferAppendBlob(a,b,c,d) sqlite3Fts5BufferAppendBlob(a,b,c,d)
#define fts5BufferSet(a,b,c,d) sqlite3Fts5BufferSet(a,b,c,d)
#define fts5BufferGrow(pRc,pBuf,nn) ( \
(pBuf)->n + (nn) <= (pBuf)->nSpace ? 0 : \
sqlite3Fts5BufferSize((pRc),(pBuf),(nn)+(pBuf)->n) \
)
#define fts5BufferAppend32(a,b,c) sqlite3Fts5BufferAppend32(a,b,c)
/* Write and decode big-endian 32-bit integer values */
void sqlite3Fts5Put32(u8*, int);
@@ -478,7 +475,7 @@ int sqlite3Fts5GetTokenizer(
char **pzErr
);
Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, Fts5Config **);
Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, int*);
/*
** End of interface to code in fts5.c.
+29 -17
View File
@@ -15,30 +15,36 @@
#include "fts5Int.h"
int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, int nByte){
int nNew = pBuf->nSpace ? pBuf->nSpace*2 : 64;
u8 *pNew;
while( nNew<nByte ){
nNew = nNew * 2;
}
pNew = sqlite3_realloc(pBuf->p, nNew);
if( pNew==0 ){
*pRc = SQLITE_NOMEM;
return 1;
}else{
pBuf->nSpace = nNew;
pBuf->p = pNew;
int sqlite3Fts5BufferGrow(int *pRc, Fts5Buffer *pBuf, int nByte){
if( (pBuf->n + nByte) > pBuf->nSpace ){
u8 *pNew;
int nNew = pBuf->nSpace ? pBuf->nSpace*2 : 64;
/* A no-op if an error has already occurred */
if( *pRc ) return 1;
while( nNew<(pBuf->n + nByte) ){
nNew = nNew * 2;
}
pNew = sqlite3_realloc(pBuf->p, nNew);
if( pNew==0 ){
*pRc = SQLITE_NOMEM;
return 1;
}else{
pBuf->nSpace = nNew;
pBuf->p = pNew;
}
}
return 0;
}
/*
** Encode value iVal as an SQLite varint and append it to the buffer object
** pBuf. If an OOM error occurs, set the error code in p.
*/
void sqlite3Fts5BufferAppendVarint(int *pRc, Fts5Buffer *pBuf, i64 iVal){
if( fts5BufferGrow(pRc, pBuf, 9) ) return;
if( sqlite3Fts5BufferGrow(pRc, pBuf, 9) ) return;
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iVal);
}
@@ -53,6 +59,12 @@ int sqlite3Fts5Get32(const u8 *aBuf){
return (aBuf[0] << 24) + (aBuf[1] << 16) + (aBuf[2] << 8) + aBuf[3];
}
void sqlite3Fts5BufferAppend32(int *pRc, Fts5Buffer *pBuf, int iVal){
if( sqlite3Fts5BufferGrow(pRc, pBuf, 4) ) return;
sqlite3Fts5Put32(&pBuf->p[pBuf->n], iVal);
pBuf->n += 4;
}
/*
** Append buffer nData/pData to buffer pBuf. If an OOM error occurs, set
** the error code in p. If an error has already occurred when this function
@@ -65,7 +77,7 @@ void sqlite3Fts5BufferAppendBlob(
const u8 *pData
){
assert( *pRc || nData>=0 );
if( fts5BufferGrow(pRc, pBuf, nData) ) return;
if( sqlite3Fts5BufferGrow(pRc, pBuf, nData) ) return;
memcpy(&pBuf->p[pBuf->n], pData, nData);
pBuf->n += nData;
}
@@ -215,7 +227,7 @@ int sqlite3Fts5PoslistWriterAppend(
){
static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32;
int rc = SQLITE_OK;
if( 0==fts5BufferGrow(&rc, pBuf, 5+5+5) ){
if( 0==sqlite3Fts5BufferGrow(&rc, pBuf, 5+5+5) ){
if( (iPos & colmask) != (pWriter->iPrev & colmask) ){
pBuf->p[pBuf->n++] = 1;
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32));
+25 -43
View File
@@ -20,7 +20,6 @@
#define FTS5_DEFAULT_PAGE_SIZE 4050
#define FTS5_DEFAULT_AUTOMERGE 4
#define FTS5_DEFAULT_CRISISMERGE 16
#define FTS5_DEFAULT_HASHSIZE (1024*1024)
/* Maximum allowed page size */
#define FTS5_MAX_PAGE_SIZE (128*1024)
@@ -707,37 +706,33 @@ int sqlite3Fts5ConfigParseRank(
*pzRank = 0;
*pzRankArgs = 0;
if( p==0 ){
rc = SQLITE_ERROR;
p = fts5ConfigSkipWhitespace(p);
pRank = p;
p = fts5ConfigSkipBareword(p);
if( p ){
zRank = sqlite3Fts5MallocZero(&rc, 1 + p - pRank);
if( zRank ) memcpy(zRank, pRank, p-pRank);
}else{
rc = SQLITE_ERROR;
}
if( rc==SQLITE_OK ){
p = fts5ConfigSkipWhitespace(p);
pRank = p;
p = fts5ConfigSkipBareword(p);
if( p ){
zRank = sqlite3Fts5MallocZero(&rc, 1 + p - pRank);
if( zRank ) memcpy(zRank, pRank, p-pRank);
}else{
rc = SQLITE_ERROR;
}
if( rc==SQLITE_OK ){
p = fts5ConfigSkipWhitespace(p);
if( *p!='(' ) rc = SQLITE_ERROR;
p++;
}
if( rc==SQLITE_OK ){
const char *pArgs;
p = fts5ConfigSkipWhitespace(p);
pArgs = p;
if( *p!=')' ){
p = fts5ConfigSkipArgs(p);
if( p==0 ){
rc = SQLITE_ERROR;
}else{
zRankArgs = sqlite3Fts5MallocZero(&rc, 1 + p - pArgs);
if( zRankArgs ) memcpy(zRankArgs, pArgs, p-pArgs);
}
if( *p!='(' ) rc = SQLITE_ERROR;
p++;
}
if( rc==SQLITE_OK ){
const char *pArgs;
p = fts5ConfigSkipWhitespace(p);
pArgs = p;
if( *p!=')' ){
p = fts5ConfigSkipArgs(p);
if( p==0 ){
rc = SQLITE_ERROR;
}else{
zRankArgs = sqlite3Fts5MallocZero(&rc, 1 + p - pArgs);
if( zRankArgs ) memcpy(zRankArgs, pArgs, p-pArgs);
}
}
}
@@ -772,18 +767,6 @@ int sqlite3Fts5ConfigSetValue(
}
}
else if( 0==sqlite3_stricmp(zKey, "hashsize") ){
int nHashSize = -1;
if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
nHashSize = sqlite3_value_int(pVal);
}
if( nHashSize<=0 ){
*pbBadkey = 1;
}else{
pConfig->nHashSize = nHashSize;
}
}
else if( 0==sqlite3_stricmp(zKey, "automerge") ){
int nAutomerge = -1;
if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
@@ -844,7 +827,6 @@ int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){
pConfig->pgsz = FTS5_DEFAULT_PAGE_SIZE;
pConfig->nAutomerge = FTS5_DEFAULT_AUTOMERGE;
pConfig->nCrisisMerge = FTS5_DEFAULT_CRISISMERGE;
pConfig->nHashSize = FTS5_DEFAULT_HASHSIZE;
zSql = sqlite3Fts5Mprintf(&rc, zSelect, pConfig->zDb, pConfig->zName);
if( zSql ){
+81 -139
View File
@@ -288,6 +288,7 @@ struct Fts5Index {
** in-memory hash tables before they are flushed to disk.
*/
Fts5Hash *pHash; /* Hash table for in-memory data */
int nMaxPendingData; /* Max pending data before flush to disk */
int nPendingData; /* Current bytes of pending data */
i64 iWriteRowid; /* Rowid for current doc being written */
int bDelete; /* Current write is a delete */
@@ -373,6 +374,26 @@ struct Fts5SegWriter {
int iBtPage; /* Page number corresponding to btterm */
};
/*
** Object for iterating through the merged results of one or more segments,
** visiting each term/rowid pair in the merged data.
**
** nSeg is always a power of two greater than or equal to the number of
** segments that this object is merging data from. Both the aSeg[] and
** aFirst[] arrays are sized at nSeg entries. The aSeg[] array is padded
** with zeroed objects - these are handled as if they were iterators opened
** on empty segments.
**
** The results of comparing segments aSeg[N] and aSeg[N+1], where N is an
** even number, is stored in aFirst[(nSeg+N)/2]. The "result" of the
** comparison in this context is the index of the iterator that currently
** points to the smaller term/rowid combination. Iterators at EOF are
** considered to be greater than all other iterators.
**
** aFirst[1] contains the index in aSeg[] of the iterator that points to
** the smallest key overall. aFirst[0] is unused.
*/
typedef struct Fts5CResult Fts5CResult;
struct Fts5CResult {
u16 iFirst; /* aSeg[] index of firstest iterator */
@@ -479,24 +500,6 @@ struct Fts5SegIter {
#define fts5LeafFirstRowidOff(x) (fts5GetU16((x)->p))
/*
** Object for iterating through the merged results of one or more segments,
** visiting each term/rowid pair in the merged data.
**
** nSeg is always a power of two greater than or equal to the number of
** segments that this object is merging data from. Both the aSeg[] and
** aFirst[] arrays are sized at nSeg entries. The aSeg[] array is padded
** with zeroed objects - these are handled as if they were iterators opened
** on empty segments.
**
** The results of comparing segments aSeg[N] and aSeg[N+1], where N is an
** even number, is stored in aFirst[(nSeg+N)/2]. The "result" of the
** comparison in this context is the index of the iterator that currently
** points to the smaller term/rowid combination. Iterators at EOF are
** considered to be greater than all other iterators.
**
** aFirst[1] contains the index in aSeg[] of the iterator that points to
** the smallest key overall. aFirst[0] is unused.
**
** poslist:
** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered.
** There is no way to tell if this is populated or not.
@@ -1005,18 +1008,6 @@ static int fts5StructureCountSegments(Fts5Structure *pStruct){
}
#endif
#define fts5BufferSafeAppendBlob(pBuf, pBlob, nBlob) { \
assert( (pBuf)->nSpace>=((pBuf)->n+nBlob) ); \
memcpy(&(pBuf)->p[(pBuf)->n], pBlob, nBlob); \
(pBuf)->n += nBlob; \
}
#define fts5BufferSafeAppendVarint(pBuf, iVal) { \
(pBuf)->n += sqlite3Fts5PutVarint(&(pBuf)->p[(pBuf)->n], (iVal)); \
assert( (pBuf)->nSpace>=(pBuf)->n ); \
}
/*
** Serialize and store the "structure" record.
**
@@ -1035,14 +1026,11 @@ static void fts5StructureWrite(Fts5Index *p, Fts5Structure *pStruct){
/* Append the current configuration cookie */
iCookie = p->pConfig->iCookie;
if( iCookie<0 ) iCookie = 0;
fts5BufferAppend32(&p->rc, &buf, iCookie);
if( 0==sqlite3Fts5BufferSize(&p->rc, &buf, 4+9+9+9) ){
sqlite3Fts5Put32(buf.p, iCookie);
buf.n = 4;
fts5BufferSafeAppendVarint(&buf, pStruct->nLevel);
fts5BufferSafeAppendVarint(&buf, pStruct->nSegment);
fts5BufferSafeAppendVarint(&buf, (i64)pStruct->nWriteCounter);
}
fts5BufferAppendVarint(&p->rc, &buf, pStruct->nLevel);
fts5BufferAppendVarint(&p->rc, &buf, pStruct->nSegment);
fts5BufferAppendVarint(&p->rc, &buf, (i64)pStruct->nWriteCounter);
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
int iSeg; /* Used to iterate through segments */
@@ -1498,7 +1486,6 @@ static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){
pIter->bDel = (nSz & 0x0001);
pIter->nPos = nSz>>1;
pIter->iLeafOffset = iOff;
assert_nc( pIter->nPos>=0 );
}
}
@@ -1672,13 +1659,12 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){
if( pNew ){
/* iTermLeafOffset may be equal to szLeaf if the term is the last
** thing on the page - i.e. the first rowid is on the following page.
** In this case leave pIter->pLeaf==0, this iterator is at EOF. */
if( pIter->iLeafPgno==pIter->iTermLeafPgno ){
assert( pIter->pLeaf==0 );
if( pIter->iTermLeafOffset<pNew->szLeaf ){
pIter->pLeaf = pNew;
pIter->iLeafOffset = pIter->iTermLeafOffset;
}
** In this case leaf pIter->pLeaf==0, this iterator is at EOF. */
if( pIter->iLeafPgno==pIter->iTermLeafPgno
&& pIter->iTermLeafOffset<pNew->szLeaf
){
pIter->pLeaf = pNew;
pIter->iLeafOffset = pIter->iTermLeafOffset;
}else{
int iRowidOff;
iRowidOff = fts5LeafFirstRowidOff(pNew);
@@ -1844,15 +1830,7 @@ static void fts5SegIterNext(
if( pbNewTerm ) *pbNewTerm = 1;
}
}else{
/* The following could be done by calling fts5SegIterLoadNPos(). But
** this block is particularly performance critical, so equivalent
** code is inlined. */
int nSz;
assert( p->rc==SQLITE_OK );
fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
pIter->bDel = (nSz & 0x0001);
pIter->nPos = nSz>>1;
assert_nc( pIter->nPos>=0 );
fts5SegIterLoadNPos(p, pIter);
}
}
}
@@ -2061,14 +2039,11 @@ static void fts5LeafSeek(
if( pIter->pLeaf==0 ) return;
a = pIter->pLeaf->p;
if( fts5LeafIsTermless(pIter->pLeaf)==0 ){
iPgidx = pIter->pLeaf->szLeaf;
iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff);
fts5GetVarint32(&pIter->pLeaf->p[pIter->pLeaf->szLeaf], iOff);
if( iOff<4 || iOff>=pIter->pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
}else{
nKeep = 0;
iTermOff = iOff;
n = pIter->pLeaf->nn;
iOff += fts5GetVarint32(&a[iOff], nNew);
break;
}
@@ -2618,35 +2593,6 @@ static void fts5MultiIterNext(
}
}
static void fts5MultiIterNext2(
Fts5Index *p,
Fts5IndexIter *pIter,
int *pbNewTerm /* OUT: True if *might* be new term */
){
assert( pIter->bSkipEmpty );
if( p->rc==SQLITE_OK ){
do {
int iFirst = pIter->aFirst[1].iFirst;
Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
int bNewTerm = 0;
fts5SegIterNext(p, pSeg, &bNewTerm);
if( pSeg->pLeaf==0 || bNewTerm
|| fts5MultiIterAdvanceRowid(p, pIter, iFirst)
){
fts5MultiIterAdvanced(p, pIter, iFirst, 1);
fts5MultiIterSetEof(pIter);
*pbNewTerm = 1;
}else{
*pbNewTerm = 0;
}
fts5AssertMultiIterSetup(p, pIter);
}while( fts5MultiIterIsEmpty(p, pIter) );
}
}
static Fts5IndexIter *fts5MultiIterAlloc(
Fts5Index *p, /* FTS5 backend to iterate within */
int nSeg
@@ -3400,12 +3346,9 @@ static void fts5WriteInit(
pWriter->bFirstTermInPage = 1;
pWriter->iBtPage = 1;
assert( pWriter->writer.buf.n==0 );
assert( pWriter->writer.pgidx.n==0 );
/* Grow the two buffers to pgsz + padding bytes in size. */
sqlite3Fts5BufferSize(&p->rc, &pWriter->writer.pgidx, nBuffer);
sqlite3Fts5BufferSize(&p->rc, &pWriter->writer.buf, nBuffer);
fts5BufferGrow(&p->rc, &pWriter->writer.pgidx, nBuffer);
fts5BufferGrow(&p->rc, &pWriter->writer.buf, nBuffer);
if( p->pIdxWriter==0 ){
Fts5Config *pConfig = p->pConfig;
@@ -3758,6 +3701,17 @@ static int fts5PoslistPrefix(const u8 *aBuf, int nMax){
return ret;
}
#define fts5BufferSafeAppendBlob(pBuf, pBlob, nBlob) { \
assert( (pBuf)->nSpace>=((pBuf)->n+nBlob) ); \
memcpy(&(pBuf)->p[(pBuf)->n], pBlob, nBlob); \
(pBuf)->n += nBlob; \
}
#define fts5BufferSafeAppendVarint(pBuf, iVal) { \
(pBuf)->n += sqlite3Fts5PutVarint(&(pBuf)->p[(pBuf)->n], (iVal)); \
assert( (pBuf)->nSpace>=(pBuf)->n ); \
}
/*
** Flush the contents of in-memory hash table iHash to a new level-0
** segment on disk. Also update the corresponding structure record.
@@ -4106,7 +4060,7 @@ static int fts5IndexExtractCol(
const u8 *pEnd = &p[n]; /* One byte past end of position list */
u8 prev = 0;
while( iCol>iCurrent ){
while( iCol!=iCurrent ){
/* Advance pointer p until it points to pEnd or an 0x01 byte that is
** not part of a varint */
while( (prev & 0x80) || *p!=0x01 ){
@@ -4116,7 +4070,6 @@ static int fts5IndexExtractCol(
*pa = p++;
p += fts5GetVarint32(p, iCurrent);
}
if( iCol!=iCurrent ) return 0;
/* Advance pointer p until it points to pEnd or an 0x01 byte that is
** not part of a varint */
@@ -4154,6 +4107,18 @@ static int fts5AppendPoslist(
assert( fts5MultiIterEof(p, pMulti)==0 );
assert( pSeg->nPos>0 );
if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+9+9) ){
int iSv1;
int iSv2;
int iData;
/* Append iDelta */
iSv1 = pBuf->n;
fts5BufferSafeAppendVarint(pBuf, iDelta);
/* WRITEPOSLISTSIZE */
iSv2 = pBuf->n;
fts5BufferSafeAppendVarint(pBuf, pSeg->nPos*2);
iData = pBuf->n;
if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf
&& (pColset==0 || pColset->nCol==1)
@@ -4162,45 +4127,27 @@ static int fts5AppendPoslist(
int nPos;
if( pColset ){
nPos = fts5IndexExtractCol(&pPos, pSeg->nPos, pColset->aiCol[0]);
if( nPos==0 ) return 1;
}else{
nPos = pSeg->nPos;
}
assert( nPos>0 );
fts5BufferSafeAppendVarint(pBuf, iDelta);
fts5BufferSafeAppendVarint(pBuf, nPos*2);
fts5BufferSafeAppendBlob(pBuf, pPos, nPos);
}else{
int iSv1;
int iSv2;
int iData;
/* Append iDelta */
iSv1 = pBuf->n;
fts5BufferSafeAppendVarint(pBuf, iDelta);
/* WRITEPOSLISTSIZE */
iSv2 = pBuf->n;
fts5BufferSafeAppendVarint(pBuf, pSeg->nPos*2);
iData = pBuf->n;
fts5SegiterPoslist(p, pSeg, pColset, pBuf);
}
if( pColset ){
int nActual = pBuf->n - iData;
if( nActual!=pSeg->nPos ){
if( nActual==0 ){
pBuf->n = iSv1;
return 1;
}else{
int nReq = sqlite3Fts5GetVarintLen((u32)(nActual*2));
while( iSv2<(iData-nReq) ){ pBuf->p[iSv2++] = 0x80; }
sqlite3Fts5PutVarint(&pBuf->p[iSv2], nActual*2);
}
if( pColset ){
int nActual = pBuf->n - iData;
if( nActual!=pSeg->nPos ){
if( nActual==0 ){
pBuf->n = iSv1;
return 1;
}else{
int nReq = sqlite3Fts5GetVarintLen((u32)(nActual*2));
while( iSv2<(iData-nReq) ){ pBuf->p[iSv2++] = 0x80; }
sqlite3Fts5PutVarint(&pBuf->p[iSv2], nActual*2);
}
}
}
}
}
@@ -4289,7 +4236,7 @@ static void fts5MergePrefixLists(
memset(&out, 0, sizeof(out));
memset(&tmp, 0, sizeof(tmp));
sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n);
sqlite3Fts5BufferGrow(&p->rc, &out, p1->n + p2->n);
fts5DoclistIterInit(p1, &i1);
fts5DoclistIterInit(p2, &i2);
while( p->rc==SQLITE_OK && (i1.aPoslist!=0 || i2.aPoslist!=0) ){
@@ -4380,20 +4327,17 @@ static void fts5SetupPrefixIter(
Fts5IndexIter *p1 = 0; /* Iterator used to gather data from index */
Fts5Data *pData;
Fts5Buffer doclist;
int bNewTerm = 1;
memset(&doclist, 0, sizeof(doclist));
for(fts5MultiIterNew(p, pStruct, 1, flags, pToken, nToken, -1, 0, &p1);
fts5MultiIterEof(p, p1)==0;
fts5MultiIterNext2(p, p1, &bNewTerm)
fts5MultiIterNext(p, p1, 0, 0)
){
i64 iRowid = fts5MultiIterRowid(p1);
int nTerm;
const u8 *pTerm = fts5MultiIterTerm(p1, &nTerm);
assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 );
if( bNewTerm ){
if( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break;
}
if( nTerm<nToken || memcmp(pToken, pTerm, nToken) ) break;
if( doclist.n>0 && iRowid<=iLastRowid ){
for(i=0; p->rc==SQLITE_OK && doclist.n; i++){
@@ -4452,7 +4396,7 @@ int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
/* Flush the hash table to disk if required */
if( iRowid<p->iWriteRowid
|| (iRowid==p->iWriteRowid && p->bDelete==0)
|| (p->nPendingData > p->pConfig->nHashSize)
|| (p->nPendingData > p->nMaxPendingData)
){
fts5IndexFlush(p);
}
@@ -4518,6 +4462,7 @@ int sqlite3Fts5IndexOpen(
if( rc==SQLITE_OK ){
p->pConfig = pConfig;
p->nWorkUnit = FTS5_WORK_UNIT;
p->nMaxPendingData = 1024*1024;
p->zDataTbl = sqlite3Fts5Mprintf(&rc, "%s_data", pConfig->zName);
if( p->zDataTbl && bCreate ){
rc = sqlite3Fts5CreateTable(
@@ -4652,9 +4597,11 @@ int sqlite3Fts5IndexQuery(
Fts5Buffer buf = {0, 0, 0};
/* If the QUERY_SCAN flag is set, all other flags must be clear. */
assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN );
assert( (flags & FTS5INDEX_QUERY_SCAN)==0
|| (flags & FTS5INDEX_QUERY_SCAN)==FTS5INDEX_QUERY_SCAN
);
if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
if( sqlite3Fts5BufferGrow(&p->rc, &buf, nToken+1)==0 ){
memcpy(&buf.p[1], pToken, nToken);
#ifdef SQLITE_DEBUG
@@ -5339,11 +5286,9 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
Fts5IndexIter *pIter; /* Used to iterate through entire index */
Fts5Structure *pStruct; /* Index structure */
#ifdef SQLITE_DEBUG
/* Used by extra internal tests only run if NDEBUG is not defined */
u64 cksum3 = 0; /* Checksum based on contents of indexes */
Fts5Buffer term = {0,0,0}; /* Buffer used to hold most recent term */
#endif
/* Load the FTS index structure */
pStruct = fts5StructureRead(p);
@@ -5399,9 +5344,7 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
if( p->rc==SQLITE_OK && cksum!=cksum2 ) p->rc = FTS5_CORRUPT;
fts5StructureRelease(pStruct);
#ifdef SQLITE_DEBUG
fts5BufferFree(&term);
#endif
fts5BufferFree(&poslist);
return fts5IndexReturn(p);
}
@@ -5586,9 +5529,8 @@ static int fts5DecodeDoclist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
}
while( iOff<n ){
int nPos;
int bDel;
iOff += fts5GetPoslistSize(&a[iOff], &nPos, &bDel);
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " nPos=%d%s", nPos, bDel?"*":"");
int bDummy;
iOff += fts5GetPoslistSize(&a[iOff], &nPos, &bDummy);
iOff += fts5DecodePoslist(pRc, pBuf, &a[iOff], MIN(n-iOff, nPos));
if( iOff<n ){
i64 iDelta;
+13 -50
View File
@@ -395,15 +395,6 @@ static int fts5InitVtab(
rc = sqlite3Fts5ConfigDeclareVtab(pConfig);
}
/* Load the initial configuration */
if( rc==SQLITE_OK ){
assert( pConfig->pzErrmsg==0 );
pConfig->pzErrmsg = pzErr;
rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
sqlite3Fts5IndexRollback(pTab->pIndex);
pConfig->pzErrmsg = 0;
}
if( rc!=SQLITE_OK ){
fts5FreeVtab(pTab);
pTab = 0;
@@ -838,42 +829,13 @@ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){
return rc;
}
static sqlite3_stmt *fts5PrepareStatement(
int *pRc,
Fts5Config *pConfig,
const char *zFmt,
...
){
sqlite3_stmt *pRet = 0;
va_list ap;
va_start(ap, zFmt);
if( *pRc==SQLITE_OK ){
int rc;
char *zSql = sqlite3_vmprintf(zFmt, ap);
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pRet, 0);
if( rc!=SQLITE_OK ){
*pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
}
sqlite3_free(zSql);
}
*pRc = rc;
}
va_end(ap);
return pRet;
}
static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
Fts5Config *pConfig = pTab->pConfig;
Fts5Sorter *pSorter;
int nPhrase;
int nByte;
int rc = SQLITE_OK;
char *zSql;
const char *zRank = pCsr->zRank;
const char *zRankArgs = pCsr->zRankArgs;
@@ -891,13 +853,17 @@ static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
** table, saving it creates a circular reference.
**
** If SQLite a built-in statement cache, this wouldn't be a problem. */
pSorter->pStmt = fts5PrepareStatement(&rc, pConfig,
zSql = sqlite3Fts5Mprintf(&rc,
"SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s",
pConfig->zDb, pConfig->zName, zRank, pConfig->zName,
(zRankArgs ? ", " : ""),
(zRankArgs ? zRankArgs : ""),
bDesc ? "DESC" : "ASC"
);
if( zSql ){
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pSorter->pStmt, 0);
sqlite3_free(zSql);
}
pCsr->pSorter = pSorter;
if( rc==SQLITE_OK ){
@@ -1485,10 +1451,7 @@ static int fts5UpdateMethod(
**
** Cases 3 and 4 may violate the rowid constraint.
*/
int eConflict = SQLITE_ABORT;
if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
eConflict = sqlite3_vtab_on_conflict(pConfig->db);
}
int eConflict = sqlite3_vtab_on_conflict(pConfig->db);
assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
assert( nArg!=1 || eType0==SQLITE_INTEGER );
@@ -2058,20 +2021,20 @@ static void fts5ApiCallback(
** Given cursor id iId, return a pointer to the corresponding Fts5Index
** object. Or NULL If the cursor id does not exist.
**
** If successful, set *ppConfig to point to the associated config object
** before returning.
** If successful, set *pnCol to the number of indexed columns in the
** table before returning.
*/
Fts5Index *sqlite3Fts5IndexFromCsrid(
Fts5Global *pGlobal, /* FTS5 global context for db handle */
i64 iCsrId, /* Id of cursor to find */
Fts5Config **ppConfig /* OUT: Configuration object */
Fts5Global *pGlobal,
i64 iCsrId,
int *pnCol
){
Fts5Cursor *pCsr;
Fts5Table *pTab;
pCsr = fts5CursorFromCsrid(pGlobal, iCsrId);
pTab = (Fts5Table*)pCsr->base.pVtab;
*ppConfig = pTab->pConfig;
*pnCol = pTab->pConfig->nCol;
return pTab->pIndex;
}
+9 -11
View File
@@ -513,15 +513,13 @@ int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel){
}
/* Delete the %_content record */
if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
if( rc==SQLITE_OK ){
rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_CONTENT, &pDel, 0);
}
if( rc==SQLITE_OK ){
sqlite3_bind_int64(pDel, 1, iDel);
sqlite3_step(pDel);
rc = sqlite3_reset(pDel);
}
if( rc==SQLITE_OK ){
rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_CONTENT, &pDel, 0);
}
if( rc==SQLITE_OK ){
sqlite3_bind_int64(pDel, 1, iDel);
sqlite3_step(pDel);
rc = sqlite3_reset(pDel);
}
/* Write the averages record */
@@ -916,12 +914,12 @@ int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
/* Check that the %_docsize and %_content tables contain the expected
** number of rows. */
if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
i64 nRow = 0;
i64 nRow;
rc = fts5StorageCount(p, "content", &nRow);
if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
}
if( rc==SQLITE_OK && pConfig->bColumnsize ){
i64 nRow = 0;
i64 nRow;
rc = fts5StorageCount(p, "docsize", &nRow);
if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
}
+35 -147
View File
@@ -55,18 +55,16 @@ struct Fts5VocabCursor {
int bEof; /* True if this cursor is at EOF */
Fts5IndexIter *pIter; /* Term/rowid iterator object */
int nLeTerm; /* Size of zLeTerm in bytes */
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
/* These are used by 'col' tables only */
Fts5Config *pConfig; /* Fts5 table configuration */
int nCol;
int iCol;
i64 *aCnt;
i64 *aDoc;
/* Output values used by 'row' and 'col' tables */
/* Output values */
i64 rowid; /* This table's current rowid value */
Fts5Buffer term; /* Current value of 'term' column */
i64 aVal[3]; /* Up to three columns left of 'term' */
};
#define FTS5_VOCAB_COL 0
@@ -75,14 +73,6 @@ struct Fts5VocabCursor {
#define FTS5_VOCAB_COL_SCHEMA "term, col, doc, cnt"
#define FTS5_VOCAB_ROW_SCHEMA "term, doc, cnt"
/*
** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
*/
#define FTS5_VOCAB_TERM_EQ 0x01
#define FTS5_VOCAB_TERM_GE 0x02
#define FTS5_VOCAB_TERM_LE 0x04
/*
** Translate a string containing an fts5vocab table type to an
** FTS5_VOCAB_XXX constant. If successful, set *peType to the output
@@ -180,7 +170,7 @@ static int fts5VocabInitVtab(
const char *zType = bDb ? argv[5] : argv[4];
int nDb = (int)strlen(zDb)+1;
int nTab = (int)strlen(zTab)+1;
int eType = 0;
int eType;
rc = fts5VocabTableType(zType, pzErr, &eType);
if( rc==SQLITE_OK ){
@@ -240,45 +230,6 @@ static int fts5VocabBestIndexMethod(
sqlite3_vtab *pVTab,
sqlite3_index_info *pInfo
){
int i;
int iTermEq = -1;
int iTermGe = -1;
int iTermLe = -1;
int idxNum = 0;
int nArg = 0;
for(i=0; i<pInfo->nConstraint; i++){
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
if( p->usable==0 ) continue;
if( p->iColumn==0 ){ /* term column */
if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ) iTermEq = i;
if( p->op==SQLITE_INDEX_CONSTRAINT_LE ) iTermLe = i;
if( p->op==SQLITE_INDEX_CONSTRAINT_LT ) iTermLe = i;
if( p->op==SQLITE_INDEX_CONSTRAINT_GE ) iTermGe = i;
if( p->op==SQLITE_INDEX_CONSTRAINT_GT ) iTermGe = i;
}
}
if( iTermEq>=0 ){
idxNum |= FTS5_VOCAB_TERM_EQ;
pInfo->aConstraintUsage[iTermEq].argvIndex = ++nArg;
pInfo->estimatedCost = 100;
}else{
pInfo->estimatedCost = 1000000;
if( iTermGe>=0 ){
idxNum |= FTS5_VOCAB_TERM_GE;
pInfo->aConstraintUsage[iTermGe].argvIndex = ++nArg;
pInfo->estimatedCost = pInfo->estimatedCost / 2;
}
if( iTermLe>=0 ){
idxNum |= FTS5_VOCAB_TERM_LE;
pInfo->aConstraintUsage[iTermLe].argvIndex = ++nArg;
pInfo->estimatedCost = pInfo->estimatedCost / 2;
}
}
pInfo->idxNum = idxNum;
return SQLITE_OK;
}
@@ -291,11 +242,12 @@ static int fts5VocabOpenMethod(
){
Fts5VocabTable *pTab = (Fts5VocabTable*)pVTab;
Fts5Index *pIndex = 0;
Fts5Config *pConfig = 0;
int nCol = 0;
Fts5VocabCursor *pCsr = 0;
int rc = SQLITE_OK;
sqlite3_stmt *pStmt = 0;
char *zSql = 0;
int nByte;
zSql = sqlite3Fts5Mprintf(&rc,
"SELECT t.%Q FROM %Q.%Q AS t WHERE t.%Q MATCH '*id'",
@@ -310,7 +262,7 @@ static int fts5VocabOpenMethod(
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
i64 iId = sqlite3_column_int64(pStmt, 0);
pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &pConfig);
pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &nCol);
}
if( rc==SQLITE_OK && pIndex==0 ){
@@ -324,17 +276,14 @@ static int fts5VocabOpenMethod(
}
}
if( rc==SQLITE_OK ){
int nByte = pConfig->nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor);
pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
}
nByte = nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor);
pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
if( pCsr ){
pCsr->pIndex = pIndex;
pCsr->pStmt = pStmt;
pCsr->pConfig = pConfig;
pCsr->nCol = nCol;
pCsr->aCnt = (i64*)&pCsr[1];
pCsr->aDoc = &pCsr->aCnt[pConfig->nCol];
pCsr->aDoc = &pCsr->aCnt[nCol];
}else{
sqlite3_finalize(pStmt);
}
@@ -347,9 +296,6 @@ static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
pCsr->rowid = 0;
sqlite3Fts5IterClose(pCsr->pIter);
pCsr->pIter = 0;
sqlite3_free(pCsr->zLeTerm);
pCsr->nLeTerm = -1;
pCsr->zLeTerm = 0;
}
/*
@@ -373,17 +319,16 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
int rc = SQLITE_OK;
int nCol = pCsr->pConfig->nCol;
pCsr->rowid++;
if( pTab->eType==FTS5_VOCAB_COL ){
for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){
for(pCsr->iCol++; pCsr->iCol<pCsr->nCol; pCsr->iCol++){
if( pCsr->aCnt[pCsr->iCol] ) break;
}
}
if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){
if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=pCsr->nCol ){
if( sqlite3Fts5IterEof(pCsr->pIter) ){
pCsr->bEof = 1;
}else{
@@ -391,18 +336,10 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
int nTerm;
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
if( pCsr->nLeTerm>=0 ){
int nCmp = MIN(nTerm, pCsr->nLeTerm);
int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){
pCsr->bEof = 1;
return SQLITE_OK;
}
}
sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm);
memset(pCsr->aCnt, 0, nCol * sizeof(i64));
memset(pCsr->aDoc, 0, nCol * sizeof(i64));
memset(pCsr->aVal, 0, sizeof(pCsr->aVal));
memset(pCsr->aCnt, 0, pCsr->nCol * sizeof(i64));
memset(pCsr->aDoc, 0, pCsr->nCol * sizeof(i64));
pCsr->iCol = 0;
assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
@@ -416,9 +353,9 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
if( rc==SQLITE_OK ){
if( pTab->eType==FTS5_VOCAB_ROW ){
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
pCsr->aCnt[0]++;
pCsr->aVal[1]++;
}
pCsr->aDoc[0]++;
pCsr->aVal[0]++;
}else{
int iCol = -1;
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
@@ -432,12 +369,9 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
}
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
}
if( rc==SQLITE_OK ){
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ){
break;
}
if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ) break;
if( sqlite3Fts5IterEof(pCsr->pIter) ) break;
}
}
@@ -446,7 +380,9 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
if( pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){
while( pCsr->aCnt[pCsr->iCol]==0 ) pCsr->iCol++;
assert( pCsr->iCol<pCsr->pConfig->nCol );
pCsr->aVal[0] = pCsr->iCol;
pCsr->aVal[1] = pCsr->aDoc[pCsr->iCol];
pCsr->aVal[2] = pCsr->aCnt[pCsr->iCol];
}
return rc;
}
@@ -462,47 +398,11 @@ static int fts5VocabFilterMethod(
sqlite3_value **apVal /* Arguments for the indexing scheme */
){
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
int rc = SQLITE_OK;
int iVal = 0;
int f = FTS5INDEX_QUERY_SCAN;
const char *zTerm = 0;
int nTerm = 0;
sqlite3_value *pEq = 0;
sqlite3_value *pGe = 0;
sqlite3_value *pLe = 0;
int rc;
const int flags = FTS5INDEX_QUERY_SCAN;
fts5VocabResetCursor(pCsr);
if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
if( pEq ){
zTerm = (const char *)sqlite3_value_text(pEq);
nTerm = sqlite3_value_bytes(pEq);
f = 0;
}else{
if( pGe ){
zTerm = (const char *)sqlite3_value_text(pGe);
nTerm = sqlite3_value_bytes(pGe);
}
if( pLe ){
const char *zCopy = (const char *)sqlite3_value_text(pLe);
pCsr->nLeTerm = sqlite3_value_bytes(pLe);
pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1);
if( pCsr->zLeTerm==0 ){
rc = SQLITE_NOMEM;
}else{
memcpy(pCsr->zLeTerm, zCopy, pCsr->nLeTerm+1);
}
}
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
}
rc = sqlite3Fts5IndexQuery(pCsr->pIndex, 0, 0, flags, 0, &pCsr->pIter);
if( rc==SQLITE_OK ){
rc = fts5VocabNextMethod(pCursor);
}
@@ -525,29 +425,17 @@ static int fts5VocabColumnMethod(
int iCol /* Index of column to read value from */
){
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
switch( iCol ){
case 0: /* term */
sqlite3_result_text(
pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT
);
break;
if( iCol==0 ){
sqlite3_result_text(
pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT
);
}
else if( ((Fts5VocabTable*)(pCursor->pVtab))->eType==FTS5_VOCAB_COL ){
assert( iCol==1 || iCol==2 || iCol==3 );
if( iCol==1 ){
const char *z = pCsr->pConfig->azCol[pCsr->iCol];
sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
}else if( iCol==2 ){
sqlite3_result_int64(pCtx, pCsr->aDoc[pCsr->iCol]);
}else{
sqlite3_result_int64(pCtx, pCsr->aCnt[pCsr->iCol]);
}
}else{
assert( iCol==1 || iCol==2 );
if( iCol==1 ){
sqlite3_result_int64(pCtx, pCsr->aDoc[0]);
}else{
sqlite3_result_int64(pCtx, pCsr->aCnt[0]);
}
default:
assert( iCol<4 && iCol>0 );
sqlite3_result_int64(pCtx, pCsr->aVal[iCol-1]);
break;
}
return SQLITE_OK;
}
+4 -12
View File
@@ -58,18 +58,6 @@
*/
#define yytestcase(X) testcase(X)
/*
** Indicate that sqlite3ParserFree() will never be called with a null
** pointer.
*/
#define YYPARSEFREENOTNULL 1
/*
** Alternative datatype for the argument to the malloc() routine passed
** into sqlite3ParserAlloc(). The default is size_t.
*/
#define YYMALLOCARGTYPE u64
} // end %include
%left OR.
@@ -180,3 +168,7 @@ phrase(A) ::= STRING(Y) star_opt(Z). {
star_opt(A) ::= STAR. { A = 1; }
star_opt(A) ::= . { A = 0; }
+1 -1
View File
@@ -15,7 +15,7 @@
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5aa
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
-70
View File
@@ -1,70 +0,0 @@
# 2015 October 27
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS5 module.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5conflict
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE TABLE t1(x INTEGER PRIMARY KEY, a, b);
CREATE VIRTUAL TABLE ft USING fts5(a, b, content=t1, content_rowid=x);
}
do_execsql_test 1.1 {
REPLACE INTO ft(rowid, a, b) VALUES(1, 'a b c', 'a b c');
REPLACE INTO t1 VALUES(1, 'a b c', 'a b c');
}
do_execsql_test 1.2 {
INSERT INTO ft(ft) VALUES('integrity-check');
}
do_execsql_test 2.0 {
CREATE TABLE tbl(a INTEGER PRIMARY KEY, b, c);
CREATE VIRTUAL TABLE fts_idx USING fts5(b, c, content=tbl, content_rowid=a);
CREATE TRIGGER tbl_ai AFTER INSERT ON tbl BEGIN
INSERT INTO fts_idx(rowid, b, c) VALUES (new.a, new.b, new.c);
END;
CREATE TRIGGER tbl_ad AFTER DELETE ON tbl BEGIN
INSERT INTO fts_idx(fts_idx, rowid, b, c)
VALUES('delete', old.a, old.b, old.c);
END;
CREATE TRIGGER tbl_au AFTER UPDATE ON tbl BEGIN
INSERT INTO fts_idx(fts_idx, rowid, b, c)
VALUES('delete', old.a, old.b, old.c);
INSERT INTO fts_idx(rowid, b, c) VALUES (new.a, new.b, new.c);
END;
}
do_execsql_test 2.1 {
PRAGMA recursive_triggers = 1;
INSERT INTO tbl VALUES(1, 'x y z', '1 2 3');
INSERT INTO tbl VALUES(10, 'x y z', '1 2 3');
INSERT INTO tbl VALUES(100, 'x 1 z', '1 y 3');
UPDATE tbl SET b = '1 2 x' WHERE rowid=10;
REPLACE INTO tbl VALUES(1, '4 5 6', '3 2 1');
DELETE FROM tbl WHERE a=100;
INSERT INTO fts_idx(fts_idx) VALUES('integrity-check');
}
finish_test
+3 -3
View File
@@ -52,7 +52,7 @@ do_faultsim_test 2 -prep {
INSERT INTO t1 VALUES('a b c', 'a bc def ghij klmno');
}
} -test {
faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}}
faultsim_test_result {0 {}}
}
reset_db
@@ -66,7 +66,7 @@ do_faultsim_test 3 -prep {
} -body {
execsql { DELETE FROM t1 }
} -test {
faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}}
faultsim_test_result {0 {}}
}
reset_db
@@ -101,7 +101,7 @@ foreach {tn expr res} {
} -body "
execsql { SELECT rowid FROM t2 WHERE t2 MATCH '$expr' }
" -test "
faultsim_test_result {[list 0 $res]} {1 {vtable constructor failed: t2}}
faultsim_test_result {[list 0 $res]}
"
}
+1 -1
View File
@@ -107,7 +107,7 @@ set ::res [db eval {SELECT rowid, x1 FROM x1 WHERE x1 MATCH '*reads'}]
do_faultsim_test 4 -faults oom-* -body {
db eval {SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'}
} -test {
faultsim_test_result {0 {0 {} 4}}
faultsim_test_result {0 {0 {} 3}}
}
#-------------------------------------------------------------------------
-8
View File
@@ -90,14 +90,6 @@ do_faultsim_test 3.1 -faults oom-t* -body {
faultsim_test_result {0 {0 1 10 11 12 13 14 15 16 17 18 19 2 3 4 5 6 7 8 9}}
}
do_faultsim_test 3.2 -faults oom-t* -body {
db eval {
SELECT term FROM tv WHERE term BETWEEN '1' AND '2';
}
} -test {
faultsim_test_result {0 {1 10 11 12 13 14 15 16 17 18 19 2}}
}
finish_test
+1 -48
View File
@@ -9,7 +9,7 @@
#
#***********************************************************************
#
# This file contains tests focused on the integrity-check procedure.
# This file containst tests focused on the integrity-check procedure.
#
source [file join [file dirname [info script]] fts5_common.tcl]
@@ -102,53 +102,6 @@ do_catchsql_test 4.5 {
#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM zz_data} {puts $r}
#exit
execsql { ROLLBACK }
#-------------------------------------------------------------------------
# Test that integrity-check works on a reasonably large db with many
# different terms.
# Document generator command.
proc rnddoc {n} {
set doc [list]
for {set i 0} {$i<$n} {incr i} {
lappend doc [format %.5d [expr int(rand()*10000)]]
}
return $doc
}
db func rnddoc rnddoc
expr srand(0)
do_execsql_test 5.0 {
CREATE VIRTUAL TABLE gg USING fts5(a, prefix="1,2,3");
INSERT INTO gg(gg, rank) VALUES('pgsz', 256);
INSERT INTO gg VALUES(rnddoc(20));
INSERT INTO gg SELECT rnddoc(20) FROM gg;
INSERT INTO gg SELECT rnddoc(20) FROM gg;
INSERT INTO gg SELECT rnddoc(20) FROM gg;
INSERT INTO gg SELECT rnddoc(20) FROM gg;
INSERT INTO gg SELECT rnddoc(20) FROM gg;
INSERT INTO gg SELECT rnddoc(20) FROM gg;
INSERT INTO gg SELECT rnddoc(20) FROM gg;
INSERT INTO gg SELECT rnddoc(20) FROM gg;
INSERT INTO gg SELECT rnddoc(20) FROM gg;
INSERT INTO gg SELECT rnddoc(20) FROM gg;
INSERT INTO gg SELECT rnddoc(20) FROM gg;
}
do_execsql_test 5.1 {
INSERT INTO gg(gg) VALUES('integrity-check');
}
do_execsql_test 5.2 {
INSERT INTO gg(gg) VALUES('optimize');
}
breakpoint
do_execsql_test 5.3 {
INSERT INTO gg(gg) VALUES('integrity-check');
}
finish_test
-83
View File
@@ -1,83 +0,0 @@
# 2015 October 27
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS5 module.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5query
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
for {set tn 1 ; set pgsz 64} {$tn<32} {incr tn; incr pgsz 16} {
reset_db
do_test 1.$tn.1 {
execsql {
CREATE VIRTUAL TABLE t1 USING fts5(x);
INSERT INTO t1(t1, rank) VALUES('pgsz', $pgsz);
BEGIN;
}
foreach x [list aaa bbb ccc ddd eee fff ggg hhh iii jjj] {
set doc [string repeat "$x " 30]
execsql { INSERT INTO t1 VALUES($doc) }
}
execsql COMMIT
} {}
do_execsql_test 1.$tn.2 {
INSERT INTO t1(t1) VALUES('integrity-check');
}
set ret 1
foreach x [list a b c d e f g h i j] {
do_execsql_test 1.$tn.3.$ret {
SELECT rowid FROM t1 WHERE t1 MATCH $x || '*';
} $ret
incr ret
}
}
for {set tn 1 ; set pgsz 64} {$tn<32} {incr tn; incr pgsz 16} {
reset_db
do_test 2.$tn.1 {
execsql {
CREATE VIRTUAL TABLE t1 USING fts5(x);
INSERT INTO t1(t1, rank) VALUES('pgsz', $pgsz);
BEGIN;
}
foreach x [list bbb ddd fff hhh jjj lll nnn ppp rrr ttt] {
set doc [string repeat "$x " 30]
execsql { INSERT INTO t1 VALUES($doc) }
}
execsql COMMIT
} {}
do_execsql_test 1.$tn.2 {
INSERT INTO t1(t1) VALUES('integrity-check');
}
set ret 1
foreach x [list a c e g i k m o q s u] {
do_execsql_test 2.$tn.3.$ret {
SELECT rowid FROM t1 WHERE t1 MATCH $x || '*';
} {}
incr ret
}
}
finish_test
-55
View File
@@ -41,60 +41,5 @@ do_execsql_test 1.3 {
WHERE xyz MATCH 'x AND y' ORDER BY rank
} [list [string map {x [x] y [y]} $doc]]
#-------------------------------------------------------------------------
# Check that the 'rank' option really is persistent.
#
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE tt USING fts5(a);
INSERT INTO tt VALUES('a x x x x');
INSERT INTO tt VALUES('x x a a a');
INSERT INTO tt VALUES('x a a x x');
}
proc firstinst {cmd} {
foreach {p c o} [$cmd xInst 0] {}
return $o
}
sqlite3_fts5_create_function db firstinst firstinst
do_execsql_test 2.1 {
SELECT rowid FROM tt('a') ORDER BY rank;
} {2 3 1}
do_execsql_test 2.2 {
SELECT rowid FROM tt('a', 'firstinst()') ORDER BY rank;
} {1 3 2}
do_execsql_test 2.3 {
INSERT INTO tt(tt, rank) VALUES('rank', 'firstinst()');
SELECT rowid FROM tt('a') ORDER BY rank;
} {1 3 2}
do_test 2.4 {
sqlite3 db2 test.db
catchsql { SELECT rowid FROM tt('a') ORDER BY rank; } db2
} {1 {no such function: firstinst}}
do_test 2.5 {
db2 close
sqlite3 db2 test.db
sqlite3_fts5_create_function db2 firstinst firstinst
execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db2
} {1 3 2}
do_test 2.6 {
execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db2
} {1 3 2}
do_test 2.7 {
execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db
} {1 3 2}
finish_test
+1 -30
View File
@@ -18,7 +18,7 @@ ifcapable !fts5 {
finish_test
return
}
#-------------------------------------------------------------------------
#
set doc "x x [string repeat {y } 50]z z"
@@ -322,34 +322,5 @@ do_execsql_test 13.3 {
INSERT INTO xy(xy) VALUES('integrity-check');
}
#-------------------------------------------------------------------------
#
do_execsql_test 14.1 {
CREATE VIRTUAL TABLE ttt USING fts5(x);
BEGIN;
INSERT INTO ttt(rowid, x) VALUES(1, 'a b c');
INSERT INTO ttt(rowid, x) VALUES(2, 'a b c');
INSERT INTO ttt(rowid, x) VALUES(3, 'a b c');
COMMIT;
}
do_test 14.2 {
fts5_level_segs ttt
} {1}
#-------------------------------------------------------------------------
db func rnddoc fts5_rnddoc
do_execsql_test 4.0 {
CREATE VIRTUAL TABLE x1 USING fts5(x);
INSERT INTO x1(x1, rank) VALUES('pgsz', 32);
WITH ii(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<10 )
INSERT INTO x1 SELECT rnddoc(5) FROM ii;
}
do_execsql_test 4.1 {
SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'
} {0 {} 4}
finish_test
+10 -142
View File
@@ -56,7 +56,7 @@ do_execsql_test 1.4.1 {
do_execsql_test 1.4.2 {
SELECT * FROM v2;
} {x one 2 4 y one 1 1 z one 1 1}
} {x 0 2 4 y 0 1 1 z 0 1 1}
do_execsql_test 1.5.1 {
BEGIN;
@@ -67,7 +67,7 @@ do_execsql_test 1.5.1 {
do_execsql_test 1.5.2 {
SELECT * FROM v2 WHERE term<'d';
COMMIT;
} {a one 1 1 b one 1 1 c one 1 1}
} {a 0 1 1 b 0 1 1 c 0 1 1}
do_execsql_test 1.6 {
DELETE FROM t1 WHERE one = 'a b c';
@@ -91,14 +91,14 @@ do_execsql_test 2.0 {
}
set res_col {
a a 6 11 a b 7 9
b a 6 7 b b 7 7
c a 6 12 c b 5 8
d a 4 6 d b 9 13
e a 6 7 e b 6 6
f a 9 10 f b 7 10
g a 5 7 g b 5 7
x a 1 1 y b 1 1
a 0 6 11 a 1 7 9
b 0 6 7 b 1 7 7
c 0 6 12 c 1 5 8
d 0 4 6 d 1 9 13
e 0 6 7 e 1 6 6
f 0 9 10 f 1 7 10
g 0 5 7 g 1 5 7
x 0 1 1 y 1 1 1
}
set res_row {
a 10 20 b 9 14 c 9 20 d 9 19
@@ -213,137 +213,5 @@ do_catchsql_test 6.2 {
SELECT * FROM vocab3;
} {1 {no such fts5 table: main.lll}}
#-------------------------------------------------------------------------
# Test single term queries on fts5vocab tables (i.e. those with term=?
# constraints in the WHERE clause).
#
do_execsql_test 7.0 {
CREATE VIRTUAL TABLE tx USING fts5(one, two);
INSERT INTO tx VALUES('g a ggg g a b eee', 'cc d aa ff g ee');
INSERT INTO tx VALUES('dd fff i a i jjj', 'f fff hh jj e f');
INSERT INTO tx VALUES('ggg a f f fff dd aa', 'd ggg f f j gg ddd');
INSERT INTO tx VALUES('e bb h jjj ii gg', 'e aa e f c fff');
INSERT INTO tx VALUES('j ff aa a h', 'h a j bbb bb');
INSERT INTO tx VALUES('cc i ff c d f', 'dd ii fff f c cc d');
INSERT INTO tx VALUES('jjj g i bb cc eee', 'hhh iii aaa b bbb aaa');
INSERT INTO tx VALUES('hhh hhh hhh bb fff f', 'fff gg aa ii h a');
INSERT INTO tx VALUES('b c cc aaa iii ggg f', 'iii ff ee a ff c cc');
INSERT INTO tx VALUES('hhh b hhh aaa j i i', 'dd ee ee aa bbb iii');
INSERT INTO tx VALUES('hh dd h b g ff i', 'ccc bb cc ccc f a d');
INSERT INTO tx VALUES('g d b ggg jj', 'fff jj ff jj g gg ee');
INSERT INTO tx VALUES('g ee ggg ggg cc bb eee', 'aa j jjj bbb dd eee ff');
INSERT INTO tx VALUES('c jjj hh ddd dd h', 'e aaa h jjj gg');
CREATE VIRTUAL TABLE txr USING fts5vocab(tx, row);
CREATE VIRTUAL TABLE txc USING fts5vocab(tx, col);
}
proc cont {L elem} {
set n 0
foreach e $L { if {$elem==$e} {incr n} }
set n
}
db func cont cont
foreach {term} {
a aa aaa
b bb bbb
c cc ccc
d dd ddd
e ee eee
f ff fff
g gg ggg
h hh hhh
i ii iii
j jj jjj
} {
set resr [db eval {
SELECT $term,
sum(cont(one || ' ' || two, $term) > 0),
sum(cont(one || ' ' || two, $term))
FROM tx
}]
if {[lindex $resr 1]==0} {set resr [list]}
set r1 [db eval {
SELECT $term, 'one', sum(cont(one, $term)>0), sum(cont(one, $term)) FROM tx
}]
if {[lindex $r1 2]==0} {set r1 [list]}
set r2 [db eval {
SELECT $term, 'two', sum(cont(two, $term)>0), sum(cont(two, $term)) FROM tx
}]
if {[lindex $r2 2]==0} {set r2 [list]}
set resc [concat $r1 $r2]
do_execsql_test 7.$term.1 {SELECT * FROM txc WHERE term=$term} $resc
do_execsql_test 7.$term.2 {SELECT * FROM txr WHERE term=$term} $resr
}
do_execsql_test 7.1 {
CREATE TABLE txr_c AS SELECT * FROM txr;
CREATE TABLE txc_c AS SELECT * FROM txc;
}
# Test range queries on the fts5vocab tables created above.
#
foreach {tn a b} {
1 a jjj
2 bb j
3 ccc ddd
4 dd xyz
5 xzy dd
6 h hh
} {
do_execsql_test 7.2.$tn.1 {
SELECT * FROM txr WHERE term>=$a
} [db eval {SELECT * FROM txr_c WHERE term>=$a}]
do_execsql_test 7.2.$tn.2 {
SELECT * FROM txr WHERE term<=$b
} [db eval {SELECT * FROM txr_c WHERE term <=$b}]
do_execsql_test 7.2.$tn.3 {
SELECT * FROM txr WHERE term>=$a AND term<=$b
} [db eval {SELECT * FROM txr_c WHERE term>=$a AND term <=$b}]
do_execsql_test 7.2.$tn.4 {
SELECT * FROM txc WHERE term>=$a
} [db eval {SELECT * FROM txc_c WHERE term>=$a}]
do_execsql_test 7.2.$tn.5 {
SELECT * FROM txc WHERE term<=$b
} [db eval {SELECT * FROM txc_c WHERE term <=$b}]
do_execsql_test 7.2.$tn.6 {
SELECT * FROM txc WHERE term>=$a AND term<=$b
} [db eval {SELECT * FROM txc_c WHERE term>=$a AND term <=$b}]
do_execsql_test 7.2.$tn.7 {
SELECT * FROM txr WHERE term>$a
} [db eval {SELECT * FROM txr_c WHERE term>$a}]
do_execsql_test 7.2.$tn.8 {
SELECT * FROM txr WHERE term<$b
} [db eval {SELECT * FROM txr_c WHERE term<$b}]
do_execsql_test 7.2.$tn.9 {
SELECT * FROM txr WHERE term>$a AND term<$b
} [db eval {SELECT * FROM txr_c WHERE term>$a AND term <$b}]
do_execsql_test 7.2.$tn.10 {
SELECT * FROM txc WHERE term>$a
} [db eval {SELECT * FROM txc_c WHERE term>$a}]
do_execsql_test 7.2.$tn.11 {
SELECT * FROM txc WHERE term<$b
} [db eval {SELECT * FROM txc_c WHERE term<$b}]
do_execsql_test 7.2.$tn.12 {
SELECT * FROM txc WHERE term>$a AND term<$b
} [db eval {SELECT * FROM txc_c WHERE term>$a AND term <$b}]
}
do_execsql_test 7.3.1 {
SELECT count(*) FROM txr, txr_c WHERE txr.term = txr_c.term;
} {30}
do_execsql_test 7.3.2 {
SELECT count(*) FROM txc, txc_c
WHERE txc.term = txc_c.term AND txc.col=txc_c.col;
} {57}
finish_test
+20 -5
View File
@@ -25,7 +25,7 @@ is exhausted.
exit -1
}
set O(aColSize) [list 10 10 10]
set O(aColsize) [list 10 10 10]
set O(tblname) t1
set O(fts) fts5
@@ -61,7 +61,22 @@ if {$i > [llength $argv]-2} usage
set O(db) [lindex $argv $i]
set O(files) [lrange $argv [expr $i+1] end]
foreach {k v} [lrange $argv 0 end-2] {
switch -- $k {
-colsize {
set O(aColSize) $v
}
-colsize {
set O(aColSize) $v
}
}
}
sqlite3 db $O(db)
load_static_extension db fts5
# Create the FTS table in the db. Return a list of the table columns.
#
@@ -69,7 +84,7 @@ proc create_table {} {
global O
set cols [list a b c d e f g h i j k l m n o p q r s t u v w x y z]
set nCol [llength $O(aColSize)]
set nCol [llength $O(aColsize)]
set cols [lrange $cols 0 [expr $nCol-1]]
set sql "CREATE VIRTUAL TABLE IF NOT EXISTS $O(tblname) USING $O(fts) ("
@@ -102,14 +117,14 @@ set i 0
set cols [create_table]
set sql "INSERT INTO $O(tblname) VALUES(\$[lindex $cols 0]"
foreach c [lrange $cols 1 end] {
append sql ", \$A($c)"
append sql ", \$$c"
}
append sql ")"
db eval BEGIN
while {$i < $N} {
foreach c $cols s $O(aColSize) {
set A($c) [lrange $tokens $i [expr $i+$s-1]]
foreach c $cols s $O(aColsize) {
set $c [lrange $tokens $i [expr $i+$s-1]]
incr i $s
}
db eval $sql
-16
View File
@@ -48,7 +48,6 @@ proc usage {} {
puts stderr " -crisismerge N (set the crisismerge parameter to N)"
puts stderr " -prefix PREFIX (comma separated prefix= argument)"
puts stderr " -trans N (commit after N inserts - 0 == never)"
puts stderr " -hashsize N (set the fts5 hashsize parameter to N)"
exit 1
}
@@ -60,7 +59,6 @@ set O(automerge) -1
set O(crisismerge) -1
set O(prefix) ""
set O(trans) 0
set O(hashsize) -1
if {[llength $argv]<2} usage
set nOpt [expr {[llength $argv]-2}]
@@ -108,11 +106,6 @@ for {set i 0} {$i < $nOpt} {incr i} {
set O(prefix) [lindex $argv $i]
}
-hashsize {
if { [incr i]>=$nOpt } usage
set O(hashsize) [lindex $argv $i]
}
default {
usage
}
@@ -133,14 +126,6 @@ db eval BEGIN
db eval "CREATE VIRTUAL TABLE t1 USING $O(vtab) (path, content$O(tok)$pref)"
db eval "INSERT INTO t1(t1, rank) VALUES('pgsz', 4050);"
}
if {$O(hashsize)>=0} {
catch {
db eval "INSERT INTO t1(t1, rank) VALUES('hashsize', $O(hashsize));"
}
}
if {$O(automerge)>=0} {
if {$O(vtab) == "fts5"} {
db eval { INSERT INTO t1(t1, rank) VALUES('automerge', $O(automerge)) }
@@ -156,7 +141,6 @@ db eval BEGIN
}
load_hierachy [lindex $argv end]
db eval COMMIT
puts ""
+3 -5
View File
@@ -78,7 +78,7 @@ proc fts5c_printfile {zIn} {
global G
set data [readfile $zIn]
set zTail [file tail $zIn]
puts $G(fd) "#line 1 \"$zTail\""
puts $G(fd) "#line 2 \"$zTail\""
set sub_map [list --FTS5-SOURCE-ID-- [fts5_source_id $::srcdir]]
if {$zTail=="fts5parse.c"} {
@@ -86,10 +86,8 @@ proc fts5c_printfile {zIn} {
}
foreach line [split $data "\n"] {
if {[regexp {^#include.*fts5} $line]} {
set line "/* $line */"
} elseif {
![regexp { sqlite3Fts5Init\(} $line]
if {[regexp {^#include.*fts5} $line]} continue
if { ![regexp { sqlite3Fts5Init\(} $line]
&& [regexp {^(const )?[a-zA-Z][a-zA-Z0-9]* [*]?sqlite3Fts5} $line]
} {
set line "static $line"
-13
View File
@@ -8,13 +8,11 @@ proc usage {} {
puts stderr "usage: $::argv0 ?OPTIONS? database table"
puts stderr ""
puts stderr " -nterm (count number of terms in each segment)"
puts stderr " -segments (output segment contents)"
puts stderr ""
exit 1
}
set O(nterm) 0
set O(segments) 0
if {[llength $argv]<2} usage
foreach a [lrange $argv 0 end-2] {
@@ -23,10 +21,6 @@ foreach a [lrange $argv 0 end-2] {
set O(nterm) 1
}
-segments {
set O(segments) 1
}
default {
usage
}
@@ -84,13 +78,6 @@ db eval "SELECT fts5_decode(rowid, block) AS d FROM ${tbl}_data WHERE id=10" {
}
}
if {$O(segments)} {
puts ""
db eval "SELECT fts5_decode(rowid, block) AS d FROM ${tbl}_data WHERE id>10" {
puts $d
}
}
+2 -2
View File
@@ -816,10 +816,10 @@ static const char *amatchValueOfKey(const char *zKey, const char *zStr){
int i;
if( nStr<nKey+1 ) return 0;
if( memcmp(zStr, zKey, nKey)!=0 ) return 0;
for(i=nKey; isspace((unsigned char)zStr[i]); i++){}
for(i=nKey; isspace(zStr[i]); i++){}
if( zStr[i]!='=' ) return 0;
i++;
while( isspace((unsigned char)zStr[i]) ){ i++; }
while( isspace(zStr[i]) ){ i++; }
return zStr+i;
}
+2 -2
View File
@@ -486,10 +486,10 @@ static const char *closureValueOfKey(const char *zKey, const char *zStr){
int i;
if( nStr<nKey+1 ) return 0;
if( memcmp(zStr, zKey, nKey)!=0 ) return 0;
for(i=nKey; isspace((unsigned char)zStr[i]); i++){}
for(i=nKey; isspace(zStr[i]); i++){}
if( zStr[i]!='=' ) return 0;
i++;
while( isspace((unsigned char)zStr[i]) ){ i++; }
while( isspace(zStr[i]) ){ i++; }
return zStr+i;
}
+3 -3
View File
@@ -94,16 +94,16 @@ static void ieee754func(
m >>= 1;
e++;
}
while( m!=0 && ((m>>32)&0xfff00000)==0 ){
while( ((m>>32)&0xfff00000)==0 ){
m <<= 1;
e--;
}
e += 1075;
if( e<0 ) e = m = 0;
if( e>0x7ff ) e = 0x7ff;
if( e>0x7ff ) m = 0;
a = m & ((((sqlite3_int64)1)<<52)-1);
a |= e<<52;
if( isNeg ) a |= ((sqlite3_uint64)1)<<63;
if( isNeg ) a |= ((sqlite3_int64)1)<<63;
memcpy(&r, &a, sizeof(r));
sqlite3_result_double(context, r);
}
+5 -19
View File
@@ -28,6 +28,7 @@
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <ctype.h> /* amalgamator: keep */
#include <stdlib.h>
#include <stdarg.h>
@@ -42,17 +43,8 @@ SQLITE_EXTENSION_INIT1
** Versions of isspace(), isalnum() and isdigit() to which it is safe
** to pass signed char values.
*/
#ifdef sqlite3Isdigit
/* Use the SQLite core versions if this routine is part of the
** SQLite amalgamation */
# define safe_isdigit(x) sqlite3Isdigit(x)
# define safe_isalnum(x) sqlite3Isalnum(x)
#else
/* Use the standard library for separate compilation */
#include <ctype.h> /* amalgamator: keep */
# define safe_isdigit(x) isdigit((unsigned char)(x))
# define safe_isalnum(x) isalnum((unsigned char)(x))
#endif
#define safe_isdigit(x) isdigit((unsigned char)(x))
#define safe_isalnum(x) isalnum((unsigned char)(x))
/*
** Growing our own isspace() routine this way is twice as fast as
@@ -60,7 +52,7 @@ SQLITE_EXTENSION_INIT1
** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
*/
static const char jsonIsSpace[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -522,13 +514,7 @@ static void jsonReturn(
int_as_real: /* fall through to real */;
}
case JSON_REAL: {
double r;
#ifdef SQLITE_AMALGAMATION
const char *z = pNode->u.zJContent;
sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
#else
r = strtod(pNode->u.zJContent, 0);
#endif
double r = strtod(pNode->u.zJContent, 0);
sqlite3_result_double(pCtx, r);
break;
}
+1 -1
View File
@@ -1851,7 +1851,7 @@ static char *spellfix1Dequote(const char *zIn){
char *zOut;
int i, j;
char c;
while( isspace((unsigned char)zIn[0]) ) zIn++;
while( isspace(zIn[0]) ) zIn++;
zOut = sqlite3_mprintf("%s", zIn);
if( zOut==0 ) return 0;
i = (int)strlen(zOut);
-3
View File
@@ -341,9 +341,6 @@ sqlite3rbu *sqlite3rbu_open(
** If an error has occurred, either while opening or stepping the RBU object,
** this function may return NULL. The error code and message may be collected
** when sqlite3rbu_close() is called.
**
** Database handles returned by this function remain valid until the next
** call to any sqlite3rbu_xxx() function other than sqlite3rbu_db().
*/
sqlite3 *sqlite3rbu_db(sqlite3rbu*, int bRbu);
+6 -30
View File
@@ -56,34 +56,20 @@ static int test_sqlite3rbu_cmd(
){
int ret = TCL_OK;
sqlite3rbu *pRbu = (sqlite3rbu*)clientData;
struct RbuCmd {
const char *zName;
int nArg;
const char *zUsage;
} aCmd[] = {
{"step", 2, ""}, /* 0 */
{"close", 2, ""}, /* 1 */
{"create_rbu_delta", 2, ""}, /* 2 */
{"savestate", 2, ""}, /* 3 */
{"dbMain_eval", 3, "SQL"}, /* 4 */
{0,0,0}
const char *azMethod[] = {
"step", "close", "create_rbu_delta", "savestate", 0
};
int iCmd;
int iMethod;
if( objc<2 ){
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "METHOD");
return TCL_ERROR;
}
ret = Tcl_GetIndexFromObjStruct(
interp, objv[1], aCmd, sizeof(aCmd[0]), "method", 0, &iCmd
);
if( ret ) return TCL_ERROR;
if( objc!=aCmd[iCmd].nArg ){
Tcl_WrongNumArgs(interp, 1, objv, aCmd[iCmd].zUsage);
if( Tcl_GetIndexFromObj(interp, objv[1], azMethod, "method", 0, &iMethod) ){
return TCL_ERROR;
}
switch( iCmd ){
switch( iMethod ){
case 0: /* step */ {
int rc = sqlite3rbu_step(pRbu);
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
@@ -126,16 +112,6 @@ static int test_sqlite3rbu_cmd(
break;
}
case 4: /* dbMain_eval */ {
sqlite3 *db = sqlite3rbu_db(pRbu, 0);
int rc = sqlite3_exec(db, Tcl_GetString(objv[2]), 0, 0, 0);
if( rc!=SQLITE_OK ){
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(db), -1));
ret = TCL_ERROR;
}
break;
}
default: /* seems unlikely */
assert( !"cannot happen" );
break;
+3 -3
View File
@@ -554,9 +554,9 @@ fts3amal.c: target_source $(TOP)/ext/fts3/mkfts3amal.tcl
# Rules to build the LEMON compiler generator
#
lemon: $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
lemon: $(TOP)/tool/lemon.c $(TOP)/src/lempar.c
$(BCC) -o lemon $(TOP)/tool/lemon.c
cp $(TOP)/tool/lempar.c .
cp $(TOP)/src/lempar.c .
# Rules to build individual *.o files from generated *.c files. This
# applies to:
@@ -755,7 +755,7 @@ fastfuzztest: fuzzcheck$(EXE) $(FUZZDATA)
./fuzzcheck$(EXE) --limit-mem 100M $(FUZZDATA)
valgrindfuzz: fuzzcheck$(EXE) $(FUZZDATA)
valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA)
valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M $(FUZZDATA)
# A very quick test using only testfixture and omitting all the slower
# tests. Designed to run in under 3 minutes on a workstation.
+113 -121
View File
@@ -1,10 +1,10 @@
C Fix\sharmless\scompiler\swarnings\sin\sFTS5.
D 2015-11-10T12:31:25.172
F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1
C Experiments\swith\san\sOP_Unpack\sopcode\sthat\sextracts\smultiple\scolumns\sfrom\na\srecord\swithout\scaching.
D 2015-10-15T20:17:15.103
F Makefile.in 2ea961bc09e441874eb3d1bf7398e04feb24f3ee
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc e928e68168df69b353300ac87c10105206653a03
F Makefile.msc 8e42cb55739cd8c12e1fd25401956e2019448f6a
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
F VERSION 8b9d3ac6f1962f94e06ba05462422a544f9c4e36
F VERSION cacf16a72f9a03cd06b939a764e32f6f53254c7f
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -15,7 +15,7 @@ F autoconf/README 14458f1046c118efa721aadec5f227e876d3cd38
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/config.guess 94cc57e2a3fdb9c235b362ace86d77e89d188cad x
F autoconf/config.sub 1efb390a8fb4bfafd74783a15a8fb5311c84300e x
F autoconf/configure.ac bec3caf78cf1bdbaad903dcd5c6029292eda3d2d
F autoconf/configure.ac a1fe4eee429fd9d3170be41941514a2b7120ba4e
F autoconf/depcomp 0b26f101e3bc9fd1ff0be1da9fb4a82371142f92 x
F autoconf/install-sh 06ee6336e63bb845c8439d777c32eb2eccc4fbf1 x
F autoconf/ltmain.sh 7a658a24028f02331c1d2446562758083c5eadd1
@@ -30,13 +30,13 @@ F autoconf/tea/pkgIndex.tcl.in 3ef61715cf1c7bdcff56947ffadb26bc991ca39d
F autoconf/tea/tclconfig/install-sh bdd5e293591621ae60d9824d86a4b1c5f22c3d00
F autoconf/tea/tclconfig/tcl.m4 66ddf0a5d5e4b1d29bff472c0985fd7fa89d0fb5
F autoconf/tea/win/makefile.vc f89d0184d0eee5f7e356ea407964dcd139939928
F autoconf/tea/win/nmakehlp.c 247538ad8e8c508f33c03ec1fbd67d3a07ef6291
F autoconf/tea/win/nmakehlp.c 2070e086f39866b353a482d3a14dedaf26196506
F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure e511ceefe595e35051933a90c848ab4fa1d48add x
F configure.ac fcfc67b323d32daaa3e46cf7782d9465ed423a6d
F configure 99485c9c0446d1236a78a53de6f2737f45f0aca5 x
F configure.ac f36bd4fb8c53eed8374c5a5ef319807c08c23fa9
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
@@ -48,7 +48,7 @@ F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
F ext/fts1/ft_hash.c 3927bd880e65329bdc6f506555b228b28924921b
F ext/fts1/ft_hash.h 06df7bba40dadd19597aa400a875dbc2fed705ea
F ext/fts1/fts1.c a39f7d21c2994d27c959ef9c3505c81542c81432
F ext/fts1/fts1.c f7739dc37500a613cc0dab8fc04d1b5577d02998
F ext/fts1/fts1.h 6060b8f62c1d925ea8356cb1a6598073eb9159a6
F ext/fts1/fts1_hash.c 3196cee866edbebb1c0521e21672e6d599965114
F ext/fts1/fts1_hash.h e7f0d761353996a8175eda351104acfde23afcb0
@@ -57,7 +57,7 @@ F ext/fts1/fts1_tokenizer.h fdea722c38a9f82ed921642981234f666e47919c
F ext/fts1/fts1_tokenizer1.c fd00d1fe4dc30dfc5c64cba695ce34f4af20d2fa
F ext/fts1/fulltext.c 37698e1909584f6d8ea67d1485e3ad39dbf42d19
F ext/fts1/fulltext.h 08525a47852d1d62a0be81d3fc3fe2d23b094efd
F ext/fts1/simple_tokenizer.c bbfa4e3b2a26ef17d4edc6d98cd4a3f5396d998a
F ext/fts1/simple_tokenizer.c 1844d72f7194c3fd3d7e4173053911bf0661b70d
F ext/fts1/tokenizer.h 0c53421b832366d20d720d21ea3e1f6e66a36ef9
F ext/fts2/README.tokenizers 21e3684ea5a095b55d70f6878b4ce6af5932dfb7
F ext/fts2/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
@@ -103,25 +103,25 @@ F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252
F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
F ext/fts5/fts5.h 8b9a13b309b180e9fb88ea5666c0d8d73c6102d9
F ext/fts5/fts5Int.h acf968e43d57b6b1caf7554d34ec35d6ed3b4fe8
F ext/fts5/fts5Int.h 38667e39859ff3f3bc91f47efe672023a145a118
F ext/fts5/fts5_aux.c 1f384972d606375b8fa078319f25ab4b5feb1b35
F ext/fts5/fts5_buffer.c 1e49512a535045e621246dc7f4f65f3593fa0fc2
F ext/fts5/fts5_config.c 6fc92c0b1bda5244c28a54c9ba740736bd5513d9
F ext/fts5/fts5_buffer.c 9a3aa73a4e7b26b1c805b9c92c1344ba3d19d2a8
F ext/fts5/fts5_config.c 88a77f5d5e4dfbb2355b8f6cc9969b7f02d94685
F ext/fts5/fts5_expr.c 28b15c9ae296204bc0a2e5cf7a667d840a9d2900
F ext/fts5/fts5_hash.c a9d4c1efebc2a91d26ad7ebdfcbf2678ceac405f
F ext/fts5/fts5_index.c b622a0a70f57a96469e6828da2dd70e0872aeb37
F ext/fts5/fts5_main.c 7581280ee242785477df67402f2853c66f77d45b
F ext/fts5/fts5_storage.c 9ea3d92178743758b6c54d9fe8836bbbdcc92e3b
F ext/fts5/fts5_index.c c76d636d6cd22e3b82b1dbf3a3993447091c3bed
F ext/fts5/fts5_main.c d3fde32e1fdd7962dc7062400d1d8c7ec2297acf
F ext/fts5/fts5_storage.c 9b30115742b758706de70595a8d1d084e940c978
F ext/fts5/fts5_tcl.c 3bf445e66de32137d4693694ff7b1fd6074e32bd
F ext/fts5/fts5_test_mi.c e96be827aa8f571031e65e481251dc1981d608bf
F ext/fts5/fts5_tokenize.c 12c5d925286491a71bb3dad7c8924ce9cfd18320
F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c
F ext/fts5/fts5_varint.c 3f86ce09cab152e3d45490d7586b7ed2e40c13f1
F ext/fts5/fts5_vocab.c 3742d0abfe8aa8c3cb4a7df56aa38f2e3c3fb1c2
F ext/fts5/fts5parse.y 1647eba089b9b3fc058b4dc989d9da87d15b9580
F ext/fts5/fts5_vocab.c 85ebf2e93089c9d3d136cc69163370592fc040f3
F ext/fts5/fts5parse.y e83dca6028e3309178d05b5bd920e372dc295d35
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
F ext/fts5/test/fts5_common.tcl 51f7ef3af444b89c6f6ce3896a0ac349ff4e996d
F ext/fts5/test/fts5aa.test 2c553eea4dab4bc5a75928f56729277c7bc1d206
F ext/fts5/test/fts5aa.test 34ad813e9e958115d388658b2c4a8dde6b1474a5
F ext/fts5/test/fts5ab.test 6fe3a56731d15978afbb74ae51b355fc9310f2ad
F ext/fts5/test/fts5ac.test 9737992d08c56bfd4803e933744d2d764e23795c
F ext/fts5/test/fts5ad.test e3dfb150fce971b4fd832498c29f56924d451b63
@@ -140,7 +140,6 @@ F ext/fts5/test/fts5auxdata.test 141a7cbffcceb1bd2799b4b29c183ff8780d586e
F ext/fts5/test/fts5bigpl.test 04ee0d7eebbebf17c31f5a0b5c5f9494eac3a0cb
F ext/fts5/test/fts5columnsize.test a8cfef21ffa1c264b9f670a7d94eeaccb5341c07
F ext/fts5/test/fts5config.test ad2ff42ddc856aed2d05bf89dc1c578c8a39ea3b
F ext/fts5/test/fts5conflict.test 26f4e46c4d31e16221794832a990dc4e30e18de5
F ext/fts5/test/fts5content.test 9a952c95518a14182dc3b59e3c8fa71cda82a4e1
F ext/fts5/test/fts5corrupt.test c2ad090192708150d50d961278df10ae7a4b8b62
F ext/fts5/test/fts5corrupt2.test 26c0a39dd9ff73207e6229f83b50b21d37c7658c
@@ -149,16 +148,16 @@ F ext/fts5/test/fts5dlidx.test ecba5e62ea8b26c33829961602069c546228046d
F ext/fts5/test/fts5doclist.test 8edb5b57e5f144030ed74ec00ef6fa4294fed79b
F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0
F ext/fts5/test/fts5eb.test 3e5869af2008cbc4ad03a175a0b6f6e58134cd43
F ext/fts5/test/fts5fault1.test 4b39c47ca3544615daa8a2f733b911fa08022c77
F ext/fts5/test/fts5fault1.test 7a562367cb4a735b57b410dbdb62dcc8d971faec
F ext/fts5/test/fts5fault2.test 28c36c843bb39ae855ba79827417ecc37f114341
F ext/fts5/test/fts5fault3.test d6e9577d4312e331a913c72931bf131704efc8f3
F ext/fts5/test/fts5fault4.test 4864f2b5c2c083440dbe85aff60897bc1aa04603
F ext/fts5/test/fts5fault5.test f2b8645053d48982e8979749e93994c43011c118
F ext/fts5/test/fts5fault4.test 762991d526ee67c2b374351a17248097ea38bee7
F ext/fts5/test/fts5fault5.test 54da9fd4c3434a1d4f6abdcb6469299d91cf5875
F ext/fts5/test/fts5fault6.test 9682664d679643ac6736e90c225526cc84073cda
F ext/fts5/test/fts5fault7.test 01be274bfc8d9bf22451a3bf5892e9399d044f1b
F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741
F ext/fts5/test/fts5hash.test 7cf4607b8657c383f0b520668a99971e95d8b139
F ext/fts5/test/fts5integrity.test 87db5d4e7da0ce04a1dcba5ba91658673c997a65
F ext/fts5/test/fts5integrity.test 29f41d2c7126c6122fbb5d54e556506456876145
F ext/fts5/test/fts5matchinfo.test 2163b0013e824bba65499da9e34ea4da41349cc2
F ext/fts5/test/fts5merge.test 8f3cdba2ec9c5e7e568246e81b700ad37f764367
F ext/fts5/test/fts5near.test b214cddb1c1f1bddf45c75af768f20145f7e71cc
@@ -169,12 +168,11 @@ F ext/fts5/test/fts5plan.test 6a55ecbac9890765b0e16f8c421c7e0888cfe436
F ext/fts5/test/fts5porter.test 7cdc07bef301d70eebbfa75dcaf45c3680e1d0e1
F ext/fts5/test/fts5porter2.test 2e65633d58a1c525d5af0f6c01e5a59155bb3487
F ext/fts5/test/fts5prefix.test 7ccbdf180ed561a912acef520519e85af8642239
F ext/fts5/test/fts5query.test f5ec25f5f2fbb70033424113cdffc101b1985a40
F ext/fts5/test/fts5rank.test 7e9e64eac7245637f6f2033aec4b292aaf611aab
F ext/fts5/test/fts5rank.test 11dcebba31d822f7e99685b4ea2c2ae3ec0b16f1
F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b
F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17
F ext/fts5/test/fts5rowid.test 400384798349d658eaf06aefa1e364957d5d4821
F ext/fts5/test/fts5simple.test 9bded45827b4ab8933c87b7b3bcc3cd47f7378a4
F ext/fts5/test/fts5simple.test 41333e267c6145efc3620342af53dfe65d5676b7
F ext/fts5/test/fts5synonym.test cf88c0a56d5ea9591e3939ef1f6e294f7f2d0671
F ext/fts5/test/fts5tokenizer.test ea4df698b35cc427ebf2ba22829d0e28386d8c89
F ext/fts5/test/fts5unicode.test fbef8d8a3b4b88470536cc57604a82ca52e51841
@@ -182,29 +180,29 @@ F ext/fts5/test/fts5unicode2.test c1dd890ba32b7609adba78e420faa847abe43b59
F ext/fts5/test/fts5unicode3.test 35c3d02aa7acf7d43d8de3bfe32c15ba96e8928e
F ext/fts5/test/fts5unindexed.test e9539d5b78c677315e7ed8ea911d4fd25437c680
F ext/fts5/test/fts5version.test 978f59541d8cef7e8591f8be2115ec5ccb863e2e
F ext/fts5/test/fts5vocab.test c88a5554d0409494da95ba647bbdb4879b2624b0
F ext/fts5/tool/fts5txt2db.tcl c374c4c4797e8cdfadabdfaeeb5412dcd6686e84
F ext/fts5/tool/loadfts5.tcl 4cc2d6af43b58d4fac05bc4fdabd0e5862c3b2c1
F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
F ext/fts5/test/fts5vocab.test cdf97b9678484e9bad5062edf9c9106e5c3b0c5c
F ext/fts5/tool/fts5txt2db.tcl 3d19fb8ffb234031d33d7d2151acfbc55e9cfcc4
F ext/fts5/tool/loadfts5.tcl 58e90407cc5c2b1770460119488fd7c0090d4dd3
F ext/fts5/tool/mkfts5c.tcl 09ce6a7997440508360f5ba1651ab7e923a8bf31
F ext/fts5/tool/showfts5.tcl 9eaf6c3df352f98a2ab5ce1921dd94128ab1381d
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
F ext/icu/icu.c b2732aef0b076e4276d9b39b5a33cec7a05e1413
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/misc/amatch.c a1a8f66c29d40bd71b075546ddeddb477b17a2bb
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
F ext/misc/amatch.c 27b9b601fb1453084e18a3432ea0240d7af8decb
F ext/misc/closure.c 636024302cde41b2bf0c542f81c40c624cfb7012
F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83
F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
F ext/misc/json1.c 4f45afd9dbcd6feca8c528251efbb7fc09299a09
F ext/misc/ieee754.c b0362167289170627659e84173f5d2e8fee8566e
F ext/misc/json1.c fed5b948168f26f39e67d898b03d93dd00e75196
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
F ext/misc/series.c b8fb7befd85b3a9b4a10e701b30b2b79ca92b6d4
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c b9065af7ab1f2597b505a8aa9892620866d502fc
F ext/misc/spellfix.c 86998fb73aefb7b5dc346ba8a58912f312da4996
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
@@ -232,8 +230,8 @@ F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda
F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
F ext/rbu/sqlite3rbu.c ea47de615e911b3a69a8e7fb3be3866298403a25
F ext/rbu/sqlite3rbu.h 0bdeb3be211aaba7d85445fa36f4701a25a3dbde
F ext/rbu/test_rbu.c 4a4cdcef4ef9379fc2a21f008805c80b27bcf573
F ext/rbu/sqlite3rbu.h 1d568cb33738d7900975cc5c72e6f68049f15914
F ext/rbu/test_rbu.c 2a3652241fa45d5eaa141775e4ae68c1d3582c03
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 0f9b595bd0debcbedf1d7a63d0e0678d619e6c9c
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
@@ -263,13 +261,13 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk ae99be5eb22933b1ecf80f94d41d25a3ea80aaf3
F main.mk 47b879ad92fe896895dcfc1bbec5c119ee2aa690
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
F mptest/crash02.subtest f4ef05adcd15d60e5d2bd654204f2c008b519df8
F mptest/mptest.c e7b499cb0cf8c3de65eaf24dec9b36daa4e013e4
F mptest/mptest.c fca59f0a922e03f95ed17c44b1515ed37a841c81
F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
@@ -279,20 +277,20 @@ F src/alter.c 9d649e46c780166e416fb11dbd23f8d49aab8267
F src/analyze.c 4c308880cf53c558070cb8513bdff4ffb1a38a77
F src/attach.c e944d0052b577703b9b83aac1638452ff42a8395
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc
F src/backup.c c3a9c4209439b806c44cf30daf466955727bf46c
F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
F src/btree.c 9e5d713bf54be8bfcae9b60210173dd53570f56d
F src/btree.h 1b8bf2818b5e256c25a5e09126720113b1d783da
F src/btreeInt.h 3ab435ed27adea54d040584b0bcc488ee7db1e38
F src/build.c ca574d33ffb1763cfd2979383f4d507095bfbe19
F src/btree.c 0b74bc28b2dc907cba03b5b4b3b81584273be699
F src/btree.h 40189aefdc2b830d25c8b58fd7d56538481bfdd7
F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0
F src/build.c d6162335d690396dfc5c4bd59e8b2b0c14ba6285
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
F src/ctime.c 509ef9c64d1321f42448f111da86400b1799218a
F src/date.c fb1c99172017dcc8e237339132c91a21a0788584
F src/dbstat.c ffd63fc8ba7541476ced189b95e95d7f2bc63f78
F src/delete.c c4c6fb9da78b946fcba2a6aac5b24bc5c15e752a
F src/expr.c 0080c0f12806eca91e75a23a121a68918e9da357
F src/dbstat.c e637e7a7ff40ef32132a418c6fdf1cfb63aa27c7
F src/delete.c 35c939eb8bacc9dd8a6715964e5f69feb8c20e44
F src/expr.c e8765542b21bc7ff801ca82d5cf11f0b13a219af
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 31900763094a3736a5fc887469202eb579fef2d0
F src/func.c ecdd69ec6a1e406f04cc73324be2ebbf6354197f
@@ -300,14 +298,15 @@ F src/global.c 508e4087f7b41d688e4762dcf4d4fe28cfbc87f9
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c 419a947f27ce2da18eebf440a5aa80cc825defae
F src/insert.c 6dadbb671c2cc035ddbbf11a0b0209185d5bfe2c
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c d344a95d60c24e2f490ee59db9784b1b17439012
F src/loadext.c 18586e45a215325f15096821e9c082035d4fb810
F src/main.c f393acc6e5d604cbe0054376d62f668a5560b3f1
F src/malloc.c 337bbe9c7d436ef9b7d06b5dd10bbfc8f3025972
F src/main.c fec97668771438033a7559883401067b139729e1
F src/malloc.c 0a2e42b835c980ba91c17866e9b6a9810ff54d75
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
F src/mem1.c 52485a88f22649c3b3b4f3eb15760505d49ccf71
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
F src/mem5.c c1ab1153bd6443bdf6f71e4213c6fb31221b9eb7
@@ -323,35 +322,35 @@ F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8
F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf
F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c cf72e06e15839ebe7121e01d3eebf256c039b0ca
F src/os_unix.c fc93d55f96bb978f0b0168c6ea7d6fc60b0e172c
F src/os_win.c 1716291e5ec2dbfc5a1fe0b32182030f1f7d8acf
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
F src/pager.c ed5cff11793b6a4146582aabb29ed8613a6cf89e
F src/pager.h 7fc069c07f3120ee466ff3d48a9d376974ebffa7
F src/parse.y 56cd095d669ad7cf50599a39525277f37f8148f9
F src/pager.c 2fbeeba28f4e6d08a15bc106f36c43346a81f09e
F src/pager.h ac213f8143ebfee6a8bfb91cf4ca02c9a83343c5
F src/parse.y f599aa5e871a493330d567ced93de696f61f48f7
F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
F src/pcache1.c 902e1bc7bdaa81b40f8543407c5e2ac8ef4dc035
F src/pragma.c 8fd4c8a12e25f0d916426f160255ebe25415eba7
F src/pragma.c dcfe3a35d2de935feeaba1455528b4a5c4f1208c
F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c 00a2a10d4298a685d0eeb05b09ef018a2bd81bf8
F src/select.c a4478981ce53cb7e28d0252417deece6ad5fe693
F src/shell.c d25df04168d6ba5a4fa05bdbf859df667f9eb621
F src/sqlite.h.in 3cfc86c55e57c63d86b9e1e92869e2bfb162ca8e
F src/sqlite.h.in 839c818e16ea68703d90d17bd2bb3607191debce
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924
F src/sqliteInt.h bc6d24460fe544323517630b1e20539146379077
F src/sqliteInt.h 1ad779ee62efee60494af0a75d8d45592f9f53c3
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
F src/status.c 286f6398a4d2cd1e8ff0771e3d30f8dddb4768ea
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
F src/tclsqlite.c d9439b6a910985b7fff43ba6756bcef00de22649
F src/test1.c a719afff3144f7f01c6dc3f7d118ac31d15e7527
F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b
F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f
F src/test1.c 8fff9c5aa63d6490f516d018b70c12a9cb9a4d8a
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
F src/test6.c 41cacf3b0dd180823919bf9e1fbab287c9266723
@@ -363,7 +362,7 @@ F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803
F src/test_blob.c e5a7a81d61a780da79101aeb1e60d300af169e07
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
F src/test_config.c 426527fbb12fc23669a1e973ecdc8c5e92c2e2cf
F src/test_config.c ada6f38b0acb6722fb7f0ed8c54fd66df41085b9
F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
@@ -395,20 +394,20 @@ F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0
F src/tokenize.c 5606871a377f390af7040ec3c12e0d183512d785
F src/treeview.c 78842e90c1f71269e7a73a1d4221b6fe360bab66
F src/tokenize.c 338bc8f7c9dd103188952cda7964696bacac6d22
F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
F src/update.c 40e51cd0883cb5bfd6abb7d8a7cd8aa47fab2945
F src/update.c aa10336a2719bd1b9f89004f3d7ba6d566623a49
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
F src/vdbe.c 7a9b18027414368d800716e6319e2acd699c70db
F src/vdbe.h efb7a8c1459e31f3ea4377824c6a7e4cb5068637
F src/vdbeInt.h 33403622c6a8feaaac5f0f3f17f5d1bf6df42286
F src/vdbe.c a0a2aea6a146e2479bdb7dba584f3e625ceccc30
F src/vdbe.h 4bc88bd0e06f8046ee6ab7487c0015e85ad949ad
F src/vdbeInt.h 8b867eac234e28627ffcace3cd4b4b79bbec664b
F src/vdbeapi.c 020681b943e77766b32ae1cddf86d7831b7374ca
F src/vdbeaux.c da9eddc62e025148e30267600a6fe3882d5e912f
F src/vdbeaux.c fd00b489ab3f44f2dca1e4344faf289b7bfcf649
F src/vdbeblob.c 565fabd302f5fca3bdf3d56cac330483616a39b6
F src/vdbemem.c fdd1578e47bea61390d472de53c565781d81e045
F src/vdbemem.c 19b3036aa4d676e7103b0fb5efd6327da455f915
F src/vdbesort.c 8b23930a1289526f6d2a3a9f2e965bcc963e4a68
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
F src/vtab.c 2a8b44aa372c33f6154208e7a7f6c44254549806
@@ -416,9 +415,9 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba
F src/where.c 6aceb72cc58dc06922a9e1604d559c8ca4c3e728
F src/where.c 4c4646675e794ac71e701289edefd7cd81bac844
F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647
F src/wherecode.c 4c96182e7b25e4be54008dee2da5b9c2f8480b9b
F src/wherecode.c b924b78acd9e623fb69bfa2cb65cd7d542166dd3
F src/whereexpr.c e63244ca06c503e5f3c5b7f3c9aea0db826089ed
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
@@ -452,7 +451,7 @@ F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
F test/atof1.test ff0b0156fd705b67c506e1f2bfe9e26102bea9bd
F test/atof1.test 08a61df9365c341f334a65f4348897312d8f3db7
F test/attach.test 437107943f14d131cf5efc2ae5305a94d7cb1d58
F test/attach2.test 0ec5defa340363de6cd50fd595046465e9aaba2d
F test/attach3.test 359eb65d00102cdfcef6fa4e81dc1648f8f80b27
@@ -466,7 +465,7 @@ F test/autoindex1.test 14b63a9f1e405fe6d5bfc8c8d00249c2ebaf13ea
F test/autoindex2.test af7e595c6864cc6ef5fc38d5db579a3e34940cb8
F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
F test/autoindex5.test 96f084a5e6024ea07cace5888df3223f3ea86990
F test/autoindex5.test 6f487290ce2a667c24517191651bfb8c7d86b6dc
F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
@@ -479,7 +478,7 @@ F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135
F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f
F test/bc_common.tcl 3eda41ef9cda7d5f6c205462c96228b301da4191
F test/bc_common.tcl 5c8689cc6d2fb44b7c0968ae4f85eb26d50022fa
F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
@@ -502,7 +501,6 @@ F test/btree02.test fe69453d474d8154d19b904157ff1db4812fed99
F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
F test/cacheflush.test a755c93482ce2e20c04825304bef27e7b7ea0111
F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738
F test/capi3.test bf6f0308bbbba1e770dac13aa08e5c2ac61c7324
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
@@ -510,7 +508,6 @@ F test/capi3c.test fdc0d67a2cb8e8fc400d5b7735e330161ea057a2
F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
F test/cffault.test 1647eef45512817265c360ed4539538eed26ac69
F test/check.test 5831ddb6f2c687782eaf2e1a07b6e17f24c4f763
F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
@@ -518,7 +515,7 @@ F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
F test/collate1.test 08c18e7512a5a32c97938854263fa15362eeb846
F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621
F test/collate3.test 89defc49983ddfbf0a0555aca8c0521a676f56a5
F test/collate4.test c953715fb498b87163e3e73dd94356bff1f317bd
F test/collate4.test f04d5168685f2eef637ecfa2d4ddf8ec0d600177
F test/collate5.test 65d928034d30d2d263a80f6359f7549ee1598ec6
F test/collate6.test 8be65a182abaac8011a622131486dafb8076e907
F test/collate7.test 8ec29d98f3ee4ccebce6e16ce3863fb6b8c7b868
@@ -566,7 +563,6 @@ F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
F test/cursorhint.test 432811b62bd5ffb812729f49bba3b9ad687550bb
F test/date.test 42973251b9429f2c41b77eb98a7b0b0ba2d3b2c0
F test/dbstatus.test 8de104bb5606f19537d23cd553b41349b5ab1204
F test/dbstatus2.test 10418e62b3db5dca070f0c3eef3ea13946f339c2
@@ -600,7 +596,7 @@ F test/e_select.test 52692ff3849541e828ad4661fe3773a9b8711763
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528
F test/e_uri.test eed3eb41b22d051a1164110dacdc778899126e14
F test/e_uri.test 5ae33760fb2039c61aa2d90886f1664664173585
F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9
F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
F test/e_walauto.test 280714ddf14e1a47dcbc59d515cd0b026dfd5567
@@ -632,7 +628,6 @@ F test/fkey6.test abb59f866c1b44926fd02d1fdd217d831fe04f48
F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13
F test/fkey8.test 8f08203458321e6c19a263829de4cfc936274ab0
F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749
F test/fordelete.test ba12ec1d27cc34a4c23db4446029126d773f3849
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7
@@ -753,7 +748,7 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
F test/fuzz3.test 53fabcd5f0f430f8b221282f6c12c4d0903c21eb
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
F test/fuzzcheck.c ee926f1d4090d053ed542899720d4e4d30811bcc
F test/fuzzcheck.c c84086021a514360268190a1bc6ae8ed78d7c94f
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -764,7 +759,6 @@ F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
F test/hexlit.test 1d312fa816dfd3650a3bb488093bc09a0c927f67
F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
F test/ieee754.test 118b665a97a8df0e8f2fbdb07d113e596f4a6b53
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
F test/in.test 61a24ae38d4b64ec69f06ccdf022992f68a98176
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
@@ -784,7 +778,7 @@ F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635
F test/index.test fe3c7a1aad82af92623747e9c3f3aa94ccd51238
F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407
F test/index3.test 81bc47890b8abfb181bc35f8d10b56c069803386
F test/index3.test fa3e49bbaa4f38091c9c742e36a1abe67c4ef1fc
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
F test/index6.test 7102ec371414c42dfb1d5ca37eb4519aa9edc23a
@@ -821,7 +815,7 @@ F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307
F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
F test/json101.test f0178422b3a2418f423fd0d3caf3571c8d1b9863
F test/json101.test 83e6ebfb3cef6329853ab854403ec82b1787b537
F test/json102.test bf3fe7a706d30936a76a0f7a0375e1e8e73aff5a
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
@@ -902,7 +896,6 @@ F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
F test/notnull.test f8fcf58669ddba79274daa2770d61dfad8274f62
F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2
F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
F test/orderby1.test 870e150450437d3980badbde3d0166b81d9e33f6
@@ -914,7 +907,7 @@ F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
F test/oserror.test 361346396ae18462c7393c1ac5c3f17237bd89b2
F test/oserror.test 14fec2796c2b6fe431c7823750e8a18a761176d7
F test/ovfl.test 4f7ca651cba5c059a12d8c67dddd49bec5747799
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
@@ -929,7 +922,7 @@ F test/parser1.test 222b5cbf3e2e659fec1bf7d723488c8b9c94f1d0
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test 4ea119731c62d2f7d0aa86dd5b184cbb61ca411b
F test/permutations.test ac3b00c299250cc087d4a527b5c75a0f8aef4e54
F test/pragma.test a44253f911e7d50127d4a08f927f47c861a4c772
F test/pragma2.test b5e2ce4c892afceb308c6ae6163a9099b2a0d8d7
F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
@@ -949,7 +942,7 @@ F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.tcl 2d000ceded3115758be96abb9c10a5669fb27862
F test/releasetest.tcl 67a82199e6ddee609211488bc04ed3f9ea3aa28a
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
@@ -1033,7 +1026,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c f8bf04214e7b5f745feea99f7bde68b1c4870666
F test/speedtest1.c 857439869d1cb4db35e1c720ee9c2756eb9ea2a0
F test/spellfix.test 0597065ff57042df1f138e6a2611ae19c2698135
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5
@@ -1047,9 +1040,8 @@ F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
F test/symlink.test 2513f7c030df0f435c6415687ba8b739f3d312df
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
F test/syscall.test fba9ebdc6905d05bba6a835e691f20ed9ea2cc88
F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
F test/tabfunc01.test 03c4ad422c6ab596cff6dcaf86dd061a9f039525
F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
@@ -1302,10 +1294,10 @@ F test/walro.test 34422d1d95aaff0388f0791ec20edb34e2a3ed57
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a
F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e
F test/where.test 9902a3d84e9bc80357a2c54ed0e76c0d6d04a867
F test/where.test 66d4c107e82dfe86c01a96277b77e7a8809aff0b
F test/where2.test af78c55589cbc82d793449493adba0dc3d659f23
F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
F test/where4.test 44f506bf1737cf0fa4fc795e340208250f1fcd89
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8
@@ -1328,9 +1320,8 @@ F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/with1.test 05c8fc7f809f178a8a0519f02c21fe430948c895
F test/with1.test a1e8660be88e2eb4648f8860f831d1e38b5b5443
F test/with2.test 2b40da883658eb74ad8ad06afabe11a408e7fb87
F test/with3.test 511bacdbe41c49cf34f9fd1bd3245fe1575bca98
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
F test/without_rowid1.test 1a7b9bd51b899928d327052df9741d2fe8dbe701
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
@@ -1338,29 +1329,28 @@ F test/without_rowid3.test aad4f9d383e199349b6c7e508a778f7dff5dff79
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
F test/without_rowid5.test 61256715b686359df48ca1742db50cc7e3e7b862
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
F test/wordcount.c 2a0a6c0d0e8e8bbbac1f06d72a6791828c37c0cf
F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
F tool/GetTclKit.bat 8606413d3035c05373a0d7fae82ebf59ae9e16c3
F tool/addopcodes.tcl f1fd17b639910226749d1ae006beef8f60378274
F tool/build-all-msvc.bat e42141ca3c3812315432f9813ef9eb78aa8d99c9 x
F tool/addopcodes.tcl 7cc82ecca456a6b3148abf492b0419b83140881a
F tool/build-all-msvc.bat 2b1703b322da121e56b955cb58de091107f777c3 x
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
F tool/fuzzershell.c 94019b185caceffc9f7c7b678a6489e42bc2aefa
F tool/fuzzershell.c 87cc3d6f00239d786d231954289f106131989cc7
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d
F tool/lempar.c 02cd882bd3144a5e25c86c652af49a6bc07baeae
F tool/lemon.c 039f813b520b9395740c52f9cbf36c90b5d8df03
F tool/lempar.c 3617143ddb9b176c3605defe6a9c798793280120
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
F tool/mkautoconfamal.sh 4bdf61548a143e5977bd86ab93d68b694d10c8fa
F tool/mkkeywordhash.c 37f9c2e62c31384b697ede8825e2d344e98db22c
F tool/mkautoconfamal.sh d1a2da0e15b2ed33d60af35c7e9d483f13a8eb9f
F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670
F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b
F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
@@ -1377,32 +1367,34 @@ F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
F tool/replace.tcl 7727c60a04299b65a92f5e1590896fea0f25b9e0
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
F tool/run-speed-test.sh 0ae485af4fe9f826e2b494be8c81f8ca9e222a4a
F tool/showdb.c d4476e000a64eca9f5e2c2f68741e747b9778e8d
F tool/showdb.c b1e16174385d5bd0815823a7fda1ecc82ed6088b
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
F tool/showstat4.c bda40d6e395df7edb6e9ea630784d3d762c35b4b
F tool/showwal.c ec79959834f7b21f1e0a2aa52bb7c056d2203977
F tool/showstat4.c 9515faa8ec176599d4a8288293ba8ec61f7b728a
F tool/showwal.c 85cb36d4fe3e93e2fbd63e786e0d1ce42d0c4fad
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/spaceanal.tcl 93c1fdc9733c525b17a2024c7df193daa002e037
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
F tool/sqldiff.c 40e3458f0015290be8ecb6e03f9dbf1bb1e264c0
F tool/sqldiff.c b318efc2eaf7a7fac4d281a0ce736193cb2506df
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f
F tool/tostr.tcl 96022f35ada2194f6f8ccf6fd95809e90ed277c4
F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003
F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c
F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 6ea2df86c95c226052f528424e9bee367a2e765a
R c4fc880f1c9308c0365b7757399767dc
P 871e091df651b2275a672c35ff938bd4b6db0d7f
R 12f17dff849f2a06a10012eebf93b957
T *branch * unpack-opcode
T *sym-unpack-opcode *
T -sym-trunk *
U drh
Z 622f282d2cf652046e0082888bbfa948
Z 51853eb094abb609c64d30de1af24213
+1 -1
View File
@@ -1 +1 @@
09752e51a18ac1b4c9642965e6ee1b6a32de00df
39ae92f5c63de4b95502f438dc7e9f2669efdf91
+19 -22
View File
@@ -46,9 +46,6 @@
#include <assert.h>
#include <ctype.h>
#define ISSPACE(X) isspace((unsigned char)(X))
#define ISDIGIT(X) isdigit((unsigned char)(X))
/* The suffix to append to the child command lines, if any */
#if defined(_WIN32)
# define GETPID (int)GetCurrentProcessId
@@ -190,10 +187,10 @@ int strglob(const char *zGlob, const char *z){
}
if( c2==0 || (seen ^ invert)==0 ) return 0;
}else if( c=='#' ){
if( (z[0]=='-' || z[0]=='+') && ISDIGIT(z[1]) ) z++;
if( !ISDIGIT(z[0]) ) return 0;
if( (z[0]=='-' || z[0]=='+') && isdigit(z[1]) ) z++;
if( !isdigit(z[0]) ) return 0;
z++;
while( ISDIGIT(z[0]) ){ z++; }
while( isdigit(z[0]) ){ z++; }
}else{
if( c!=(*(z++)) ) return 0;
}
@@ -292,7 +289,7 @@ static void logMessage(const char *zFormat, ...){
*/
static int clipLength(const char *z){
int n = (int)strlen(z);
while( n>0 && ISSPACE(z[n-1]) ){ n--; }
while( n>0 && isspace(z[n-1]) ){ n--; }
return n;
}
@@ -447,7 +444,7 @@ static void stringAppendTerm(String *p, const char *z){
stringAppend(p, "nil", 3);
return;
}
for(i=0; z[i] && !ISSPACE(z[i]); i++){}
for(i=0; z[i] && !isspace(z[i]); i++){}
if( i>0 && z[i]==0 ){
stringAppend(p, z, i);
return;
@@ -702,7 +699,7 @@ static char *readFile(const char *zFilename){
*/
static int tokenLength(const char *z, int *pnLine){
int n = 0;
if( ISSPACE(z[0]) || (z[0]=='/' && z[1]=='*') ){
if( isspace(z[0]) || (z[0]=='/' && z[1]=='*') ){
int inC = 0;
int c;
if( z[0]=='/' ){
@@ -711,7 +708,7 @@ static int tokenLength(const char *z, int *pnLine){
}
while( (c = z[n++])!=0 ){
if( c=='\n' ) (*pnLine)++;
if( ISSPACE(c) ) continue;
if( isspace(c) ) continue;
if( inC && c=='*' && z[n]=='/' ){
n++;
inC = 0;
@@ -737,7 +734,7 @@ static int tokenLength(const char *z, int *pnLine){
}
}else{
int c;
for(n=1; (c = z[n])!=0 && !ISSPACE(c) && c!='"' && c!='\'' && c!=';'; n++){}
for(n=1; (c = z[n])!=0 && !isspace(c) && c!='"' && c!='\'' && c!=';'; n++){}
}
return n;
}
@@ -751,7 +748,7 @@ static int extractToken(const char *zIn, int nIn, char *zOut, int nOut){
zOut[0] = 0;
return 0;
}
for(i=0; i<nIn && i<nOut-1 && !ISSPACE(zIn[i]); i++){ zOut[i] = zIn[i]; }
for(i=0; i<nIn && i<nOut-1 && !isspace(zIn[i]); i++){ zOut[i] = zIn[i]; }
zOut[i] = 0;
return i;
}
@@ -761,7 +758,7 @@ static int extractToken(const char *zIn, int nIn, char *zOut, int nOut){
*/
static int findEnd(const char *z, int *pnLine){
int n = 0;
while( z[n] && (strncmp(z+n,"--end",5) || !ISSPACE(z[n+5])) ){
while( z[n] && (strncmp(z+n,"--end",5) || !isspace(z[n+5])) ){
n += tokenLength(z+n, pnLine);
}
return n;
@@ -776,12 +773,12 @@ static int findEndif(const char *z, int stopAtElse, int *pnLine){
int n = 0;
while( z[n] ){
int len = tokenLength(z+n, pnLine);
if( (strncmp(z+n,"--endif",7)==0 && ISSPACE(z[n+7]))
|| (stopAtElse && strncmp(z+n,"--else",6)==0 && ISSPACE(z[n+6]))
if( (strncmp(z+n,"--endif",7)==0 && isspace(z[n+7]))
|| (stopAtElse && strncmp(z+n,"--else",6)==0 && isspace(z[n+6]))
){
return n+len;
}
if( strncmp(z+n,"--if",4)==0 && ISSPACE(z[n+4]) ){
if( strncmp(z+n,"--if",4)==0 && isspace(z[n+4]) ){
int skip = findEndif(z+n+len, 0, pnLine);
n += skip + len;
}else{
@@ -891,7 +888,7 @@ static void runScript(
while( (c = zScript[ii])!=0 ){
prevLine = lineno;
len = tokenLength(zScript+ii, &lineno);
if( ISSPACE(c) || (c=='/' && zScript[ii+1]=='*') ){
if( isspace(c) || (c=='/' && zScript[ii+1]=='*') ){
ii += len;
continue;
}
@@ -912,7 +909,7 @@ static void runScript(
if( g.iTrace>=2 ) logMessage("%.*s", len, zScript+ii);
n = extractToken(zScript+ii+2, len-2, zCmd, sizeof(zCmd));
for(nArg=0; n<len-2 && nArg<MX_ARG; nArg++){
while( n<len-2 && ISSPACE(zScript[ii+2+n]) ){ n++; }
while( n<len-2 && isspace(zScript[ii+2+n]) ){ n++; }
if( n>=len-2 ) break;
n += extractToken(zScript+ii+2+n, len-2-n,
azArg[nArg], sizeof(azArg[nArg]));
@@ -979,7 +976,7 @@ static void runScript(
if( strcmp(zCmd, "match")==0 ){
int jj;
char *zAns = zScript+ii;
for(jj=7; jj<len-1 && ISSPACE(zAns[jj]); jj++){}
for(jj=7; jj<len-1 && isspace(zAns[jj]); jj++){}
zAns += jj;
if( len-jj-1!=sResult.n || strncmp(sResult.z, zAns, len-jj-1) ){
errorMessage("line %d of %s:\nExpected [%.*s]\n Got [%s]",
@@ -1001,7 +998,7 @@ static void runScript(
char *zAns = zScript+ii;
char *zCopy;
int isGlob = (zCmd[0]=='g');
for(jj=9-3*isGlob; jj<len-1 && ISSPACE(zAns[jj]); jj++){}
for(jj=9-3*isGlob; jj<len-1 && isspace(zAns[jj]); jj++){}
zAns += jj;
zCopy = sqlite3_mprintf("%.*s", len-jj-1, zAns);
if( (sqlite3_strglob(zCopy, sResult.z)==0)^isGlob ){
@@ -1053,7 +1050,7 @@ static void runScript(
*/
if( strcmp(zCmd, "print")==0 ){
int jj;
for(jj=7; jj<len && ISSPACE(zScript[ii+jj]); jj++){}
for(jj=7; jj<len && isspace(zScript[ii+jj]); jj++){}
logMessage("%.*s", len-jj, zScript+ii+jj);
}else
@@ -1065,7 +1062,7 @@ static void runScript(
if( strcmp(zCmd, "if")==0 ){
int jj, rc;
sqlite3_stmt *pStmt;
for(jj=4; jj<len && ISSPACE(zScript[ii+jj]); jj++){}
for(jj=4; jj<len && isspace(zScript[ii+jj]); jj++){}
pStmt = prepareSql("SELECT %.*s", len-jj, zScript+ii+jj);
rc = sqlite3_step(pStmt);
if( rc!=SQLITE_ROW || sqlite3_column_int(pStmt, 0)==0 ){
+5 -4
View File
@@ -293,7 +293,7 @@ static int backupOnePage(
DbPage *pDestPg = 0;
Pgno iDest = (Pgno)(iOff/nDestPgsz)+1;
if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt) ) continue;
if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg, 0))
if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg))
&& SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg))
){
const u8 *zIn = &zSrcData[iOff%nSrcPgsz];
@@ -419,7 +419,8 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
const Pgno iSrcPg = p->iNext; /* Source page number */
if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
DbPage *pSrcPg; /* Source page object */
rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg,PAGER_GET_READONLY);
rc = sqlite3PagerAcquire(pSrcPager, iSrcPg, &pSrcPg,
PAGER_GET_READONLY);
if( rc==SQLITE_OK ){
rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
sqlite3PagerUnref(pSrcPg);
@@ -519,7 +520,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){
DbPage *pPg;
rc = sqlite3PagerGet(pDestPager, iPg, &pPg, 0);
rc = sqlite3PagerGet(pDestPager, iPg, &pPg);
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite(pPg);
sqlite3PagerUnref(pPg);
@@ -539,7 +540,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
){
PgHdr *pSrcPg = 0;
const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg, 0);
rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
if( rc==SQLITE_OK ){
u8 *zData = sqlite3PagerGetData(pSrcPg);
rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
+36 -50
View File
@@ -858,26 +858,6 @@ int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){
return SQLITE_OK;
}
#ifdef SQLITE_ENABLE_CURSOR_HINTS
/*
** Provide hints to the cursor. The particular hint given (and the type
** and number of the varargs parameters) is determined by the eHintType
** parameter. See the definitions of the BTREE_HINT_* macros for details.
*/
void sqlite3BtreeCursorHint(BtCursor *pCur, int eHintType, ...){
/* Used only by system that substitute their own storage engine */
}
#endif
/*
** Provide flag hints to the cursor.
*/
void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){
assert( x==BTREE_SEEK_EQ || x==BTREE_BULKLOAD || x==0 );
pCur->hints = x;
}
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
** Given a page number of a regular database page, return the page
@@ -931,7 +911,7 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
return;
}
iPtrmap = PTRMAP_PAGENO(pBt, key);
rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0);
rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage);
if( rc!=SQLITE_OK ){
*pRC = rc;
return;
@@ -974,7 +954,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
assert( sqlite3_mutex_held(pBt->mutex) );
iPtrmap = PTRMAP_PAGENO(pBt, key);
rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0);
rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage);
if( rc!=0 ){
return rc;
}
@@ -1901,14 +1881,11 @@ static void zeroPage(MemPage *pPage, int flags){
*/
static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){
MemPage *pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
if( pgno!=pPage->pgno ){
pPage->aData = sqlite3PagerGetData(pDbPage);
pPage->pDbPage = pDbPage;
pPage->pBt = pBt;
pPage->pgno = pgno;
pPage->hdrOffset = pgno==1 ? 100 : 0;
}
assert( pPage->aData==sqlite3PagerGetData(pDbPage) );
pPage->aData = sqlite3PagerGetData(pDbPage);
pPage->pDbPage = pDbPage;
pPage->pBt = pBt;
pPage->pgno = pgno;
pPage->hdrOffset = pgno==1 ? 100 : 0;
return pPage;
}
@@ -1934,7 +1911,7 @@ static int btreeGetPage(
assert( flags==0 || flags==PAGER_GET_NOCONTENT || flags==PAGER_GET_READONLY );
assert( sqlite3_mutex_held(pBt->mutex) );
rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, flags);
rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, flags);
if( rc ) return rc;
*ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
return SQLITE_OK;
@@ -1999,25 +1976,24 @@ static int getAndInitPage(
rc = SQLITE_CORRUPT_BKPT;
goto getAndInitPage_error;
}
rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly);
rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly);
if( rc ){
goto getAndInitPage_error;
}
*ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
*ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
if( (*ppPage)->isInit==0 ){
btreePageFromDbPage(pDbPage, pgno, pBt);
rc = btreeInitPage(*ppPage);
if( rc!=SQLITE_OK ){
releasePage(*ppPage);
goto getAndInitPage_error;
}
}
assert( (*ppPage)->pgno==pgno );
assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) );
/* If obtaining a child page for a cursor, we must verify that the page is
** compatible with the root page. */
if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){
if( pCur
&& ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey)
){
rc = SQLITE_CORRUPT_BKPT;
releasePage(*ppPage);
goto getAndInitPage_error;
@@ -4079,16 +4055,13 @@ static int btreeCursor(
BtCursor *pX; /* Looping over other all cursors */
assert( sqlite3BtreeHoldsMutex(p) );
assert( wrFlag==0
|| wrFlag==BTREE_WRCSR
|| wrFlag==(BTREE_WRCSR|BTREE_FORDELETE)
);
assert( wrFlag==0 || wrFlag==1 );
/* The following assert statements verify that if this is a sharable
** b-tree database, the connection is holding the required table locks,
** and that no other connection has any open cursor that conflicts with
** this lock. */
assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1)) );
assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, wrFlag+1) );
assert( wrFlag==0 || !hasReadConflicts(p, iTable) );
/* Assert that the caller has opened the required transaction. */
@@ -4113,7 +4086,8 @@ static int btreeCursor(
pCur->pKeyInfo = pKeyInfo;
pCur->pBtree = p;
pCur->pBt = pBt;
pCur->curFlags = wrFlag ? BTCF_WriteFlag : 0;
assert( wrFlag==0 || wrFlag==BTCF_WriteFlag );
pCur->curFlags = wrFlag;
pCur->curPagerFlags = wrFlag ? 0 : PAGER_GET_READONLY;
/* If there are two or more cursors on the same btree, then all such
** cursors *must* have the BTCF_Multiple flag set. */
@@ -4525,9 +4499,7 @@ static int accessPayload(
/* If required, populate the overflow page-list cache. */
if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){
assert( pCur->aOverflow[iIdx]==0
|| pCur->aOverflow[iIdx]==nextPage
|| CORRUPT_DB );
assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage);
pCur->aOverflow[iIdx] = nextPage;
}
@@ -4597,7 +4569,7 @@ static int accessPayload(
{
DbPage *pDbPage;
rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage,
rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage,
((eOp&0x01)==0 ? PAGER_GET_READONLY : 0)
);
if( rc==SQLITE_OK ){
@@ -5041,8 +5013,6 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
** *pRes>0 The cursor is left pointing at an entry that
** is larger than intKey/pIdxKey.
**
** For index tables, the pIdxKey->eqSeen field is set to 1 if there
** exists an entry in the table that exactly matches pIdxKey.
*/
int sqlite3BtreeMovetoUnpacked(
BtCursor *pCur, /* The cursor to be moved */
@@ -6966,6 +6936,9 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
** If aOvflSpace is set to a null pointer, this function returns
** SQLITE_NOMEM.
*/
#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
#pragma optimize("", off)
#endif
static int balance_nonroot(
MemPage *pParent, /* Parent page of siblings being balanced */
int iParentIdx, /* Index of "the page" in pParent */
@@ -7711,6 +7684,9 @@ balance_cleanup:
return rc;
}
#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
#pragma optimize("", on)
#endif
/*
@@ -8909,7 +8885,7 @@ static void checkList(
break;
}
if( checkRef(pCheck, iPage) ) break;
if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){
if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage) ){
checkAppendMsg(pCheck, "failed to get page %d", iPage);
break;
}
@@ -9646,6 +9622,15 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
return rc;
}
/*
** set the mask of hint flags for cursor pCsr.
*/
void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
assert( mask==BTREE_BULKLOAD || mask==BTREE_SEEK_EQ || mask==0 );
pCsr->hints = mask;
}
#ifdef SQLITE_DEBUG
/*
** Return true if the cursor has a hint specified. This routine is
** only used from within assert() statements
@@ -9653,6 +9638,7 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){
return (pCsr->hints & mask)!=0;
}
#endif
/*
** Return true if the given Btree is read-only.
+5 -51
View File
@@ -150,37 +150,8 @@ int sqlite3BtreeNewDb(Btree *p);
#define BTREE_DATA_VERSION 15 /* A virtual meta-value */
/*
** Kinds of hints that can be passed into the sqlite3BtreeCursorHint()
** interface.
**
** BTREE_HINT_RANGE (arguments: Expr*, Mem*)
**
** The first argument is an Expr* (which is guaranteed to be constant for
** the lifetime of the cursor) that defines constraints on which rows
** might be fetched with this cursor. The Expr* tree may contain
** TK_REGISTER nodes that refer to values stored in the array of registers
** passed as the second parameter. In other words, if Expr.op==TK_REGISTER
** then the value of the node is the value in Mem[pExpr.iTable]. Any
** TK_COLUMN node in the expression tree refers to the Expr.iColumn-th
** column of the b-tree of the cursor. The Expr tree will not contain
** any function calls nor subqueries nor references to b-trees other than
** the cursor being hinted.
**
** The design of the _RANGE hint is aid b-tree implementations that try
** to prefetch content from remote machines - to provide those
** implementations with limits on what needs to be prefetched and thereby
** reduce network bandwidth.
**
** Note that BTREE_HINT_FLAGS with BTREE_BULKLOAD is the only hint used by
** standard SQLite. The other hints are provided for extentions that use
** the SQLite parser and code generator but substitute their own storage
** engine.
*/
#define BTREE_HINT_RANGE 0 /* Range constraints on queries */
/*
** Values that may be OR'd together to form the argument to the
** BTREE_HINT_FLAGS hint for sqlite3BtreeCursorHint():
** Values that may be OR'd together to form the second argument of an
** sqlite3BtreeCursorHints() call.
**
** The BTREE_BULKLOAD flag is set on index cursors when the index is going
** to be filled with content that is already in sorted order.
@@ -194,22 +165,6 @@ int sqlite3BtreeNewDb(Btree *p);
#define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */
#define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */
/*
** Flags passed as the third argument to sqlite3BtreeCursor().
**
** For read-only cursors the wrFlag argument is always zero. For read-write
** cursors it may be set to either (BTREE_WRCSR|BTREE_FORDELETE) or
** (BTREE_WRCSR). If the BTREE_FORDELETE flag is set, then the cursor will
** only be used by SQLite for the following:
**
** * to seek to and delete specific entries, and/or
**
** * to read values that will be used to create keys that other
** BTREE_FORDELETE cursors will seek to and delete.
*/
#define BTREE_WRCSR 0x00000004 /* read-write cursor */
#define BTREE_FORDELETE 0x00000008 /* Cursor is for seek/delete only */
int sqlite3BtreeCursor(
Btree*, /* BTree containing table to open */
int iTable, /* Index of root page */
@@ -219,10 +174,6 @@ int sqlite3BtreeCursor(
);
int sqlite3BtreeCursorSize(void);
void sqlite3BtreeCursorZero(BtCursor*);
void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
void sqlite3BtreeCursorHint(BtCursor*, int, ...);
#endif
int sqlite3BtreeCloseCursor(BtCursor*);
int sqlite3BtreeMovetoUnpacked(
@@ -257,7 +208,10 @@ int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
void sqlite3BtreeIncrblobCursor(BtCursor *);
void sqlite3BtreeClearCursor(BtCursor *);
int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
#ifdef SQLITE_DEBUG
int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
#endif
int sqlite3BtreeIsReadonly(Btree *pBt);
int sqlite3HeaderSizeBtree(void);
+1 -1
View File
@@ -517,7 +517,7 @@ struct BtCursor {
int skipNext; /* Prev() is noop if negative. Next() is noop if positive.
** Error code if eState==CURSOR_FAULT */
u8 curFlags; /* zero or more BTCF_* flags defined below */
u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */
u8 curPagerFlags; /* Flags to send to sqlite3PagerAcquire() */
u8 eState; /* One of the CURSOR_XXX constants (see below) */
u8 hints; /* As configured by CursorSetHints() */
/* All fields above are zeroed when the cursor is allocated. See
+24 -25
View File
@@ -1271,30 +1271,6 @@ void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){
sqlite3ExprDelete(db, pSpan->pExpr);
}
/*
** Backwards Compatibility Hack:
**
** Historical versions of SQLite accepted strings as column names in
** indexes and PRIMARY KEY constraints and in UNIQUE constraints. Example:
**
** CREATE TABLE xyz(a,b,c,d,e,PRIMARY KEY('a'),UNIQUE('b','c' COLLATE trim)
** CREATE INDEX abc ON xyz('c','d' DESC,'e' COLLATE nocase DESC);
**
** This is goofy. But to preserve backwards compatibility we continue to
** accept it. This routine does the necessary conversion. It converts
** the expression given in its argument from a TK_STRING into a TK_ID
** if the expression is just a TK_STRING with an optional COLLATE clause.
** If the epxression is anything other than TK_STRING, the expression is
** unchanged.
*/
static void sqlite3StringToId(Expr *p){
if( p->op==TK_STRING ){
p->op = TK_ID;
}else if( p->op==TK_COLLATE && p->pLeft->op==TK_STRING ){
p->pLeft->op = TK_ID;
}
}
/*
** Designate the PRIMARY KEY for the table. pList is a list of names
** of columns that form the primary key. If pList is NULL, then the
@@ -1341,7 +1317,6 @@ void sqlite3AddPrimaryKey(
for(i=0; i<nTerm; i++){
Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[i].pExpr);
assert( pCExpr!=0 );
sqlite3StringToId(pCExpr);
if( pCExpr->op==TK_ID ){
const char *zCName = pCExpr->u.zToken;
for(iCol=0; iCol<pTab->nCol; iCol++){
@@ -2880,6 +2855,30 @@ Index *sqlite3AllocateIndexObject(
return p;
}
/*
** Backwards Compatibility Hack:
**
** Historical versions of SQLite accepted strings as column names in
** indexes and PRIMARY KEY constraints and in UNIQUE constraints. Example:
**
** CREATE TABLE xyz(a,b,c,d,e,PRIMARY KEY('a'),UNIQUE('b','c' COLLATE trim)
** CREATE INDEX abc ON xyz('c','d' DESC,'e' COLLATE nocase DESC);
**
** This is goofy. But to preserve backwards compatibility we continue to
** accept it. This routine does the necessary conversion. It converts
** the expression given in its argument from a TK_STRING into a TK_ID
** if the expression is just a TK_STRING with an optional COLLATE clause.
** If the epxression is anything other than TK_STRING, the expression is
** unchanged.
*/
static void sqlite3StringToId(Expr *p){
if( p->op==TK_STRING ){
p->op = TK_ID;
}else if( p->op==TK_COLLATE && p->pLeft->op==TK_STRING ){
p->pLeft->op = TK_ID;
}
}
/*
** Create a new index for an SQL table. pName1.pName2 is the name of the index
** and pTblList is the name of the table that is to be indexed. Both will
+3 -3
View File
@@ -386,7 +386,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
int rc;
u32 iPrev = pCell->aOvfl[j-1];
DbPage *pPg = 0;
rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPrev, &pPg, 0);
rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPrev, &pPg);
if( rc!=SQLITE_OK ){
assert( pPg==0 );
return rc;
@@ -454,7 +454,7 @@ statNextRestart:
pCsr->isEof = 1;
return sqlite3_reset(pCsr->pStmt);
}
rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg, 0);
rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg);
pCsr->aPage[0].iPgno = iRoot;
pCsr->aPage[0].iCell = 0;
pCsr->aPage[0].zPath = z = sqlite3_mprintf("/");
@@ -514,7 +514,7 @@ statNextRestart:
}else{
p[1].iPgno = p->aCell[p->iCell].iChildPg;
}
rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg, 0);
rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg);
p[1].iCell = 0;
p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell);
p->iCell++;
+2 -3
View File
@@ -478,13 +478,12 @@ void sqlite3DeleteFrom(
*/
if( !isView ){
int iAddrOnce = 0;
u8 p5 = (eOnePass==ONEPASS_OFF ? 0 : OPFLAG_FORDELETE);
if( eOnePass==ONEPASS_MULTI ){
iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
}
testcase( IsVirtual(pTab) );
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, p5, iTabCur,
aToOpen, &iDataCur, &iIdxCur);
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iTabCur, aToOpen,
&iDataCur, &iIdxCur);
assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur );
assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 );
if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce);
+2 -22
View File
@@ -548,11 +548,11 @@ Expr *sqlite3PExpr(
const Token *pToken /* Argument token */
){
Expr *p;
if( op==TK_AND && pParse->nErr==0 ){
if( op==TK_AND && pLeft && pRight && pParse->nErr==0 ){
/* Take advantage of short-circuit false optimization for AND */
p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
}else{
p = sqlite3ExprAlloc(pParse->db, op & TKFLG_MASK, pToken, 1);
p = sqlite3ExprAlloc(pParse->db, op, pToken, 1);
sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
}
if( p ) {
@@ -1415,22 +1415,6 @@ int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
return exprIsConst(p, 4+isInit, 0);
}
#ifdef SQLITE_ENABLE_CURSOR_HINTS
/*
** Walk an expression tree. Return 1 if the expression contains a
** subquery of some kind. Return 0 if there are no subqueries.
*/
int sqlite3ExprContainsSubquery(Expr *p){
Walker w;
memset(&w, 0, sizeof(w));
w.eCode = 1;
w.xExprCallback = sqlite3ExprWalkNoop;
w.xSelectCallback = selectNodeIsConstant;
sqlite3WalkExpr(&w, p);
return w.eCode==0;
}
#endif
/*
** If the expression p codes a constant integer that is small enough
** to fit in a 32-bit integer, return 1 and put the value of the integer
@@ -3372,10 +3356,6 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
**
** The SQLITE_ECEL_FACTOR argument allows constant arguments to be
** factored out into initialization code.
**
** The SQLITE_ECEL_REF flag means that expressions in the list with
** ExprList.a[].u.x.iOrderByCol>0 have already been evaluated and stored
** in registers at srcReg, and so the value can be copied from there.
*/
int sqlite3ExprCodeExprList(
Parse *pParse, /* Parsing context */
+1 -4
View File
@@ -762,7 +762,7 @@ void sqlite3Insert(
/* If this is not a view, open the table and and all indices */
if( !isView ){
int nIdx;
nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0,
nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, -1, 0,
&iDataCur, &iIdxCur);
aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));
if( aRegIdx==0 ){
@@ -1650,7 +1650,6 @@ int sqlite3OpenTableAndIndices(
Parse *pParse, /* Parsing context */
Table *pTab, /* Table to be opened */
int op, /* OP_OpenRead or OP_OpenWrite */
u8 p5, /* P5 value for OP_Open* instructions */
int iBase, /* Use this for the table cursor, if there is one */
u8 *aToOpen, /* If not NULL: boolean for each table and index */
int *piDataCur, /* Write the database source cursor number here */
@@ -1663,7 +1662,6 @@ int sqlite3OpenTableAndIndices(
Vdbe *v;
assert( op==OP_OpenRead || op==OP_OpenWrite );
assert( op==OP_OpenWrite || p5==0 );
if( IsVirtual(pTab) ){
/* This routine is a no-op for virtual tables. Leave the output
** variables *piDataCur and *piIdxCur uninitialized so that valgrind
@@ -1691,7 +1689,6 @@ int sqlite3OpenTableAndIndices(
if( aToOpen==0 || aToOpen[i+1] ){
sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
sqlite3VdbeChangeP5(v, p5);
VdbeComment((v, "%s", pIdx->zName));
}
}
+895
View File
@@ -0,0 +1,895 @@
/* Driver template for the LEMON parser generator.
** The author disclaims copyright to this source code.
**
** This version of "lempar.c" is modified, slightly, for use by SQLite.
** The only modifications are the addition of a couple of NEVER()
** macros to disable tests that are needed in the case of a general
** LALR(1) grammar but which are always false in the
** specific grammar used by SQLite.
*/
/* First off, code is included that follows the "include" declaration
** in the input grammar file. */
#include <stdio.h>
%%
/* Next is all token values, in a form suitable for use by makeheaders.
** This section will be null unless lemon is run with the -m switch.
*/
/*
** These constants (all generated automatically by the parser generator)
** specify the various kinds of tokens (terminals) that the parser
** understands.
**
** Each symbol here is a terminal symbol in the grammar.
*/
%%
/* Make sure the INTERFACE macro is defined.
*/
#ifndef INTERFACE
# define INTERFACE 1
#endif
/* The next thing included is series of defines which control
** various aspects of the generated parser.
** YYCODETYPE is the data type used for storing terminal
** and nonterminal numbers. "unsigned char" is
** used if there are fewer than 250 terminals
** and nonterminals. "int" is used otherwise.
** YYNOCODE is a number of type YYCODETYPE which corresponds
** to no legal terminal or nonterminal number. This
** number is used to fill in empty slots of the hash
** table.
** YYFALLBACK If defined, this indicates that one or more tokens
** have fall-back values which should be used if the
** original value of the token will not parse.
** YYACTIONTYPE is the data type used for storing terminal
** and nonterminal numbers. "unsigned char" is
** used if there are fewer than 250 rules and
** states combined. "int" is used otherwise.
** ParseTOKENTYPE is the data type used for minor tokens given
** directly to the parser from the tokenizer.
** YYMINORTYPE is the data type used for all minor tokens.
** This is typically a union of many types, one of
** which is ParseTOKENTYPE. The entry in the union
** for base tokens is called "yy0".
** YYSTACKDEPTH is the maximum depth of the parser's stack. If
** zero the stack is dynamically sized using realloc()
** ParseARG_SDECL A static variable declaration for the %extra_argument
** ParseARG_PDECL A parameter declaration for the %extra_argument
** ParseARG_STORE Code to store %extra_argument into yypParser
** ParseARG_FETCH Code to extract %extra_argument from yypParser
** YYERRORSYMBOL is the code number of the error symbol. If not
** defined, then do no error processing.
** YYNSTATE the combined number of states.
** YYNRULE the number of rules in the grammar
** YY_MAX_SHIFT Maximum value for shift actions
** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
** YY_MIN_REDUCE Maximum value for reduce actions
** YY_ERROR_ACTION The yy_action[] code for syntax error
** YY_ACCEPT_ACTION The yy_action[] code for accept
** YY_NO_ACTION The yy_action[] code for no-op
*/
%%
/* The yyzerominor constant is used to initialize instances of
** YYMINORTYPE objects to zero. */
static const YYMINORTYPE yyzerominor = { 0 };
/* Define the yytestcase() macro to be a no-op if is not already defined
** otherwise.
**
** Applications can choose to define yytestcase() in the %include section
** to a macro that can assist in verifying code coverage. For production
** code the yytestcase() macro should be turned off. But it is useful
** for testing.
*/
#ifndef yytestcase
# define yytestcase(X)
#endif
/* Next are the tables used to determine what action to take based on the
** current state and lookahead token. These tables are used to implement
** functions that take a state number and lookahead value and return an
** action integer.
**
** Suppose the action integer is N. Then the action is determined as
** follows
**
** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead
** token onto the stack and goto state N.
**
** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then
** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE.
**
** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE
** and YY_MAX_REDUCE
** N == YY_ERROR_ACTION A syntax error has occurred.
**
** N == YY_ACCEPT_ACTION The parser accepts its input.
**
** N == YY_NO_ACTION No such action. Denotes unused
** slots in the yy_action[] table.
**
** The action table is constructed as a single large table named yy_action[].
** Given state S and lookahead X, the action is computed as
**
** yy_action[ yy_shift_ofst[S] + X ]
**
** If the index value yy_shift_ofst[S]+X is out of range or if the value
** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
** and that yy_default[S] should be used instead.
**
** The formula above is for computing the action when the lookahead is
** a terminal symbol. If the lookahead is a non-terminal (as occurs after
** a reduce action) then the yy_reduce_ofst[] array is used in place of
** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
** YY_SHIFT_USE_DFLT.
**
** The following are the tables generated in this section:
**
** yy_action[] A single table containing all actions.
** yy_lookahead[] A table containing the lookahead for each entry in
** yy_action. Used to detect hash collisions.
** yy_shift_ofst[] For each state, the offset into yy_action for
** shifting terminals.
** yy_reduce_ofst[] For each state, the offset into yy_action for
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
*/
%%
/* The next table maps tokens into fallback tokens. If a construct
** like the following:
**
** %fallback ID X Y Z.
**
** appears in the grammar, then ID becomes a fallback token for X, Y,
** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
** but it does not parse, the type of the token is changed to ID and
** the parse is retried before an error is thrown.
*/
#ifdef YYFALLBACK
static const YYCODETYPE yyFallback[] = {
%%
};
#endif /* YYFALLBACK */
/* The following structure represents a single element of the
** parser's stack. Information stored includes:
**
** + The state number for the parser at this level of the stack.
**
** + The value of the token stored at this level of the stack.
** (In other words, the "major" token.)
**
** + The semantic value stored at this level of the stack. This is
** the information used by the action routines in the grammar.
** It is sometimes called the "minor" token.
**
** After the "shift" half of a SHIFTREDUCE action, the stateno field
** actually contains the reduce action for the second half of the
** SHIFTREDUCE.
*/
struct yyStackEntry {
YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */
YYCODETYPE major; /* The major token value. This is the code
** number for the token at this stack level */
YYMINORTYPE minor; /* The user-supplied minor token value. This
** is the value of the token */
};
typedef struct yyStackEntry yyStackEntry;
/* The state of the parser is completely contained in an instance of
** the following structure */
struct yyParser {
int yyidx; /* Index of top element in stack */
#ifdef YYTRACKMAXSTACKDEPTH
int yyidxMax; /* Maximum value of yyidx */
#endif
int yyerrcnt; /* Shifts left before out of the error */
ParseARG_SDECL /* A place to hold %extra_argument */
#if YYSTACKDEPTH<=0
int yystksz; /* Current side of the stack */
yyStackEntry *yystack; /* The parser's stack */
#else
yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
#endif
};
typedef struct yyParser yyParser;
#ifndef NDEBUG
#include <stdio.h>
static FILE *yyTraceFILE = 0;
static char *yyTracePrompt = 0;
#endif /* NDEBUG */
#ifndef NDEBUG
/*
** Turn parser tracing on by giving a stream to which to write the trace
** and a prompt to preface each trace message. Tracing is turned off
** by making either argument NULL
**
** Inputs:
** <ul>
** <li> A FILE* to which trace output should be written.
** If NULL, then tracing is turned off.
** <li> A prefix string written at the beginning of every
** line of trace output. If NULL, then tracing is
** turned off.
** </ul>
**
** Outputs:
** None.
*/
void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
yyTraceFILE = TraceFILE;
yyTracePrompt = zTracePrompt;
if( yyTraceFILE==0 ) yyTracePrompt = 0;
else if( yyTracePrompt==0 ) yyTraceFILE = 0;
}
#endif /* NDEBUG */
#ifndef NDEBUG
/* For tracing shifts, the names of all terminals and nonterminals
** are required. The following table supplies these names */
static const char *const yyTokenName[] = {
%%
};
#endif /* NDEBUG */
#ifndef NDEBUG
/* For tracing reduce actions, the names of all rules are required.
*/
static const char *const yyRuleName[] = {
%%
};
#endif /* NDEBUG */
#if YYSTACKDEPTH<=0
/*
** Try to increase the size of the parser stack.
*/
static void yyGrowStack(yyParser *p){
int newSize;
yyStackEntry *pNew;
newSize = p->yystksz*2 + 100;
pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
if( pNew ){
p->yystack = pNew;
p->yystksz = newSize;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sStack grows to %d entries!\n",
yyTracePrompt, p->yystksz);
}
#endif
}
}
#endif
/*
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
** malloc.
**
** Inputs:
** A pointer to the function used to allocate memory.
**
** Outputs:
** A pointer to a parser. This pointer is used in subsequent calls
** to Parse and ParseFree.
*/
void *ParseAlloc(void *(*mallocProc)(u64)){
yyParser *pParser;
pParser = (yyParser*)(*mallocProc)( (u64)sizeof(yyParser) );
if( pParser ){
pParser->yyidx = -1;
#ifdef YYTRACKMAXSTACKDEPTH
pParser->yyidxMax = 0;
#endif
#if YYSTACKDEPTH<=0
pParser->yystack = NULL;
pParser->yystksz = 0;
yyGrowStack(pParser);
#endif
}
return pParser;
}
/* The following function deletes the value associated with a
** symbol. The symbol can be either a terminal or nonterminal.
** "yymajor" is the symbol code, and "yypminor" is a pointer to
** the value.
*/
static void yy_destructor(
yyParser *yypParser, /* The parser */
YYCODETYPE yymajor, /* Type code for object to destroy */
YYMINORTYPE *yypminor /* The object to be destroyed */
){
ParseARG_FETCH;
switch( yymajor ){
/* Here is inserted the actions which take place when a
** terminal or non-terminal is destroyed. This can happen
** when the symbol is popped from the stack during a
** reduce or during error processing or when a parser is
** being destroyed before it is finished parsing.
**
** Note: during a reduce, the only symbols destroyed are those
** which appear on the RHS of the rule, but which are not used
** inside the C code.
*/
%%
default: break; /* If no destructor action specified: do nothing */
}
}
/*
** Pop the parser's stack once.
**
** If there is a destructor routine associated with the token which
** is popped from the stack, then call it.
**
** Return the major token number for the symbol popped.
*/
static int yy_pop_parser_stack(yyParser *pParser){
YYCODETYPE yymajor;
yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
/* There is no mechanism by which the parser stack can be popped below
** empty in SQLite. */
assert( pParser->yyidx>=0 );
#ifndef NDEBUG
if( yyTraceFILE && pParser->yyidx>=0 ){
fprintf(yyTraceFILE,"%sPopping %s\n",
yyTracePrompt,
yyTokenName[yytos->major]);
}
#endif
yymajor = yytos->major;
yy_destructor(pParser, yymajor, &yytos->minor);
pParser->yyidx--;
return yymajor;
}
/*
** Deallocate and destroy a parser. Destructors are all called for
** all stack elements before shutting the parser down.
**
** Inputs:
** <ul>
** <li> A pointer to the parser. This should be a pointer
** obtained from ParseAlloc.
** <li> A pointer to a function used to reclaim memory obtained
** from malloc.
** </ul>
*/
void ParseFree(
void *p, /* The parser to be deleted */
void (*freeProc)(void*) /* Function used to reclaim memory */
){
yyParser *pParser = (yyParser*)p;
/* In SQLite, we never try to destroy a parser that was not successfully
** created in the first place. */
if( NEVER(pParser==0) ) return;
while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
#if YYSTACKDEPTH<=0
free(pParser->yystack);
#endif
(*freeProc)((void*)pParser);
}
/*
** Return the peak depth of the stack for a parser.
*/
#ifdef YYTRACKMAXSTACKDEPTH
int ParseStackPeak(void *p){
yyParser *pParser = (yyParser*)p;
return pParser->yyidxMax;
}
#endif
/*
** Find the appropriate action for a parser given the terminal
** look-ahead token iLookAhead.
**
** If the look-ahead token is YYNOCODE, then check to see if the action is
** independent of the look-ahead. If it is, return the action, otherwise
** return YY_NO_ACTION.
*/
static int yy_find_shift_action(
yyParser *pParser, /* The parser */
YYCODETYPE iLookAhead /* The look-ahead token */
){
int i;
int stateno = pParser->yystack[pParser->yyidx].stateno;
if( stateno>=YY_MIN_REDUCE ) return stateno;
assert( stateno <= YY_SHIFT_COUNT );
i = yy_shift_ofst[stateno];
if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno];
assert( iLookAhead!=YYNOCODE );
i += iLookAhead;
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
if( iLookAhead>0 ){
#ifdef YYFALLBACK
YYCODETYPE iFallback; /* Fallback token */
if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
&& (iFallback = yyFallback[iLookAhead])!=0 ){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
}
#endif
return yy_find_shift_action(pParser, iFallback);
}
#endif
#ifdef YYWILDCARD
{
int j = i - iLookAhead + YYWILDCARD;
if(
#if YY_SHIFT_MIN+YYWILDCARD<0
j>=0 &&
#endif
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
j<YY_ACTTAB_COUNT &&
#endif
yy_lookahead[j]==YYWILDCARD
){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]);
}
#endif /* NDEBUG */
return yy_action[j];
}
}
#endif /* YYWILDCARD */
}
return yy_default[stateno];
}else{
return yy_action[i];
}
}
/*
** Find the appropriate action for a parser given the non-terminal
** look-ahead token iLookAhead.
**
** If the look-ahead token is YYNOCODE, then check to see if the action is
** independent of the look-ahead. If it is, return the action, otherwise
** return YY_NO_ACTION.
*/
static int yy_find_reduce_action(
int stateno, /* Current state number */
YYCODETYPE iLookAhead /* The look-ahead token */
){
int i;
#ifdef YYERRORSYMBOL
if( stateno>YY_REDUCE_COUNT ){
return yy_default[stateno];
}
#else
assert( stateno<=YY_REDUCE_COUNT );
#endif
i = yy_reduce_ofst[stateno];
assert( i!=YY_REDUCE_USE_DFLT );
assert( iLookAhead!=YYNOCODE );
i += iLookAhead;
#ifdef YYERRORSYMBOL
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
return yy_default[stateno];
}
#else
assert( i>=0 && i<YY_ACTTAB_COUNT );
assert( yy_lookahead[i]==iLookAhead );
#endif
return yy_action[i];
}
/*
** The following routine is called if the stack overflows.
*/
static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
ParseARG_FETCH;
yypParser->yyidx--;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
}
#endif
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will execute if the parser
** stack every overflows */
%%
ParseARG_STORE; /* Suppress warning about unused %extra_argument var */
}
/*
** Print tracing information for a SHIFT action
*/
#ifndef NDEBUG
static void yyTraceShift(yyParser *yypParser, int yyNewState){
if( yyTraceFILE ){
int i;
if( yyNewState<YYNSTATE ){
fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
for(i=1; i<=yypParser->yyidx; i++)
fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
fprintf(yyTraceFILE,"\n");
}else{
fprintf(yyTraceFILE,"%sShift *\n",yyTracePrompt);
}
}
}
#else
# define yyTraceShift(X,Y)
#endif
/*
** Perform a shift action. Return the number of errors.
*/
static void yy_shift(
yyParser *yypParser, /* The parser to be shifted */
int yyNewState, /* The new state to shift in */
int yyMajor, /* The major token to shift in */
YYMINORTYPE *yypMinor /* Pointer to the minor token to shift in */
){
yyStackEntry *yytos;
yypParser->yyidx++;
#ifdef YYTRACKMAXSTACKDEPTH
if( yypParser->yyidx>yypParser->yyidxMax ){
yypParser->yyidxMax = yypParser->yyidx;
}
#endif
#if YYSTACKDEPTH>0
if( yypParser->yyidx>=YYSTACKDEPTH ){
yyStackOverflow(yypParser, yypMinor);
return;
}
#else
if( yypParser->yyidx>=yypParser->yystksz ){
yyGrowStack(yypParser);
if( yypParser->yyidx>=yypParser->yystksz ){
yyStackOverflow(yypParser, yypMinor);
return;
}
}
#endif
yytos = &yypParser->yystack[yypParser->yyidx];
yytos->stateno = (YYACTIONTYPE)yyNewState;
yytos->major = (YYCODETYPE)yyMajor;
yytos->minor = *yypMinor;
yyTraceShift(yypParser, yyNewState);
}
/* The following table contains information about every rule that
** is used during the reduce.
*/
static const struct {
YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
unsigned char nrhs; /* Number of right-hand side symbols in the rule */
} yyRuleInfo[] = {
%%
};
static void yy_accept(yyParser*); /* Forward Declaration */
/*
** Perform a reduce action and the shift that must immediately
** follow the reduce.
*/
static void yy_reduce(
yyParser *yypParser, /* The parser */
int yyruleno /* Number of the rule by which to reduce */
){
int yygoto; /* The next state */
int yyact; /* The next action */
YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
yyStackEntry *yymsp; /* The top of the parser's stack */
int yysize; /* Amount to pop the stack */
ParseARG_FETCH;
yymsp = &yypParser->yystack[yypParser->yyidx];
#ifndef NDEBUG
if( yyTraceFILE && yyruleno>=0
&& yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
yysize = yyRuleInfo[yyruleno].nrhs;
fprintf(yyTraceFILE, "%sReduce [%s] -> state %d.\n", yyTracePrompt,
yyRuleName[yyruleno], yymsp[-yysize].stateno);
}
#endif /* NDEBUG */
/* Silence complaints from purify about yygotominor being uninitialized
** in some cases when it is copied into the stack after the following
** switch. yygotominor is uninitialized when a rule reduces that does
** not set the value of its left-hand side nonterminal. Leaving the
** value of the nonterminal uninitialized is utterly harmless as long
** as the value is never used. So really the only thing this code
** accomplishes is to quieten purify.
**
** 2007-01-16: The wireshark project (www.wireshark.org) reports that
** without this code, their parser segfaults. I'm not sure what there
** parser is doing to make this happen. This is the second bug report
** from wireshark this week. Clearly they are stressing Lemon in ways
** that it has not been previously stressed... (SQLite ticket #2172)
*/
/*memset(&yygotominor, 0, sizeof(yygotominor));*/
yygotominor = yyzerominor;
switch( yyruleno ){
/* Beginning here are the reduction cases. A typical example
** follows:
** case 0:
** #line <lineno> <grammarfile>
** { ... } // User supplied code
** #line <lineno> <thisfile>
** break;
*/
%%
};
assert( yyruleno>=0 && yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
yygoto = yyRuleInfo[yyruleno].lhs;
yysize = yyRuleInfo[yyruleno].nrhs;
yypParser->yyidx -= yysize;
yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
if( yyact <= YY_MAX_SHIFTREDUCE ){
if( yyact>YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
/* If the reduce action popped at least
** one element off the stack, then we can push the new element back
** onto the stack here, and skip the stack overflow test in yy_shift().
** That gives a significant speed improvement. */
if( yysize ){
yypParser->yyidx++;
yymsp -= yysize-1;
yymsp->stateno = (YYACTIONTYPE)yyact;
yymsp->major = (YYCODETYPE)yygoto;
yymsp->minor = yygotominor;
yyTraceShift(yypParser, yyact);
}else{
yy_shift(yypParser,yyact,yygoto,&yygotominor);
}
}else{
assert( yyact == YY_ACCEPT_ACTION );
yy_accept(yypParser);
}
}
/*
** The following code executes when the parse fails
*/
#ifndef YYNOERRORRECOVERY
static void yy_parse_failed(
yyParser *yypParser /* The parser */
){
ParseARG_FETCH;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
}
#endif
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will be executed whenever the
** parser fails */
%%
ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
#endif /* YYNOERRORRECOVERY */
/*
** The following code executes when a syntax error first occurs.
*/
static void yy_syntax_error(
yyParser *yypParser, /* The parser */
int yymajor, /* The major type of the error token */
YYMINORTYPE yyminor /* The minor type of the error token */
){
ParseARG_FETCH;
#define TOKEN (yyminor.yy0)
%%
ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
/*
** The following is executed when the parser accepts
*/
static void yy_accept(
yyParser *yypParser /* The parser */
){
ParseARG_FETCH;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
}
#endif
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will be executed whenever the
** parser accepts */
%%
ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
/* The main parser program.
** The first argument is a pointer to a structure obtained from
** "ParseAlloc" which describes the current state of the parser.
** The second argument is the major token number. The third is
** the minor token. The fourth optional argument is whatever the
** user wants (and specified in the grammar) and is available for
** use by the action routines.
**
** Inputs:
** <ul>
** <li> A pointer to the parser (an opaque structure.)
** <li> The major token number.
** <li> The minor token number.
** <li> An option argument of a grammar-specified type.
** </ul>
**
** Outputs:
** None.
*/
void Parse(
void *yyp, /* The parser */
int yymajor, /* The major token code number */
ParseTOKENTYPE yyminor /* The value for the token */
ParseARG_PDECL /* Optional %extra_argument parameter */
){
YYMINORTYPE yyminorunion;
int yyact; /* The parser action. */
#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
int yyendofinput; /* True if we are at the end of input */
#endif
#ifdef YYERRORSYMBOL
int yyerrorhit = 0; /* True if yymajor has invoked an error */
#endif
yyParser *yypParser; /* The parser */
/* (re)initialize the parser, if necessary */
yypParser = (yyParser*)yyp;
if( yypParser->yyidx<0 ){
#if YYSTACKDEPTH<=0
if( yypParser->yystksz <=0 ){
/*memset(&yyminorunion, 0, sizeof(yyminorunion));*/
yyminorunion = yyzerominor;
yyStackOverflow(yypParser, &yyminorunion);
return;
}
#endif
yypParser->yyidx = 0;
yypParser->yyerrcnt = -1;
yypParser->yystack[0].stateno = 0;
yypParser->yystack[0].major = 0;
}
yyminorunion.yy0 = yyminor;
#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
yyendofinput = (yymajor==0);
#endif
ParseARG_STORE;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
}
#endif
do{
yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
if( yyact <= YY_MAX_SHIFTREDUCE ){
if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
yy_shift(yypParser,yyact,yymajor,&yyminorunion);
yypParser->yyerrcnt--;
yymajor = YYNOCODE;
}else if( yyact <= YY_MAX_REDUCE ){
yy_reduce(yypParser,yyact-YY_MIN_REDUCE);
}else{
assert( yyact == YY_ERROR_ACTION );
#ifdef YYERRORSYMBOL
int yymx;
#endif
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
}
#endif
#ifdef YYERRORSYMBOL
/* A syntax error has occurred.
** The response to an error depends upon whether or not the
** grammar defines an error token "ERROR".
**
** This is what we do if the grammar does define ERROR:
**
** * Call the %syntax_error function.
**
** * Begin popping the stack until we enter a state where
** it is legal to shift the error symbol, then shift
** the error symbol.
**
** * Set the error count to three.
**
** * Begin accepting and shifting new tokens. No new error
** processing will occur until three tokens have been
** shifted successfully.
**
*/
if( yypParser->yyerrcnt<0 ){
yy_syntax_error(yypParser,yymajor,yyminorunion);
}
yymx = yypParser->yystack[yypParser->yyidx].major;
if( yymx==YYERRORSYMBOL || yyerrorhit ){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sDiscard input token %s\n",
yyTracePrompt,yyTokenName[yymajor]);
}
#endif
yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion);
yymajor = YYNOCODE;
}else{
while(
yypParser->yyidx >= 0 &&
yymx != YYERRORSYMBOL &&
(yyact = yy_find_reduce_action(
yypParser->yystack[yypParser->yyidx].stateno,
YYERRORSYMBOL)) >= YY_MIN_REDUCE
){
yy_pop_parser_stack(yypParser);
}
if( yypParser->yyidx < 0 || yymajor==0 ){
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
yy_parse_failed(yypParser);
yymajor = YYNOCODE;
}else if( yymx!=YYERRORSYMBOL ){
YYMINORTYPE u2;
u2.YYERRSYMDT = 0;
yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
}
}
yypParser->yyerrcnt = 3;
yyerrorhit = 1;
#elif defined(YYNOERRORRECOVERY)
/* If the YYNOERRORRECOVERY macro is defined, then do not attempt to
** do any kind of error recovery. Instead, simply invoke the syntax
** error routine and continue going as if nothing had happened.
**
** Applications can set this macro (for example inside %include) if
** they intend to abandon the parse upon the first syntax error seen.
*/
yy_syntax_error(yypParser,yymajor,yyminorunion);
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
yymajor = YYNOCODE;
#else /* YYERRORSYMBOL is not defined */
/* This is what we do if the grammar does not define ERROR:
**
** * Report an error message, and throw away the input token.
**
** * If the input token is $, then fail the parse.
**
** As before, subsequent error messages are suppressed until
** three input tokens have been successfully shifted.
*/
if( yypParser->yyerrcnt<=0 ){
yy_syntax_error(yypParser,yymajor,yyminorunion);
}
yypParser->yyerrcnt = 3;
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
if( yyendofinput ){
yy_parse_failed(yypParser);
}
yymajor = YYNOCODE;
#endif
}
}while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sReturn\n",yyTracePrompt);
}
#endif
return;
}
-45
View File
@@ -740,36 +740,6 @@ int sqlite3_db_release_memory(sqlite3 *db){
return SQLITE_OK;
}
/*
** Flush any dirty pages in the pager-cache for any attached database
** to disk.
*/
int sqlite3_db_cacheflush(sqlite3 *db){
int i;
int rc = SQLITE_OK;
int bSeenBusy = 0;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
sqlite3_mutex_enter(db->mutex);
sqlite3BtreeEnterAll(db);
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt && sqlite3BtreeIsInTrans(pBt) ){
Pager *pPager = sqlite3BtreePager(pBt);
rc = sqlite3PagerFlush(pPager);
if( rc==SQLITE_BUSY ){
bSeenBusy = 1;
rc = SQLITE_OK;
}
}
}
sqlite3BtreeLeaveAll(db);
sqlite3_mutex_leave(db->mutex);
return ((rc==SQLITE_OK && bSeenBusy) ? SQLITE_BUSY : rc);
}
/*
** Configuration settings for an individual database connection
*/
@@ -2984,21 +2954,6 @@ opendb_out:
void *pArg = sqlite3GlobalConfig.pSqllogArg;
sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0);
}
#endif
#if defined(SQLITE_HAS_CODEC)
if( rc==SQLITE_OK ){
const char *zHexKey = sqlite3_uri_parameter(zOpen, "hexkey");
if( zHexKey && zHexKey[0] ){
u8 iByte;
int i;
char zKey[40];
for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zHexKey[i]); i++){
iByte = (iByte<<4) + sqlite3HexToInt(zHexKey[i]);
if( (i&1)!=0 ) zKey[i/2] = iByte;
}
sqlite3_key_v2(db, 0, zKey, i/2);
}
}
#endif
return rc & 0xff;
}
+1 -1
View File
@@ -455,7 +455,7 @@ void sqlite3_free(void *p){
** *db->pnBytesFreed.
*/
static SQLITE_NOINLINE void measureAllocationSize(sqlite3 *db, void *p){
*db->pnBytesFreed += sqlite3DbMallocSize(db,p);
if( p ) *db->pnBytesFreed += sqlite3DbMallocSize(db,p);
}
/*
+1 -2
View File
@@ -171,12 +171,11 @@ static void sqlite3MemFree(void *pPrior){
** or xRealloc().
*/
static int sqlite3MemSize(void *pPrior){
#ifdef SQLITE_MALLOCSIZE
assert( pPrior!=0 );
#ifdef SQLITE_MALLOCSIZE
return (int)SQLITE_MALLOCSIZE(pPrior);
#else
sqlite3_int64 *p;
assert( pPrior!=0 );
p = (sqlite3_int64*)pPrior;
p--;
return (int)p[0];
+7 -47
View File
@@ -464,9 +464,6 @@ static struct unix_syscall {
{ "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 },
#define osGetpagesize ((int(*)(void))aSyscall[24].pCurrent)
{ "readlink", (sqlite3_syscall_ptr)readlink, 0 },
#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[25].pCurrent)
#endif
}; /* End of the overrideable system calls */
@@ -6029,7 +6026,6 @@ static int unixFullPathname(
int nOut, /* Size of output buffer in bytes */
char *zOut /* Output buffer */
){
int nByte;
/* It's odd to simulate an io-error here, but really this is just
** using the io-error infrastructure to test that SQLite handles this
@@ -6041,53 +6037,17 @@ static int unixFullPathname(
assert( pVfs->mxPathname==MAX_PATHNAME );
UNUSED_PARAMETER(pVfs);
/* Attempt to resolve the path as if it were a symbolic link. If it is
** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if
** the identified file is not a symbolic link or does not exist, then
** zPath is copied directly into zOut. Either way, nByte is left set to
** the size of the string copied into zOut[] in bytes. */
nByte = osReadlink(zPath, zOut, nOut-1);
if( nByte<0 ){
if( errno!=EINVAL && errno!=ENOENT ){
return unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zPath);
}
zOut[nOut-1] = '\0';
sqlite3_snprintf(nOut-1, zOut, "%s", zPath);
nByte = sqlite3Strlen30(zOut);
zOut[nOut-1] = '\0';
if( zPath[0]=='/' ){
sqlite3_snprintf(nOut, zOut, "%s", zPath);
}else{
zOut[nByte] = '\0';
}
/* If buffer zOut[] now contains an absolute path there is nothing more
** to do. If it contains a relative path, do the following:
**
** * move the relative path string so that it is at the end of th
** zOut[] buffer.
** * Call getcwd() to read the path of the current working directory
** into the start of the zOut[] buffer.
** * Append a '/' character to the cwd string and move the
** relative path back within the buffer so that it immediately
** follows the '/'.
**
** This code is written so that if the combination of the CWD and relative
** path are larger than the allocated size of zOut[] the CWD is silently
** truncated to make it fit. This is Ok, as SQLite refuses to open any
** file for which this function returns a full path larger than (nOut-8)
** bytes in size. */
if( zOut[0]!='/' ){
int nCwd;
int nRem = nOut-nByte-1;
memmove(&zOut[nRem], zOut, nByte+1);
zOut[nRem-1] = '\0';
if( osGetcwd(zOut, nRem-1)==0 ){
if( osGetcwd(zOut, nOut-1)==0 ){
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
}
nCwd = sqlite3Strlen30(zOut);
assert( nCwd<=nRem-1 );
zOut[nCwd] = '/';
memmove(&zOut[nCwd+1], &zOut[nRem], nByte+1);
nCwd = (int)strlen(zOut);
sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath);
}
return SQLITE_OK;
}
@@ -7582,7 +7542,7 @@ int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
assert( ArraySize(aSyscall)==26 );
assert( ArraySize(aSyscall)==25 );
/* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
+16 -39
View File
@@ -2333,7 +2333,7 @@ static int pager_playback_one_page(
assert( isSavepnt );
assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 );
pPager->doNotSpill |= SPILLFLAG_ROLLBACK;
rc = sqlite3PagerGet(pPager, pgno, &pPg, 1);
rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1);
assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 );
pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK;
if( rc!=SQLITE_OK ) return rc;
@@ -4473,25 +4473,6 @@ static int pagerStress(void *p, PgHdr *pPg){
return pager_error(pPager, rc);
}
/*
** Flush all unreferenced dirty pages to disk.
*/
int sqlite3PagerFlush(Pager *pPager){
int rc = pPager->errCode;
if( !MEMDB ){
PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
assert( assert_pager_state(pPager) );
while( rc==SQLITE_OK && pList ){
PgHdr *pNext = pList->pDirty;
if( pList->nRef==0 ){
rc = pagerStress((void*)pPager, pList);
}
pList = pNext;
}
}
return rc;
}
/*
** Allocate and initialize a new Pager object and put a pointer to it
@@ -4969,7 +4950,7 @@ static int hasHotJournal(Pager *pPager, int *pExists){
/*
** This function is called to obtain a shared lock on the database file.
** It is illegal to call sqlite3PagerGet() until after this function
** It is illegal to call sqlite3PagerAcquire() until after this function
** has been successfully called. If a shared-lock is already held when
** this function is called, it is a no-op.
**
@@ -5272,7 +5253,7 @@ static void pagerUnlockIfUnused(Pager *pPager){
** Since Lookup() never goes to disk, it never has to deal with locks
** or journal files.
*/
int sqlite3PagerGet(
int sqlite3PagerAcquire(
Pager *pPager, /* The pager open on the database file */
Pgno pgno, /* Page number to fetch */
DbPage **ppPage, /* Write a pointer to the page here */
@@ -5858,7 +5839,7 @@ static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){
PgHdr *pPage;
if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
if( pg!=PAGER_MJ_PGNO(pPager) ){
rc = sqlite3PagerGet(pPager, pg, &pPage, 0);
rc = sqlite3PagerGet(pPager, pg, &pPage);
if( rc==SQLITE_OK ){
rc = pager_write(pPage);
if( pPage->flags&PGHDR_NEED_SYNC ){
@@ -5915,10 +5896,9 @@ int sqlite3PagerWrite(PgHdr *pPg){
Pager *pPager = pPg->pPager;
assert( (pPg->flags & PGHDR_MMAP)==0 );
assert( pPager->eState>=PAGER_WRITER_LOCKED );
assert( pPager->eState!=PAGER_ERROR );
assert( assert_pager_state(pPager) );
if( pPager->errCode ){
return pPager->errCode;
}else if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){
if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){
if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg);
return SQLITE_OK;
}else if( pPager->sectorSize > (u32)pPager->pageSize ){
@@ -6018,7 +5998,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
assert( !pPager->tempFile && isOpen(pPager->fd) );
/* Open page 1 of the file for writing. */
rc = sqlite3PagerGet(pPager, 1, &pPgHdr, 0);
rc = sqlite3PagerGet(pPager, 1, &pPgHdr);
assert( pPgHdr==0 || rc==SQLITE_OK );
/* If page one was fetched successfully, and this function is not
@@ -6096,17 +6076,14 @@ int sqlite3PagerSync(Pager *pPager, const char *zMaster){
** returned.
*/
int sqlite3PagerExclusiveLock(Pager *pPager){
int rc = pPager->errCode;
int rc = SQLITE_OK;
assert( pPager->eState==PAGER_WRITER_CACHEMOD
|| pPager->eState==PAGER_WRITER_DBMOD
|| pPager->eState==PAGER_WRITER_LOCKED
);
assert( assert_pager_state(pPager) );
if( rc==SQLITE_OK ){
assert( pPager->eState==PAGER_WRITER_CACHEMOD
|| pPager->eState==PAGER_WRITER_DBMOD
|| pPager->eState==PAGER_WRITER_LOCKED
);
assert( assert_pager_state(pPager) );
if( 0==pagerUseWal(pPager) ){
rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
}
if( 0==pagerUseWal(pPager) ){
rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
}
return rc;
}
@@ -6173,7 +6150,7 @@ int sqlite3PagerCommitPhaseOne(
if( pList==0 ){
/* Must have at least one page for the WAL commit flag.
** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */
rc = sqlite3PagerGet(pPager, 1, &pPageOne, 0);
rc = sqlite3PagerGet(pPager, 1, &pPageOne);
pList = pPageOne;
pList->pDirty = 0;
}
@@ -6878,7 +6855,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
** the journal file twice, but that is not a problem.
*/
PgHdr *pPgHdr;
rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr, 0);
rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr);
if( rc!=SQLITE_OK ){
if( needSyncPgno<=pPager->dbOrigSize ){
assert( pPager->pTmpSpace!=0 );
+3 -3
View File
@@ -79,7 +79,7 @@ typedef struct PgHdr DbPage;
#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */
/*
** Flags that make up the mask passed to sqlite3PagerGet().
** Flags that make up the mask passed to sqlite3PagerAcquire().
*/
#define PAGER_GET_NOCONTENT 0x01 /* Do not load data from disk */
#define PAGER_GET_READONLY 0x02 /* Read-only page is acceptable */
@@ -132,10 +132,10 @@ int sqlite3PagerGetJournalMode(Pager*);
int sqlite3PagerOkToChangeJournalMode(Pager*);
i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
sqlite3_backup **sqlite3PagerBackupPtr(Pager*);
int sqlite3PagerFlush(Pager*);
/* Functions used to obtain and release page references. */
int sqlite3PagerGet(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0)
DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
void sqlite3PagerRef(DbPage*);
void sqlite3PagerUnref(DbPage*);
+7 -25
View File
@@ -60,18 +60,6 @@
*/
#define yytestcase(X) testcase(X)
/*
** Indicate that sqlite3ParserFree() will never be called with a null
** pointer.
*/
#define YYPARSEFREENOTNULL 1
/*
** Alternative datatype for the argument to the malloc() routine passed
** into sqlite3ParserAlloc(). The default is size_t.
*/
#define YYMALLOCARGTYPE u64
/*
** An instance of this structure holds information about the
** LIMIT clause of a SELECT statement.
@@ -651,6 +639,7 @@ dbnm(A) ::= DOT nm(X). {A = X;}
fullname(A) ::= nm(X) dbnm(Y). {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y);}
%type joinop {int}
%type joinop2 {int}
joinop(X) ::= COMMA|JOIN. { X = JT_INNER; }
joinop(X) ::= JOIN_KW(A) JOIN. { X = sqlite3JoinType(pParse,&A,0,0); }
joinop(X) ::= JOIN_KW(A) nm(B) JOIN. { X = sqlite3JoinType(pParse,&A,&B,0); }
@@ -940,13 +929,6 @@ term(A) ::= CTIME_KW(OP). {
pOut->zStart = pLeft->zStart;
pOut->zEnd = pRight->zEnd;
}
/* If doNot is true, then add a TK_NOT Expr-node wrapper around the
** outside of *ppExpr.
*/
static void exprNot(Parse *pParse, int doNot, Expr **ppExpr){
if( doNot ) *ppExpr = sqlite3PExpr(pParse, TK_NOT, *ppExpr, 0, 0);
}
}
expr(A) ::= expr(X) AND(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
@@ -969,7 +951,7 @@ expr(A) ::= expr(X) likeop(OP) expr(Y). [LIKE_KW] {
pList = sqlite3ExprListAppend(pParse,0, Y.pExpr);
pList = sqlite3ExprListAppend(pParse,pList, X.pExpr);
A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator);
exprNot(pParse, OP.bNot, &A.pExpr);
if( OP.bNot ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
A.zStart = X.zStart;
A.zEnd = Y.zEnd;
if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc;
@@ -980,7 +962,7 @@ expr(A) ::= expr(X) likeop(OP) expr(Y) ESCAPE expr(E). [LIKE_KW] {
pList = sqlite3ExprListAppend(pParse,pList, X.pExpr);
pList = sqlite3ExprListAppend(pParse,pList, E.pExpr);
A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator);
exprNot(pParse, OP.bNot, &A.pExpr);
if( OP.bNot ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
A.zStart = X.zStart;
A.zEnd = E.zEnd;
if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc;
@@ -1070,7 +1052,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
exprNot(pParse, N, &A.pExpr);
if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
A.zStart = W.zStart;
A.zEnd = Y.zEnd;
}
@@ -1125,7 +1107,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
}else{
sqlite3ExprListDelete(pParse->db, Y);
}
exprNot(pParse, N, &A.pExpr);
if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
}
A.zStart = X.zStart;
A.zEnd = &E.z[E.n];
@@ -1151,7 +1133,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
}else{
sqlite3SelectDelete(pParse->db, Y);
}
exprNot(pParse, N, &A.pExpr);
if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
A.zStart = X.zStart;
A.zEnd = &E.z[E.n];
}
@@ -1165,7 +1147,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
}else{
sqlite3SrcListDelete(pParse->db, pSrc);
}
exprNot(pParse, N, &A.pExpr);
if( N ) A.pExpr = sqlite3PExpr(pParse, TK_NOT, A.pExpr, 0, 0);
A.zStart = X.zStart;
A.zEnd = Z.z ? &Z.z[Z.n] : &Y.z[Y.n];
}
+1 -1
View File
@@ -1465,7 +1465,7 @@ void sqlite3Pragma(
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeJumpHere(v, addr);
sqlite3ExprCacheClear(pParse);
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead,
1, 0, &iDataCur, &iIdxCur);
sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+14 -17
View File
@@ -1230,15 +1230,16 @@ static void generateSortTail(
codeOffset(v, p->iOffset, addrContinue);
sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab);
bSeq = 0;
sqlite3VdbeAddOp4Int(v, OP_Unpack, regSortOut, regRow, nSortData, nKey);
}else{
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
codeOffset(v, p->iOffset, addrContinue);
iSortTab = iTab;
bSeq = 1;
}
for(i=0; i<nSortData; i++){
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq+i, regRow+i);
VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
for(i=0; i<nSortData; i++){
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq+i, regRow+i);
VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
}
}
switch( eDest ){
case SRT_EphemTab: {
@@ -3972,7 +3973,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
** object that the returned CTE belongs to.
*/
static struct Cte *searchWith(
With *pWith, /* Current innermost WITH clause */
With *pWith, /* Current outermost WITH clause */
struct SrcList_item *pItem, /* FROM clause element to resolve */
With **ppContext /* OUT: WITH clause return value belongs to */
){
@@ -4003,12 +4004,11 @@ static struct Cte *searchWith(
** statement with which it is associated.
*/
void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
assert( bFree==0 || (pParse->pWith==0 && pParse->pWithToFree==0) );
assert( bFree==0 || pParse->pWith==0 );
if( pWith ){
assert( pParse->pWith!=pWith );
pWith->pOuter = pParse->pWith;
pParse->pWith = pWith;
if( bFree ) pParse->pWithToFree = pWith;
pParse->bFreeWith = bFree;
}
}
@@ -4101,7 +4101,6 @@ static int withExpand(
pSavedWith = pParse->pWith;
pParse->pWith = pWith;
sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel);
pParse->pWith = pWith;
for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior);
pEList = pLeft->pEList;
@@ -4454,7 +4453,7 @@ static int selectExpander(Walker *pWalker, Select *p){
** Walker.xSelectCallback is set to do something useful for every
** subquery in the parser tree.
*/
int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
UNUSED_PARAMETER2(NotUsed, NotUsed2);
return WRC_Continue;
}
@@ -4475,7 +4474,7 @@ int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
Walker w;
memset(&w, 0, sizeof(w));
w.xExprCallback = sqlite3ExprWalkNoop;
w.xExprCallback = exprWalkNoop;
w.pParse = pParse;
if( pParse->hasCompound ){
w.xSelectCallback = convertCompoundSelectToSubquery;
@@ -4542,7 +4541,7 @@ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
Walker w;
memset(&w, 0, sizeof(w));
w.xSelectCallback2 = selectAddSubqueryTypeInfo;
w.xExprCallback = sqlite3ExprWalkNoop;
w.xExprCallback = exprWalkNoop;
w.pParse = pParse;
sqlite3WalkSelect(&w, pSelect);
#endif
@@ -5342,11 +5341,9 @@ int sqlite3Select(
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx,
sortOut, sortPTab);
}
for(j=0; j<pGroupBy->nExpr; j++){
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
}else{
sqlite3VdbeAddOp4Int(v, OP_Unpack, sortOut, iBMem, pGroupBy->nExpr, 0);
}else{
for(j=0; j<pGroupBy->nExpr; j++){
sAggInfo.directMode = 1;
sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
}
-30
View File
@@ -478,7 +478,6 @@ int sqlite3_exec(
#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8))
#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8))
#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
@@ -7792,35 +7791,6 @@ int sqlite3_stmt_scanstatus(
*/
void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
/*
** CAPI3REF: Flush caches to disk mid-transaction
**
** If a write-transaction is open when this function is called, any dirty
** pages in the pager-cache that are not currently in use are written out
** to disk. A dirty page may be in use if a database cursor created by an
** active SQL statement is reading from it, or if it is page 1 of a database
** file (page 1 is always "in use"). Dirty pages are flushed for all
** databases - "main", "temp" and any attached databases.
**
** If this function needs to obtain extra database locks before dirty pages
** can be flushed to disk, it does so. If said locks cannot be obtained
** immediately and there is a busy-handler callback configured, it is invoked
** in the usual manner. If the required lock still cannot be obtained, then
** the database is skipped and an attempt made to flush any dirty pages
** belonging to the next (if any) database. If any databases are skipped
** because locks cannot be obtained, but no other error occurs, this
** function returns SQLITE_BUSY.
**
** If any other error occurs while flushing dirty pages to disk (for
** example an IO error or out-of-memory condition), then processing is
** abandoned and an SQLite error code returned to the caller immediately.
**
** Otherwise, if no error occurs, SQLITE_OK is returned.
**
** This function does not set the database handle error code or message
** returned by the sqlite3_errcode() and sqlite3_errmsg() functions.
*/
int sqlite3_db_cacheflush(sqlite3*);
/*
** Undo the hack that converts floating point types to integer for
+13 -40
View File
@@ -1310,7 +1310,6 @@ struct sqlite3 {
#define SQLITE_Transitive 0x0200 /* Transitive constraints */
#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
#define SQLITE_CursorHints 0x2000 /* Add OP_CursorHint opcodes */
#define SQLITE_AllOpts 0xffff /* All optimizations */
/*
@@ -1812,8 +1811,9 @@ struct KeyInfo {
};
/*
** This object holds a record which has been parsed out into individual
** fields, for the purposes of doing a comparison.
** An instance of the following structure holds information about a
** single index record that has already been parsed out into individual
** values.
**
** A record is an object that contains one or more fields of data.
** Records are used to store the content of a table row and to store
@@ -1821,40 +1821,20 @@ struct KeyInfo {
** the OP_MakeRecord opcode of the VDBE and is disassembled by the
** OP_Column opcode.
**
** An instance of this object serves as a "key" for doing a search on
** an index b+tree. The goal of the search is to find the entry that
** is closed to the key described by this object. This object might hold
** just a prefix of the key. The number of fields is given by
** pKeyInfo->nField.
** This structure holds a record that has already been disassembled
** into its constituent fields.
**
** The r1 and r2 fields are the values to return if this key is less than
** or greater than a key in the btree, respectively. These are normally
** -1 and +1 respectively, but might be inverted to +1 and -1 if the b-tree
** is in DESC order.
**
** The key comparison functions actually return default_rc when they find
** an equals comparison. default_rc can be -1, 0, or +1. If there are
** multiple entries in the b-tree with the same key (when only looking
** at the first pKeyInfo->nFields,) then default_rc can be set to -1 to
** cause the search to find the last match, or +1 to cause the search to
** find the first match.
**
** The key comparison functions will set eqSeen to true if they ever
** get and equal results when comparing this structure to a b-tree record.
** When default_rc!=0, the search might end up on the record immediately
** before the first match or immediately after the last match. The
** eqSeen field will indicate whether or not an exact match exists in the
** b-tree.
** The r1 and r2 member variables are only used by the optimized comparison
** functions vdbeRecordCompareInt() and vdbeRecordCompareString().
*/
struct UnpackedRecord {
KeyInfo *pKeyInfo; /* Collation and sort-order information */
Mem *aMem; /* Values */
u16 nField; /* Number of entries in apMem[] */
i8 default_rc; /* Comparison result if keys are equal */
u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */
i8 r1; /* Value to return if (lhs > rhs) */
i8 r2; /* Value to return if (rhs < lhs) */
u8 eqSeen; /* True if an equality comparison has been seen */
Mem *aMem; /* Values */
int r1; /* Value to return if (lhs > rhs) */
int r2; /* Value to return if (rhs < lhs) */
};
@@ -2754,6 +2734,7 @@ struct Parse {
int nVar; /* Number of '?' variables seen in the SQL so far */
int nzVar; /* Number of available slots in azVar[] */
u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */
u8 bFreeWith; /* True if pWith should be freed with parser */
u8 explain; /* True if the EXPLAIN flag is found on the query */
#ifndef SQLITE_OMIT_VIRTUALTABLE
u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
@@ -2780,7 +2761,6 @@ struct Parse {
Table *pZombieTab; /* List of Table objects to delete after code gen */
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
With *pWith; /* Current WITH clause, or NULL */
With *pWithToFree; /* Free this WITH object at the end of the parse */
};
/*
@@ -2814,8 +2794,7 @@ struct AuthContext {
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */
#define OPFLAG_FORDELETE 0x08 /* OP_Open is opening for-delete csr */
#define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */
#define OPFLAG_P2ISREG 0x04 /* P2 to OP_Open** is a register number */
#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
/*
@@ -3044,7 +3023,6 @@ struct Walker {
int iCur; /* A cursor number */
SrcList *pSrcList; /* FROM clause */
struct SrcCount *pSrcCount; /* Counting column references */
struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
} u;
};
@@ -3054,7 +3032,6 @@ int sqlite3WalkExprList(Walker*, ExprList*);
int sqlite3WalkSelect(Walker*, Select*);
int sqlite3WalkSelectExpr(Walker*, Select*);
int sqlite3WalkSelectFrom(Walker*, Select*);
int sqlite3ExprWalkNoop(Walker*, Expr*);
/*
** Return code from the parse-tree walking primitives and their
@@ -3271,7 +3248,6 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
void sqlite3TreeViewWith(TreeView*, const With*, u8);
#endif
@@ -3472,9 +3448,6 @@ int sqlite3ExprIsConstant(Expr*);
int sqlite3ExprIsConstantNotJoin(Expr*);
int sqlite3ExprIsConstantOrFunction(Expr*, u8);
int sqlite3ExprIsTableConstant(Expr*,int);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
int sqlite3ExprContainsSubquery(Expr*);
#endif
int sqlite3ExprIsInteger(Expr*, int*);
int sqlite3ExprCanBeNull(const Expr*);
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
@@ -3487,7 +3460,7 @@ void sqlite3ResolvePartIdxLabel(Parse*,int);
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
u8,u8,int,int*);
void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*);
int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, u8*, int*, int*);
void sqlite3BeginWriteOperation(Parse*, int, int);
void sqlite3MultiWrite(Parse*);
void sqlite3MayAbort(Parse*);
+9 -12
View File
@@ -19,15 +19,15 @@
/*
** Variables in which to record status information.
*/
#if SQLITE_PTRSIZE>4
typedef sqlite3_int64 sqlite3StatValueType;
#else
typedef u32 sqlite3StatValueType;
#endif
typedef struct sqlite3StatType sqlite3StatType;
static SQLITE_WSD struct sqlite3StatType {
sqlite3StatValueType nowValue[10]; /* Current value */
sqlite3StatValueType mxValue[10]; /* Maximum value */
#if SQLITE_PTRSIZE>4
sqlite3_int64 nowValue[10]; /* Current value */
sqlite3_int64 mxValue[10]; /* Maximum value */
#else
u32 nowValue[10]; /* Current value */
u32 mxValue[10]; /* Maximum value */
#endif
} sqlite3Stat = { {0,}, {0,} };
/*
@@ -112,10 +112,7 @@ void sqlite3StatusDown(int op, int N){
** The caller must hold the appropriate mutex.
*/
void sqlite3StatusHighwater(int op, int X){
sqlite3StatValueType newValue;
wsdStatInit;
assert( X>=0 );
newValue = (sqlite3StatValueType)X;
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
assert( op>=0 && op<ArraySize(statMutex) );
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
@@ -124,8 +121,8 @@ void sqlite3StatusHighwater(int op, int X){
|| op==SQLITE_STATUS_PAGECACHE_SIZE
|| op==SQLITE_STATUS_SCRATCH_SIZE
|| op==SQLITE_STATUS_PARSER_STACK );
if( newValue>wsdStat.mxValue[op] ){
wsdStat.mxValue[op] = newValue;
if( X>wsdStat.mxValue[op] ){
wsdStat.mxValue[op] = X;
}
}
-32
View File
@@ -4688,34 +4688,6 @@ static int test_db_release_memory(
return TCL_OK;
}
/*
** Usage: sqlite3_db_cacheflush DB
**
** Attempt to flush any dirty pages to disk.
*/
static int test_db_cacheflush(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
sqlite3 *db;
int rc;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB");
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
rc = sqlite3_db_cacheflush(db);
if( rc ){
Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
return TCL_ERROR;
}
Tcl_ResetResult(interp);
return TCL_OK;
}
/*
** Usage: sqlite3_db_filename DB DBNAME
**
@@ -6904,7 +6876,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_release_memory", test_release_memory, 0},
{ "sqlite3_db_release_memory", test_db_release_memory, 0},
{ "sqlite3_db_cacheflush", test_db_cacheflush, 0},
{ "sqlite3_db_filename", test_db_filename, 0},
{ "sqlite3_db_readonly", test_db_readonly, 0},
{ "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
@@ -7039,7 +7010,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
};
static int bitmask_size = sizeof(Bitmask)*8;
static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
int i;
extern int sqlite3_sync_count, sqlite3_fullsync_count;
extern int sqlite3_opentemp_count;
@@ -7140,8 +7110,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
(char*)&sqlite3_data_directory, TCL_LINK_STRING);
Tcl_LinkVar(interp, "bitmask_size",
(char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
Tcl_LinkVar(interp, "longdouble_size",
(char*)&longdouble_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
Tcl_LinkVar(interp, "sqlite_sync_count",
(char*)&sqlite3_sync_count, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_fullsync_count",
+1 -1
View File
@@ -322,7 +322,7 @@ static int page_get(
if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
rc = sqlite3PagerSharedLock(pPager);
if( rc==SQLITE_OK ){
rc = sqlite3PagerGet(pPager, pgno, &pPage, 0);
rc = sqlite3PagerGet(pPager, pgno, &pPage);
}
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
+1 -52
View File
@@ -214,19 +214,16 @@ static int btree_cursor(
pBt = sqlite3TestTextToPtr(argv[1]);
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR;
if( wrFlag ) wrFlag = BTREE_WRCSR;
pCur = (BtCursor *)ckalloc(sqlite3BtreeCursorSize());
memset(pCur, 0, sqlite3BtreeCursorSize());
sqlite3_mutex_enter(pBt->db->mutex);
sqlite3BtreeEnter(pBt);
#ifndef SQLITE_OMIT_SHARED_CACHE
rc = sqlite3BtreeLockTable(pBt, iTable, !!wrFlag);
rc = sqlite3BtreeLockTable(pBt, iTable, wrFlag);
#endif
if( rc==SQLITE_OK ){
rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur);
}
sqlite3BtreeLeave(pBt);
sqlite3_mutex_leave(pBt->db->mutex);
if( rc ){
ckfree((char *)pCur);
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
@@ -259,11 +256,9 @@ static int btree_close_cursor(
}
pCur = sqlite3TestTextToPtr(argv[1]);
pBt = pCur->pBtree;
sqlite3_mutex_enter(pBt->db->mutex);
sqlite3BtreeEnter(pBt);
rc = sqlite3BtreeCloseCursor(pCur);
sqlite3BtreeLeave(pBt);
sqlite3_mutex_leave(pBt->db->mutex);
ckfree((char *)pCur);
if( rc ){
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
@@ -603,50 +598,6 @@ static int btree_set_cache_size(
return TCL_OK;
}
/*
** usage: btree_insert CSR ?KEY? VALUE
**
** Set the size of the cache used by btree $ID.
*/
static int btree_insert(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[]
){
BtCursor *pCur;
int rc;
void *pKey = 0;
int nKey = 0;
void *pData = 0;
int nData = 0;
if( objc!=4 && objc!=3 ){
Tcl_WrongNumArgs(interp, 1, objv, "?-intkey? CSR KEY VALUE");
return TCL_ERROR;
}
if( objc==4 ){
if( Tcl_GetIntFromObj(interp, objv[2], &nKey) ) return TCL_ERROR;
pData = (void*)Tcl_GetByteArrayFromObj(objv[3], &nData);
}else{
pKey = (void*)Tcl_GetByteArrayFromObj(objv[2], &nKey);
}
pCur = (BtCursor*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
sqlite3_mutex_enter(pCur->pBtree->db->mutex);
sqlite3BtreeEnter(pCur->pBtree);
rc = sqlite3BtreeInsert(pCur, pKey, nKey, pData, nData, 0, 0, 0);
sqlite3BtreeLeave(pCur->pBtree);
sqlite3_mutex_leave(pCur->pBtree->db->mutex);
Tcl_ResetResult(interp);
if( rc ){
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
return TCL_ERROR;
}
return TCL_OK;
}
/*
@@ -678,7 +629,5 @@ int Sqlitetest3_Init(Tcl_Interp *interp){
Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
}
Tcl_CreateObjCommand(interp, "btree_insert", btree_insert, 0, 0);
return TCL_OK;
}
-6
View File
@@ -119,12 +119,6 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "8_3_names", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_CURSOR_HINTS
Tcl_SetVar2(interp, "sqlite_options", "cursorhints", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "cursorhints", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_MEMSYS3
Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY);
#else
+25 -15
View File
@@ -369,8 +369,8 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
break;
}
for(i=1; IdChar(z[i]); i++){}
*tokenType = TK_ID;
return keywordCode((char*)z, i, tokenType);
*tokenType = keywordCode((char*)z, i);
return i;
}
}
*tokenType = TK_ILLEGAL;
@@ -416,7 +416,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
assert( pParse->azVar==0 );
enableLookaside = db->lookaside.bEnabled;
if( db->lookaside.pStart ) db->lookaside.bEnabled = 1;
while( zSql[i]!=0 ){
while( !db->mallocFailed && zSql[i]!=0 ){
assert( i>=0 );
pParse->sLastToken.z = &zSql[i];
pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType);
@@ -425,25 +425,35 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
pParse->rc = SQLITE_TOOBIG;
break;
}
if( tokenType>=TK_SPACE ){
assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL );
if( db->u1.isInterrupted ){
sqlite3ErrorMsg(pParse, "interrupt");
pParse->rc = SQLITE_INTERRUPT;
switch( tokenType ){
case TK_SPACE: {
if( db->u1.isInterrupted ){
sqlite3ErrorMsg(pParse, "interrupt");
pParse->rc = SQLITE_INTERRUPT;
goto abort_parse;
}
break;
}
if( tokenType==TK_ILLEGAL ){
case TK_ILLEGAL: {
sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"",
&pParse->sLastToken);
goto abort_parse;
}
case TK_SEMI: {
pParse->zTail = &zSql[i];
/* Fall thru into the default case */
}
default: {
sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse);
lastTokenParsed = tokenType;
if( pParse->rc!=SQLITE_OK ){
goto abort_parse;
}
break;
}
}else{
if( tokenType==TK_SEMI ) pParse->zTail = &zSql[i];
sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse);
lastTokenParsed = tokenType;
if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break;
}
}
abort_parse:
assert( nErr==0 );
if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){
assert( zSql[i]==0 );
@@ -500,7 +510,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
sqlite3DeleteTable(db, pParse->pNewTable);
}
sqlite3WithDelete(db, pParse->pWithToFree);
if( pParse->bFreeWith ) sqlite3WithDelete(db, pParse->pWith);
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]);
sqlite3DbFree(db, pParse->azVar);
-44
View File
@@ -79,45 +79,6 @@ static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
sqlite3TreeViewLine(p, "%s", zLabel);
}
/*
** Generate a human-readable description of a WITH clause.
*/
void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
int i;
if( pWith==0 ) return;
if( pWith->nCte==0 ) return;
if( pWith->pOuter ){
sqlite3TreeViewLine(pView, "WITH (0x%p, pOuter=0x%p)",pWith,pWith->pOuter);
}else{
sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith);
}
if( pWith->nCte>0 ){
pView = sqlite3TreeViewPush(pView, 1);
for(i=0; i<pWith->nCte; i++){
StrAccum x;
char zLine[1000];
const struct Cte *pCte = &pWith->a[i];
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
sqlite3XPrintf(&x, 0, "%s", pCte->zName);
if( pCte->pCols && pCte->pCols->nExpr>0 ){
char cSep = '(';
int j;
for(j=0; j<pCte->pCols->nExpr; j++){
sqlite3XPrintf(&x, 0, "%c%s", cSep, pCte->pCols->a[j].zName);
cSep = ',';
}
sqlite3XPrintf(&x, 0, ")");
}
sqlite3XPrintf(&x, 0, " AS");
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1);
sqlite3TreeViewSelect(pView, pCte->pSelect, 0);
sqlite3TreeViewPop(pView);
}
sqlite3TreeViewPop(pView);
}
}
/*
** Generate a human-readable description of a the Select object.
@@ -126,11 +87,6 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
int n = 0;
int cnt = 0;
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( p->pWith ){
sqlite3TreeViewWith(pView, p->pWith, 1);
cnt = 1;
sqlite3TreeViewPush(pView, 1);
}
do{
sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x",
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
+1 -1
View File
@@ -429,7 +429,7 @@ void sqlite3Update(
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0;
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0;
}
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen,
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iBaseCur, aToOpen,
0, 0);
}
+116 -109
View File
@@ -2368,7 +2368,7 @@ case OP_Column: {
const u8 *zHdr; /* Next unparsed byte of the header */
const u8 *zEndHdr; /* Pointer to first byte after the header */
u32 offset; /* Offset into the data */
u64 offset64; /* 64-bit offset */
u32 szField; /* Number of bytes in the content of a field */
u32 avail; /* Number of bytes of available data */
u32 t; /* A type code from the record header */
u16 fx; /* pDest->flags value */
@@ -2439,6 +2439,19 @@ case OP_Column: {
pC->nHdrParsed = 0;
aOffset[0] = offset;
/* Make sure a corrupt database has not given us an oversize header.
** Do this now to avoid an oversize memory allocation.
**
** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte
** types use so much data space that there can only be 4096 and 32 of
** them, respectively. So the maximum header length results from a
** 3-byte type for each of the maximum of 32768 columns plus three
** extra bytes for the header length itself. 32768*3 + 3 = 98307.
*/
if( offset > 98307 || offset > pC->payloadSize ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_error;
}
if( avail<offset ){
/* pC->aRow does not have to hold the entire row, but it does at least
@@ -2447,20 +2460,6 @@ case OP_Column: {
** dynamically allocated. */
pC->aRow = 0;
pC->szRow = 0;
/* Make sure a corrupt database has not given us an oversize header.
** Do this now to avoid an oversize memory allocation.
**
** Type entries can be between 1 and 5 bytes each. But 4 and 5 byte
** types use so much data space that there can only be 4096 and 32 of
** them, respectively. So the maximum header length results from a
** 3-byte type for each of the maximum of 32768 columns plus three
** extra bytes for the header length itself. 32768*3 + 3 = 98307.
*/
if( offset > 98307 || offset > pC->payloadSize ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_error;
}
}
/* The following goto is an optimization. It can be omitted and
@@ -2483,8 +2482,11 @@ case OP_Column: {
/* Make sure zData points to enough of the record to cover the header. */
if( pC->aRow==0 ){
memset(&sMem, 0, sizeof(sMem));
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0], !pC->isTable, &sMem);
if( rc!=SQLITE_OK ) goto op_column_error;
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0],
!pC->isTable, &sMem);
if( rc!=SQLITE_OK ){
goto op_column_error;
}
zData = (u8*)sMem.z;
}else{
zData = pC->aRow;
@@ -2492,32 +2494,44 @@ case OP_Column: {
/* Fill in pC->aType[i] and aOffset[i] values through the p2-th field. */
i = pC->nHdrParsed;
offset64 = aOffset[i];
offset = aOffset[i];
zHdr = zData + pC->iHdrOffset;
zEndHdr = zData + aOffset[0];
assert( i<=p2 && zHdr<zEndHdr );
do{
if( (t = zHdr[0])<0x80 ){
if( zHdr[0]<0x80 ){
t = zHdr[0];
zHdr++;
offset64 += sqlite3VdbeOneByteSerialTypeLen(t);
}else{
zHdr += sqlite3GetVarint32(zHdr, &t);
offset64 += sqlite3VdbeSerialTypeLen(t);
}
pC->aType[i++] = t;
aOffset[i] = (u32)(offset64 & 0xffffffff);
pC->aType[i] = t;
szField = sqlite3VdbeSerialTypeLen(t);
offset += szField;
if( offset<szField ){ /* True if offset overflows */
zHdr = &zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
break;
}
i++;
aOffset[i] = offset;
}while( i<=p2 && zHdr<zEndHdr );
pC->nHdrParsed = i;
pC->iHdrOffset = (u32)(zHdr - zData);
if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem);
if( pC->aRow==0 ){
sqlite3VdbeMemRelease(&sMem);
sMem.flags = MEM_Null;
}
/* The record is corrupt if any of the following are true:
** (1) the bytes of the header extend past the declared header size
** (zHdr>zEndHdr)
** (2) the entire header was used but not all data was used
** (zHdr==zEndHdr && offset!=pC->payloadSize)
** (3) the end of the data extends beyond the end of the record.
** (offset > pC->payloadSize)
*/
if( (zHdr>=zEndHdr && (zHdr>zEndHdr || offset64!=pC->payloadSize))
|| (offset64 > pC->payloadSize)
if( (zHdr>=zEndHdr && (zHdr>zEndHdr || offset!=pC->payloadSize))
|| (offset > pC->payloadSize)
){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_error;
@@ -2536,8 +2550,6 @@ case OP_Column: {
}
goto op_column_out;
}
}else{
t = pC->aType[p2];
}
/* Extract the content for the p2+1-th column. Control can only
@@ -2548,7 +2560,7 @@ case OP_Column: {
assert( rc==SQLITE_OK );
assert( sqlite3VdbeCheckMemInvariants(pDest) );
if( VdbeMemDynamic(pDest) ) sqlite3VdbeMemSetNull(pDest);
assert( t==pC->aType[p2] );
t = pC->aType[p2];
if( pC->szRow>=aOffset[p2+1] ){
/* This is the common case where the desired content fits on the original
** page - where the content is not on an overflow page */
@@ -2602,6 +2614,51 @@ op_column_error:
break;
}
/* Opcode: Unpack P1 P2 P3 P4 *
** Synopsis: r[P2@P3] = unpack(P1)
**
** Decode the P3 fields of the record object held in register P1
** start with the P4-th field and store the values in registers P2
** and following.
*/
case OP_Unpack: {
const unsigned char *aKey;
int d;
u32 idx; /* Offset in aKey[] to read from */
u16 u; /* Unsigned loop counter */
u32 szHdr;
int nField;
u32 serial_type;
int iOfst; /* Skip this many fields */
pIn1 = &aMem[pOp->p1];
assert( pIn1->flags & MEM_Blob );
aKey = (const unsigned char*)pIn1->z;
pOut = &aMem[pOp->p2];
nField = pOp->p3;
assert( pOp->p4type==P4_INT32 );
iOfst = pOp->p4.i;
idx = getVarint32(aKey, szHdr);
d = szHdr;
u = 0;
while( idx<szHdr && d<=pIn1->n ){
idx += getVarint32(&aKey[idx], serial_type);
if( iOfst ){
iOfst--;
d += sqlite3VdbeSerialTypeLen(serial_type);
}else{
memAboutToChange(p, pOut);
sqlite3VdbeMemSetNull(pOut);
pOut->enc = encoding;
d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pOut);
REGISTER_TRACE((int)(pOut - aMem), pOut);
pOut++;
if( (++u)>=nField ) break;
}
}
break;
}
/* Opcode: Affinity P1 P2 * P4 *
** Synopsis: affinity(r[P1@P2])
**
@@ -2660,7 +2717,7 @@ case OP_MakeRecord: {
int file_format; /* File format to use for encoding */
int i; /* Space used in zNewRecord[] header */
int j; /* Space used in zNewRecord[] content */
u32 len; /* Length of a field */
int len; /* Length of a field */
/* Assuming the record contains N fields, the record format looks
** like this:
@@ -2710,7 +2767,8 @@ case OP_MakeRecord: {
pRec = pLast;
do{
assert( memIsValid(pRec) );
pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format);
len = sqlite3VdbeSerialTypeLen(serial_type);
if( pRec->flags & MEM_Zero ){
if( nData ){
if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
@@ -3324,6 +3382,7 @@ case OP_ReopenIdx: {
case OP_OpenRead:
case OP_OpenWrite:
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR|OPFLAG_SEEKEQ))==pOp->p5 );
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
assert( p->bIsReader );
assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
@@ -3344,8 +3403,7 @@ case OP_OpenWrite:
pX = pDb->pBt;
assert( pX!=0 );
if( pOp->opcode==OP_OpenWrite ){
assert( OPFLAG_FORDELETE==BTREE_FORDELETE );
wrFlag = BTREE_WRCSR | (pOp->p5 & OPFLAG_FORDELETE);
wrFlag = 1;
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( pDb->pSchema->file_format < p->minWriteFileFormat ){
p->minWriteFileFormat = pDb->pSchema->file_format;
@@ -3397,12 +3455,8 @@ case OP_OpenWrite:
open_cursor_set_hints:
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ );
testcase( pOp->p5 & OPFLAG_BULKCSR );
#ifdef SQLITE_ENABLE_CURSOR_HINT
testcase( pOp->p2 & OPFLAG_SEEKEQ );
#endif
sqlite3BtreeCursorHintFlags(pCur->pCursor,
(pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
sqlite3BtreeCursorHints(pCur->pCursor,
(pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
break;
}
@@ -3469,11 +3523,11 @@ case OP_OpenEphemeral: {
assert( pKeyInfo->db==db );
assert( pKeyInfo->enc==ENC(db) );
pCx->pKeyInfo = pKeyInfo;
rc = sqlite3BtreeCursor(pCx->pBt, pgno, BTREE_WRCSR, pKeyInfo, pCx->pCursor);
rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, pKeyInfo, pCx->pCursor);
}
pCx->isTable = 0;
}else{
rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, BTREE_WRCSR, 0, pCx->pCursor);
rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor);
pCx->isTable = 1;
}
}
@@ -3597,13 +3651,6 @@ case OP_ColumnsUsed: {
** is greater than or equal to the key value. If there are no records
** greater than or equal to the key and P2 is not zero, then jump to P2.
**
** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
** opcode will always land on a record that equally equals the key, or
** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this
** opcode must be followed by an IdxLE opcode with the same arguments.
** The IdxLE opcode will be skipped if this opcode succeeds, but the
** IdxLE opcode will be used on subsequent loop iterations.
**
** This opcode leaves the cursor configured to move in forward order,
** from the beginning toward the end. In other words, the cursor is
** configured to use Next, not Prev.
@@ -3662,26 +3709,18 @@ case OP_ColumnsUsed: {
** from the end toward the beginning. In other words, the cursor is
** configured to use Prev, not Next.
**
** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
** opcode will always land on a record that equally equals the key, or
** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this
** opcode must be followed by an IdxGE opcode with the same arguments.
** The IdxGE opcode will be skipped if this opcode succeeds, but the
** IdxGE opcode will be used on subsequent loop iterations.
**
** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
*/
case OP_SeekLT: /* jump, in3 */
case OP_SeekLE: /* jump, in3 */
case OP_SeekGE: /* jump, in3 */
case OP_SeekGT: { /* jump, in3 */
int res; /* Comparison result */
int oc; /* Opcode */
VdbeCursor *pC; /* The cursor to seek */
UnpackedRecord r; /* The key to seek for */
int nField; /* Number of columns or fields in the key */
i64 iKey; /* The rowid we are to seek to */
int eqOnly; /* Only interested in == results */
int res;
int oc;
VdbeCursor *pC;
UnpackedRecord r;
int nField;
i64 iKey; /* The rowid we are to seek to */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p2!=0 );
@@ -3694,16 +3733,27 @@ case OP_SeekGT: { /* jump, in3 */
assert( pC->isOrdered );
assert( pC->pCursor!=0 );
oc = pOp->opcode;
eqOnly = 0;
pC->nullRow = 0;
#ifdef SQLITE_DEBUG
pC->seekOp = pOp->opcode;
#endif
/* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and
** OP_SeekLE opcodes are allowed, and these must be immediately followed
** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key.
*/
#ifdef SQLITE_DEBUG
if( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ) ){
assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
assert( pOp[1].p1==pOp[0].p1 );
assert( pOp[1].p2==pOp[0].p2 );
assert( pOp[1].p3==pOp[0].p3 );
assert( pOp[1].p4.i==pOp[0].p4.i );
}
#endif
if( pC->isTable ){
/* The BTREE_SEEK_EQ flag is only set on index cursors */
assert( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ)==0 );
/* The input value in P3 might be of any type: integer, real, string,
** blob, or NULL. But it needs to be an integer before we can do
** the seek, so convert it. */
@@ -3752,20 +3802,6 @@ case OP_SeekGT: { /* jump, in3 */
goto abort_due_to_error;
}
}else{
/* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and
** OP_SeekLE opcodes are allowed, and these must be immediately followed
** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key.
*/
if( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ) ){
eqOnly = 1;
assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
assert( pOp[1].p1==pOp[0].p1 );
assert( pOp[1].p2==pOp[0].p2 );
assert( pOp[1].p3==pOp[0].p3 );
assert( pOp[1].p4.i==pOp[0].p4.i );
}
nField = pOp->p4.i;
assert( pOp->p4type==P4_INT32 );
assert( nField>0 );
@@ -3790,15 +3826,10 @@ case OP_SeekGT: { /* jump, in3 */
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
#endif
ExpandBlob(r.aMem);
r.eqSeen = 0;
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
if( eqOnly && r.eqSeen==0 ){
assert( res!=0 );
goto seek_not_found;
}
}
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
@@ -3826,14 +3857,10 @@ case OP_SeekGT: { /* jump, in3 */
res = sqlite3BtreeEof(pC->pCursor);
}
}
seek_not_found:
assert( pOp->p2>0 );
VdbeBranchTaken(res!=0,2);
if( res ){
goto jump_to_p2;
}else if( eqOnly ){
assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
pOp++; /* Skip the OP_IdxLt or OP_IdxGT that follows */
}
break;
}
@@ -6618,26 +6645,6 @@ case OP_Init: { /* jump */
break;
}
#ifdef SQLITE_ENABLE_CURSOR_HINTS
/* Opcode: CursorHint P1 * * P4 *
**
** Provide a hint to cursor P1 that it only needs to return rows that
** satisfy the Expr in P4. TK_REGISTER terms in the P4 expression refer
** to values currently held in registers. TK_COLUMN terms in the P4
** expression refer to columns in the b-tree to which cursor P1 is pointing.
*/
case OP_CursorHint: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p4type==P4_EXPR );
pC = p->apCsr[pOp->p1];
if( pC ){
sqlite3BtreeCursorHint(pC->pCursor, BTREE_HINT_RANGE, pOp->p4.pExpr, aMem);
}
break;
}
#endif /* SQLITE_ENABLE_CURSOR_HINTS */
/* Opcode: Noop * * * * *
**
-4
View File
@@ -60,9 +60,6 @@ struct VdbeOp {
KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */
int *ai; /* Used when p4type is P4_INTARRAY */
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
#ifdef SQLITE_ENABLE_CURSOR_HINTS
Expr *pExpr; /* Used when p4type is P4_EXPR */
#endif
int (*xAdvance)(BtCursor *, int *);
} p4;
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
@@ -113,7 +110,6 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */
#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */
#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */
#define P4_EXPR (-7) /* P4 is a pointer to an Expr tree */
#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */
#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */
+1 -13
View File
@@ -26,17 +26,6 @@
# define SQLITE_MAX_SCHEMA_RETRY 50
#endif
/*
** VDBE_DISPLAY_P4 is true or false depending on whether or not the
** "explain" P4 display logic is enabled.
*/
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
|| defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
# define VDBE_DISPLAY_P4 1
#else
# define VDBE_DISPLAY_P4 0
#endif
/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine. Each instruction is an instance
@@ -423,8 +412,7 @@ int sqlite3VdbeCursorRestore(VdbeCursor*);
void sqlite3VdbePrintOp(FILE*, int, Op*);
#endif
u32 sqlite3VdbeSerialTypeLen(u32);
u8 sqlite3VdbeOneByteSerialTypeLen(u8);
u32 sqlite3VdbeSerialType(Mem*, int, u32*);
u32 sqlite3VdbeSerialType(Mem*, int);
u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
+52 -210
View File
@@ -157,12 +157,6 @@ static void test_addop_breakpoint(void){
** the sqlite3VdbeChangeP4() function to change the value of the P4
** operand.
*/
static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){
assert( p->pParse->nOpAlloc<=p->nOp );
if( growOpArray(p, 1) ) return 1;
assert( p->pParse->nOpAlloc>p->nOp );
return sqlite3VdbeAddOp3(p, op, p1, p2, p3);
}
int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
int i;
VdbeOp *pOp;
@@ -171,7 +165,9 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
assert( p->magic==VDBE_MAGIC_INIT );
assert( op>0 && op<0xff );
if( p->pParse->nOpAlloc<=i ){
return growOp3(p, op, p1, p2, p3);
if( growOpArray(p, 1) ){
return 1;
}
}
p->nOp++;
pOp = &p->aOp[i];
@@ -767,12 +763,6 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4);
break;
}
#ifdef SQLITE_ENABLE_CURSOR_HINTS
case P4_EXPR: {
sqlite3ExprDelete(db, (Expr*)p4);
break;
}
#endif
case P4_MPRINTF: {
if( db->pnBytesFreed==0 ) sqlite3_free(p4);
break;
@@ -905,15 +895,6 @@ void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
}else if( n==P4_KEYINFO ){
pOp->p4.p = (void*)zP4;
pOp->p4type = P4_KEYINFO;
#ifdef SQLITE_ENABLE_CURSOR_HINTS
}else if( n==P4_EXPR ){
/* Responsibility for deleting the Expr tree is handed over to the
** VDBE by this operation. The caller should have already invoked
** sqlite3ExprDup() or whatever other routine is needed to make a
** private copy of the tree. */
pOp->p4.pExpr = (Expr*)zP4;
pOp->p4type = P4_EXPR;
#endif
}else if( n==P4_VTAB ){
pOp->p4.p = (void*)zP4;
pOp->p4type = P4_VTAB;
@@ -1104,84 +1085,9 @@ static int displayComment(
}
#endif /* SQLITE_DEBUG */
#if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS)
/*
** Translate the P4.pExpr value for an OP_CursorHint opcode into text
** that can be displayed in the P4 column of EXPLAIN output.
*/
static int displayP4Expr(int nTemp, char *zTemp, Expr *pExpr){
const char *zOp = 0;
int n;
switch( pExpr->op ){
case TK_STRING:
sqlite3_snprintf(nTemp, zTemp, "%Q", pExpr->u.zToken);
break;
case TK_INTEGER:
sqlite3_snprintf(nTemp, zTemp, "%d", pExpr->u.iValue);
break;
case TK_NULL:
sqlite3_snprintf(nTemp, zTemp, "NULL");
break;
case TK_REGISTER: {
sqlite3_snprintf(nTemp, zTemp, "r[%d]", pExpr->iTable);
break;
}
case TK_COLUMN: {
if( pExpr->iColumn<0 ){
sqlite3_snprintf(nTemp, zTemp, "rowid");
}else{
sqlite3_snprintf(nTemp, zTemp, "c%d", (int)pExpr->iColumn);
}
break;
}
case TK_LT: zOp = "LT"; break;
case TK_LE: zOp = "LE"; break;
case TK_GT: zOp = "GT"; break;
case TK_GE: zOp = "GE"; break;
case TK_NE: zOp = "NE"; break;
case TK_EQ: zOp = "EQ"; break;
case TK_IS: zOp = "IS"; break;
case TK_ISNOT: zOp = "ISNOT"; break;
case TK_AND: zOp = "AND"; break;
case TK_OR: zOp = "OR"; break;
case TK_PLUS: zOp = "ADD"; break;
case TK_STAR: zOp = "MUL"; break;
case TK_MINUS: zOp = "SUB"; break;
case TK_REM: zOp = "REM"; break;
case TK_BITAND: zOp = "BITAND"; break;
case TK_BITOR: zOp = "BITOR"; break;
case TK_SLASH: zOp = "DIV"; break;
case TK_LSHIFT: zOp = "LSHIFT"; break;
case TK_RSHIFT: zOp = "RSHIFT"; break;
case TK_CONCAT: zOp = "CONCAT"; break;
case TK_UMINUS: zOp = "MINUS"; break;
case TK_UPLUS: zOp = "PLUS"; break;
case TK_BITNOT: zOp = "BITNOT"; break;
case TK_NOT: zOp = "NOT"; break;
case TK_ISNULL: zOp = "ISNULL"; break;
case TK_NOTNULL: zOp = "NOTNULL"; break;
default:
sqlite3_snprintf(nTemp, zTemp, "%s", "expr");
break;
}
if( zOp ){
sqlite3_snprintf(nTemp, zTemp, "%s(", zOp);
n = sqlite3Strlen30(zTemp);
n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pLeft);
if( n<nTemp-1 && pExpr->pRight ){
zTemp[n++] = ',';
n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pRight);
}
sqlite3_snprintf(nTemp-n, zTemp+n, ")");
}
return sqlite3Strlen30(zTemp);
}
#endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */
#if VDBE_DISPLAY_P4
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
|| defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
/*
** Compute a string that describes the P4 parameter for an opcode.
** Use zTemp for any required temporary buffer space.
@@ -1221,12 +1127,6 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
assert( i<nTemp );
break;
}
#ifdef SQLITE_ENABLE_CURSOR_HINTS
case P4_EXPR: {
displayP4Expr(nTemp, zTemp, pOp->p4.pExpr);
break;
}
#endif
case P4_COLLSEQ: {
CollSeq *pColl = pOp->p4.pColl;
sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName);
@@ -1302,7 +1202,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
assert( zP4!=0 );
return zP4;
}
#endif /* VDBE_DISPLAY_P4 */
#endif
/*
** Declare to the Vdbe that the BTree object at db->aDb[i] is used.
@@ -1616,12 +1516,12 @@ int sqlite3VdbeList(
pMem->u.i = pOp->p3; /* P3 */
pMem++;
if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */
if( sqlite3VdbeMemClearAndResize(pMem, 32) ){ /* P4 */
assert( p->db->mallocFailed );
return SQLITE_ERROR;
}
pMem->flags = MEM_Str|MEM_Term;
zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
zP4 = displayP4(pOp, pMem->z, 32);
if( zP4!=pMem->z ){
sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
}else{
@@ -3040,13 +2940,11 @@ int sqlite3VdbeCursorMoveto(VdbeCursor *p){
/*
** Return the serial-type for the value stored in pMem.
*/
u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
int flags = pMem->flags;
u32 n;
assert( pLen!=0 );
if( flags&MEM_Null ){
*pLen = 0;
return 0;
}
if( flags&MEM_Int ){
@@ -3060,23 +2958,15 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
u = i;
}
if( u<=127 ){
if( (i&1)==i && file_format>=4 ){
*pLen = 0;
return 8+(u32)u;
}else{
*pLen = 1;
return 1;
}
return ((i&1)==i && file_format>=4) ? 8+(u32)u : 1;
}
if( u<=32767 ){ *pLen = 2; return 2; }
if( u<=8388607 ){ *pLen = 3; return 3; }
if( u<=2147483647 ){ *pLen = 4; return 4; }
if( u<=MAX_6BYTE ){ *pLen = 6; return 5; }
*pLen = 8;
if( u<=32767 ) return 2;
if( u<=8388607 ) return 3;
if( u<=2147483647 ) return 4;
if( u<=MAX_6BYTE ) return 5;
return 6;
}
if( flags&MEM_Real ){
*pLen = 8;
return 7;
}
assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) );
@@ -3085,46 +2975,26 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
if( flags & MEM_Zero ){
n += pMem->u.nZero;
}
*pLen = n;
return ((n*2) + 12 + ((flags&MEM_Str)!=0));
}
/*
** The sizes for serial types less than 128
** The sizes for serial types less than 12
*/
static const u8 sqlite3SmallTypeSizes[] = {
/* 0 1 2 3 4 5 6 7 8 9 */
/* 0 */ 0, 1, 2, 3, 4, 6, 8, 8, 0, 0,
/* 10 */ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
/* 20 */ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
/* 30 */ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
/* 40 */ 14, 14, 15, 15, 16, 16, 17, 17, 18, 18,
/* 50 */ 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
/* 60 */ 24, 24, 25, 25, 26, 26, 27, 27, 28, 28,
/* 70 */ 29, 29, 30, 30, 31, 31, 32, 32, 33, 33,
/* 80 */ 34, 34, 35, 35, 36, 36, 37, 37, 38, 38,
/* 90 */ 39, 39, 40, 40, 41, 41, 42, 42, 43, 43,
/* 100 */ 44, 44, 45, 45, 46, 46, 47, 47, 48, 48,
/* 110 */ 49, 49, 50, 50, 51, 51, 52, 52, 53, 53,
/* 120 */ 54, 54, 55, 55, 56, 56, 57, 57
0, 1, 2, 3, 4, 6, 8, 8, 0, 0, 0, 0
};
/*
** Return the length of the data corresponding to the supplied serial-type.
*/
u32 sqlite3VdbeSerialTypeLen(u32 serial_type){
if( serial_type>=128 ){
if( serial_type>=12 ){
return (serial_type-12)/2;
}else{
assert( serial_type<12
|| sqlite3SmallTypeSizes[serial_type]==(serial_type - 12)/2 );
return sqlite3SmallTypeSizes[serial_type];
}
}
u8 sqlite3VdbeOneByteSerialTypeLen(u8 serial_type){
assert( serial_type<128 );
return sqlite3SmallTypeSizes[serial_type];
}
/*
** If we are on an architecture with mixed-endian floating
@@ -3323,10 +3193,6 @@ u32 sqlite3VdbeSerialGet(
/* EVIDENCE-OF: R-01849-26079 Value is a big-endian 32-bit
** twos-complement integer. */
pMem->u.i = FOUR_BYTE_INT(buf);
#ifdef __HP_cc
/* Work around a sign-extension bug in the HP compiler for HP/UX */
if( buf[0]&0x80 ) pMem->u.i |= 0xffffffff80000000LL;
#endif
pMem->flags = MEM_Int;
testcase( pMem->u.i<0 );
return 4;
@@ -3642,34 +3508,6 @@ static SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){
return pB1->n - pB2->n;
}
/*
** Do a comparison between a 64-bit signed integer and a 64-bit floating-point
** number. Return negative, zero, or positive if the first (i64) is less than,
** equal to, or greater than the second (double).
*/
static int sqlite3IntFloatCompare(i64 i, double r){
if( sizeof(LONGDOUBLE_TYPE)>8 ){
LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
if( x<r ) return -1;
if( x>r ) return +1;
return 0;
}else{
i64 y;
double s;
if( r<-9223372036854775808.0 ) return +1;
if( r>9223372036854775807.0 ) return -1;
y = (i64)r;
if( i<y ) return -1;
if( i>y ){
if( y==SMALLEST_INT64 && r>0.0 ) return -1;
return +1;
}
s = (double)i;
if( s<r ) return -1;
if( s>r ) return +1;
return 0;
}
}
/*
** Compare the values contained by the two memory cells, returning
@@ -3696,34 +3534,34 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
return (f2&MEM_Null) - (f1&MEM_Null);
}
/* At least one of the two values is a number
/* If one value is a number and the other is not, the number is less.
** If both are numbers, compare as reals if one is a real, or as integers
** if both values are integers.
*/
if( combined_flags&(MEM_Int|MEM_Real) ){
double r1, r2;
if( (f1 & f2 & MEM_Int)!=0 ){
if( pMem1->u.i < pMem2->u.i ) return -1;
if( pMem1->u.i > pMem2->u.i ) return +1;
if( pMem1->u.i > pMem2->u.i ) return 1;
return 0;
}
if( (f1 & f2 & MEM_Real)!=0 ){
if( pMem1->u.r < pMem2->u.r ) return -1;
if( pMem1->u.r > pMem2->u.r ) return +1;
return 0;
}
if( (f1&MEM_Int)!=0 ){
if( (f2&MEM_Real)!=0 ){
return sqlite3IntFloatCompare(pMem1->u.i, pMem2->u.r);
}else{
return -1;
}
}
if( (f1&MEM_Real)!=0 ){
if( (f2&MEM_Int)!=0 ){
return -sqlite3IntFloatCompare(pMem2->u.i, pMem1->u.r);
}else{
return -1;
}
r1 = pMem1->u.r;
}else if( (f1&MEM_Int)!=0 ){
r1 = (double)pMem1->u.i;
}else{
return 1;
}
return +1;
if( (f2&MEM_Real)!=0 ){
r2 = pMem2->u.r;
}else if( (f2&MEM_Int)!=0 ){
r2 = (double)pMem2->u.i;
}else{
return -1;
}
if( r1<r2 ) return -1;
if( r1>r2 ) return 1;
return 0;
}
/* If one value is a string and the other is a blob, the string is less.
@@ -3874,8 +3712,13 @@ int sqlite3VdbeRecordCompareWithSkip(
}else if( serial_type==0 ){
rc = -1;
}else if( serial_type==7 ){
double rhs = (double)pRhs->u.i;
sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
rc = -sqlite3IntFloatCompare(pRhs->u.i, mem1.u.r);
if( mem1.u.r<rhs ){
rc = -1;
}else if( mem1.u.r>rhs ){
rc = +1;
}
}else{
i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
i64 rhs = pRhs->u.i;
@@ -3899,15 +3742,18 @@ int sqlite3VdbeRecordCompareWithSkip(
}else if( serial_type==0 ){
rc = -1;
}else{
double rhs = pRhs->u.r;
double lhs;
sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
if( serial_type==7 ){
if( mem1.u.r<pRhs->u.r ){
rc = -1;
}else if( mem1.u.r>pRhs->u.r ){
rc = +1;
}
lhs = mem1.u.r;
}else{
rc = sqlite3IntFloatCompare(mem1.u.i, pRhs->u.r);
lhs = (double)mem1.u.i;
}
if( lhs<rhs ){
rc = -1;
}else if( lhs>rhs ){
rc = +1;
}
}
}
@@ -3997,7 +3843,6 @@ int sqlite3VdbeRecordCompareWithSkip(
|| vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc)
|| pKeyInfo->db->mallocFailed
);
pPKey2->eqSeen = 1;
return pPKey2->default_rc;
}
int sqlite3VdbeRecordCompare(
@@ -4097,7 +3942,6 @@ static int vdbeRecordCompareInt(
/* The first fields of the two keys are equal and there are no trailing
** fields. Return pPKey2->default_rc in this case. */
res = pPKey2->default_rc;
pPKey2->eqSeen = 1;
}
assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, res) );
@@ -4118,7 +3962,6 @@ static int vdbeRecordCompareString(
int serial_type;
int res;
assert( pPKey2->aMem[0].flags & MEM_Str );
vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
getVarint32(&aKey1[1], serial_type);
if( serial_type<12 ){
@@ -4145,7 +3988,6 @@ static int vdbeRecordCompareString(
res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
}else{
res = pPKey2->default_rc;
pPKey2->eqSeen = 1;
}
}else if( res>0 ){
res = pPKey2->r2;
+4 -3
View File
@@ -1427,16 +1427,17 @@ static void recordFunc(
sqlite3_value **argv
){
const int file_format = 1;
u32 iSerial; /* Serial type */
int iSerial; /* Serial type */
int nSerial; /* Bytes of space for iSerial as varint */
u32 nVal; /* Bytes of space required for argv[0] */
int nVal; /* Bytes of space required for argv[0] */
int nRet;
sqlite3 *db;
u8 *aRet;
UNUSED_PARAMETER( argc );
iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal);
iSerial = sqlite3VdbeSerialType(argv[0], file_format);
nSerial = sqlite3VarintLen(iSerial);
nVal = sqlite3VdbeSerialTypeLen(iSerial);
db = sqlite3_context_db_handle(context);
nRet = 1 + nSerial + nVal;
+11 -42
View File
@@ -485,20 +485,14 @@ static LogEst estLog(LogEst N){
** Convert OP_Column opcodes to OP_Copy in previously generated code.
**
** This routine runs over generated VDBE code and translates OP_Column
** opcodes into OP_Copy when the table is being accessed via co-routine
** instead of via table lookup.
**
** If the bIncrRowid parameter is 0, then any OP_Rowid instructions on
** cursor iTabCur are transformed into OP_Null. Or, if bIncrRowid is non-zero,
** then each OP_Rowid is transformed into an instruction to increment the
** value stored in its output register.
** opcodes into OP_Copy, and OP_Rowid into OP_Null, when the table is being
** accessed via co-routine instead of via table lookup.
*/
static void translateColumnToCopy(
Vdbe *v, /* The VDBE containing code to translate */
int iStart, /* Translate from this opcode to the end */
int iTabCur, /* OP_Column/OP_Rowid references to this table */
int iRegister, /* The first column is in this register */
int bIncrRowid /* If non-zero, transform OP_rowid to OP_AddImm(1) */
int iRegister /* The first column is in this register */
){
VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart);
int iEnd = sqlite3VdbeCurrentAddr(v);
@@ -510,16 +504,9 @@ static void translateColumnToCopy(
pOp->p2 = pOp->p3;
pOp->p3 = 0;
}else if( pOp->opcode==OP_Rowid ){
if( bIncrRowid ){
/* Increment the value stored in the P2 operand of the OP_Rowid. */
pOp->opcode = OP_AddImm;
pOp->p1 = pOp->p2;
pOp->p2 = 1;
}else{
pOp->opcode = OP_Null;
pOp->p1 = 0;
pOp->p3 = 0;
}
pOp->opcode = OP_Null;
pOp->p1 = 0;
pOp->p3 = 0;
}
}
}
@@ -627,8 +614,6 @@ static void constructAutomaticIndex(
Expr *pPartial = 0; /* Partial Index Expression */
int iContinue = 0; /* Jump here to skip excluded rows */
struct SrcList_item *pTabItem; /* FROM clause term being indexed */
int addrCounter = 0; /* Address where integer counter is initialized */
int regBase; /* Array of registers where record is assembled */
/* Generate code to skip over the creation and initialization of the
** transient index on 2nd and subsequent iterations of the loop. */
@@ -757,7 +742,6 @@ static void constructAutomaticIndex(
pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom];
if( pTabItem->fg.viaCoroutine ){
int regYield = pTabItem->regReturn;
addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0);
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield);
VdbeCoverage(v);
@@ -771,15 +755,12 @@ static void constructAutomaticIndex(
pLoop->wsFlags |= WHERE_PARTIALIDX;
}
regRecord = sqlite3GetTempReg(pParse);
regBase = sqlite3GenerateIndexKey(
pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0
);
sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue);
if( pTabItem->fg.viaCoroutine ){
sqlite3VdbeChangeP2(v, addrCounter, regBase+n);
translateColumnToCopy(v, addrTop, pLevel->iTabCur, pTabItem->regResult, 1);
translateColumnToCopy(v, addrTop, pLevel->iTabCur, pTabItem->regResult);
sqlite3VdbeGoto(v, addrTop);
pTabItem->fg.viaCoroutine = 0;
}else{
@@ -4010,7 +3991,6 @@ WhereInfo *sqlite3WhereBegin(
int ii; /* Loop counter */
sqlite3 *db; /* Database connection */
int rc; /* Return code */
u8 bFordelete = 0;
assert( (wctrlFlags & WHERE_ONEPASS_MULTIROW)==0 || (
(wctrlFlags & WHERE_ONEPASS_DESIRED)!=0
@@ -4266,11 +4246,8 @@ WhereInfo *sqlite3WhereBegin(
&& 0==(wsFlags & WHERE_VIRTUALTABLE)
)){
pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI;
if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){
if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){
bFordelete = OPFLAG_FORDELETE;
}
pWInfo->a[0].pWLoop->wsFlags = (wsFlags & ~WHERE_IDX_ONLY);
if( HasRowid(pTabList->a[0].pTab) ){
pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY;
}
}
}
@@ -4318,14 +4295,6 @@ WhereInfo *sqlite3WhereBegin(
SQLITE_INT_TO_PTR(n), P4_INT32);
assert( n<=pTab->nCol );
}
#ifdef SQLITE_ENABLE_CURSOR_HINTS
if( pLoop->u.btree.pIndex!=0 ){
sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ|bFordelete);
}else
#endif
{
sqlite3VdbeChangeP5(v, bFordelete);
}
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, pTabItem->iCursor, 0, 0,
(const u8*)&pTabItem->colUsed, P4_INT64);
@@ -4540,7 +4509,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
*/
if( pTabItem->fg.viaCoroutine && !db->mallocFailed ){
translateColumnToCopy(v, pLevel->addrBody, pLevel->iTabCur,
pTabItem->regResult, 0);
pTabItem->regResult);
continue;
}
+10 -161
View File
@@ -590,154 +590,6 @@ static void whereLikeOptimizationStringFixup(
}
}
#ifdef SQLITE_ENABLE_CURSOR_HINTS
/*
** Information is passed from codeCursorHint() down to individual nodes of
** the expression tree (by sqlite3WalkExpr()) using an instance of this
** structure.
*/
struct CCurHint {
int iTabCur; /* Cursor for the main table */
int iIdxCur; /* Cursor for the index, if pIdx!=0. Unused otherwise */
Index *pIdx; /* The index used to access the table */
};
/*
** This function is called for every node of an expression that is a candidate
** for a cursor hint on an index cursor. For TK_COLUMN nodes that reference
** the table CCurHint.iTabCur, verify that the same column can be
** accessed through the index. If it cannot, then set pWalker->eCode to 1.
*/
static int codeCursorHintCheckExpr(Walker *pWalker, Expr *pExpr){
struct CCurHint *pHint = pWalker->u.pCCurHint;
assert( pHint->pIdx!=0 );
if( pExpr->op==TK_COLUMN
&& pExpr->iTable==pHint->iTabCur
&& sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn)<0
){
pWalker->eCode = 1;
}
return WRC_Continue;
}
/*
** This function is called on every node of an expression tree used as an
** argument to the OP_CursorHint instruction. If the node is a TK_COLUMN
** that accesses any table other than the one identified by
** CCurHint.iTabCur, then do the following:
**
** 1) allocate a register and code an OP_Column instruction to read
** the specified column into the new register, and
**
** 2) transform the expression node to a TK_REGISTER node that reads
** from the newly populated register.
**
** Also, if the node is a TK_COLUMN that does access the table idenified
** by pCCurHint.iTabCur, and an index is being used (which we will
** know because CCurHint.pIdx!=0) then transform the TK_COLUMN into
** an access of the index rather than the original table.
*/
static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){
int rc = WRC_Continue;
struct CCurHint *pHint = pWalker->u.pCCurHint;
if( pExpr->op==TK_COLUMN ){
if( pExpr->iTable!=pHint->iTabCur ){
Vdbe *v = pWalker->pParse->pVdbe;
int reg = ++pWalker->pParse->nMem; /* Register for column value */
sqlite3ExprCodeGetColumnOfTable(
v, pExpr->pTab, pExpr->iTable, pExpr->iColumn, reg
);
pExpr->op = TK_REGISTER;
pExpr->iTable = reg;
}else if( pHint->pIdx!=0 ){
pExpr->iTable = pHint->iIdxCur;
pExpr->iColumn = sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn);
assert( pExpr->iColumn>=0 );
}
}else if( pExpr->op==TK_AGG_FUNCTION ){
/* An aggregate function in the WHERE clause of a query means this must
** be a correlated sub-query, and expression pExpr is an aggregate from
** the parent context. Do not walk the function arguments in this case.
**
** todo: It should be possible to replace this node with a TK_REGISTER
** expression, as the result of the expression must be stored in a
** register at this point. The same holds for TK_AGG_COLUMN nodes. */
rc = WRC_Prune;
}
return rc;
}
/*
** Insert an OP_CursorHint instruction if it is appropriate to do so.
*/
static void codeCursorHint(
WhereInfo *pWInfo, /* The where clause */
WhereLevel *pLevel, /* Which loop to provide hints for */
WhereTerm *pEndRange /* Hint this end-of-scan boundary term if not NULL */
){
Parse *pParse = pWInfo->pParse;
sqlite3 *db = pParse->db;
Vdbe *v = pParse->pVdbe;
Expr *pExpr = 0;
WhereLoop *pLoop = pLevel->pWLoop;
int iCur;
WhereClause *pWC;
WhereTerm *pTerm;
int i, j;
struct CCurHint sHint;
Walker sWalker;
if( OptimizationDisabled(db, SQLITE_CursorHints) ) return;
iCur = pLevel->iTabCur;
assert( iCur==pWInfo->pTabList->a[pLevel->iFrom].iCursor );
sHint.iTabCur = iCur;
sHint.iIdxCur = pLevel->iIdxCur;
sHint.pIdx = pLoop->u.btree.pIndex;
memset(&sWalker, 0, sizeof(sWalker));
sWalker.pParse = pParse;
sWalker.u.pCCurHint = &sHint;
pWC = &pWInfo->sWC;
for(i=0; i<pWC->nTerm; i++){
pTerm = &pWC->a[i];
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( pTerm->prereqAll & pLevel->notReady ) continue;
if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) continue;
/* All terms in pWLoop->aLTerm[] except pEndRange are used to initialize
** the cursor. These terms are not needed as hints for a pure range
** scan (that has no == terms) so omit them. */
if( pLoop->u.btree.nEq==0 && pTerm!=pEndRange ){
for(j=0; j<pLoop->nLTerm && pLoop->aLTerm[j]!=pTerm; j++){}
if( j<pLoop->nLTerm ) continue;
}
/* No subqueries or non-deterministic functions allowed */
if( sqlite3ExprContainsSubquery(pTerm->pExpr) ) continue;
/* For an index scan, make sure referenced columns are actually in
** the index. */
if( sHint.pIdx!=0 ){
sWalker.eCode = 0;
sWalker.xExprCallback = codeCursorHintCheckExpr;
sqlite3WalkExpr(&sWalker, pTerm->pExpr);
if( sWalker.eCode ) continue;
}
/* If we survive all prior tests, that means this term is worth hinting */
pExpr = sqlite3ExprAnd(db, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0));
}
if( pExpr!=0 ){
sWalker.xExprCallback = codeCursorHintFixExpr;
sqlite3WalkExpr(&sWalker, pExpr);
sqlite3VdbeAddOp4(v, OP_CursorHint,
(sHint.pIdx ? sHint.iIdxCur : sHint.iTabCur), 0, 0,
(const char*)pExpr, P4_EXPR);
}
}
#else
# define codeCursorHint(A,B,C) /* No-op */
#endif /* SQLITE_ENABLE_CURSOR_HINTS */
/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
@@ -902,7 +754,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
pStart = pEnd;
pEnd = pTerm;
}
codeCursorHint(pWInfo, pLevel, pEnd);
if( pStart ){
Expr *pX; /* The expression that defines the start bound */
int r1, rTemp; /* Registers for holding the start boundary */
@@ -1096,6 +947,15 @@ Bitmask sqlite3WhereCodeOneLoopStart(
}
assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );
/* Generate code to evaluate all constraint terms using == or IN
** and store the values of those terms in an array of registers
** starting at regBase.
*/
regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff);
assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq );
if( zStartAff ) cEndAff = zStartAff[nEq];
addrNxt = pLevel->addrNxt;
/* If we are doing a reverse order scan on an ascending index, or
** a forward order scan on a descending index, interchange the
** start and end terms (pRangeStart and pRangeEnd).
@@ -1107,16 +967,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
SWAP(u8, bSeekPastNull, bStopAtNull);
}
/* Generate code to evaluate all constraint terms using == or IN
** and store the values of those terms in an array of registers
** starting at regBase.
*/
codeCursorHint(pWInfo, pLevel, pRangeEnd);
regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff);
assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq );
if( zStartAff ) cEndAff = zStartAff[nEq];
addrNxt = pLevel->addrNxt;
testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 );
testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 );
testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 );
@@ -1399,7 +1249,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
}
if( pAndExpr ){
pAndExpr = sqlite3PExpr(pParse, TK_AND|TKFLG_DONTFOLD, 0, pAndExpr, 0);
pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0);
}
}
@@ -1555,7 +1405,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** a pseudo-cursor. No need to Rewind or Next such cursors. */
pLevel->op = OP_Noop;
}else{
codeCursorHint(pWInfo, pLevel, 0);
pLevel->op = aStep[bRev];
pLevel->p1 = iCur;
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
+1 -1
View File
@@ -15,7 +15,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
if {$::longdouble_size<=8} {
if {![info exists __GNUC__] || [regexp arm $tcl_platform(machine)]} {
finish_test
return
}
-21
View File
@@ -17,7 +17,6 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix autoindex5
# Schema is from the Debian security database
#
@@ -104,26 +103,6 @@ do_execsql_test autoindex5-1.1 {
OR sp.release = 'wheezy' OR sp.release = 'squeeze' )
ORDER BY sp.name, st.bug_name, sp.release, sp.subrelease;
} {/SEARCH SUBQUERY 2 USING AUTOMATIC COVERING INDEX .bug_name=/}
#-------------------------------------------------------------------------
# Test that ticket [8a2adec1] has been fixed.
#
do_execsql_test 2.1 {
CREATE TABLE one(o);
INSERT INTO one DEFAULT VALUES;
CREATE TABLE t1(x, z);
INSERT INTO t1 VALUES('aaa', 4.0);
INSERT INTO t1 VALUES('aaa', 4.0);
CREATE VIEW vvv AS
SELECT * FROM t1
UNION ALL
SELECT 0, 0 WHERE 0;
SELECT (
SELECT sum(z) FROM vvv WHERE x='aaa'
) FROM one;
} {8.0}
finish_test
+1 -3
View File
@@ -7,13 +7,11 @@ proc bc_find_binaries {zCaption} {
# against.
#
set binaries [list]
set self [file tail [info nameofexec]]
set pattern "$self?*"
set pattern "[file tail [info nameofexec]]?*"
if {$::tcl_platform(platform)=="windows"} {
set pattern [string map {\.exe {}} $pattern]
}
foreach file [glob -nocomplain $pattern] {
if {$file==$self} continue
if {[file executable $file] && [file isfile $file]} {lappend binaries $file}
}
-324
View File
@@ -1,324 +0,0 @@
# 2011 November 16
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains test cases for sqlite3_db_cacheflush API.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix cacheflush
test_set_config_pagecache 0 0
# Run the supplied SQL on a copy of the database currently stored on
# disk in file $dbfile.
proc diskquery {dbfile sql} {
forcecopy $dbfile dq.db
sqlite3 dq dq.db
set res [execsql $sql dq]
dq close
set res
}
# Simplest possible test.
#
do_execsql_test 1.1.0 {
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
BEGIN;
INSERT INTO t1 VALUES(3, 4);
}
do_test 1.1.1 {
diskquery test.db { SELECT * FROM t1 }
} {1 2}
do_test 1.1.2 {
sqlite3_db_cacheflush db
diskquery test.db { SELECT * FROM t1 }
} {1 2 3 4}
# Test that multiple pages may be flushed to disk.
#
do_execsql_test 1.2.0 {
COMMIT;
CREATE TABLE t2(a, b);
BEGIN;
INSERT INTO t1 VALUES(5, 6);
INSERT INTO t2 VALUES('a', 'b');
}
do_test 1.2.1 {
diskquery test.db {
SELECT * FROM t1;
SELECT * FROM t2;
}
} {1 2 3 4}
do_test 1.2.2 {
sqlite3_db_cacheflush db
diskquery test.db {
SELECT * FROM t1;
SELECT * FROM t2;
}
} {1 2 3 4 5 6 a b}
# Test that pages with nRef!=0 are not flushed to disk.
#
do_execsql_test 1.3.0 {
COMMIT;
CREATE TABLE t3(a, b);
BEGIN;
INSERT INTO t1 VALUES(7, 8);
INSERT INTO t2 VALUES('c', 'd');
INSERT INTO t3 VALUES('i', 'ii');
}
do_test 1.3.1 {
diskquery test.db {
SELECT * FROM t1;
SELECT * FROM t2;
SELECT * FROM t3;
}
} {1 2 3 4 5 6 a b}
do_test 1.3.2 {
db eval { SELECT a FROM t1 } {
if {$a==3} {
sqlite3_db_cacheflush db
}
}
diskquery test.db {
SELECT * FROM t1;
SELECT * FROM t2;
SELECT * FROM t3;
}
} {1 2 3 4 5 6 a b c d i ii}
do_test 1.3.2 {
sqlite3_db_cacheflush db
diskquery test.db {
SELECT * FROM t1;
SELECT * FROM t2;
SELECT * FROM t3;
}
} {1 2 3 4 5 6 7 8 a b c d i ii}
# Check that SQLITE_BUSY is returned if pages cannot be flushed due to
# conflicting read locks.
#
do_execsql_test 1.4.0 {
COMMIT;
BEGIN;
INSERT INTO t1 VALUES(9, 10);
}
do_test 1.4.1 {
sqlite3 db2 test.db
db2 eval {
BEGIN;
SELECT * FROM t1;
}
diskquery test.db {
SELECT * FROM t1;
}
} {1 2 3 4 5 6 7 8}
do_test 1.4.2 {
list [catch { sqlite3_db_cacheflush db } msg] $msg
} {1 {database is locked}}
do_test 1.4.3 {
diskquery test.db {
SELECT * FROM t1;
}
} {1 2 3 4 5 6 7 8}
do_test 1.4.4 {
db2 close
sqlite3_db_cacheflush db
diskquery test.db {
SELECT * FROM t1;
}
} {1 2 3 4 5 6 7 8 9 10}
do_execsql_test 1.4.5 { COMMIT }
#-------------------------------------------------------------------------
# Test that ATTACHed database caches are also flushed.
#
forcedelete test.db2
do_execsql_test 2.1.0 {
ATTACH 'test.db2' AS aux;
CREATE TABLE aux.t4(x, y);
INSERT INTO t4 VALUES('A', 'B');
BEGIN;
INSERT INTO t1 VALUES(11, 12);
INSERT INTO t4 VALUES('C', 'D');
}
do_test 2.1.1 {
diskquery test.db { SELECT * FROM t1; }
} {1 2 3 4 5 6 7 8 9 10}
do_test 2.1.2 {
diskquery test.db2 { SELECT * FROM t4; }
} {A B}
do_test 2.1.3 {
sqlite3_db_cacheflush db
diskquery test.db { SELECT * FROM t1; }
} {1 2 3 4 5 6 7 8 9 10 11 12}
do_test 2.1.4 {
sqlite3_db_cacheflush db
diskquery test.db2 { SELECT * FROM t4; }
} {A B C D}
do_execsql_test 2.1.5 { COMMIT }
# And that hitting an SQLITE_BUSY when flushing "main" does not stop
# SQLite from going on to flush "aux".
#
do_execsql_test 2.2.0 {
BEGIN;
INSERT INTO t1 VALUES(13, 14);
INSERT INTO t4 VALUES('E', 'F');
}
do_test 2.2.1 {
diskquery test.db { SELECT * FROM t1; }
} {1 2 3 4 5 6 7 8 9 10 11 12}
do_test 2.2.2 {
diskquery test.db2 { SELECT * FROM t4; }
} {A B C D}
do_test 2.2.3 {
sqlite3 db2 test.db
execsql {
BEGIN;
SELECT * FROM t1;
} db2
list [catch { sqlite3_db_cacheflush db } msg] $msg
} {1 {database is locked}}
do_test 2.2.4 {
diskquery test.db { SELECT * FROM t1; }
} {1 2 3 4 5 6 7 8 9 10 11 12}
do_test 2.2.5 {
diskquery test.db2 { SELECT * FROM t4; }
} {A B C D E F}
do_test 2.2.6 {
db2 close
sqlite3_db_cacheflush db
diskquery test.db { SELECT * FROM t1; }
} {1 2 3 4 5 6 7 8 9 10 11 12 13 14}
do_execsql_test 2.2.7 { COMMIT }
#-------------------------------------------------------------------------
# Test that nothing terrible happens if sqlite3_db_cacheflush() is
# called on an in-memory database.
#
do_test 3.0 {
db close
sqlite3 db :memory:
db eval {
CREATE TABLE t1(x PRIMARY KEY);
CREATE TABLE t2(y PRIMARY KEY);
BEGIN;
INSERT INTO t1 VALUES(randomblob(100));
INSERT INTO t2 VALUES(randomblob(100));
INSERT INTO t1 VALUES(randomblob(100));
INSERT INTO t2 VALUES(randomblob(100));
}
sqlite3_db_cacheflush db
} {}
do_execsql_test 3.1 { PRAGMA integrity_check } ok
do_execsql_test 3.2 { COMMIT }
do_execsql_test 3.3 { PRAGMA integrity_check } ok
do_execsql_test 3.4 {
SELECT count(*) FROM t1;
SELECT count(*) FROM t2;
} {2 2}
#-------------------------------------------------------------------------
# Test that calling sqlite3_db_cacheflush() does not interfere with
# savepoint transactions.
#
do_test 4.0 {
reset_db
execsql {
CREATE TABLE ta(a, aa);
CREATE TABLE tb(b, bb);
INSERT INTO ta VALUES('a', randomblob(500));
INSERT INTO tb VALUES('b', randomblob(500));
BEGIN;
UPDATE ta SET a = 'A';
SAVEPOINT one;
UPDATE tb SET b = 'B';
}
sqlite3_db_cacheflush db
diskquery test.db {
SELECT a FROM ta;
SELECT b FROM tb;
}
} {A B}
do_test 4.1 {
execsql {
ROLLBACK TO one;
}
sqlite3_db_cacheflush db
diskquery test.db {
SELECT a FROM ta;
SELECT b FROM tb;
}
} {A b}
do_test 4.2 {
execsql {
INSERT INTO tb VALUES('c', randomblob(10));
INSERT INTO tb VALUES('d', randomblob(10));
INSERT INTO tb VALUES('e', randomblob(10));
}
sqlite3_db_cacheflush db
diskquery test.db {
SELECT a FROM ta;
SELECT b FROM tb;
}
} {A b c d e}
do_test 4.3 {
execsql {
SAVEPOINT two;
UPDATE tb SET b = upper(b);
}
sqlite3_db_cacheflush db
diskquery test.db {
SELECT a FROM ta;
SELECT b FROM tb;
}
} {A B C D E}
do_test 4.4 {
execsql {
ROLLBACK TO two;
}
sqlite3_db_cacheflush db
diskquery test.db {
SELECT a FROM ta;
SELECT b FROM tb;
}
} {A b c d e}
do_test 4.4 {
execsql {
ROLLBACK TO one;
}
sqlite3_db_cacheflush db
diskquery test.db {
SELECT a FROM ta;
SELECT b FROM tb;
}
} {A b}
do_test 4.5 {
execsql {
ROLLBACK;
SELECT a FROM ta;
SELECT b FROM tb;
}
} {a b}
test_restore_config_pagecache
finish_test
-159
View File
@@ -1,159 +0,0 @@
# 2011 November 16
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains fault-injection test cases for the
# sqlite3_db_cacheflush API.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix cacheflush
source $testdir/malloc_common.tcl
# Run the supplied SQL on a copy of the database currently stored on
# disk in file $dbfile.
proc diskquery {dbfile sql} {
forcecopy $dbfile dq.db
sqlite3 dq dq.db
set res [execsql $sql dq]
dq close
set res
}
do_execsql_test 1.0 {
CREATE TABLE t1(a PRIMARY KEY, b);
CREATE INDEX i1 ON t1(b);
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
INSERT INTO t1 VALUES(5, 6);
INSERT INTO t1 VALUES(7, 8);
}
faultsim_save_and_close
do_faultsim_test 1.1 -prep {
faultsim_restore_and_reopen
db eval {
BEGIN;
UPDATE t1 SET b=b+1;
}
} -body {
sqlite3_db_cacheflush db
} -test {
if {[sqlite3_get_autocommit db]} { error "Transaction rolled back!" }
faultsim_test_result {0 {}} {1 {disk I/O error}}
catch { db eval COMMIT }
faultsim_integrity_check
}
do_faultsim_test 1.2 -prep {
faultsim_restore_and_reopen
db eval {
BEGIN;
UPDATE t1 SET b=b+1;
}
} -body {
set result [list]
db eval { SELECT * FROM t1 } {
if {$a==5} { catch { sqlite3_db_cacheflush db } }
lappend result $a $b
}
set result
} -test {
faultsim_test_result {0 {1 3 3 5 5 7 7 9}} {1 {disk I/O error}}
catch { db eval COMMIT }
faultsim_integrity_check
}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
CREATE TABLE t1(a PRIMARY KEY, b, c);
CREATE INDEX i1 ON t1(b);
CREATE INDEX i2 ON t1(c, b);
INSERT INTO t1 VALUES(1, 2, randomblob(600));
INSERT INTO t1 VALUES(3, 4, randomblob(600));
INSERT INTO t1 VALUES(5, 6, randomblob(600));
INSERT INTO t1 VALUES(7, 8, randomblob(600));
INSERT INTO t1 VALUES(9, 10, randomblob(600));
}
faultsim_save_and_close
do_faultsim_test 2.1 -prep {
faultsim_restore_and_reopen
db eval {
BEGIN;
UPDATE t1 SET b=b+1;
}
} -body {
set result [list]
db eval { SELECT * FROM t1 } {
if {$a==5} { catch { sqlite3_db_cacheflush db } }
lappend result $a $b
}
set result
} -test {
faultsim_test_result {0 {1 3 3 5 5 7 7 9 9 11}} {1 {disk I/O error}}
catch { db eval { INSERT INTO t1 VALUES(11, 12, randomblob(600)) } }
catch { db eval COMMIT }
faultsim_integrity_check
}
do_faultsim_test 2.2 -prep {
faultsim_restore_and_reopen
db eval {
BEGIN;
UPDATE t1 SET b=b+1;
}
} -body {
sqlite3_db_cacheflush db
} -test {
if {[sqlite3_get_autocommit db]} { error "Transaction rolled back!" }
faultsim_test_result {0 {}} {1 {disk I/O error}}
catch { db eval { SELECT * FROM t1 } }
catch { db eval COMMIT }
faultsim_integrity_check
}
do_faultsim_test 2.3 -prep {
faultsim_restore_and_reopen
db eval {
BEGIN;
UPDATE t1 SET b=b-1;
}
} -body {
sqlite3_db_cacheflush db
} -test {
if {[sqlite3_get_autocommit db]} { error "Transaction rolled back!" }
faultsim_test_result {0 {}} {1 {disk I/O error}}
catch { db eval { INSERT INTO t1 VALUES(11, 12, randomblob(600)) } }
catch { db eval COMMIT }
faultsim_integrity_check
}
do_faultsim_test 2.4 -prep {
faultsim_restore_and_reopen
db eval {
BEGIN;
UPDATE t1 SET b=b-1;
}
} -body {
catch { sqlite3_db_cacheflush db }
catch { sqlite3_db_release_memory db }
catch { sqlite3_db_cacheflush db }
execsql { SELECT a, b FROM t1 }
} -test {
faultsim_test_result {0 {1 1 3 3 5 5 7 7 9 9}} {1 {disk I/O error}}
catchsql ROLLBACK
faultsim_integrity_check
}
finish_test
+4 -4
View File
@@ -352,7 +352,7 @@ do_test collate4-2.1.2 {
count {
SELECT * FROM collate4t2, collate4t1 WHERE a = b;
}
} {A a A A 4}
} {A a A A 5}
do_test collate4-2.1.3 {
count {
SELECT * FROM collate4t2, collate4t1 WHERE b = a;
@@ -372,7 +372,7 @@ do_test collate4-2.1.5 {
count {
SELECT * FROM collate4t2, collate4t1 WHERE b = a;
}
} {A A 3}
} {A A 4}
ifcapable subquery {
do_test collate4-2.1.6 {
count {
@@ -389,12 +389,12 @@ ifcapable subquery {
SELECT a FROM collate4t1 WHERE a IN (SELECT * FROM collate4t2)
ORDER BY rowid
}
} {a A 5}
} {a A 6}
do_test collate4-2.1.8 {
count {
SELECT a FROM collate4t1 WHERE a IN ('z', 'a');
}
} {a A 4}
} {a A 5}
do_test collate4-2.1.9 {
execsql {
DROP INDEX collate4i1;
-162
View File
@@ -1,162 +0,0 @@
# 2014 July 15
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix cursorhint
ifcapable !cursorhints {
finish_test
return
}
do_execsql_test 1.0 {
CREATE TABLE t1(a,b,c,d);
CREATE TABLE t2(x,y,z);
INSERT INTO t1(a,b) VALUES(10, 15);
INSERT INTO t1(a,b) VALUES(20, 25);
INSERT INTO t2(x,y) VALUES('ten', 'fifteen');
INSERT INTO t2(x,y) VALUES('twenty', 'twentyfive');
CREATE TABLE t3(id TEXT PRIMARY KEY, a, b, c, d) WITHOUT ROWID;
INSERT INTO t3(id,a,b,c,d) SELECT rowid, a, b, c, d FROM t1;
PRAGMA automatic_index = 0;
}
# Run EXPLAIN on $sql. Return a list of P4 values for all $opcode
# opcodes.
#
proc p4_of_opcode {db opcode sql} {
set res {}
$db eval "EXPLAIN $sql" x {
if {$x(opcode)==$opcode} {lappend res $x(p4)}
}
return $res
}
# Run EXPLAIN on $sql. Return a list of P5 values for all $opcode
# opcodes that contain regexp $comment in their comment
#
proc p5_of_opcode {db opcode comment sql} {
set res {}
$db eval "EXPLAIN $sql" x {
if {$x(opcode)==$opcode && [regexp $comment $x(comment)]} {
lappend res $x(p5)
}
}
return $res
}
# Verify that when t1 is in the outer loop and t2 is in the inner loop,
# no cursor hints occur for t1 (since it is a full table scan) but that
# each t2 access has a cursor hint based on the current t1.a value.
#
do_test 1.1 {
p4_of_opcode db CursorHint {
SELECT * FROM t1 CROSS JOIN t2 WHERE a=x
}
} {{EQ(r[1],c0)}}
do_test 1.2 {
p5_of_opcode db OpenRead . {
SELECT * FROM t1 CROSS JOIN t2 WHERE a=x
}
} {00 00}
# Do the same test the other way around.
#
do_test 2.1 {
p4_of_opcode db CursorHint {
SELECT * FROM t2 CROSS JOIN t1 WHERE a=x
}
} {{EQ(c0,r[1])}}
do_test 2.2 {
p5_of_opcode db OpenRead . {
SELECT * FROM t2 CROSS JOIN t1 WHERE a=x
}
} {00 00}
# Various expressions captured by CursorHint
#
do_test 3.1 {
p4_of_opcode db CursorHint {
SELECT * FROM t1 WHERE a=15 AND c=22 AND rowid!=98
}
} {AND(AND(EQ(c0,15),EQ(c2,22)),NE(rowid,98))}
do_test 3.2 {
p4_of_opcode db CursorHint {
SELECT * FROM t3 WHERE a<15 AND b>22 AND id!=98
}
} {AND(AND(LT(c1,15),GT(c2,22)),NE(c0,98))}
# Indexed queries
#
do_test 4.1asc {
db eval {
CREATE INDEX t1bc ON t1(b,c);
CREATE INDEX t2yz ON t2(y,z);
}
p4_of_opcode db CursorHint {
SELECT * FROM t1 WHERE b>11 ORDER BY b ASC;
}
} {}
do_test 4.1desc {
p4_of_opcode db CursorHint {
SELECT * FROM t1 WHERE b>11 ORDER BY b DESC;
}
} {GT(c0,11)}
do_test 4.2 {
p5_of_opcode db OpenRead . {
SELECT * FROM t1 WHERE b>11;
}
} {02 00}
do_test 4.3asc {
p4_of_opcode db CursorHint {
SELECT c FROM t1 WHERE b<11 ORDER BY b ASC;
}
} {LT(c0,11)}
do_test 4.3desc {
p4_of_opcode db CursorHint {
SELECT c FROM t1 WHERE b<11 ORDER BY b DESC;
}
} {}
do_test 4.4 {
p5_of_opcode db OpenRead . {
SELECT c FROM t1 WHERE b<11;
}
} {00}
do_test 4.5asc {
p4_of_opcode db CursorHint {
SELECT c FROM t1 WHERE b>=10 AND b<=20 ORDER BY b ASC;
}
} {LE(c0,20)}
do_test 4.5desc {
p4_of_opcode db CursorHint {
SELECT c FROM t1 WHERE b>=10 AND b<=20 ORDER BY b DESC;
}
} {GE(c0,10)}
# If there are any equality terms used in the constraint, then all terms
# should be hinted.
#
do_test 4.6asc {
p4_of_opcode db CursorHint {
SELECT rowid FROM t1 WHERE b=22 AND c>=10 AND c<=20 ORDER BY b,c ASC;
}
} {AND(AND(EQ(c0,22),GE(c1,10)),LE(c1,20))}
do_test 4.6desc {
p4_of_opcode db CursorHint {
SELECT rowid FROM t1 WHERE b=22 AND c>=10 AND c<=20 ORDER BY b,c DESC;
}
} {AND(AND(EQ(c0,22),GE(c1,10)),LE(c1,20))}
finish_test
-2
View File
@@ -26,9 +26,7 @@ proc parse_uri {uri} {
set DB [sqlite3_open_v2 $uri {
SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_WAL
} tvfs]
set fileName [sqlite3_db_filename $DB main]
sqlite3_close $DB
forcedelete $fileName
tvfs delete
tvfs2 delete
-130
View File
@@ -1,130 +0,0 @@
# 2001 September 15
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the SELECT statement.
#
# $Id: select1.test,v 1.70 2009/05/28 01:00:56 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix fordelete
# This function returns a list of the tables or indexes opened with
# OP_OpenWrite instructions when the SQL statement passed as the only
# argument is executed. If the OPFLAG_FORDELETE flag is specified on
# the OP_OpenWrite, an asterix is appended to the object name. The list
# is sorted in [lsort] order before it is returned.
#
proc analyze_delete_program {sql} {
# Build a map from root page to table/index name.
db eval {
SELECT name, rootpage FROM sqlite_master
} {
set T($rootpage) $name
}
# Calculate the results.
set res [list]
db eval "EXPLAIN $sql" R {
if {$R(opcode) == "OpenWrite"} {
set obj $T($R(p2))
if {"0x$R(p5)" & 0x08} { append obj *}
lappend res $obj
}
}
lsort $res
}
proc do_adp_test {tn sql res} {
uplevel [list do_test $tn [list analyze_delete_program $sql] [list {*}$res]]
}
do_execsql_test 1.0 {
CREATE TABLE t1(a PRIMARY KEY, b);
}
foreach {tn sql res} {
1 { DELETE FROM t1 WHERE a=?} { sqlite_autoindex_t1_1 t1* }
2 { DELETE FROM t1 WHERE a=? AND b=? } { sqlite_autoindex_t1_1 t1 }
3 { DELETE FROM t1 WHERE a>? } { sqlite_autoindex_t1_1 t1* }
4 { DELETE FROM t1 WHERE rowid=? } { sqlite_autoindex_t1_1* t1 }
} {
do_adp_test 1.$tn $sql $res
}
do_execsql_test 2.0 {
CREATE TABLE t2(a, b, c);
CREATE INDEX t2a ON t2(a);
CREATE INDEX t2b ON t2(b);
CREATE INDEX t2c ON t2(c);
}
foreach {tn sql res} {
1 { DELETE FROM t2 WHERE a=?} { t2* t2a t2b* t2c* }
2 { DELETE FROM t2 WHERE a=? AND +b=?} { t2 t2a t2b* t2c* }
3 { DELETE FROM t2 WHERE a=? OR b=?} { t2 t2a* t2b* t2c* }
4 { DELETE FROM t2 WHERE +a=? } { t2 t2a* t2b* t2c* }
5 { DELETE FROM t2 WHERE rowid=? } { t2 t2a* t2b* t2c* }
} {
do_adp_test 2.$tn $sql $res
}
#-------------------------------------------------------------------------
# Test that a record that consists of the bytes:
#
# 0x01 0x00
#
# is interpreted by OP_Column as a vector of NULL values (assuming the
# default column values are NULL). Also test that:
#
# 0x00
#
# is handled in the same way.
#
do_execsql_test 3.0 {
CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c, d);
CREATE TABLE x2(a INTEGER PRIMARY KEY, b, c, d);
}
do_test 3.1 {
set root [db one { SELECT rootpage FROM sqlite_master WHERE name = 'x1' }]
db eval {
BEGIN IMMEDIATE;
}
set bt [btree_from_db db]
set csr [btree_cursor $bt $root 1]
btree_insert $csr 5 "\000"
btree_close_cursor $csr
db eval { COMMIT }
db eval {
SELECT * FROM x1;
}
} {5 {} {} {}}
do_test 3.2 {
set root [db one { SELECT rootpage FROM sqlite_master WHERE name = 'x2' }]
db eval {
BEGIN IMMEDIATE;
}
set bt [btree_from_db db]
set csr [btree_cursor $bt $root 1]
btree_insert $csr 6 "\000"
btree_close_cursor $csr
db eval { COMMIT }
db eval {
SELECT * FROM x2;
}
} {6 {} {} {}}
finish_test
+3 -6
View File
@@ -70,9 +70,6 @@
#include <stdarg.h>
#include <ctype.h>
#include "sqlite3.h"
#define ISSPACE(X) isspace((unsigned char)(X))
#define ISDIGIT(X) isdigit((unsigned char)(X))
#ifdef __unix__
# include <signal.h>
@@ -636,9 +633,9 @@ static void runSql(sqlite3 *db, const char *zSql, unsigned runFlags){
if( runFlags & SQL_TRACE ){
const char *z = zSql;
int n;
while( z<zMore && ISSPACE(z[0]) ) z++;
while( z<zMore && isspace(z[0]) ) z++;
n = (int)(zMore - z);
while( n>0 && ISSPACE(z[n-1]) ) n--;
while( n>0 && isspace(z[n-1]) ) n--;
if( n==0 ) break;
if( pStmt==0 ){
printf("TRACE: %.*s (error: %s)\n", n, z, sqlite3_errmsg(db));
@@ -760,7 +757,7 @@ static int integerValue(const char *zArg){
zArg++;
}
}else{
while( ISDIGIT(zArg[0]) ){
while( isdigit(zArg[0]) ){
v = v*10 + zArg[0] - '0';
zArg++;
}
-56
View File
@@ -1,56 +0,0 @@
# 2015-11-06
#
# 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.
#
#***********************************************************************
#
# Tests of the iee754 extension
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
load_static_extension db ieee754
foreach {id float rep} {
1 1.0 1,0
2 2.0 2,0
3 0.5 1,-1
4 1.5 3,-1
5 0.0 0,-1075
6 4.9406564584124654e-324 4503599627370497,-1075
7 2.2250738585072009e-308 9007199254740991,-1075
8 2.2250738585072014e-308 1,-1022
} {
do_test ieee754-100-$id-1 {
db eval "SELECT ieee754($float);"
} "ieee754($rep)"
do_test ieee754-100-$id-2 {
db eval "SELECT ieee754($rep)==$float;"
} {1}
if {$float!=0.0} {
do_test ieee754-100-$id-3 {
db eval "SELECT ieee754(-$float);"
} "ieee754(-$rep)"
do_test ieee754-100-$id-4 {
db eval "SELECT ieee754(-$rep)==-$float;"
} {1}
}
}
do_execsql_test ieee754-110 {
SELECT ieee754(1,1024), ieee754(4503599627370495,972);
} {Inf 1.79769313486232e+308}
do_execsql_test ieee754-111 {
SELECT ieee754(-1,1024), ieee754(-4503599627370495,972);
} {-Inf -1.79769313486232e+308}
do_execsql_test ieee754-112 {
SELECT ieee754(4503599627370495,973) is null;
} {1}
finish_test
-15
View File
@@ -62,21 +62,6 @@ do_execsql_test index3-2.2eqp {
EXPLAIN QUERY PLAN
SELECT a FROM t1 WHERE b='ab005xy' COLLATE nocase;
} {/USING INDEX/}
do_execsql_test index3-2.3 {
SELECT name FROM sqlite_master WHERE tbl_name='t1' ORDER BY name
} {sqlite_autoindex_t1_1 sqlite_autoindex_t1_2 t1 t1c t1d}
do_execsql_test index3-2.4 {
CREATE TABLE t2a(a integer, b, PRIMARY KEY(a));
CREATE TABLE t2b("a" integer, b, PRIMARY KEY("a"));
CREATE TABLE t2c([a] integer, b, PRIMARY KEY([a]));
CREATE TABLE t2d('a' integer, b, PRIMARY KEY('a'));
}
do_execsql_test index3-2.5 {
SELECT name FROM sqlite_master WHERE tbl_name LIKE 't2_' ORDER BY name
} {t2a t2b t2c t2d}
# This test corrupts the database file so it must be the last test
-17
View File
@@ -324,22 +324,5 @@ do_execsql_test json-6.4 {
SELECT json_valid('["a",55,"b",72]');
} {1}
# White-space tests. Note that form-feed is not white-space in JSON.
# ticket [57eec374ae1d0a1d4a23077a95f4e173fe269113]
#
foreach {tn isvalid ws} {
7.1 1 char(0x20)
7.2 1 char(0x09)
7.3 1 char(0x0A)
7.4 1 char(0x0D)
7.5 0 char(0x0C)
7.6 1 char(0x20,0x09,0x0a,0x0d,0x20)
7.7 0 char(0x20,0x09,0x0a,0x0c,0x0d,0x20)
} {
do_execsql_test json-$tn.1 \
"SELECT json_valid(printf('%s{%s\"x\"%s:%s9%s}%s',
$::ws,$::ws,$::ws,$::ws,$::ws,$::ws));" \
$isvalid
}
finish_test
-79
View File
@@ -1,79 +0,0 @@
# 2015-11-05
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements tests for indexes on large numeric values.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Test cases from Zsbán Ambrus:
#
do_execsql_test numindex1-1.1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
CREATE INDEX t1b ON t1(b);
INSERT INTO t1(a,b) VALUES(100, 356282677878746339);
INSERT INTO t1(a,b) VALUES(50, 356282677878746339.0);
INSERT INTO t1(a,b) VALUES(0, 356282677878746340);
DELETE FROM t1 WHERE a=50;
PRAGMA integrity_check;
} {ok}
do_execsql_test numindex1-1.2 {
CREATE TABLE t2(a,b);
INSERT INTO t2(a,b) VALUES('b', 1<<58),
('c', (1<<58)+1e-7), ('d', (1<<58)+1);
SELECT a, b, typeof(b), '|' FROM t2 ORDER BY +a;
} {b 288230376151711744 integer | c 2.88230376151712e+17 real | d 288230376151711745 integer |}
do_execsql_test numindex1-1.3 {
SELECT x.a || CASE WHEN x.b==y.b THEN '==' ELSE '<>' END || y.a
FROM t2 AS x, t2 AS y
ORDER BY +x.a, +x.b;
} {b==b b==c b<>d c==b c==c c<>d d<>b d<>c d==d}
# New test cases
#
do_execsql_test numindex1-2.1 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a INTEGER PRIMARY KEY,b);
CREATE INDEX t1b ON t1(b);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
INSERT INTO t1(a,b) SELECT x, 10000000000000004.0 FROM c
WHERE x NOT IN (23,37);
INSERT INTO t1(a,b) VALUES(23,10000000000000005);
INSERT INTO t1(a,b) VALUES(37,10000000000000003);
DELETE FROM t1 WHERE a NOT IN (23,37);
PRAGMA integrity_check;
} {ok}
do_execsql_test numindex1-3.1 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a INTEGER PRIMARY KEY,b);
CREATE INDEX t1b ON t1(b);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<20)
INSERT INTO t1(a,b) SELECT x, 100000000000000005.0
FROM c WHERE x NOT IN (3,5,7,11,13,17,19);
INSERT INTO t1(a,b) VALUES(3,100000000000000005);
INSERT INTO t1(a,b) VALUES(5,100000000000000000);
INSERT INTO t1(a,b) VALUES(7,100000000000000008);
INSERT INTO t1(a,b) VALUES(11,100000000000000006);
INSERT INTO t1(a,b) VALUES(13,100000000000000001);
INSERT INTO t1(a,b) VALUES(17,100000000000000004);
INSERT INTO t1(a,b) VALUES(19,100000000000000003);
PRAGMA integrity_check;
} {ok}
do_execsql_test numindex1-3.2 {
SELECT a FROM t1 ORDER BY b;
} {1 2 4 5 6 8 9 10 12 14 15 16 18 20 13 19 17 3 11 7}
finish_test
+1 -3
View File
@@ -93,9 +93,7 @@ do_test 1.4.1 {
list [catch { sqlite3 dbh /root/test.db } msg] $msg
} {1 {unable to open database file}}
do_re_test 1.4.2 {
lindex $::log 0
} {^os_unix.c:\d*: \(\d+\) (open|readlink)\(.*test.db\) - }
do_re_test 1.4.2 { lindex $::log 0 } {^os_unix.c:\d*: \(\d+\) open\(.*test.db\) - }
#--------------------------------------------------------------------------
# Tests oserror-1.* test failures in the unlink() system call.
+3 -3
View File
@@ -178,7 +178,7 @@ test_suite "valgrind" -prefix "" -description {
} -files [
test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test \
shell*.test crash8.test atof1.test selectG.test \
tkt-fc62af4523.test numindex1.test
tkt-fc62af4523.test
] -initialize {
set ::G(valgrind) 1
} -shutdown {
@@ -707,7 +707,7 @@ test_suite "inmemory_journal" -description {
pragma journal_mode = 'memory'
} -files [test_set $::allquicktests -exclude {
# Exclude all tests that simulate IO errors.
autovacuum_ioerr2.test cffault.test incrvacuum_ioerr.test ioerr.test
autovacuum_ioerr2.test incrvacuum_ioerr.test ioerr.test
ioerr.test ioerr2.test ioerr3.test ioerr4.test ioerr5.test
vacuum3.test incrblob_err.test diskfull.test backup_ioerr.test
e_fts3.test fts3cov.test fts3malloc.test fts3rnd.test
@@ -723,7 +723,7 @@ test_suite "inmemory_journal" -description {
corrupt5.test corruptA.test pageropt.test
# Exclude stmt.test, which expects sub-journals to use temporary files.
stmt.test symlink.test
stmt.test
zerodamage.test
+76 -282
View File
@@ -19,8 +19,6 @@ optional) are:
--dryrun (Print what would have happened)
--info (Show diagnostic info)
--with-tcl=DIR (Use TCL build at DIR)
--jobs N (Use N processes - default 1)
--progress (Show progress messages)
The default value for --srcdir is the parent of the directory holding
this script.
@@ -34,12 +32,6 @@ Every test begins with a fresh run of the configure script at the top
of the SQLite source tree.
}
# Return a timestamp of the form HH:MM:SS
#
proc now {} {
return [clock format [clock seconds] -format %H:%M:%S]
}
# Omit comments (text between # and \n) in a long multi-line string.
#
proc strip_comments {in} {
@@ -128,7 +120,6 @@ array set ::Configs [strip_comments {
-DSQLITE_ENABLE_STAT4
-DSQLITE_ENABLE_RBU
-DSQLITE_MAX_ATTACHED=125
-DLONGDOUBLE_TYPE=double
}
"Device-One" {
-O2
@@ -232,7 +223,6 @@ array set ::Configs [strip_comments {
array set ::Platforms [strip_comments {
Linux-x86_64 {
"Check-Symbols" checksymbols
"Fast-One" fuzztest
"Debug-One" "mptest test"
"Have-Not" test
"Secure-Delete" test
@@ -243,9 +233,10 @@ array set ::Platforms [strip_comments {
"No-lookaside" test
"Devkit" test
"Sanitize" {QUICKTEST_OMIT=func4.test,nan.test test}
"Device-One" fulltest
"Default" "threadtest fulltest"
"Fast-One" fuzztest
"Valgrind" valgrindtest
"Default" "threadtest fulltest"
"Device-One" fulltest
}
Linux-i686 {
"Devkit" test
@@ -266,12 +257,12 @@ array set ::Platforms [strip_comments {
"OS-X" "threadtest fulltest"
}
"Windows NT-intel" {
"Have-Not" test
"Default" "mptest fulltestonly"
"Have-Not" test
}
"Windows NT-amd64" {
"Have-Not" test
"Default" "mptest fulltestonly"
"Have-Not" test
}
# The Failure-Detection platform runs various tests that deliberately
@@ -294,9 +285,6 @@ array set ::Platforms [strip_comments {
#########################################################################
#########################################################################
# Configuration verification: Check that each entry in the list of configs
# specified for each platforms exists.
#
foreach {key value} [array get ::Platforms] {
foreach {v t} $value {
if {0==[info exists ::Configs($v)]} {
@@ -384,8 +372,9 @@ proc count_tests_and_errors {logfile rcVar errmsgVar} {
}
close $fd
if {$::BUILDONLY} {
incr ::NTESTCASE
if {$rc!=0} {
if {$rc==0} {
set errmsg "Build complete"
} else {
set errmsg "Build failed"
}
} elseif {!$seen} {
@@ -397,169 +386,12 @@ proc count_tests_and_errors {logfile rcVar errmsgVar} {
}
}
#--------------------------------------------------------------------------
# This command is invoked as the [main] routine for scripts run with the
# "--slave" option.
#
# For each test (i.e. "configure && make test" execution), the master
# process spawns a process with the --slave option. It writes two lines
# to the slaves stdin. The first contains a single boolean value - the
# value of ::TRACE to use in the slave script. The second line contains a
# list in the same format as each element of the list passed to the
# [run_all_test_suites] command in the master process.
#
# The slave then runs the "configure && make test" commands specified. It
# exits successfully if the tests passes, or with a non-zero error code
# otherwise.
#
proc run_slave_test {} {
# Read global vars configuration from stdin.
set V [gets stdin]
foreach {::TRACE ::MSVC ::DRYRUN} $V {}
# Read the test-suite configuration from stdin.
set T [gets stdin]
foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}
# Create and switch to the test directory.
trace_cmd file mkdir $dir
trace_cmd cd $dir
catch {file delete core}
catch {file delete test.log}
# Run the "./configure && make" commands.
set rc 0
set rc [catch [configureCommand $configOpts]]
if {!$rc} {
if {[info exists ::env(TCLSH_CMD)]} {
set savedEnv(TCLSH_CMD) $::env(TCLSH_CMD)
} else {
unset -nocomplain savedEnv(TCLSH_CMD)
}
set ::env(TCLSH_CMD) [file nativename [info nameofexecutable]]
set rc [catch [makeCommand $testtarget $makeOpts $cflags $opts]]
if {[info exists savedEnv(TCLSH_CMD)]} {
set ::env(TCLSH_CMD) $savedEnv(TCLSH_CMD)
} else {
unset -nocomplain ::env(TCLSH_CMD)
}
}
# Exis successfully if the test passed, or with a non-zero error code
# otherwise.
exit $rc
}
# This command is invoked in the master process each time a slave
# file-descriptor is readable.
#
proc slave_fileevent {fd T tm1} {
global G
foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}
if {[eof $fd]} {
fconfigure $fd -blocking 1
set rc [catch { close $fd }]
set errmsg {}
set logfile [file join $dir test.log]
if {[file exists $logfile]} {
count_tests_and_errors [file join $dir test.log] rc errmsg
} elseif {$rc==0 && !$::DRYRUN} {
set rc 1
set errmsg "no test.log file..."
}
if {!$::TRACE} {
set tm2 [clock seconds]
set hours [expr {($tm2-$tm1)/3600}]
set minutes [expr {(($tm2-$tm1)/60)%60}]
set seconds [expr {($tm2-$tm1)%60}]
set tm [format (%02d:%02d:%02d) $hours $minutes $seconds]
if {$rc} {
set status FAIL
incr ::NERR
} else {
set status Ok
}
set n [string length $title]
if {$::PROGRESS_MSGS} {
PUTS "finished: ${title}[string repeat . [expr {53-$n}]] $status $tm"
} else {
PUTS "${title}[string repeat . [expr {63-$n}]] $status $tm"
}
if {$errmsg!=""} {PUTS " $errmsg"}
flush stdout
}
incr G(nJob) -1
} else {
set line [gets $fd]
if {[string trim $line] != ""} {
puts "Trace : $title - \"$line\""
}
}
}
#--------------------------------------------------------------------------
# The only argument passed to this function is a list of test-suites to
# run. Each "test-suite" is itself a list consisting of the following
# elements:
#
# * Test title (for display).
# * The name of the directory to run the test in.
# * The argument for [configureCommand]
# * The first argument for [makeCommand]
# * The second argument for [makeCommand]
# * The third argument for [makeCommand]
#
proc run_all_test_suites {alltests} {
global G
set tests $alltests
set G(nJob) 0
while {[llength $tests]>0 || $G(nJob)>0} {
if {$G(nJob)>=$::JOBS || [llength $tests]==0} {
vwait G(nJob)
}
if {[llength $tests]>0} {
set T [lindex $tests 0]
set tests [lrange $tests 1 end]
foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}
if {$::PROGRESS_MSGS && !$::TRACE} {
set n [string length $title]
PUTS "starting: ${title} at [now]"
flush stdout
}
# Run the job.
#
set tm1 [clock seconds]
incr G(nJob)
set script [file normalize [info script]]
set fd [open "|[info nameofexecutable] $script --slave" r+]
fconfigure $fd -blocking 0
fileevent $fd readable [list slave_fileevent $fd $T $tm1]
puts $fd [list $::TRACE $::MSVC $::DRYRUN]
puts $fd [list {*}$T]
flush $fd
}
}
}
proc add_test_suite {listvar name testtarget config} {
upvar $listvar alltests
proc run_test_suite {name testtarget config} {
# Tcl variable $opts is used to build up the value used to set the
# OPTS Makefile variable. Variable $cflags holds the value for
# CFLAGS. The makefile will pass OPTS to both gcc and lemon, but
# CFLAGS is only passed to gcc.
#
set makeOpts ""
set cflags [expr {$::MSVC ? "-Zi" : "-g"}]
set opts ""
set title ${name}($testtarget)
@@ -572,74 +404,67 @@ proc add_test_suite {listvar name testtarget config} {
} elseif {[regexp {^[A-Z]+=} $arg]} {
lappend testtarget $arg
} elseif {[regexp {^--(enable|disable)-} $arg]} {
if {$::MSVC} {
if {$arg eq "--disable-amalgamation"} {
lappend makeOpts USE_AMALGAMATION=0
continue
}
if {$arg eq "--disable-shared"} {
lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0
continue
}
if {$arg eq "--enable-fts5"} {
lappend opts -DSQLITE_ENABLE_FTS5
continue
}
if {$arg eq "--enable-json1"} {
lappend opts -DSQLITE_ENABLE_JSON1
continue
}
if {$arg eq "--enable-shared"} {
lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1
continue
}
}
lappend configOpts $arg
} else {
if {$::MSVC} {
if {$arg eq "-g"} {
lappend cflags -Zi
continue
}
if {[regexp -- {^-O(\d+)$} $arg all level]} then {
lappend makeOpts OPTIMIZATIONS=$level
continue
}
}
lappend cflags $arg
}
}
# Disable sync to make testing faster.
#
lappend opts -DSQLITE_NO_SYNC=1
set cflags [join $cflags " "]
set opts [join $opts " "]
append opts " -DSQLITE_NO_SYNC=1"
# Some configurations already set HAVE_USLEEP; in that case, skip it.
#
if {[lsearch -regexp $opts {^-DHAVE_USLEEP(?:=|$)}]==-1} {
lappend opts -DHAVE_USLEEP=1
}
# Add the define for this platform.
#
if {$::tcl_platform(platform)=="windows"} {
lappend opts -DSQLITE_OS_WIN=1
} else {
lappend opts -DSQLITE_OS_UNIX=1
if {![regexp { -DHAVE_USLEEP$} $opts]
&& ![regexp { -DHAVE_USLEEP[ =]+} $opts]} {
append opts " -DHAVE_USLEEP=1"
}
# Set the sub-directory to use.
#
set dir [string tolower [string map {- _ " " _} $name]]
# Join option lists into strings, using space as delimiter.
#
set makeOpts [join $makeOpts " "]
set cflags [join $cflags " "]
set opts [join $opts " "]
if {$::tcl_platform(platform)=="windows"} {
append opts " -DSQLITE_OS_WIN=1"
} else {
append opts " -DSQLITE_OS_UNIX=1"
}
lappend alltests [list \
$title $dir $configOpts $testtarget $makeOpts $cflags $opts]
if {!$::TRACE} {
set n [string length $title]
PUTS -nonewline "${title}[string repeat . [expr {63-$n}]]"
flush stdout
}
set rc 0
set tm1 [clock seconds]
set origdir [pwd]
trace_cmd file mkdir $dir
trace_cmd cd $dir
set errmsg {}
catch {file delete core}
set rc [catch [configureCommand $configOpts]]
if {!$rc} {
set rc [catch [makeCommand $testtarget $cflags $opts]]
count_tests_and_errors test.log rc errmsg
}
trace_cmd cd $origdir
set tm2 [clock seconds]
if {!$::TRACE} {
set hours [expr {($tm2-$tm1)/3600}]
set minutes [expr {(($tm2-$tm1)/60)%60}]
set seconds [expr {($tm2-$tm1)%60}]
set tm [format (%02d:%02d:%02d) $hours $minutes $seconds]
if {$rc} {
PUTS " FAIL $tm"
incr ::NERR
} else {
PUTS " Ok $tm"
}
if {$errmsg!=""} {PUTS " $errmsg"}
}
}
# The following procedure returns the "configure" command to be exectued for
@@ -659,19 +484,15 @@ proc configureCommand {opts} {
# The following procedure returns the "make" command to be executed for the
# specified targets, compiler flags, and options.
#
proc makeCommand { targets makeOpts cflags opts } {
proc makeCommand { targets cflags opts } {
set result [list trace_cmd exec]
if {$::MSVC} {
set nmakeDir [file nativename $::SRCDIR]
set nmakeFile [file nativename [file join $nmakeDir Makefile.msc]]
lappend result nmake /f $nmakeFile TOP=$nmakeDir
set nmakeFile [file join $nmakeDir Makefile.msc]
lappend result nmake /f $nmakeFile TOP=$nmakeDir clean
} else {
lappend result make
lappend result make clean
}
foreach makeOpt $makeOpts {
lappend result $makeOpt
}
lappend result clean
foreach target $targets {
lappend result $target
}
@@ -686,11 +507,9 @@ proc trace_cmd {args} {
if {$::TRACE} {
PUTS $args
}
set res ""
if {!$::DRYRUN} {
set res [uplevel 1 $args]
uplevel 1 $args
}
return $res
}
@@ -701,14 +520,13 @@ proc trace_cmd {args} {
#
proc process_options {argv} {
set ::SRCDIR [file normalize [file dirname [file dirname $::argv0]]]
set ::QUICK 0
set ::MSVC 0
set ::BUILDONLY 0
set ::DRYRUN 0
set ::TRACE 0
set ::JOBS 1
set ::PROGRESS_MSGS 0
set ::WITHTCL {}
set ::QUICK 0
set ::MSVC 0
set ::BUILDONLY 0
set ::DRYRUN 0
set ::EXEC exec
set ::TRACE 0
set ::WITHTCL {}
set config {}
set platform $::tcl_platform(os)-$::tcl_platform(machine)
@@ -716,11 +534,6 @@ proc process_options {argv} {
set x [lindex $argv $i]
if {[regexp {^--[a-z]} $x]} {set x [string range $x 1 end]}
switch -glob -- $x {
-slave {
run_slave_test
exit
}
-srcdir {
incr i
set ::SRCDIR [file normalize [lindex $argv $i]]
@@ -731,15 +544,6 @@ proc process_options {argv} {
set platform [lindex $argv $i]
}
-jobs {
incr i
set ::JOBS [lindex $argv $i]
}
-progress {
set ::PROGRESS_MSGS 1
}
-quick {
set ::QUICK 1
}
@@ -793,7 +597,11 @@ proc process_options {argv} {
}
-g {
lappend ::EXTRACONFIG [lindex $argv $i]
if {$::MSVC} {
lappend ::EXTRACONFIG -Zi
} else {
lappend ::EXTRACONFIG [lindex $argv $i]
}
}
-with-tcl=* {
@@ -832,20 +640,11 @@ proc process_options {argv} {
if {[llength $config]==1} {lappend config fulltest}
set ::CONFIGLIST $config
} else {
if {$::JOBS>1} {
set ::CONFIGLIST {}
foreach {target zConfig} [lreverse $::Platforms($platform)] {
append ::CONFIGLIST [format " %-25s %s\n" \
[list $zConfig] [list $target]]
}
} else {
set ::CONFIGLIST $::Platforms($platform)
}
set ::CONFIGLIST $::Platforms($platform)
}
PUTS "Running the following test configurations for $platform:"
PUTS " [string trim $::CONFIGLIST]"
PUTS -nonewline "Flags:"
if {$::PROGRESS_MSGS} {PUTS -nonewline " --progress"}
if {$::DRYRUN} {PUTS -nonewline " --dryrun"}
if {$::BUILDONLY} {PUTS -nonewline " --buildonly"}
if {$::MSVC} {PUTS -nonewline " --msvc"}
@@ -853,7 +652,6 @@ proc process_options {argv} {
1 {PUTS -nonewline " --quick"}
2 {PUTS -nonewline " --veryquick"}
}
if {$::JOBS>1} {PUTS -nonewline " --jobs $::JOBS"}
PUTS ""
}
@@ -885,15 +683,13 @@ proc main {argv} {
}
if {$::BUILDONLY} {
set target testfixture
if {$::tcl_platform(platform)=="windows"} {
append target .exe
}
if {$::MSVC} {append target .exe}
}
}
set config_options [concat $::Configs($zConfig) $::EXTRACONFIG]
incr NTEST
add_test_suite all $zConfig $target $config_options
run_test_suite $zConfig $target $config_options
# If the configuration included the SQLITE_DEBUG option, then remove
# it and run veryquick.test. If it did not include the SQLITE_DEBUG option
@@ -907,18 +703,16 @@ proc main {argv} {
if {$debug_idx < 0} {
incr NTEST
append config_options " -DSQLITE_DEBUG=1"
add_test_suite all "${zConfig}_debug" $xtarget $config_options
run_test_suite "${zConfig}_debug" $xtarget $config_options
} else {
incr NTEST
regsub { *-DSQLITE_MEMDEBUG[^ ]* *} $config_options { } config_options
regsub { *-DSQLITE_DEBUG[^ ]* *} $config_options { } config_options
add_test_suite all "${zConfig}_ndebug" $xtarget $config_options
run_test_suite "${zConfig}_ndebug" $xtarget $config_options
}
}
}
run_all_test_suites $all
set elapsetime [expr {[clock seconds]-$STARTTIME}]
set hr [expr {$elapsetime/3600}]
set min [expr {($elapsetime/60)%60}]
+2 -4
View File
@@ -47,8 +47,6 @@ static const char zHelp[] =
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#define ISSPACE(X) isspace((unsigned char)(X))
#define ISDIGIT(X) isdigit((unsigned char)(X))
#if SQLITE_VERSION_NUMBER<3005000
# define sqlite3_int64 sqlite_int64
@@ -317,7 +315,7 @@ void speedtest1_final(void){
/* Print an SQL statement to standard output */
static void printSql(const char *zSql){
int n = (int)strlen(zSql);
while( n>0 && (zSql[n-1]==';' || ISSPACE(zSql[n-1])) ){ n--; }
while( n>0 && (zSql[n-1]==';' || isspace(zSql[n-1])) ){ n--; }
if( g.bExplain ) printf("EXPLAIN ");
printf("%.*s;\n", n, zSql);
if( g.bExplain
@@ -416,7 +414,7 @@ void speedtest1_run(void){
/* The sqlite3_trace() callback function */
static void traceCallback(void *NotUsed, const char *zSql){
int n = (int)strlen(zSql);
while( n>0 && (zSql[n-1]==';' || ISSPACE(zSql[n-1])) ) n--;
while( n>0 && (zSql[n-1]==';' || isspace(zSql[n-1])) ) n--;
fprintf(stderr,"%.*s;\n", n, zSql);
}
-119
View File
@@ -1,119 +0,0 @@
# 2015 October 31
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing that SQLite can follow symbolic links.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix symlink
# This only runs on unix.
if {$::tcl_platform(platform)!="unix"} {
finish_test
return
}
# Ensure that test.db has been created.
#
do_execsql_test 1.0 {
CREATE TABLE t1(x, y);
}
# Test that SQLite follows symlinks when opening files.
#
forcedelete test.db2
do_test 1.1 {
file link test.db2 test.db
sqlite3 db2 test.db2
sqlite3_db_filename db2 main
} [file join [pwd] test.db]
# Test that if the symlink points to a file that does not exists, it is
# created when it is opened.
#
do_test 1.2.1 {
db2 close
db close
forcedelete test.db
file exists test.db
} 0
do_test 1.2.2 {
sqlite3 db2 test.db2
file exists test.db
} 1
do_test 1.2.3 {
sqlite3_db_filename db2 main
} [file join [pwd] test.db]
db2 close
# Test that a loop of symlinks cannot be opened.
#
do_test 1.3 {
forcedelete test.db
# Note: Tcl [file link] command is too smart to create loops of symlinks.
exec ln -s test.db2 test.db
list [catch { sqlite3 db test.db } msg] $msg
} {1 {unable to open database file}}
# Test that overly large paths cannot be opened.
#
do_test 1.4 {
set name "test.db[string repeat x 502]"
list [catch { sqlite3 db $name } msg] $msg
} {1 {unable to open database file}}
do_test 1.5 {
set r [expr 510 - [string length test.db] - [string length [pwd]]]
set name "test.db[string repeat x $r]"
list [catch { sqlite3 db $name } msg] $msg
} {1 {unable to open database file}}
#-------------------------------------------------------------------------
# Test that journal and wal files are created next to the real file,
# not the symlink.
#
do_test 2.0 {
catch { db close }
catch { db2 close }
forcedelete test.db test.db2
sqlite3 db test.db
execsql { CREATE TABLE t1(x) }
file link test.db2 test.db
sqlite3 db2 test.db2
file exists test.db-journal
} 0
do_test 2.1 {
execsql {
BEGIN;
INSERT INTO t1 VALUES(1);
} db2
file exists test.db-journal
} 1
do_test 2.2 {
file exists test.db2-journal
} 0
do_test 2.3 {
execsql {
COMMIT;
PRAGMA journal_mode = wal;
INSERT INTO t1 VALUES(2);
} db2
file exists test.db-wal
} 1
do_test 2.4 {
file exists test.db2-wal
} 0
do_execsql_test 2.5 {
SELECT * FROM t1;
} {1 2}
finish_test
+1 -1
View File
@@ -61,7 +61,7 @@ foreach s {
fcntl read pread write pwrite fchmod fallocate
pread64 pwrite64 unlink openDirectory mkdir rmdir
statvfs fchown umask mmap munmap mremap
getpagesize readlink
getpagesize
} {
if {[test_syscall exists $s]} {lappend syscall_list $s}
}
+8 -8
View File
@@ -412,22 +412,22 @@ ifcapable subquery {
count {
SELECT * FROM t1 WHERE w IN (-1,1,2,3) order by 1;
}
} {1 0 4 2 1 9 3 1 16 12}
} {1 0 4 2 1 9 3 1 16 13}
do_test where-5.3b {
count {
SELECT * FROM t1 WHERE w IN (3,-1,1,2) order by 1;
}
} {1 0 4 2 1 9 3 1 16 12}
} {1 0 4 2 1 9 3 1 16 13}
do_test where-5.3c {
count {
SELECT * FROM t1 WHERE w IN (3,2,-1,1,2) order by 1;
}
} {1 0 4 2 1 9 3 1 16 12}
} {1 0 4 2 1 9 3 1 16 13}
do_test where-5.3d {
count {
SELECT * FROM t1 WHERE w IN (-1,1,2,3) order by 1 DESC;
}
} {3 1 16 2 1 9 1 0 4 11}
} {3 1 16 2 1 9 1 0 4 12}
do_test where-5.4 {
count {
SELECT * FROM t1 WHERE w+0 IN (-1,1,2,3) order by 1;
@@ -465,7 +465,7 @@ ifcapable subquery {
count {
SELECT * FROM t1 WHERE x IN (1,7) ORDER BY 1;
}
} {2 1 9 3 1 16 6}
} {2 1 9 3 1 16 7}
do_test where-5.10 {
count {
SELECT * FROM t1 WHERE x+0 IN (1,7) ORDER BY 1;
@@ -485,17 +485,17 @@ ifcapable subquery {
count {
SELECT * FROM t1 WHERE x IN (1,7) AND y NOT IN (6400,8100) ORDER BY 1;
}
} {2 1 9 3 1 16 6}
} {2 1 9 3 1 16 7}
do_test where-5.14 {
count {
SELECT * FROM t1 WHERE x IN (1,7) AND y IN (9,10) ORDER BY 1;
}
} {2 1 9 5}
} {2 1 9 8}
do_test where-5.15 {
count {
SELECT * FROM t1 WHERE x IN (1,7) AND y IN (9,16) ORDER BY 1;
}
} {2 1 9 3 1 16 9}
} {2 1 9 3 1 16 11}
do_test where-5.100 {
db eval {
SELECT w, x, y FROM t1 WHERE x IN (1,5) AND y IN (9,8,3025,1000,3969)
+1 -1
View File
@@ -91,7 +91,7 @@ do_test where4-1.10 {
} {6 2}
do_test where4-1.11 {
count {SELECT rowid FROM t1 WHERE w=x'78' AND x IS NULL AND y=123}
} {0}
} {1}
do_test where4-1.12 {
count {SELECT rowid FROM t1 WHERE w=x'78' AND x IS NULL AND y=x'7A'}
} {6 2}

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