Merge recent enhancements from trunk.
FossilOrigin-Name: f6c9273cab877b8b6b327250195f3392393d060a
This commit is contained in:
+1
-1
@@ -1169,7 +1169,7 @@ THREADTEST3_SRC = $(TOP)/test/threadtest3.c \
|
||||
$(TOP)/test/tt3_lookaside1.c
|
||||
|
||||
threadtest3$(TEXE): sqlite3.lo $(THREADTEST3_SRC)
|
||||
$(LTLINK) $(TOP)/test/threadtest3.c sqlite3.lo -o $@ $(TLIBS)
|
||||
$(LTLINK) $(TOP)/test/threadtest3.c $(TOP)/src/test_multiplex.c sqlite3.lo -o $@ $(TLIBS)
|
||||
|
||||
threadtest: threadtest3$(TEXE)
|
||||
./threadtest3$(TEXE)
|
||||
|
||||
Vendored
-1530
File diff suppressed because it is too large
Load Diff
Vendored
-1773
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@
|
||||
#
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT(sqlite, 3.7.5, http://www.sqlite.org)
|
||||
AC_INIT(sqlite, --SQLITE-VERSION--, http://www.sqlite.org)
|
||||
AC_CONFIG_SRCDIR([sqlite3.c])
|
||||
|
||||
# Use automake.
|
||||
|
||||
@@ -1,708 +0,0 @@
|
||||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2012-03-27.16; # UTC
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
|
||||
# 2011, 2012 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by 'PROGRAMS ARGS'.
|
||||
object Object file output by 'PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputting dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
# A tabulation character.
|
||||
tab=' '
|
||||
# A newline character.
|
||||
nl='
|
||||
'
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
cygpath_u="cygpath -u -f -"
|
||||
if test "$depmode" = msvcmsys; then
|
||||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
if test "$depmode" = msvc7msys; then
|
||||
# This is just like msvc7 but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvc7
|
||||
fi
|
||||
|
||||
if test "$depmode" = xlc; then
|
||||
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations.
|
||||
gccflag=-qmakedep=gcc,-MF
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||
## the command line argument order; so add the flags where they
|
||||
## appear in depend2.am. Note that the slowdown incurred here
|
||||
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||
*) set fnord "$@" "$arg" ;;
|
||||
esac
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
done
|
||||
"$@"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say).
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
|
||||
## The second -e expression handles DOS-style file names with drive letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the "deleted header file" problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
tr ' ' "$nl" < "$tmpdepfile" |
|
||||
## Some versions of gcc put a space before the ':'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||
## to the object. Take care to not repeat it in the output.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
|
||||
tr "$nl" ' ' >> "$depfile"
|
||||
echo >> "$depfile"
|
||||
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
xlc)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
# Each line is of the form 'foo.o: dependent.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# '$object: dependent.h' and one to simply 'dependent.h:'.
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
icc)
|
||||
# Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'.
|
||||
# However on
|
||||
# $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c
|
||||
# ICC 7.0 will fill foo.d with something like
|
||||
# foo.o: sub/foo.c
|
||||
# foo.o: sub/foo.h
|
||||
# which is wrong. We want
|
||||
# sub/foo.o: sub/foo.c
|
||||
# sub/foo.o: sub/foo.h
|
||||
# sub/foo.c:
|
||||
# sub/foo.h:
|
||||
# ICC 7.1 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using '\':
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
# tcc 0.9.26 (FIXME still under development at the moment of writing)
|
||||
# will emit a similar output, but also prepend the continuation lines
|
||||
# with horizontal tabulation characters.
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form 'foo.o: dependent.h',
|
||||
# or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# '$object: dependent.h' and one to simply 'dependent.h:'.
|
||||
sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \
|
||||
< "$tmpdepfile" > "$depfile"
|
||||
sed '
|
||||
s/[ '"$tab"'][ '"$tab"']*/ /g
|
||||
s/^ *//
|
||||
s/ *\\*$//
|
||||
s/^[^:]*: *//
|
||||
/^$/d
|
||||
/:$/d
|
||||
s/$/ :/
|
||||
' < "$tmpdepfile" >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp2)
|
||||
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||
# compilers, which have integrated preprocessors. The correct option
|
||||
# to use with these is +Maked; it writes dependencies to a file named
|
||||
# 'foo.d', which lands next to the object file, wherever that
|
||||
# happens to be.
|
||||
# Much of this is similar to the tru64 case; see comments there.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir.libs/$base.d
|
||||
"$@" -Wc,+Maked
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
"$@" +Maked
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add 'dependent.h:' lines.
|
||||
sed -ne '2,${
|
||||
s/^ *//
|
||||
s/ \\*$//
|
||||
s/$/:/
|
||||
p
|
||||
}' "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in 'foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# With Tru64 cc, shared objects can also be used to make a
|
||||
# static library. This mechanism is used in libtool 1.4 series to
|
||||
# handle both shared and static libraries in a single compilation.
|
||||
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
|
||||
#
|
||||
# With libtool 1.5 this exception was removed, and libtool now
|
||||
# generates 2 separate objects for the 2 libraries. These two
|
||||
# compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
|
||||
tmpdepfile2=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
|
||||
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.o.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
tmpdepfile4=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7)
|
||||
if test "$libtool" = yes; then
|
||||
showIncludes=-Wc,-showIncludes
|
||||
else
|
||||
showIncludes=-showIncludes
|
||||
fi
|
||||
"$@" $showIncludes > "$tmpdepfile"
|
||||
stat=$?
|
||||
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||
if test "$stat" = 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The first sed program below extracts the file names and escapes
|
||||
# backslashes for cygpath. The second sed program outputs the file
|
||||
# name when reading, but also accumulates all include files in the
|
||||
# hold buffer in order to output them again at the end. This only
|
||||
# works with sed implementations that can handle large buffers.
|
||||
sed < "$tmpdepfile" -n '
|
||||
/^Note: including file: *\(.*\)/ {
|
||||
s//\1/
|
||||
s/\\/\\\\/g
|
||||
p
|
||||
}' | $cygpath_u | sort -u | sed -n '
|
||||
s/ /\\ /g
|
||||
s/\(.*\)/'"$tab"'\1 \\/p
|
||||
s/.\(.*\) \\/\1:/
|
||||
H
|
||||
$ {
|
||||
s/.*/'"$tab"'/
|
||||
G
|
||||
p
|
||||
}' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7msys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for ':'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
tr ' ' "$nl" < "$tmpdepfile" | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no eat=no
|
||||
for arg
|
||||
do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
if test $eat = yes; then
|
||||
eat=no
|
||||
continue
|
||||
fi
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-arch)
|
||||
eat=yes ;;
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
# makedepend may prepend the VPATH from the source file name to the object.
|
||||
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||
sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E |
|
||||
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
|
||||
sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E 2>/dev/null |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||
echo "$tab" >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvcmsys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
@@ -1,527 +0,0 @@
|
||||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2011-01-19.21; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
|
||||
nl='
|
||||
'
|
||||
IFS=" "" $nl"
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit=${DOITPROG-}
|
||||
if test -z "$doit"; then
|
||||
doit_exec=exec
|
||||
else
|
||||
doit_exec=$doit
|
||||
fi
|
||||
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
posix_glob='?'
|
||||
initialize_posix_glob='
|
||||
test "$posix_glob" != "?" || {
|
||||
if (set -f) 2>/dev/null; then
|
||||
posix_glob=
|
||||
else
|
||||
posix_glob=:
|
||||
fi
|
||||
}
|
||||
'
|
||||
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
stripcmd=
|
||||
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dst_arg=
|
||||
|
||||
copy_on_change=false
|
||||
no_target_directory=
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve the last data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) ;;
|
||||
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
case $mode in
|
||||
*' '* | *' '* | *'
|
||||
'* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift;;
|
||||
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-t) dst_arg=$2
|
||||
# Protect names problematic for `test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-T) no_target_directory=true;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
# Protect names problematic for `test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call `install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
do_exit='(exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names problematic for `test' and other utilities.
|
||||
case $src in
|
||||
-* | [=\(\)!]) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
dst=$dst_arg
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dst=$dstdir/`basename "$src"`
|
||||
dstdir_status=0
|
||||
else
|
||||
# Prefer dirname, but fall back on a substitute if dirname fails.
|
||||
dstdir=`
|
||||
(dirname "$dst") 2>/dev/null ||
|
||||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$dst" : 'X\(//\)[^/]' \| \
|
||||
X"$dst" : 'X\(//\)$' \| \
|
||||
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
echo X"$dst" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)[^/].*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'
|
||||
`
|
||||
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||
umask=`umask`
|
||||
case $stripcmd.$umask in
|
||||
# Optimize common cases.
|
||||
*[2367][2367]) mkdir_umask=$umask;;
|
||||
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
mkdir_umask=`expr $umask + 22 \
|
||||
- $umask % 100 % 40 + $umask % 20 \
|
||||
- $umask % 10 % 4 + $umask % 2
|
||||
`;;
|
||||
*) mkdir_umask=$umask,go-w;;
|
||||
esac
|
||||
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
posix_mkdir=false
|
||||
case $umask in
|
||||
*[123567][0-7][0-7])
|
||||
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
if (umask $mkdir_umask &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writeable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/d" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
[-=\(\)!]*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
eval "$initialize_posix_glob"
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
$posix_glob set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
$posix_glob set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test X"$d" = X && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
if $posix_mkdir; then
|
||||
(umask=$mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
|
||||
eval "$initialize_posix_glob" &&
|
||||
$posix_glob set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
$posix_glob set +f &&
|
||||
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
-9655
File diff suppressed because it is too large
Load Diff
@@ -1,331 +0,0 @@
|
||||
#! /bin/sh
|
||||
# Common stub for a few missing GNU programs while installing.
|
||||
|
||||
scriptversion=2012-01-06.13; # UTC
|
||||
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
|
||||
# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
|
||||
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run=:
|
||||
sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
|
||||
sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
|
||||
|
||||
# In the cases where this matters, `missing' is being run in the
|
||||
# srcdir already.
|
||||
if test -f configure.ac; then
|
||||
configure_ac=configure.ac
|
||||
else
|
||||
configure_ac=configure.in
|
||||
fi
|
||||
|
||||
msg="missing on your system"
|
||||
|
||||
case $1 in
|
||||
--run)
|
||||
# Try to run requested program, and just exit if it succeeds.
|
||||
run=
|
||||
shift
|
||||
"$@" && exit 0
|
||||
# Exit code 63 means version mismatch. This often happens
|
||||
# when the user try to use an ancient version of a tool on
|
||||
# a file that requires a minimum version. In this case we
|
||||
# we should proceed has if the program had been absent, or
|
||||
# if --run hadn't been passed.
|
||||
if test $? = 63; then
|
||||
run=:
|
||||
msg="probably too old"
|
||||
fi
|
||||
;;
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
|
||||
error status if there is no known handling for PROGRAM.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
--run try to run the given command, and emulate it if it fails
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal touch file \`aclocal.m4'
|
||||
autoconf touch file \`configure'
|
||||
autoheader touch file \`config.h.in'
|
||||
autom4te touch the output file, or create a stub one
|
||||
automake touch all \`Makefile.in' files
|
||||
bison create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
flex create \`lex.yy.c', if possible, from existing .c
|
||||
help2man touch the output file
|
||||
lex create \`lex.yy.c', if possible, from existing .c
|
||||
makeinfo touch the output file
|
||||
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
|
||||
Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
|
||||
\`g' are ignored when checking the name.
|
||||
|
||||
Send bug reports to <bug-automake@gnu.org>."
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing $scriptversion (GNU Automake)"
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: Unknown \`$1' option"
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# normalize program name to check for.
|
||||
program=`echo "$1" | sed '
|
||||
s/^gnu-//; t
|
||||
s/^gnu//; t
|
||||
s/^g//; t'`
|
||||
|
||||
# Now exit if we have it, but it failed. Also exit now if we
|
||||
# don't have it and --version was passed (most likely to detect
|
||||
# the program). This is about non-GNU programs, so use $1 not
|
||||
# $program.
|
||||
case $1 in
|
||||
lex*|yacc*)
|
||||
# Not GNU programs, they don't have --version.
|
||||
;;
|
||||
|
||||
*)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
# Could not run --version or --help. This is probably someone
|
||||
# running `$TOOL --version' or `$TOOL --help' to check whether
|
||||
# $TOOL exists and not knowing $TOOL uses missing.
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# If it does not exist, or fails to run (possibly an outdated version),
|
||||
# try to emulate it.
|
||||
case $program in
|
||||
aclocal*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
|
||||
to install the \`Automake' and \`Perl' packages. Grab them from
|
||||
any GNU archive site."
|
||||
touch aclocal.m4
|
||||
;;
|
||||
|
||||
autoconf*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`${configure_ac}'. You might want to install the
|
||||
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
|
||||
archive site."
|
||||
touch configure
|
||||
;;
|
||||
|
||||
autoheader*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acconfig.h' or \`${configure_ac}'. You might want
|
||||
to install the \`Autoconf' and \`GNU m4' packages. Grab them
|
||||
from any GNU archive site."
|
||||
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
|
||||
test -z "$files" && files="config.h"
|
||||
touch_files=
|
||||
for f in $files; do
|
||||
case $f in
|
||||
*:*) touch_files="$touch_files "`echo "$f" |
|
||||
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
|
||||
*) touch_files="$touch_files $f.in";;
|
||||
esac
|
||||
done
|
||||
touch $touch_files
|
||||
;;
|
||||
|
||||
automake*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
|
||||
You might want to install the \`Automake' and \`Perl' packages.
|
||||
Grab them from any GNU archive site."
|
||||
find . -type f -name Makefile.am -print |
|
||||
sed 's/\.am$/.in/' |
|
||||
while read f; do touch "$f"; done
|
||||
;;
|
||||
|
||||
autom4te*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, but is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them.
|
||||
You can get \`$1' as part of \`Autoconf' from any GNU
|
||||
archive site."
|
||||
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo "#! /bin/sh"
|
||||
echo "# Created by GNU Automake missing as a replacement of"
|
||||
echo "# $ $@"
|
||||
echo "exit 0"
|
||||
chmod +x $file
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
bison*|yacc*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' $msg. You should only need it if
|
||||
you modified a \`.y' file. You may need the \`Bison' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Bison' from any GNU archive site."
|
||||
rm -f y.tab.c y.tab.h
|
||||
if test $# -ne 1; then
|
||||
eval LASTARG=\${$#}
|
||||
case $LASTARG in
|
||||
*.y)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" y.tab.c
|
||||
fi
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" y.tab.h
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if test ! -f y.tab.h; then
|
||||
echo >y.tab.h
|
||||
fi
|
||||
if test ! -f y.tab.c; then
|
||||
echo 'main() { return 0; }' >y.tab.c
|
||||
fi
|
||||
;;
|
||||
|
||||
lex*|flex*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.l' file. You may need the \`Flex' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Flex' from any GNU archive site."
|
||||
rm -f lex.yy.c
|
||||
if test $# -ne 1; then
|
||||
eval LASTARG=\${$#}
|
||||
case $LASTARG in
|
||||
*.l)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" lex.yy.c
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if test ! -f lex.yy.c; then
|
||||
echo 'main() { return 0; }' >lex.yy.c
|
||||
fi
|
||||
;;
|
||||
|
||||
help2man*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a dependency of a manual page. You may need the
|
||||
\`Help2man' package in order for those modifications to take
|
||||
effect. You can get \`Help2man' from any GNU archive site."
|
||||
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo ".ab help2man is required to generate this page"
|
||||
exit $?
|
||||
fi
|
||||
;;
|
||||
|
||||
makeinfo*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.texi' or \`.texinfo' file, or any other file
|
||||
indirectly affecting the aspect of the manual. The spurious
|
||||
call might also be the consequence of using a buggy \`make' (AIX,
|
||||
DU, IRIX). You might want to install the \`Texinfo' package or
|
||||
the \`GNU make' package. Grab either from any GNU archive site."
|
||||
# The file to touch is that specified with -o ...
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -z "$file"; then
|
||||
# ... or it is the one specified with @setfilename ...
|
||||
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
|
||||
file=`sed -n '
|
||||
/^@setfilename/{
|
||||
s/.* \([^ ]*\) *$/\1/
|
||||
p
|
||||
q
|
||||
}' $infile`
|
||||
# ... or it is derived from the source name (dir/f.texi becomes f.info)
|
||||
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
|
||||
fi
|
||||
# If the file does not exist, the user really needs makeinfo;
|
||||
# let's fail without touching anything.
|
||||
test -f $file || exit 1
|
||||
touch $file
|
||||
;;
|
||||
|
||||
*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, and is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them. Check the \`README' file,
|
||||
it often tells you about the needed prerequisites for installing
|
||||
this package. You may also peek at any GNU archive site, in case
|
||||
some other package would contain this missing \`$1' program."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
@@ -808,8 +808,8 @@ THREADTEST3_SRC = $(TOP)/test/threadtest3.c \
|
||||
$(TOP)/test/tt3_stress.c \
|
||||
$(TOP)/test/tt3_lookaside1.c
|
||||
|
||||
threadtest3$(EXE): sqlite3.o $(THREADTEST3_SRC)
|
||||
$(TCCX) $(TOP)/test/threadtest3.c sqlite3.o -o $@ $(THREADLIB)
|
||||
threadtest3$(EXE): sqlite3.o $(THREADTEST3_SRC) $(TOP)/src/test_multiplex.c
|
||||
$(TCCX) $(TOP)/test/threadtest3.c $(TOP)/src/test_multiplex.c sqlite3.o -o $@ $(THREADLIB)
|
||||
|
||||
threadtest: threadtest3$(EXE)
|
||||
./threadtest3$(EXE)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
C Merge\srecent\senhancements\sfrom\strunk.
|
||||
D 2015-12-02T20:40:26.162
|
||||
F Makefile.in e7d3be066453d66f333e7cb98f4c9d3e700bfc09
|
||||
D 2015-12-16T19:47:54.677
|
||||
F Makefile.in 321a54f5a2843b6752b21f7bd66ce5f96444d1ab
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 820453f6340c500e2377a6ebd681cecfa92afd79
|
||||
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
|
||||
@@ -13,13 +13,7 @@ F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am 089e5ecdb5761e64ea1013ded02feb4d8b29927d
|
||||
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 9a65da17e440466f9842288163f16f9b21298129
|
||||
F autoconf/depcomp 0b26f101e3bc9fd1ff0be1da9fb4a82371142f92 x
|
||||
F autoconf/install-sh 06ee6336e63bb845c8439d777c32eb2eccc4fbf1 x
|
||||
F autoconf/ltmain.sh 7a658a24028f02331c1d2446562758083c5eadd1
|
||||
F autoconf/missing d7c9981a81af13370d4ed152b24c0a82b7028585 x
|
||||
F autoconf/configure.ac 82c628c68f0f204d57343dc345b6dbd1789fb1bd
|
||||
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
|
||||
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
|
||||
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
|
||||
@@ -283,7 +277,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 65524a49d6bbeb624b5953ed50a8c84d9dc34d16
|
||||
F main.mk 238ecdee438a8b0ff662ac9e739899cacaae668c
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -302,17 +296,17 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
||||
F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc
|
||||
F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf
|
||||
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
||||
F src/btree.c d3bdd8462a86492e2ebc9aca4a0168429017de25
|
||||
F src/btree.c 84ede51e371a11c3dbb3e24ccc5e3e99594a6c00
|
||||
F src/btree.h 2d76dee44704c47eed323356a758662724b674a0
|
||||
F src/btreeInt.h 3ab435ed27adea54d040584b0bcc488ee7db1e38
|
||||
F src/build.c e83da4d004a4e050c01acbb821ff7a7b1019c29b
|
||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
|
||||
F src/ctime.c 58eda76364fb6f374e044aa4493219b13abf9400
|
||||
F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198
|
||||
F src/date.c fb1c99172017dcc8e237339132c91a21a0788584
|
||||
F src/dbstat.c ffd63fc8ba7541476ced189b95e95d7f2bc63f78
|
||||
F src/delete.c 86e3940d07fe69a40270c2aaf6ca6c7adf19246c
|
||||
F src/expr.c cb1a419508e5b27769a91e00e36e94724e7b1d51
|
||||
F src/expr.c ccb93d7b7e1ac5d187c9b153bae145933f93ee5c
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 31900763094a3736a5fc887469202eb579fef2d0
|
||||
F src/func.c fe50a9ab977acc0bb0fcd46741e0071fa388888e
|
||||
@@ -323,9 +317,9 @@ F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 8ab83219eb56a103edb73bb0a1e9057c4d3b976b
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||
F src/loadext.c 18586e45a215325f15096821e9c082035d4fb810
|
||||
F src/main.c cf9fcb71ea8ea46ad20b37dc1af67c1a17cf73b5
|
||||
F src/malloc.c 337bbe9c7d436ef9b7d06b5dd10bbfc8f3025972
|
||||
F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b
|
||||
F src/main.c 955f7b9d30aa7c3d7c391c0717662b21c55ff371
|
||||
F src/malloc.c 8f787669e79de26efc42272b5797bc00fff527c6
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
|
||||
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
|
||||
@@ -343,33 +337,33 @@ 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 60997373a8d90bd17e1c0e49d11ef361b713439b
|
||||
F src/os_unix.c 0ca6d8710366fbb01a275160f018334cd347cbda
|
||||
F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811
|
||||
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
|
||||
F src/pager.c f92aacd5216d8815136c9e0190041783c602641a
|
||||
F src/pager.h 9153c71a89dc82a5a77e485f3929792116c70aae
|
||||
F src/pager.c 58d2593612acb6b542de6715b4af397ea1fa0a35
|
||||
F src/pager.h bf25005b4656cd805af43487c3139fca9678d0cc
|
||||
F src/parse.y 23737e649c26ce327603799e57f5c2ff50e5e6ba
|
||||
F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23
|
||||
F src/pcache.h 1ff11adce609ba7de139b6abfabaf9a2bac947b5
|
||||
F src/pcache1.c 46a110be31a8d9f9b41431733836822ca0dd27ab
|
||||
F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051
|
||||
F src/pragma.c f3e7147299ca05ef4304a36f1fd6e002729c72c6
|
||||
F src/pragma.h 3d94aebbebd2089899fecc01909bf2608b39507d
|
||||
F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
|
||||
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
|
||||
F src/printf.c ca05561795ad6c2fa47acdd007702586282f7feb
|
||||
F src/printf.c af589a27b7d40f6f4f704e9eea99f02f18ad6d32
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c f4c897ca76ca6d5e0b3f0499c627392ffe657c8e
|
||||
F src/resolve.c a83b41104e6ff69855d03cd0aaa09e93927ec39f
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c 1611828a7116e5f6cc1e69cd07d59b0d2c662ea9
|
||||
F src/shell.c 98bf4a35a121c9d4b91940a53794f2cbc354c45c
|
||||
F src/sqlite.h.in fc89d305439df88cfe018dbbaf1770645766fa2f
|
||||
F src/select.c f8fded11fc443a9f5a73cc5db069d06b34460e2f
|
||||
F src/shell.c 341bfd2d86b806318cb24f8202fa58dc85f9f2e8
|
||||
F src/sqlite.h.in 686be87fcbaea46b1aa8197a17b7a437d39764fc
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 41ef50b0418a7c5ad1337bb80db5a7928dee764f
|
||||
F src/sqliteInt.h 0bf170994dbc42d4344eed5d59d88ed0631aa4d1
|
||||
F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d
|
||||
F src/sqliteInt.h 109deba7548c27ea534de0dde6729620103cbe87
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
|
||||
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
|
||||
F src/tclsqlite.c e2344bee0d192397f555a24ef3fab26f2ed93bcc
|
||||
F src/test1.c 4004bcc1b3b361a9137acd1d875599ecbdd6f961
|
||||
F src/test1.c 4f1b42699068b7806af3111786f5ad760c2c1ff7
|
||||
F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b
|
||||
F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f
|
||||
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
|
||||
@@ -383,10 +377,10 @@ 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 bae65b68a216f31e225a46187497bdc007c1c5e5
|
||||
F src/test_config.c a0e8eeb86a7d9393f3bbf7315932c1cccd0e8010
|
||||
F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_fs.c aab47ac456316502faa265daadf9ac832fea12b9
|
||||
F src/test_fs.c 993c7eab65bed6add4bb48cca29775e963f710cf
|
||||
F src/test_func.c 0d9c25956152adefee8881c6fadc8354793764d0
|
||||
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
|
||||
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
|
||||
@@ -394,8 +388,8 @@ F src/test_intarray.c 870124b95ec4c645d4eb84f15efb7133528fb1a5
|
||||
F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202
|
||||
F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa
|
||||
F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4
|
||||
F src/test_malloc.c 8e1c2112fa4f543b46c990a8872f9e6d37938744
|
||||
F src/test_multiplex.c 9fefd23f6cc3fa9bf0748a5e453167e7b9f193ce
|
||||
F src/test_malloc.c 96df9381a1ff1f6d3805ff7231b9baf1386aaabf
|
||||
F src/test_multiplex.c 6a088d8d9d4aad4bec45dd8878af11b15900702d
|
||||
F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3
|
||||
F src/test_mutex.c dbdfaff8580071f2212a0deae3325a93a737819c
|
||||
F src/test_onefile.c 38f7cbe79d5bafe95bde683cc3a53b8ca16daf10
|
||||
@@ -419,24 +413,24 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0
|
||||
F src/tokenize.c 5606871a377f390af7040ec3c12e0d183512d785
|
||||
F src/treeview.c 78842e90c1f71269e7a73a1d4221b6fe360bab66
|
||||
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
|
||||
F src/trigger.c de3ed31ad3218a20d7d7e18bf1b3b734e78bda66
|
||||
F src/update.c d8d675aa299336ac086ad2039d7e812cd6237db0
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
F src/util.c e802e8e311a0d6c48cd1b3e89db164f6f0248d70
|
||||
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
||||
F src/vdbe.c 5c3dd0f49bfebfddbfa4d389ed394b2b28d48cbf
|
||||
F src/vdbe.c c47b3bfcb4fcf1f24457eb505da229c4fb035a60
|
||||
F src/vdbe.h bfe3f80dba435377cdb64fd917f2529f0f48ab77
|
||||
F src/vdbeInt.h 4f3b46806b93faa92f0511c7ce30ed31aaec65be
|
||||
F src/vdbeapi.c ab2cb8fe23fb9f3195f1311eaa800495d83b6118
|
||||
F src/vdbeaux.c 514e93b162bf3e84c82478f174728cda9135b558
|
||||
F src/vdbeaux.c 6783ed3936bc484c2252523c82e9a14888fed936
|
||||
F src/vdbeblob.c cc13eca96b8ec51b6248de785a1aec5df11f5805
|
||||
F src/vdbemem.c 25b6cfd665b5073480452426e84136edd94140c0
|
||||
F src/vdbesort.c a7ec02da4494c59dfd071126dd3726be5a11459d
|
||||
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
|
||||
F src/vtab.c 2a8b44aa372c33f6154208e7a7f6c44254549806
|
||||
F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
|
||||
F src/wal.c 1569802364cd192bbd5c4a8ea3fd6de593edecbd
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/wal.c 974928c988681c5157202c79dd9f26afaa7b5086
|
||||
F src/wal.h 907943dfdef10b583e81906679a347e0ec6f1b1b
|
||||
F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba
|
||||
F src/where.c b18edbb9e5afabb77f4f27550c471c5c824e0fe7
|
||||
F src/whereInt.h e20801d89e34de1912bb6a3babb30c390da27add
|
||||
@@ -954,7 +948,7 @@ F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test 63cb93f915b4056463cef8ad035082e9f1cb524e
|
||||
F test/pragma.test a44253f911e7d50127d4a08f927f47c861a4c772
|
||||
F test/pragma2.test 00065068eeab2d15ea55465ec0f1e0a70e2c369e
|
||||
F test/pragma2.test a9400a7289605280576098b97f5cde3f204075c0
|
||||
F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
|
||||
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
|
||||
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054
|
||||
@@ -1041,6 +1035,8 @@ F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a
|
||||
F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
|
||||
F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
|
||||
F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b
|
||||
F test/snapshot.test efc6b4edc5d571161835f9dd8552e181ad1f0ac2
|
||||
F test/snapshot_fault.test 25973aeb1b86a280800e0bcf1eb5ce70e9ef57ab
|
||||
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
|
||||
F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
|
||||
F test/sort.test 3f492e5b7be1d3f756728d2ff6edf4f6091e84cb
|
||||
@@ -1075,7 +1071,7 @@ F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
|
||||
F test/symlink.test cbf6cb8c6c4b63a39e9f0f6b0d5c99e249dbc102
|
||||
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
|
||||
F test/syscall.test 2aa9e111b79fb385681ff8940124def6f8faab87
|
||||
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
|
||||
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
|
||||
F test/tabfunc01.test cc33684f9480fcf1fd5ce287ac28d22971cad1cc
|
||||
F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
|
||||
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
@@ -1095,7 +1091,7 @@ F test/thread2.test f35d2106452b77523b3a2b7d1dcde2e5ee8f9e46
|
||||
F test/thread_common.tcl 334639cadcb9f912bf82aa73f49efd5282e6cadd
|
||||
F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
|
||||
F test/threadtest2.c a70a8e94bef23339d34226eb9521015ef99f4df8
|
||||
F test/threadtest3.c 0707c28e0954acbef654f91675e14f3573cf9a10
|
||||
F test/threadtest3.c 7ca82330041456afa52e4968196bb0867371f91b
|
||||
F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
|
||||
F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c
|
||||
F test/tkt-26ff0c2d1e.test 888324e751512972c6e0d1a09df740d8f5aaf660
|
||||
@@ -1297,7 +1293,7 @@ F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292
|
||||
F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96
|
||||
F test/vtabE.test d5024aa42754962f6bb0afd261681686488e7afe
|
||||
F test/vtabF.test fd5ad376f5a34fe0891df1f3cddb4fe7c3eb077e
|
||||
F test/vtabH.test 2803a8773d1017ac93bbec6900fc7c35bb56c1c3
|
||||
F test/vtabH.test f77296bbf55675b72817cc10fbbcb236ac986abf
|
||||
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
|
||||
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
|
||||
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
|
||||
@@ -1335,7 +1331,7 @@ F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e
|
||||
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
|
||||
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
|
||||
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
|
||||
F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8
|
||||
F test/where7.test f520bcec2c3d12dc4615623b06b2aec7c2d67e94
|
||||
F test/where8.test 98eedca0d375fb400b8377269c4b4686582dfb45
|
||||
F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739
|
||||
F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2
|
||||
@@ -1355,7 +1351,7 @@ 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 cef099a491eac9874f2c28bd2dc86394fb3e47b3
|
||||
F test/with2.test 2b40da883658eb74ad8ad06afabe11a408e7fb87
|
||||
F test/with3.test 511bacdbe41c49cf34f9fd1bd3245fe1575bca98
|
||||
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
|
||||
@@ -1369,9 +1365,9 @@ F test/wordcount.c 2a0a6c0d0e8e8bbbac1f06d72a6791828c37c0cf
|
||||
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
|
||||
F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
|
||||
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
|
||||
F tool/GetTclKit.bat 8606413d3035c05373a0d7fae82ebf59ae9e16c3
|
||||
F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372
|
||||
F tool/addopcodes.tcl 4ca9c3ef196f08da30add5d07ce0c9458dc8c633
|
||||
F tool/build-all-msvc.bat e42141ca3c3812315432f9813ef9eb78aa8d99c9 x
|
||||
F tool/build-all-msvc.bat 204a039f985d5a4f4f9df3a3aa594fd17848c37e x
|
||||
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
|
||||
F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x
|
||||
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
|
||||
@@ -1386,12 +1382,12 @@ F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d
|
||||
F tool/lempar.c 3ec1463a034b37d87d782be5f6b8b10a3b1ecbe7
|
||||
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
||||
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
|
||||
F tool/mkautoconfamal.sh 4bdf61548a143e5977bd86ab93d68b694d10c8fa
|
||||
F tool/mkautoconfamal.sh 5a5441280b509d2bb3bdc71bfb63781b0d570373
|
||||
F tool/mkkeywordhash.c 06ec0b78bd4fa68c12d90ef2bdfe76b039133ff8
|
||||
F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b
|
||||
F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl e94e55d247d4fe3be34f2a4f4edb03fdcd09ce5b
|
||||
F tool/mkpragmatab.tcl f0d5bb266d1d388cf86fce5ba01a891e95d72d41
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 87240b09c20042999b41d5fabe091b7111287835
|
||||
F tool/mksqlite3c.tcl a52d7e8c0888f9384fbfa2c6ddd5f357409758b9
|
||||
@@ -1429,7 +1425,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 7d6cfc79e7e5534ebacd980479917bc528a638f7 4f2bcff94c672312805be1400050a7026f93a9d7
|
||||
R 50fae771d9c27e855af8c38f94348078
|
||||
P d1a1278d7f3306536dc9cbd8fb300898f1e373e8 f2fc3aede55c8fa0351697f9f5ce4e544334c9af
|
||||
R 517371cdb369ee85515a09f103cedd2b
|
||||
U drh
|
||||
Z 355385643ee65578020d9d55249a7cd0
|
||||
Z 301e77e09a4ba74f7629e4b1c4e7cf3d
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
d1a1278d7f3306536dc9cbd8fb300898f1e373e8
|
||||
f6c9273cab877b8b6b327250195f3392393d060a
|
||||
+3
-4
@@ -6470,7 +6470,7 @@ static int rebuildPage(
|
||||
pData = pEnd;
|
||||
for(i=0; i<nCell; i++){
|
||||
u8 *pCell = apCell[i];
|
||||
if( pCell>aData && pCell<pEnd ){
|
||||
if( SQLITE_WITHIN(pCell,aData,pEnd) ){
|
||||
pCell = &pTmp[pCell - aData];
|
||||
}
|
||||
pData -= szCell[i];
|
||||
@@ -6581,7 +6581,7 @@ static int pageFreeArray(
|
||||
|
||||
for(i=iFirst; i<iEnd; i++){
|
||||
u8 *pCell = pCArray->apCell[i];
|
||||
if( pCell>=pStart && pCell<pEnd ){
|
||||
if( SQLITE_WITHIN(pCell, pStart, pEnd) ){
|
||||
int sz;
|
||||
/* No need to use cachedCellSize() here. The sizes of all cells that
|
||||
** are to be freed have already been computing while deciding which
|
||||
@@ -7521,8 +7521,7 @@ static int balance_nonroot(
|
||||
** overflow cell), we can skip updating the pointer map entries. */
|
||||
if( iOld>=nNew
|
||||
|| pNew->pgno!=aPgno[iOld]
|
||||
|| pCell<aOld
|
||||
|| pCell>=&aOld[usableSize]
|
||||
|| !SQLITE_WITHIN(pCell,aOld,&aOld[usableSize])
|
||||
){
|
||||
if( !leafCorrection ){
|
||||
ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc);
|
||||
|
||||
@@ -63,6 +63,9 @@ static const char * const azCompileOpt[] = {
|
||||
#if SQLITE_DISABLE_LFS
|
||||
"DISABLE_LFS",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_8_3_NAMES
|
||||
"ENABLE_8_3_NAMES",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_API_ARMOR
|
||||
"ENABLE_API_ARMOR",
|
||||
#endif
|
||||
|
||||
+5
-1
@@ -853,6 +853,7 @@ static int dupedExprSize(Expr *p, int flags){
|
||||
*/
|
||||
static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
||||
Expr *pNew = 0; /* Value to return */
|
||||
assert( flags==0 || flags==EXPRDUP_REDUCE );
|
||||
if( p ){
|
||||
const int isReduced = (flags&EXPRDUP_REDUCE);
|
||||
u8 *zAlloc;
|
||||
@@ -889,7 +890,9 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
||||
}else{
|
||||
int nSize = exprStructSize(p);
|
||||
memcpy(zAlloc, p, nSize);
|
||||
memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
|
||||
if( nSize<EXPR_FULLSIZE ){
|
||||
memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
|
||||
@@ -979,6 +982,7 @@ static With *withDup(sqlite3 *db, With *p){
|
||||
** part of the in-memory representation of the database schema.
|
||||
*/
|
||||
Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){
|
||||
assert( flags==0 || flags==EXPRDUP_REDUCE );
|
||||
return exprDup(db, p, flags, 0);
|
||||
}
|
||||
ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
|
||||
|
||||
+5
-1
@@ -410,7 +410,11 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
sqlite3_bind_zeroblob64,
|
||||
/* Version 3.9.0 and later */
|
||||
sqlite3_value_subtype,
|
||||
sqlite3_result_subtype
|
||||
sqlite3_result_subtype,
|
||||
/* Version 3.10.0 and later */
|
||||
sqlite3_status64,
|
||||
sqlite3_strlike,
|
||||
sqlite3_db_cacheflush
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+87
-3
@@ -445,9 +445,10 @@ int sqlite3_config(int op, ...){
|
||||
break;
|
||||
}
|
||||
case SQLITE_CONFIG_PAGECACHE: {
|
||||
/* EVIDENCE-OF: R-31408-40510 There are three arguments to
|
||||
** SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned memory, the size
|
||||
** of each page buffer (sz), and the number of pages (N). */
|
||||
/* EVIDENCE-OF: R-18761-36601 There are three arguments to
|
||||
** SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned memory (pMem),
|
||||
** the size of each page cache line (sz), and the number of cache lines
|
||||
** (N). */
|
||||
sqlite3GlobalConfig.pPage = va_arg(ap, void*);
|
||||
sqlite3GlobalConfig.szPage = va_arg(ap, int);
|
||||
sqlite3GlobalConfig.nPage = va_arg(ap, int);
|
||||
@@ -3886,3 +3887,86 @@ int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
|
||||
pBt = sqlite3DbNameToBtree(db, zDbName);
|
||||
return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
/*
|
||||
** Obtain a snapshot handle for the snapshot of database zDb currently
|
||||
** being read by handle db.
|
||||
*/
|
||||
int sqlite3_snapshot_get(
|
||||
sqlite3 *db,
|
||||
const char *zDb,
|
||||
sqlite3_snapshot **ppSnapshot
|
||||
){
|
||||
int rc = SQLITE_ERROR;
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
int iDb;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
|
||||
iDb = sqlite3FindDbName(db, zDb);
|
||||
if( iDb==0 || iDb>1 ){
|
||||
Btree *pBt = db->aDb[iDb].pBt;
|
||||
if( 0==sqlite3BtreeIsInTrans(pBt) ){
|
||||
rc = sqlite3BtreeBeginTrans(pBt, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
#endif /* SQLITE_OMIT_WAL */
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Open a read-transaction on the snapshot idendified by pSnapshot.
|
||||
*/
|
||||
int sqlite3_snapshot_open(
|
||||
sqlite3 *db,
|
||||
const char *zDb,
|
||||
sqlite3_snapshot *pSnapshot
|
||||
){
|
||||
int rc = SQLITE_ERROR;
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( db->autoCommit==0 ){
|
||||
int iDb;
|
||||
iDb = sqlite3FindDbName(db, zDb);
|
||||
if( iDb==0 || iDb>1 ){
|
||||
Btree *pBt = db->aDb[iDb].pBt;
|
||||
if( 0==sqlite3BtreeIsInReadTrans(pBt) ){
|
||||
rc = sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), pSnapshot);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3BtreeBeginTrans(pBt, 0);
|
||||
sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
#endif /* SQLITE_OMIT_WAL */
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Free a snapshot handle obtained from sqlite3_snapshot_get().
|
||||
*/
|
||||
void sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){
|
||||
sqlite3_free(pSnapshot);
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_SNAPSHOT */
|
||||
|
||||
|
||||
+2
-2
@@ -358,7 +358,7 @@ void sqlite3ScratchFree(void *p){
|
||||
scratchAllocOut--;
|
||||
#endif
|
||||
|
||||
if( p>=sqlite3GlobalConfig.pScratch && p<mem0.pScratchEnd ){
|
||||
if( SQLITE_WITHIN(p, sqlite3GlobalConfig.pScratch, mem0.pScratchEnd) ){
|
||||
/* Release memory from the SQLITE_CONFIG_SCRATCH allocation */
|
||||
ScratchFreeslot *pSlot;
|
||||
pSlot = (ScratchFreeslot*)p;
|
||||
@@ -394,7 +394,7 @@ void sqlite3ScratchFree(void *p){
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_LOOKASIDE
|
||||
static int isLookaside(sqlite3 *db, void *p){
|
||||
return p>=db->lookaside.pStart && p<db->lookaside.pEnd;
|
||||
return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pEnd);
|
||||
}
|
||||
#else
|
||||
#define isLookaside(A,B) 0
|
||||
|
||||
+18
-12
@@ -3465,13 +3465,16 @@ static int openDirectory(const char *zFilename, int *pFd){
|
||||
char zDirname[MAX_PATHNAME+1];
|
||||
|
||||
sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
|
||||
for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
|
||||
if( ii>1 ){
|
||||
for(ii=(int)strlen(zDirname); ii>0 && zDirname[ii]!='/'; ii--);
|
||||
if( ii>0 ){
|
||||
zDirname[ii] = '\0';
|
||||
fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
|
||||
if( fd>=0 ){
|
||||
OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
|
||||
}
|
||||
}else{
|
||||
if( zDirname[0]!='/' ) zDirname[0] = '.';
|
||||
zDirname[1] = 0;
|
||||
}
|
||||
fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
|
||||
if( fd>=0 ){
|
||||
OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
|
||||
}
|
||||
*pFd = fd;
|
||||
if( fd>=0 ) return SQLITE_OK;
|
||||
@@ -5521,16 +5524,19 @@ static int findCreateFileMode(
|
||||
** used by the test_multiplex.c module.
|
||||
*/
|
||||
nDb = sqlite3Strlen30(zPath) - 1;
|
||||
#ifdef SQLITE_ENABLE_8_3_NAMES
|
||||
while( nDb>0 && sqlite3Isalnum(zPath[nDb]) ) nDb--;
|
||||
if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK;
|
||||
#else
|
||||
while( zPath[nDb]!='-' ){
|
||||
#ifndef SQLITE_ENABLE_8_3_NAMES
|
||||
/* In the normal case (8+3 filenames disabled) the journal filename
|
||||
** is guaranteed to contain a '-' character. */
|
||||
assert( nDb>0 );
|
||||
assert( zPath[nDb]!='\n' );
|
||||
assert( sqlite3Isalnum(zPath[nDb]) );
|
||||
#else
|
||||
/* If 8+3 names are possible, then the journal file might not contain
|
||||
** a '-' character. So check for that case and return early. */
|
||||
if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK;
|
||||
#endif
|
||||
nDb--;
|
||||
}
|
||||
#endif
|
||||
memcpy(zDb, zPath, nDb);
|
||||
zDb[nDb] = '\0';
|
||||
|
||||
|
||||
+28
@@ -7301,6 +7301,34 @@ int sqlite3PagerCloseWal(Pager *pPager){
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
/*
|
||||
** If this is a WAL database, obtain a snapshot handle for the snapshot
|
||||
** currently open. Otherwise, return an error.
|
||||
*/
|
||||
int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot){
|
||||
int rc = SQLITE_ERROR;
|
||||
if( pPager->pWal ){
|
||||
rc = sqlite3WalSnapshotGet(pPager->pWal, ppSnapshot);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** If this is a WAL database, store a pointer to pSnapshot. Next time a
|
||||
** read transaction is opened, attempt to read from the snapshot it
|
||||
** identifies. If this is not a WAL database, return an error.
|
||||
*/
|
||||
int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot){
|
||||
int rc = SQLITE_OK;
|
||||
if( pPager->pWal ){
|
||||
sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot);
|
||||
}else{
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_SNAPSHOT */
|
||||
#endif /* !SQLITE_OMIT_WAL */
|
||||
|
||||
#ifdef SQLITE_ENABLE_ZIPVFS
|
||||
|
||||
@@ -168,6 +168,10 @@ int sqlite3PagerSharedLock(Pager *pPager);
|
||||
int sqlite3PagerWalCallback(Pager *pPager);
|
||||
int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
|
||||
int sqlite3PagerCloseWal(Pager *pPager);
|
||||
# ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
|
||||
int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_ZIPVFS
|
||||
|
||||
+1
-1
@@ -350,7 +350,7 @@ static void *pcache1Alloc(int nByte){
|
||||
static void pcache1Free(void *p){
|
||||
int nFreed = 0;
|
||||
if( p==0 ) return;
|
||||
if( p>=pcache1.pStart && p<pcache1.pEnd ){
|
||||
if( SQLITE_WITHIN(p, pcache1.pStart, pcache1.pEnd) ){
|
||||
PgFreeslot *pSlot;
|
||||
sqlite3_mutex_enter(pcache1.mutex);
|
||||
sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1);
|
||||
|
||||
+1
-1
@@ -308,7 +308,7 @@ static const struct sPragmaNames {
|
||||
/* ePragFlag: */ 0,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#if defined(SQLITE_DEBUG)
|
||||
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE)
|
||||
{ /* zName: */ "parser_trace",
|
||||
/* ePragTyp: */ PragTyp_PARSER_TRACE,
|
||||
/* ePragFlag: */ 0,
|
||||
|
||||
+13
-4
@@ -766,8 +766,9 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
setStrAccumError(p, STRACCUM_TOOBIG);
|
||||
return N;
|
||||
}else{
|
||||
char *zOld = (p->zText==p->zBase ? 0 : p->zText);
|
||||
char *zOld = p->bMalloced ? p->zText : 0;
|
||||
i64 szNew = p->nChar;
|
||||
assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) );
|
||||
szNew += N + 1;
|
||||
if( szNew+p->nChar<=p->mxAlloc ){
|
||||
/* Force exponential buffer size growth as long as it does not overflow,
|
||||
@@ -788,9 +789,10 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
}
|
||||
if( zNew ){
|
||||
assert( p->zText!=0 || p->nChar==0 );
|
||||
if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
|
||||
if( !p->bMalloced && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
|
||||
p->zText = zNew;
|
||||
p->nAlloc = sqlite3DbMallocSize(p->db, zNew);
|
||||
p->bMalloced = 1;
|
||||
}else{
|
||||
sqlite3StrAccumReset(p);
|
||||
setStrAccumError(p, STRACCUM_NOMEM);
|
||||
@@ -808,6 +810,7 @@ void sqlite3AppendChar(StrAccum *p, int N, char c){
|
||||
if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){
|
||||
return;
|
||||
}
|
||||
assert( (p->zText==p->zBase)==(p->bMalloced==0) );
|
||||
while( (N--)>0 ) p->zText[p->nChar++] = c;
|
||||
}
|
||||
|
||||
@@ -825,6 +828,7 @@ static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){
|
||||
memcpy(&p->zText[p->nChar], z, N);
|
||||
p->nChar += N;
|
||||
}
|
||||
assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -860,11 +864,13 @@ void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){
|
||||
*/
|
||||
char *sqlite3StrAccumFinish(StrAccum *p){
|
||||
if( p->zText ){
|
||||
assert( (p->zText==p->zBase)==(p->bMalloced==0) );
|
||||
p->zText[p->nChar] = 0;
|
||||
if( p->mxAlloc>0 && p->zText==p->zBase ){
|
||||
if( p->mxAlloc>0 && p->bMalloced==0 ){
|
||||
p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
|
||||
if( p->zText ){
|
||||
memcpy(p->zText, p->zBase, p->nChar+1);
|
||||
p->bMalloced = 1;
|
||||
}else{
|
||||
setStrAccumError(p, STRACCUM_NOMEM);
|
||||
}
|
||||
@@ -877,8 +883,10 @@ char *sqlite3StrAccumFinish(StrAccum *p){
|
||||
** Reset an StrAccum string. Reclaim all malloced memory.
|
||||
*/
|
||||
void sqlite3StrAccumReset(StrAccum *p){
|
||||
if( p->zText!=p->zBase ){
|
||||
assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) );
|
||||
if( p->bMalloced ){
|
||||
sqlite3DbFree(p->db, p->zText);
|
||||
p->bMalloced = 0;
|
||||
}
|
||||
p->zText = 0;
|
||||
}
|
||||
@@ -904,6 +912,7 @@ void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){
|
||||
p->nAlloc = n;
|
||||
p->mxAlloc = mx;
|
||||
p->accError = 0;
|
||||
p->bMalloced = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+1
-2
@@ -328,7 +328,6 @@ static int lookupName(
|
||||
}
|
||||
if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){
|
||||
/* IMP: R-51414-32910 */
|
||||
/* IMP: R-44911-55124 */
|
||||
iCol = -1;
|
||||
}
|
||||
if( iCol<pTab->nCol ){
|
||||
@@ -363,7 +362,7 @@ static int lookupName(
|
||||
&& VisibleRowid(pMatch->pTab)
|
||||
){
|
||||
cnt = 1;
|
||||
pExpr->iColumn = -1; /* IMP: R-44911-55124 */
|
||||
pExpr->iColumn = -1;
|
||||
pExpr->affinity = SQLITE_AFF_INTEGER;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -1529,8 +1529,9 @@ static void generateColumnNames(
|
||||
}
|
||||
#endif
|
||||
|
||||
if( pParse->colNamesSet || db->mallocFailed ) return;
|
||||
assert( v!=0 );
|
||||
assert( pTabList!=0 );
|
||||
if( pParse->colNamesSet || NEVER(v==0) || db->mallocFailed ) return;
|
||||
pParse->colNamesSet = 1;
|
||||
fullNames = (db->flags & SQLITE_FullColNames)!=0;
|
||||
shortNames = (db->flags & SQLITE_ShortColNames)!=0;
|
||||
|
||||
+14
@@ -538,6 +538,7 @@ struct ShellState {
|
||||
int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
|
||||
int statsOn; /* True to display memory stats before each finalize */
|
||||
int scanstatsOn; /* True to display scan stats before each finalize */
|
||||
int countChanges; /* True to display change counts */
|
||||
int backslashOn; /* Resolve C-style \x escapes in SQL input text */
|
||||
int outCount; /* Revert to stdout when reaching zero */
|
||||
int cnt; /* Number of records displayed so far */
|
||||
@@ -1802,6 +1803,7 @@ static char zHelp[] =
|
||||
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
|
||||
".bail on|off Stop after hitting an error. Default OFF\n"
|
||||
".binary on|off Turn binary output on or off. Default OFF\n"
|
||||
".changes on|off Show number of rows changed by SQL\n"
|
||||
".clone NEWDB Clone data into NEWDB from the existing database\n"
|
||||
".databases List names and files of attached databases\n"
|
||||
".dbinfo ?DB? Show status information about the database\n"
|
||||
@@ -2846,6 +2848,15 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
test_breakpoint();
|
||||
}else
|
||||
|
||||
if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
p->countChanges = booleanValue(azArg[1]);
|
||||
}else{
|
||||
fprintf(stderr, "Usage: .changes on|off\n");
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
tryToClone(p, azArg[1]);
|
||||
@@ -4567,6 +4578,9 @@ static int process_input(ShellState *p, FILE *in){
|
||||
fprintf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
|
||||
}
|
||||
errCnt++;
|
||||
}else if( p->countChanges ){
|
||||
fprintf(p->out, "changes: %3d total_changes: %d\n",
|
||||
sqlite3_changes(p->db), sqlite3_total_changes(p->db));
|
||||
}
|
||||
nSql = 0;
|
||||
if( p->outCount ){
|
||||
|
||||
+109
-15
@@ -887,7 +887,7 @@ struct sqlite3_io_methods {
|
||||
** [VFSes] currently in use. ^(The argument X in
|
||||
** sqlite3_file_control(db,SQLITE_FCNTL_VFS_POINTER,X) must be
|
||||
** of type "[sqlite3_vfs] **". This opcodes will set *X
|
||||
** to a pointer to the top-level VFS.^)
|
||||
** to a pointer to the top-level VFS.)^
|
||||
** ^When there are multiple VFS shims in the stack, this opcode finds the
|
||||
** upper-most shim only.
|
||||
**
|
||||
@@ -4405,8 +4405,8 @@ unsigned int sqlite3_value_subtype(sqlite3_value*);
|
||||
** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer
|
||||
** then sqlite3_value_free(V) is a harmless no-op.
|
||||
*/
|
||||
SQLITE_EXPERIMENTAL sqlite3_value *sqlite3_value_dup(const sqlite3_value*);
|
||||
SQLITE_EXPERIMENTAL void sqlite3_value_free(sqlite3_value*);
|
||||
sqlite3_value *sqlite3_value_dup(const sqlite3_value*);
|
||||
void sqlite3_value_free(sqlite3_value*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtain Aggregate Function Context
|
||||
@@ -7851,30 +7851,32 @@ 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
|
||||
** ^If a write-transaction is open on [database connection] D when the
|
||||
** [sqlite3_db_cacheflush(D)] interface invoked, 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.
|
||||
** file (page 1 is always "in use"). ^The [sqlite3_db_cacheflush(D)]
|
||||
** interface flushes caches for all schemas - "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
|
||||
** ^If this function needs to obtain extra database locks before dirty pages
|
||||
** can be flushed to disk, it does so. ^If those 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
|
||||
** 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
|
||||
** 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
|
||||
** ^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.
|
||||
** abandoned and an SQLite [error code] is returned to the caller immediately.
|
||||
**
|
||||
** Otherwise, if no error occurs, SQLITE_OK is returned.
|
||||
** ^Otherwise, if no error occurs, [sqlite3_db_cacheflush()] returns SQLITE_OK.
|
||||
**
|
||||
** This function does not set the database handle error code or message
|
||||
** returned by the sqlite3_errcode() and sqlite3_errmsg() functions.
|
||||
** ^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*);
|
||||
|
||||
@@ -7973,6 +7975,98 @@ SQLITE_EXPERIMENTAL int sqlite3_preupdate_count(sqlite3 *);
|
||||
SQLITE_EXPERIMENTAL int sqlite3_preupdate_depth(sqlite3 *);
|
||||
SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Snapshot
|
||||
** KEYWORDS: {snapshot}
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** An instance of the snapshot object records the state of a [WAL mode]
|
||||
** database for some specific point in history.
|
||||
**
|
||||
** In [WAL mode], multiple [database connections] that are open on the
|
||||
** same database file can each be reading a different historical version
|
||||
** of the database file. When a [database connection] begins a read
|
||||
** transaction, that connection sees an unchanging copy of the database
|
||||
** as it existed for the point in time when the transaction first started.
|
||||
** Subsequent changes to the database from other connections are not seen
|
||||
** by the reader until a new read transaction is started.
|
||||
**
|
||||
** The sqlite3_snapshot object records state information about an historical
|
||||
** version of the database file so that it is possible to later open a new read
|
||||
** transaction that sees that historical version of the database rather than
|
||||
** the most recent version.
|
||||
**
|
||||
** The constructor for this object is [sqlite3_snapshot_get()]. The
|
||||
** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer
|
||||
** to an historical snapshot (if possible). The destructor for
|
||||
** sqlite3_snapshot objects is [sqlite3_snapshot_free()].
|
||||
*/
|
||||
typedef struct sqlite3_snapshot sqlite3_snapshot;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Record A Database Snapshot
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a
|
||||
** new [sqlite3_snapshot] object that records the current state of
|
||||
** schema S in database connection D. ^On success, the
|
||||
** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly
|
||||
** created [sqlite3_snapshot] object into *P and returns SQLITE_OK.
|
||||
** ^If schema S of [database connection] D is not a [WAL mode] database
|
||||
** that is in a read transaction, then [sqlite3_snapshot_get(D,S,P)]
|
||||
** leaves the *P value unchanged and returns an appropriate [error code].
|
||||
**
|
||||
** The [sqlite3_snapshot] object returned from a successful call to
|
||||
** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()]
|
||||
** to avoid a memory leak.
|
||||
**
|
||||
** The [sqlite3_snapshot_get()] interface is only available when the
|
||||
** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
|
||||
*/
|
||||
SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
|
||||
sqlite3 *db,
|
||||
const char *zSchema,
|
||||
sqlite3_snapshot **ppSnapshot
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Start a read transaction on an historical snapshot
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^The [sqlite3_snapshot_open(D,S,P)] interface attempts to move the
|
||||
** read transaction that is currently open on schema S of
|
||||
** [database connection] D so that it refers to historical [snapshot] P.
|
||||
** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success
|
||||
** or an appropriate [error code] if it fails.
|
||||
**
|
||||
** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be
|
||||
** the first operation, apart from other sqlite3_snapshot_open() calls,
|
||||
** following the [BEGIN] that starts a new read transaction.
|
||||
** ^A [snapshot] will fail to open if it has been overwritten by a
|
||||
** [checkpoint].
|
||||
**
|
||||
** The [sqlite3_snapshot_open()] interface is only available when the
|
||||
** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
|
||||
*/
|
||||
SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
|
||||
sqlite3 *db,
|
||||
const char *zSchema,
|
||||
sqlite3_snapshot *pSnapshot
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Destroy a snapshot
|
||||
** EXPERIMENTAL
|
||||
**
|
||||
** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P.
|
||||
** The application must eventually free every [sqlite3_snapshot] object
|
||||
** using this routine to avoid a memory leak.
|
||||
**
|
||||
** The [sqlite3_snapshot_free()] interface is only available when the
|
||||
** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
|
||||
*/
|
||||
SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
|
||||
|
||||
/*
|
||||
** Undo the hack that converts floating point types to integer for
|
||||
** builds on processors without floating point support.
|
||||
|
||||
@@ -276,7 +276,9 @@ struct sqlite3_api_routines {
|
||||
unsigned int (*value_subtype)(sqlite3_value*);
|
||||
void (*result_subtype)(sqlite3_context*,unsigned int);
|
||||
/* Version 3.10.0 and later */
|
||||
int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int);
|
||||
int (*strlike)(const char*,const char*,unsigned int);
|
||||
int (*db_cacheflush)(sqlite3*);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -517,7 +519,9 @@ struct sqlite3_api_routines {
|
||||
#define sqlite3_value_subtype sqlite3_api->value_subtype
|
||||
#define sqlite3_result_subtype sqlite3_api->result_subtype
|
||||
/* Version 3.10.0 and later */
|
||||
#define sqlite3_status64 sqlite3_api->status64
|
||||
#define sqlite3_strlike sqlite3_api->strlike
|
||||
#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
@@ -173,6 +173,21 @@
|
||||
# define SQLITE_PTR_TO_INT(X) ((int)(X))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The SQLITE_WITHIN(P,S,E) macro checks to see if pointer P points to
|
||||
** something between S (inclusive) and E (exclusive).
|
||||
**
|
||||
** In other words, S is a buffer and E is a pointer to the first byte after
|
||||
** the end of buffer S. This macro returns true if P points to something
|
||||
** contained within the buffer S.
|
||||
*/
|
||||
#if defined(HAVE_STDINT_H)
|
||||
# define SQLITE_WITHIN(P,S,E) \
|
||||
((uintptr_t)(P)>=(uintptr_t)(S) && (uintptr_t)(P)<(uintptr_t)(E))
|
||||
#else
|
||||
# define SQLITE_WITHIN(P,S,E) ((P)>=(S) && (P)<(E))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** A macro to hint to the compiler that a function should not be
|
||||
** inlined.
|
||||
@@ -2964,6 +2979,7 @@ struct StrAccum {
|
||||
int nAlloc; /* Amount of space allocated in zText */
|
||||
int mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */
|
||||
u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
|
||||
u8 bMalloced; /* zText points to allocated space */
|
||||
};
|
||||
#define STRACCUM_NOMEM 1
|
||||
#define STRACCUM_TOOBIG 2
|
||||
|
||||
+95
-2
@@ -2269,6 +2269,94 @@ static int vfsCurrentTimeInt64(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
/*
|
||||
** Usage: sqlite3_snapshot_get DB DBNAME
|
||||
*/
|
||||
static int test_snapshot_get(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
int rc;
|
||||
sqlite3 *db;
|
||||
char *zName;
|
||||
sqlite3_snapshot *pSnapshot = 0;
|
||||
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
zName = Tcl_GetString(objv[2]);
|
||||
|
||||
rc = sqlite3_snapshot_get(db, zName, &pSnapshot);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
||||
return TCL_ERROR;
|
||||
}else{
|
||||
char zBuf[100];
|
||||
if( sqlite3TestMakePointerStr(interp, zBuf, pSnapshot) ) return TCL_ERROR;
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(zBuf, -1));
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_SNAPSHOT */
|
||||
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
/*
|
||||
** Usage: sqlite3_snapshot_open DB DBNAME SNAPSHOT
|
||||
*/
|
||||
static int test_snapshot_open(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
int rc;
|
||||
sqlite3 *db;
|
||||
char *zName;
|
||||
sqlite3_snapshot *pSnapshot;
|
||||
|
||||
if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SNAPSHOT");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
zName = Tcl_GetString(objv[2]);
|
||||
pSnapshot = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[3]));
|
||||
|
||||
rc = sqlite3_snapshot_open(db, zName, pSnapshot);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_SNAPSHOT */
|
||||
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
/*
|
||||
** Usage: sqlite3_snapshot_free SNAPSHOT
|
||||
*/
|
||||
static int test_snapshot_free(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3_snapshot *pSnapshot;
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
pSnapshot = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
|
||||
sqlite3_snapshot_free(pSnapshot);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_SNAPSHOT */
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_next_stmt DB STMT
|
||||
**
|
||||
@@ -5906,13 +5994,13 @@ static int test_sqlite3_log(
|
||||
Tcl_DecrRefCount(logcallback.pObj);
|
||||
logcallback.pObj = 0;
|
||||
logcallback.pInterp = 0;
|
||||
sqlite3_config(SQLITE_CONFIG_LOG, 0, 0);
|
||||
sqlite3_config(SQLITE_CONFIG_LOG, (void*)0, (void*)0);
|
||||
}
|
||||
if( objc>1 ){
|
||||
logcallback.pObj = objv[1];
|
||||
Tcl_IncrRefCount(logcallback.pObj);
|
||||
logcallback.pInterp = interp;
|
||||
sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, 0);
|
||||
sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, (void*)0);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -7083,6 +7171,11 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_config_sqllog", test_config_sqllog, 0 },
|
||||
#endif
|
||||
{ "vfs_current_time_int64", vfsCurrentTimeInt64, 0 },
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
{ "sqlite3_snapshot_get", test_snapshot_get, 0 },
|
||||
{ "sqlite3_snapshot_open", test_snapshot_open, 0 },
|
||||
{ "sqlite3_snapshot_free", test_snapshot_free, 0 },
|
||||
#endif
|
||||
};
|
||||
static int bitmask_size = sizeof(Bitmask)*8;
|
||||
static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
|
||||
|
||||
@@ -149,6 +149,12 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "preupdate", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
Tcl_SetVar2(interp, "sqlite_options", "snapshot", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "snapshot", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_MUTEX_OMIT
|
||||
Tcl_SetVar2(interp, "sqlite_options", "mutex", "0", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
|
||||
+4
-1
@@ -202,7 +202,10 @@ static int fsdirBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
*/
|
||||
static int fsdirOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
|
||||
FsdirCsr *pCur;
|
||||
pCur = (FsdirCsr*)sqlite3_malloc(sizeof(FsdirCsr));
|
||||
/* Allocate an extra 256 bytes because it is undefined how big dirent.d_name
|
||||
** is and we need enough space. Linux provides plenty already, but
|
||||
** Solaris only provides one byte. */
|
||||
pCur = (FsdirCsr*)sqlite3_malloc(sizeof(FsdirCsr)+256);
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, sizeof(FsdirCsr));
|
||||
*ppCursor = &pCur->base;
|
||||
|
||||
+2
-1
@@ -222,7 +222,8 @@ static int faultsimInstall(int install){
|
||||
assert( memcmp(&m2, &memfault.m, sizeof(m2))==0 );
|
||||
|
||||
rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m);
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 0, 0);
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,
|
||||
(void*)0, (void*)0);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
+6
-11
@@ -189,8 +189,11 @@ static struct {
|
||||
int isInitialized;
|
||||
|
||||
/* For run-time access any of the other global data structures in this
|
||||
** shim, the following mutex must be held.
|
||||
*/
|
||||
** shim, the following mutex must be held. In practice, all this mutex
|
||||
** protects is add/remove operations to/from the linked list of group objects
|
||||
** starting at pGroups below. More specifically, it protects the value of
|
||||
** pGroups itself, and the pNext/pPrev fields of each multiplexGroup
|
||||
** structure. */
|
||||
sqlite3_mutex *pMutex;
|
||||
|
||||
/* List of multiplexGroup objects.
|
||||
@@ -758,11 +761,8 @@ static int multiplexRead(
|
||||
multiplexConn *p = (multiplexConn*)pConn;
|
||||
multiplexGroup *pGroup = p->pGroup;
|
||||
int rc = SQLITE_OK;
|
||||
int nMutex = 0;
|
||||
multiplexEnter(); nMutex++;
|
||||
if( !pGroup->bEnabled ){
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
|
||||
multiplexLeave(); nMutex--;
|
||||
if( pSubOpen==0 ){
|
||||
rc = SQLITE_IOERR_READ;
|
||||
}else{
|
||||
@@ -772,9 +772,7 @@ static int multiplexRead(
|
||||
while( iAmt > 0 ){
|
||||
int i = (int)(iOfst / pGroup->szChunk);
|
||||
sqlite3_file *pSubOpen;
|
||||
if( nMutex==0 ){ multiplexEnter(); nMutex++; }
|
||||
pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL, 1);
|
||||
multiplexLeave(); nMutex--;
|
||||
if( pSubOpen ){
|
||||
int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) - pGroup->szChunk;
|
||||
if( extra<0 ) extra = 0;
|
||||
@@ -791,8 +789,7 @@ static int multiplexRead(
|
||||
}
|
||||
}
|
||||
}
|
||||
assert( nMutex==0 || nMutex==1 );
|
||||
if( nMutex ) multiplexLeave();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -809,7 +806,6 @@ static int multiplexWrite(
|
||||
multiplexConn *p = (multiplexConn*)pConn;
|
||||
multiplexGroup *pGroup = p->pGroup;
|
||||
int rc = SQLITE_OK;
|
||||
multiplexEnter();
|
||||
if( !pGroup->bEnabled ){
|
||||
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
|
||||
if( pSubOpen==0 ){
|
||||
@@ -834,7 +830,6 @@ static int multiplexWrite(
|
||||
}
|
||||
}
|
||||
}
|
||||
multiplexLeave();
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
+4
-23
@@ -559,31 +559,12 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
|
||||
*/
|
||||
assert( pTable!=0 );
|
||||
if( (v = sqlite3GetVdbe(pParse))!=0 ){
|
||||
int base;
|
||||
static const int iLn = VDBE_OFFSET_LINENO(2);
|
||||
static const VdbeOpList dropTrigger[] = {
|
||||
{ OP_Rewind, 0, ADDR(9), 0},
|
||||
{ OP_String8, 0, 1, 0}, /* 1 */
|
||||
{ OP_Column, 0, 1, 2},
|
||||
{ OP_Ne, 2, ADDR(8), 1},
|
||||
{ OP_String8, 0, 1, 0}, /* 4: "trigger" */
|
||||
{ OP_Column, 0, 0, 2},
|
||||
{ OP_Ne, 2, ADDR(8), 1},
|
||||
{ OP_Delete, 0, 0, 0},
|
||||
{ OP_Next, 0, ADDR(1), 0}, /* 8 */
|
||||
};
|
||||
|
||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||
sqlite3OpenMasterTable(pParse, iDb);
|
||||
base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger, iLn);
|
||||
sqlite3VdbeChangeP4(v, base+1, pTrigger->zName, P4_TRANSIENT);
|
||||
sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC);
|
||||
sqlite3NestedParse(pParse,
|
||||
"DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'",
|
||||
db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrigger->zName
|
||||
);
|
||||
sqlite3ChangeCookie(pParse, iDb);
|
||||
sqlite3VdbeAddOp2(v, OP_Close, 0, 0);
|
||||
sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0);
|
||||
if( pParse->nMem<3 ){
|
||||
pParse->nMem = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1991,6 +1991,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
*/
|
||||
if( pOp->p5 & SQLITE_STOREP2 ){
|
||||
pOut = &aMem[pOp->p2];
|
||||
memAboutToChange(p, pOut);
|
||||
MemSetTypeFlag(pOut, MEM_Null);
|
||||
REGISTER_TRACE(pOp->p2, pOut);
|
||||
}else{
|
||||
|
||||
+38
-42
@@ -350,7 +350,7 @@ int sqlite3VdbeMakeLabel(Vdbe *v){
|
||||
if( p->aLabel ){
|
||||
p->aLabel[i] = -1;
|
||||
}
|
||||
return -1-i;
|
||||
return ADDR(i);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -360,7 +360,7 @@ int sqlite3VdbeMakeLabel(Vdbe *v){
|
||||
*/
|
||||
void sqlite3VdbeResolveLabel(Vdbe *v, int x){
|
||||
Parse *p = v->pParse;
|
||||
int j = -1-x;
|
||||
int j = ADDR(x);
|
||||
assert( v->magic==VDBE_MAGIC_INIT );
|
||||
assert( j<p->nLabel );
|
||||
assert( j>=0 );
|
||||
@@ -587,8 +587,8 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
|
||||
|
||||
pOp->opflags = sqlite3OpcodeProperty[opcode];
|
||||
if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
|
||||
assert( -1-pOp->p2<pParse->nLabel );
|
||||
pOp->p2 = aLabel[-1-pOp->p2];
|
||||
assert( ADDR(pOp->p2)<pParse->nLabel );
|
||||
pOp->p2 = aLabel[ADDR(pOp->p2)];
|
||||
}
|
||||
}
|
||||
sqlite3DbFree(p->db, pParse->aLabel);
|
||||
@@ -645,15 +645,10 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){
|
||||
addr = p->nOp;
|
||||
pOut = &p->aOp[addr];
|
||||
for(i=0; i<nOp; i++, aOp++, pOut++){
|
||||
int p2 = aOp->p2;
|
||||
pOut->opcode = aOp->opcode;
|
||||
pOut->p1 = aOp->p1;
|
||||
if( p2<0 ){
|
||||
assert( sqlite3OpcodeProperty[pOut->opcode] & OPFLG_JUMP );
|
||||
pOut->p2 = addr + ADDR(p2);
|
||||
}else{
|
||||
pOut->p2 = p2;
|
||||
}
|
||||
pOut->p2 = aOp->p2;
|
||||
assert( aOp->p2>=0 );
|
||||
pOut->p3 = aOp->p3;
|
||||
pOut->p4type = P4_NOTUSED;
|
||||
pOut->p4.p = 0;
|
||||
@@ -1726,30 +1721,31 @@ void sqlite3VdbeIOTraceSql(Vdbe *p){
|
||||
**
|
||||
** nByte is the number of bytes of space needed.
|
||||
**
|
||||
** *ppFrom points to available space and pEnd points to the end of the
|
||||
** available space. When space is allocated, *ppFrom is advanced past
|
||||
** the end of the allocated space.
|
||||
** pFrom points to *pnFrom bytes of available space. New space is allocated
|
||||
** from the end of the pFrom buffer and *pnFrom is decremented.
|
||||
**
|
||||
** *pnByte is a counter of the number of bytes of space that have failed
|
||||
** to allocate. If there is insufficient space in *ppFrom to satisfy the
|
||||
** request, then increment *pnByte by the amount of the request.
|
||||
** *pnNeeded is a counter of the number of bytes of space that have failed
|
||||
** to allocate. If there is insufficient space in pFrom to satisfy the
|
||||
** request, then increment *pnNeeded by the amount of the request.
|
||||
*/
|
||||
static void *allocSpace(
|
||||
void *pBuf, /* Where return pointer will be stored */
|
||||
int nByte, /* Number of bytes to allocate */
|
||||
u8 **ppFrom, /* IN/OUT: Allocate from *ppFrom */
|
||||
u8 *pEnd, /* Pointer to 1 byte past the end of *ppFrom buffer */
|
||||
int *pnByte /* If allocation cannot be made, increment *pnByte */
|
||||
u8 *pFrom, /* Memory available for allocation */
|
||||
int *pnFrom, /* IN/OUT: Space available at pFrom */
|
||||
int *pnNeeded /* If allocation cannot be made, increment *pnByte */
|
||||
){
|
||||
assert( EIGHT_BYTE_ALIGNMENT(*ppFrom) );
|
||||
if( pBuf ) return pBuf;
|
||||
nByte = ROUND8(nByte);
|
||||
if( &(*ppFrom)[nByte] <= pEnd ){
|
||||
pBuf = (void*)*ppFrom;
|
||||
*ppFrom += nByte;
|
||||
}else{
|
||||
*pnByte += nByte;
|
||||
assert( EIGHT_BYTE_ALIGNMENT(pFrom) );
|
||||
if( pBuf==0 ){
|
||||
nByte = ROUND8(nByte);
|
||||
if( nByte <= *pnFrom ){
|
||||
*pnFrom -= nByte;
|
||||
pBuf = &pFrom[*pnFrom];
|
||||
}else{
|
||||
*pnNeeded += nByte;
|
||||
}
|
||||
}
|
||||
assert( EIGHT_BYTE_ALIGNMENT(pBuf) );
|
||||
return pBuf;
|
||||
}
|
||||
|
||||
@@ -1822,8 +1818,8 @@ void sqlite3VdbeMakeReady(
|
||||
int nArg; /* Number of arguments in subprograms */
|
||||
int nOnce; /* Number of OP_Once instructions */
|
||||
int n; /* Loop counter */
|
||||
int nFree; /* Available free space */
|
||||
u8 *zCsr; /* Memory available for allocation */
|
||||
u8 *zEnd; /* First byte past allocated memory */
|
||||
int nByte; /* How much extra memory is needed */
|
||||
|
||||
assert( p!=0 );
|
||||
@@ -1855,16 +1851,16 @@ void sqlite3VdbeMakeReady(
|
||||
** an array to marshal SQL function arguments in.
|
||||
*/
|
||||
zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */
|
||||
zEnd = (u8*)&p->aOp[pParse->nOpAlloc]; /* First byte past end of zCsr[] */
|
||||
assert( pParse->nOpAlloc*sizeof(Op) <= 0x7fffff00 );
|
||||
nFree = (pParse->nOpAlloc - p->nOp)*sizeof(p->aOp[0]); /* Available space */
|
||||
|
||||
resolveP2Values(p, &nArg);
|
||||
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
|
||||
if( pParse->explain && nMem<10 ){
|
||||
nMem = 10;
|
||||
}
|
||||
memset(zCsr, 0, zEnd-zCsr);
|
||||
zCsr += (zCsr - (u8*)0)&7;
|
||||
assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
|
||||
memset(zCsr, 0, nFree);
|
||||
assert( EIGHT_BYTE_ALIGNMENT(&zCsr[nFree]) );
|
||||
p->expired = 0;
|
||||
|
||||
/* Memory for registers, parameters, cursor, etc, is allocated in two
|
||||
@@ -1879,21 +1875,21 @@ void sqlite3VdbeMakeReady(
|
||||
*/
|
||||
do {
|
||||
nByte = 0;
|
||||
p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte);
|
||||
p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte);
|
||||
p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte);
|
||||
p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
|
||||
p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), zCsr, &nFree, &nByte);
|
||||
p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), zCsr, &nFree, &nByte);
|
||||
p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), zCsr, &nFree, &nByte);
|
||||
p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), zCsr, &nFree, &nByte);
|
||||
p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
|
||||
&zCsr, zEnd, &nByte);
|
||||
p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, &zCsr, zEnd, &nByte);
|
||||
zCsr, &nFree, &nByte);
|
||||
p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, zCsr, &nFree, &nByte);
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), &zCsr, zEnd, &nByte);
|
||||
p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), zCsr, &nFree, &nByte);
|
||||
#endif
|
||||
if( nByte ){
|
||||
p->pFree = sqlite3DbMallocZero(db, nByte);
|
||||
}
|
||||
zCsr = p->pFree;
|
||||
zEnd = &zCsr[nByte];
|
||||
nFree = nByte;
|
||||
}while( nByte && !db->mallocFailed );
|
||||
|
||||
p->nCursor = nCursor;
|
||||
@@ -3236,7 +3232,7 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
|
||||
assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0)
|
||||
== (int)sqlite3VdbeSerialTypeLen(serial_type) );
|
||||
len = pMem->n;
|
||||
memcpy(buf, pMem->z, len);
|
||||
if( len>0 ) memcpy(buf, pMem->z, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
@@ -272,7 +272,8 @@ int sqlite3WalTrace = 0;
|
||||
|
||||
/*
|
||||
** Indices of various locking bytes. WAL_NREADER is the number
|
||||
** of available reader locks and should be at least 3.
|
||||
** of available reader locks and should be at least 3. The default
|
||||
** is SQLITE_SHM_NLOCK==8 and WAL_NREADER==5.
|
||||
*/
|
||||
#define WAL_WRITE_LOCK 0
|
||||
#define WAL_ALL_BUT_WRITE 1
|
||||
@@ -292,7 +293,10 @@ typedef struct WalCkptInfo WalCkptInfo;
|
||||
** The following object holds a copy of the wal-index header content.
|
||||
**
|
||||
** The actual header in the wal-index consists of two copies of this
|
||||
** object.
|
||||
** object followed by one instance of the WalCkptInfo object.
|
||||
** For all versions of SQLite through 3.10.0 and probably beyond,
|
||||
** the locking bytes (WalCkptInfo.aLock) start at offset 120 and
|
||||
** the total header size is 136 bytes.
|
||||
**
|
||||
** The szPage value can be any power of 2 between 512 and 32768, inclusive.
|
||||
** Or it can be 1 to represent a 65536-byte page. The latter case was
|
||||
@@ -325,6 +329,16 @@ struct WalIndexHdr {
|
||||
** However, a WAL_WRITE_LOCK thread can move the value of nBackfill from
|
||||
** mxFrame back to zero when the WAL is reset.
|
||||
**
|
||||
** nBackfillAttempted is the largest value of nBackfill that a checkpoint
|
||||
** has attempted to achieve. Normally nBackfill==nBackfillAtempted, however
|
||||
** the nBackfillAttempted is set before any backfilling is done and the
|
||||
** nBackfill is only set after all backfilling completes. So if a checkpoint
|
||||
** crashes, nBackfillAttempted might be larger than nBackfill. The
|
||||
** WalIndexHdr.mxFrame must never be less than nBackfillAttempted.
|
||||
**
|
||||
** The aLock[] field is a set of bytes used for locking. These bytes should
|
||||
** never be read or written.
|
||||
**
|
||||
** There is one entry in aReadMark[] for each reader lock. If a reader
|
||||
** holds read-lock K, then the value in aReadMark[K] is no greater than
|
||||
** the mxFrame for that reader. The value READMARK_NOT_USED (0xffffffff)
|
||||
@@ -364,6 +378,9 @@ struct WalIndexHdr {
|
||||
struct WalCkptInfo {
|
||||
u32 nBackfill; /* Number of WAL frames backfilled into DB */
|
||||
u32 aReadMark[WAL_NREADER]; /* Reader marks */
|
||||
u8 aLock[SQLITE_SHM_NLOCK]; /* Reserved space for locks */
|
||||
u32 nBackfillAttempted; /* WAL frames perhaps written, or maybe not */
|
||||
u32 notUsed0; /* Available for future enhancements */
|
||||
};
|
||||
#define READMARK_NOT_USED 0xffffffff
|
||||
|
||||
@@ -373,9 +390,8 @@ struct WalCkptInfo {
|
||||
** only support mandatory file-locks, we do not read or write data
|
||||
** from the region of the file on which locks are applied.
|
||||
*/
|
||||
#define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2 + sizeof(WalCkptInfo))
|
||||
#define WALINDEX_LOCK_RESERVED 16
|
||||
#define WALINDEX_HDR_SIZE (WALINDEX_LOCK_OFFSET+WALINDEX_LOCK_RESERVED)
|
||||
#define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2+offsetof(WalCkptInfo,aLock))
|
||||
#define WALINDEX_HDR_SIZE (sizeof(WalIndexHdr)*2+sizeof(WalCkptInfo))
|
||||
|
||||
/* Size of header before each frame in wal */
|
||||
#define WAL_FRAME_HDRSIZE 24
|
||||
@@ -434,6 +450,9 @@ struct Wal {
|
||||
#ifdef SQLITE_DEBUG
|
||||
u8 lockError; /* True if a locking error has occurred */
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1198,6 +1217,7 @@ finished:
|
||||
*/
|
||||
pInfo = walCkptInfo(pWal);
|
||||
pInfo->nBackfill = 0;
|
||||
pInfo->nBackfillAttempted = pWal->hdr.mxFrame;
|
||||
pInfo->aReadMark[0] = 0;
|
||||
for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
|
||||
if( pWal->hdr.mxFrame ) pInfo->aReadMark[1] = pWal->hdr.mxFrame;
|
||||
@@ -1269,7 +1289,11 @@ int sqlite3WalOpen(
|
||||
/* In the amalgamation, the os_unix.c and os_win.c source files come before
|
||||
** this source file. Verify that the #defines of the locking byte offsets
|
||||
** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value.
|
||||
** For that matter, if the lock offset ever changes from its initial design
|
||||
** value of 120, we need to know that so there is an assert() to check it.
|
||||
*/
|
||||
assert( 120==WALINDEX_LOCK_OFFSET );
|
||||
assert( 136==WALINDEX_HDR_SIZE );
|
||||
#ifdef WIN_SHM_BASE
|
||||
assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET );
|
||||
#endif
|
||||
@@ -1655,6 +1679,7 @@ static void walRestartHdr(Wal *pWal, u32 salt1){
|
||||
memcpy(&pWal->hdr.aSalt[1], &salt1, 4);
|
||||
walIndexWriteHdr(pWal);
|
||||
pInfo->nBackfill = 0;
|
||||
pInfo->nBackfillAttempted = 0;
|
||||
pInfo->aReadMark[1] = 0;
|
||||
for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
|
||||
assert( pInfo->aReadMark[0]==0 );
|
||||
@@ -1764,6 +1789,8 @@ static int walCheckpoint(
|
||||
i64 nSize; /* Current size of database file */
|
||||
u32 nBackfill = pInfo->nBackfill;
|
||||
|
||||
pInfo->nBackfillAttempted = mxSafeFrame;
|
||||
|
||||
/* Sync the WAL to disk */
|
||||
if( sync_flags ){
|
||||
rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
|
||||
@@ -2147,6 +2174,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
int mxI; /* Index of largest aReadMark[] value */
|
||||
int i; /* Loop counter */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
u32 mxFrame; /* Wal frame to lock to */
|
||||
|
||||
assert( pWal->readLock<0 ); /* Not currently locked */
|
||||
|
||||
@@ -2210,7 +2238,12 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
}
|
||||
|
||||
pInfo = walCkptInfo(pWal);
|
||||
if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame ){
|
||||
if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
&& (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0
|
||||
|| 0==memcmp(&pWal->hdr, pWal->pSnapshot, sizeof(WalIndexHdr)))
|
||||
#endif
|
||||
){
|
||||
/* The WAL has been completely backfilled (or it is empty).
|
||||
** and can be safely ignored.
|
||||
*/
|
||||
@@ -2248,85 +2281,88 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
*/
|
||||
mxReadMark = 0;
|
||||
mxI = 0;
|
||||
mxFrame = pWal->hdr.mxFrame;
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
if( pWal->pSnapshot && pWal->pSnapshot->mxFrame<mxFrame ){
|
||||
mxFrame = pWal->pSnapshot->mxFrame;
|
||||
}
|
||||
#endif
|
||||
for(i=1; i<WAL_NREADER; i++){
|
||||
u32 thisMark = pInfo->aReadMark[i];
|
||||
if( mxReadMark<=thisMark && thisMark<=pWal->hdr.mxFrame ){
|
||||
if( mxReadMark<=thisMark && thisMark<=mxFrame ){
|
||||
assert( thisMark!=READMARK_NOT_USED );
|
||||
mxReadMark = thisMark;
|
||||
mxI = i;
|
||||
}
|
||||
}
|
||||
/* There was once an "if" here. The extra "{" is to preserve indentation. */
|
||||
{
|
||||
if( (pWal->readOnly & WAL_SHM_RDONLY)==0
|
||||
&& (mxReadMark<pWal->hdr.mxFrame || mxI==0)
|
||||
){
|
||||
for(i=1; i<WAL_NREADER; i++){
|
||||
rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
|
||||
if( rc==SQLITE_OK ){
|
||||
mxReadMark = pInfo->aReadMark[i] = pWal->hdr.mxFrame;
|
||||
mxI = i;
|
||||
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
|
||||
break;
|
||||
}else if( rc!=SQLITE_BUSY ){
|
||||
return rc;
|
||||
}
|
||||
if( (pWal->readOnly & WAL_SHM_RDONLY)==0
|
||||
&& (mxReadMark<mxFrame || mxI==0)
|
||||
){
|
||||
for(i=1; i<WAL_NREADER; i++){
|
||||
rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
|
||||
if( rc==SQLITE_OK ){
|
||||
mxReadMark = pInfo->aReadMark[i] = mxFrame;
|
||||
mxI = i;
|
||||
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
|
||||
break;
|
||||
}else if( rc!=SQLITE_BUSY ){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if( mxI==0 ){
|
||||
assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
|
||||
return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK;
|
||||
}
|
||||
}
|
||||
if( mxI==0 ){
|
||||
assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
|
||||
return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK;
|
||||
}
|
||||
|
||||
rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
|
||||
if( rc ){
|
||||
return rc==SQLITE_BUSY ? WAL_RETRY : rc;
|
||||
}
|
||||
/* Now that the read-lock has been obtained, check that neither the
|
||||
** value in the aReadMark[] array or the contents of the wal-index
|
||||
** header have changed.
|
||||
**
|
||||
** It is necessary to check that the wal-index header did not change
|
||||
** between the time it was read and when the shared-lock was obtained
|
||||
** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
|
||||
** that the log file may have been wrapped by a writer, or that frames
|
||||
** that occur later in the log than pWal->hdr.mxFrame may have been
|
||||
** copied into the database by a checkpointer. If either of these things
|
||||
** happened, then reading the database with the current value of
|
||||
** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
|
||||
** instead.
|
||||
**
|
||||
** Before checking that the live wal-index header has not changed
|
||||
** since it was read, set Wal.minFrame to the first frame in the wal
|
||||
** file that has not yet been checkpointed. This client will not need
|
||||
** to read any frames earlier than minFrame from the wal file - they
|
||||
** can be safely read directly from the database file.
|
||||
**
|
||||
** Because a ShmBarrier() call is made between taking the copy of
|
||||
** nBackfill and checking that the wal-header in shared-memory still
|
||||
** matches the one cached in pWal->hdr, it is guaranteed that the
|
||||
** checkpointer that set nBackfill was not working with a wal-index
|
||||
** header newer than that cached in pWal->hdr. If it were, that could
|
||||
** cause a problem. The checkpointer could omit to checkpoint
|
||||
** a version of page X that lies before pWal->minFrame (call that version
|
||||
** A) on the basis that there is a newer version (version B) of the same
|
||||
** page later in the wal file. But if version B happens to like past
|
||||
** frame pWal->hdr.mxFrame - then the client would incorrectly assume
|
||||
** that it can read version A from the database file. However, since
|
||||
** we can guarantee that the checkpointer that set nBackfill could not
|
||||
** see any pages past pWal->hdr.mxFrame, this problem does not come up.
|
||||
*/
|
||||
pWal->minFrame = pInfo->nBackfill+1;
|
||||
walShmBarrier(pWal);
|
||||
if( pInfo->aReadMark[mxI]!=mxReadMark
|
||||
|| memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
|
||||
){
|
||||
walUnlockShared(pWal, WAL_READ_LOCK(mxI));
|
||||
return WAL_RETRY;
|
||||
}else{
|
||||
assert( mxReadMark<=pWal->hdr.mxFrame );
|
||||
pWal->readLock = (i16)mxI;
|
||||
}
|
||||
rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
|
||||
if( rc ){
|
||||
return rc==SQLITE_BUSY ? WAL_RETRY : rc;
|
||||
}
|
||||
/* Now that the read-lock has been obtained, check that neither the
|
||||
** value in the aReadMark[] array or the contents of the wal-index
|
||||
** header have changed.
|
||||
**
|
||||
** It is necessary to check that the wal-index header did not change
|
||||
** between the time it was read and when the shared-lock was obtained
|
||||
** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
|
||||
** that the log file may have been wrapped by a writer, or that frames
|
||||
** that occur later in the log than pWal->hdr.mxFrame may have been
|
||||
** copied into the database by a checkpointer. If either of these things
|
||||
** happened, then reading the database with the current value of
|
||||
** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
|
||||
** instead.
|
||||
**
|
||||
** Before checking that the live wal-index header has not changed
|
||||
** since it was read, set Wal.minFrame to the first frame in the wal
|
||||
** file that has not yet been checkpointed. This client will not need
|
||||
** to read any frames earlier than minFrame from the wal file - they
|
||||
** can be safely read directly from the database file.
|
||||
**
|
||||
** Because a ShmBarrier() call is made between taking the copy of
|
||||
** nBackfill and checking that the wal-header in shared-memory still
|
||||
** matches the one cached in pWal->hdr, it is guaranteed that the
|
||||
** checkpointer that set nBackfill was not working with a wal-index
|
||||
** header newer than that cached in pWal->hdr. If it were, that could
|
||||
** cause a problem. The checkpointer could omit to checkpoint
|
||||
** a version of page X that lies before pWal->minFrame (call that version
|
||||
** A) on the basis that there is a newer version (version B) of the same
|
||||
** page later in the wal file. But if version B happens to like past
|
||||
** frame pWal->hdr.mxFrame - then the client would incorrectly assume
|
||||
** that it can read version A from the database file. However, since
|
||||
** we can guarantee that the checkpointer that set nBackfill could not
|
||||
** see any pages past pWal->hdr.mxFrame, this problem does not come up.
|
||||
*/
|
||||
pWal->minFrame = pInfo->nBackfill+1;
|
||||
walShmBarrier(pWal);
|
||||
if( pInfo->aReadMark[mxI]!=mxReadMark
|
||||
|| memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
|
||||
){
|
||||
walUnlockShared(pWal, WAL_READ_LOCK(mxI));
|
||||
return WAL_RETRY;
|
||||
}else{
|
||||
assert( mxReadMark<=pWal->hdr.mxFrame );
|
||||
pWal->readLock = (i16)mxI;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -2349,6 +2385,14 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
|
||||
int rc; /* Return code */
|
||||
int cnt = 0; /* Number of TryBeginRead attempts */
|
||||
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
int bChanged = 0;
|
||||
WalIndexHdr *pSnapshot = pWal->pSnapshot;
|
||||
if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
|
||||
bChanged = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
do{
|
||||
rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
|
||||
}while( rc==WAL_RETRY );
|
||||
@@ -2356,6 +2400,66 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
|
||||
testcase( (rc&0xff)==SQLITE_IOERR );
|
||||
testcase( rc==SQLITE_PROTOCOL );
|
||||
testcase( rc==SQLITE_OK );
|
||||
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
if( rc==SQLITE_OK ){
|
||||
if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
|
||||
/* At this point the client has a lock on an aReadMark[] slot holding
|
||||
** a value equal to or smaller than pSnapshot->mxFrame, but pWal->hdr
|
||||
** is populated with the wal-index header corresponding to the head
|
||||
** of the wal file. Verify that pSnapshot is still valid before
|
||||
** continuing. Reasons why pSnapshot might no longer be valid:
|
||||
**
|
||||
** (1) The WAL file has been reset since the snapshot was taken.
|
||||
** In this case, the salt will have changed.
|
||||
**
|
||||
** (2) A checkpoint as been attempted that wrote frames past
|
||||
** pSnapshot->mxFrame into the database file. Note that the
|
||||
** checkpoint need not have completed for this to cause problems.
|
||||
*/
|
||||
volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
|
||||
|
||||
assert( pWal->readLock>0 || pWal->hdr.mxFrame==0 );
|
||||
assert( pInfo->aReadMark[pWal->readLock]<=pSnapshot->mxFrame );
|
||||
|
||||
/* It is possible that there is a checkpointer thread running
|
||||
** concurrent with this code. If this is the case, it may be that the
|
||||
** checkpointer has already determined that it will checkpoint
|
||||
** snapshot X, where X is later in the wal file than pSnapshot, but
|
||||
** has not yet set the pInfo->nBackfillAttempted variable to indicate
|
||||
** its intent. To avoid the race condition this leads to, ensure that
|
||||
** there is no checkpointer process by taking a shared CKPT lock
|
||||
** before checking pInfo->nBackfillAttempted. */
|
||||
rc = walLockShared(pWal, WAL_CKPT_LOCK);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
/* Check that the wal file has not been wrapped. Assuming that it has
|
||||
** not, also check that no checkpointer has attempted to checkpoint any
|
||||
** frames beyond pSnapshot->mxFrame. If either of these conditions are
|
||||
** true, return SQLITE_BUSY_SNAPSHOT. Otherwise, overwrite pWal->hdr
|
||||
** with *pSnapshot and set *pChanged as appropriate for opening the
|
||||
** snapshot. */
|
||||
if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
|
||||
&& pSnapshot->mxFrame>=pInfo->nBackfillAttempted
|
||||
){
|
||||
assert( pWal->readLock>0 );
|
||||
memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr));
|
||||
*pChanged = bChanged;
|
||||
}else{
|
||||
rc = SQLITE_BUSY_SNAPSHOT;
|
||||
}
|
||||
|
||||
/* Release the shared CKPT lock obtained above. */
|
||||
walUnlockShared(pWal, WAL_CKPT_LOCK);
|
||||
}
|
||||
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3WalEndReadTransaction(pWal);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3165,6 +3269,35 @@ int sqlite3WalHeapMemory(Wal *pWal){
|
||||
return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE );
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
/* Create a snapshot object. The content of a snapshot is opaque to
|
||||
** every other subsystem, so the WAL module can put whatever it needs
|
||||
** in the object.
|
||||
*/
|
||||
int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){
|
||||
int rc = SQLITE_OK;
|
||||
WalIndexHdr *pRet;
|
||||
|
||||
assert( pWal->readLock>=0 && pWal->writeLock==0 );
|
||||
|
||||
pRet = (WalIndexHdr*)sqlite3_malloc(sizeof(WalIndexHdr));
|
||||
if( pRet==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memcpy(pRet, &pWal->hdr, sizeof(WalIndexHdr));
|
||||
*ppSnapshot = (sqlite3_snapshot*)pRet;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Try to open on pSnapshot when the next read-transaction starts
|
||||
*/
|
||||
void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot){
|
||||
pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_SNAPSHOT */
|
||||
|
||||
#ifdef SQLITE_ENABLE_ZIPVFS
|
||||
/*
|
||||
** If the argument is not NULL, it points to a Wal object that holds a
|
||||
|
||||
@@ -126,6 +126,11 @@ int sqlite3WalExclusiveMode(Wal *pWal, int op);
|
||||
*/
|
||||
int sqlite3WalHeapMemory(Wal *pWal);
|
||||
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot);
|
||||
void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_ZIPVFS
|
||||
/* If the WAL file is not empty, return the number of bytes of content
|
||||
** stored in each frame (i.e. the db page-size when the WAL was created).
|
||||
|
||||
+7
-2
@@ -125,8 +125,8 @@ ifcapable attach {
|
||||
|
||||
# Default setting of PRAGMA cache_spill is always ON
|
||||
#
|
||||
# EVIDENCE-OF: R-51036-62828 PRAGMA cache_spill; PRAGMA
|
||||
# cache_spill=boolean;
|
||||
# EVIDENCE-OF: R-63549-59887 PRAGMA cache_spill; PRAGMA
|
||||
# cache_spill=boolean; PRAGMA schema.cache_spill=N;
|
||||
#
|
||||
# EVIDENCE-OF: R-23955-02765 Cache_spill is enabled by default
|
||||
#
|
||||
@@ -190,6 +190,11 @@ do_test pragma2-4.5.1 {
|
||||
PRAGMA lock_status;
|
||||
}
|
||||
} {0 main reserved temp unknown} ;# No cache spill, so no exclusive lock
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-34657-61226 The "PRAGMA cache_spill=N" form of this
|
||||
# pragma sets a minimum cache size threshold required for spilling to
|
||||
# occur.
|
||||
do_test pragma2-4.5.2 {
|
||||
db eval {
|
||||
ROLLBACK;
|
||||
|
||||
@@ -0,0 +1,340 @@
|
||||
# 2015 December 7
|
||||
#
|
||||
# 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 the sqlite3_snapshot_xxx() APIs.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !snapshot {finish_test; return}
|
||||
set testprefix snapshot
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check some error conditions in snapshot_get(). It is an error if:
|
||||
#
|
||||
# 1) snapshot_get() is called on a non-WAL database, or
|
||||
# 2) there is an open write transaction on the database.
|
||||
#
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
}
|
||||
|
||||
do_test 1.1.1 {
|
||||
execsql { BEGIN; SELECT * FROM t1; }
|
||||
list [catch { sqlite3_snapshot_get db main } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
do_execsql_test 1.1.2 COMMIT
|
||||
|
||||
do_test 1.2.1 {
|
||||
execsql {
|
||||
PRAGMA journal_mode = WAL;
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
INSERT INTO t1 VALUES(7, 8);
|
||||
}
|
||||
list [catch { sqlite3_snapshot_get db main } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
do_execsql_test 1.3.2 COMMIT
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that a simple case works. Reuse the database created by the
|
||||
# block of tests above.
|
||||
#
|
||||
do_execsql_test 2.1.0 {
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
} {1 2 3 4 5 6 7 8}
|
||||
|
||||
breakpoint
|
||||
do_test 2.1.1 {
|
||||
set snapshot [sqlite3_snapshot_get db main]
|
||||
execsql {
|
||||
COMMIT;
|
||||
INSERT INTO t1 VALUES(9, 10);
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2 3 4 5 6 7 8 9 10}
|
||||
|
||||
do_test 2.1.2 {
|
||||
execsql BEGIN
|
||||
sqlite3_snapshot_open db main $snapshot
|
||||
execsql {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2 3 4 5 6 7 8}
|
||||
|
||||
do_test 2.1.3 {
|
||||
sqlite3_snapshot_free $snapshot
|
||||
execsql COMMIT
|
||||
} {}
|
||||
|
||||
do_test 2.2.0 {
|
||||
sqlite3 db2 test.db
|
||||
execsql {
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
} db2
|
||||
} {1 2 3 4 5 6 7 8 9 10}
|
||||
|
||||
do_test 2.2.1 {
|
||||
set snapshot [sqlite3_snapshot_get db2 main]
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES(11, 12);
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2 3 4 5 6 7 8 9 10 11 12}
|
||||
|
||||
do_test 2.2.2 {
|
||||
execsql BEGIN
|
||||
sqlite3_snapshot_open db main $snapshot
|
||||
execsql {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2 3 4 5 6 7 8 9 10}
|
||||
|
||||
do_test 2.2.3 {
|
||||
sqlite3_snapshot_free $snapshot
|
||||
execsql COMMIT
|
||||
execsql COMMIT db2
|
||||
db2 close
|
||||
} {}
|
||||
|
||||
do_test 2.3.1 {
|
||||
execsql { DELETE FROM t1 WHERE a>6 }
|
||||
set snapshot [sqlite3_snapshot_get db main]
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES('a', 'b');
|
||||
INSERT INTO t1 VALUES('c', 'd');
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2 3 4 5 6 a b c d}
|
||||
do_test 2.3.2 {
|
||||
execsql BEGIN
|
||||
sqlite3_snapshot_open db main $snapshot
|
||||
execsql { SELECT * FROM t1 }
|
||||
} {1 2 3 4 5 6}
|
||||
|
||||
do_test 2.3.3 {
|
||||
catchsql {
|
||||
INSERT INTO t1 VALUES('x','y')
|
||||
}
|
||||
} {1 {database is locked}}
|
||||
do_test 2.3.4 {
|
||||
execsql COMMIT
|
||||
sqlite3_snapshot_free $snapshot
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check some errors in sqlite3_snapshot_open(). It is an error if:
|
||||
#
|
||||
# 1) the db is in auto-commit mode,
|
||||
# 2) the db has an open (read or write) transaction,
|
||||
# 3) the db is not a wal database,
|
||||
#
|
||||
# Reuse the database created by earlier tests.
|
||||
#
|
||||
do_execsql_test 3.0.0 {
|
||||
CREATE TABLE t2(x, y);
|
||||
INSERT INTO t2 VALUES('a', 'b');
|
||||
INSERT INTO t2 VALUES('c', 'd');
|
||||
BEGIN;
|
||||
SELECT * FROM t2;
|
||||
} {a b c d}
|
||||
do_test 3.0.1 {
|
||||
set snapshot [sqlite3_snapshot_get db main]
|
||||
execsql { COMMIT }
|
||||
execsql { INSERT INTO t2 VALUES('e', 'f'); }
|
||||
} {}
|
||||
|
||||
do_test 3.1 {
|
||||
list [catch {sqlite3_snapshot_open db main $snapshot } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
|
||||
do_test 3.2.1 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
SELECT * FROM t2;
|
||||
}
|
||||
} {a b c d e f}
|
||||
do_test 3.2.2 {
|
||||
list [catch {sqlite3_snapshot_open db main $snapshot } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
|
||||
do_test 3.2.3 {
|
||||
execsql {
|
||||
COMMIT;
|
||||
BEGIN;
|
||||
INSERT INTO t2 VALUES('g', 'h');
|
||||
}
|
||||
list [catch {sqlite3_snapshot_open db main $snapshot } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
do_execsql_test 3.2.4 COMMIT
|
||||
|
||||
do_test 3.3.1 {
|
||||
execsql { PRAGMA journal_mode = DELETE }
|
||||
execsql { BEGIN }
|
||||
list [catch {sqlite3_snapshot_open db main $snapshot } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
|
||||
do_test 3.3.2 {
|
||||
sqlite3_snapshot_free $snapshot
|
||||
execsql COMMIT
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that SQLITE_BUSY_SNAPSHOT is returned if the specified snapshot
|
||||
# no longer exists because the wal file has been checkpointed.
|
||||
#
|
||||
# 1. Reading a snapshot from the middle of a wal file is not possible
|
||||
# after the wal file has been checkpointed.
|
||||
#
|
||||
# 2. That a snapshot from the end of a wal file can not be read once
|
||||
# the wal file has been wrapped.
|
||||
#
|
||||
do_execsql_test 4.1.0 {
|
||||
PRAGMA journal_mode = wal;
|
||||
CREATE TABLE t3(i, j);
|
||||
INSERT INTO t3 VALUES('o', 't');
|
||||
INSERT INTO t3 VALUES('t', 'f');
|
||||
BEGIN;
|
||||
SELECT * FROM t3;
|
||||
} {wal o t t f}
|
||||
|
||||
do_test 4.1.1 {
|
||||
set snapshot [sqlite3_snapshot_get db main]
|
||||
execsql COMMIT
|
||||
} {}
|
||||
do_test 4.1.2 {
|
||||
execsql {
|
||||
INSERT INTO t3 VALUES('f', 's');
|
||||
BEGIN;
|
||||
}
|
||||
sqlite3_snapshot_open db main $snapshot
|
||||
execsql { SELECT * FROM t3 }
|
||||
} {o t t f}
|
||||
|
||||
do_test 4.1.3 {
|
||||
execsql {
|
||||
COMMIT;
|
||||
PRAGMA wal_checkpoint;
|
||||
BEGIN;
|
||||
}
|
||||
list [catch {sqlite3_snapshot_open db main $snapshot} msg] $msg
|
||||
} {1 SQLITE_BUSY_SNAPSHOT}
|
||||
do_test 4.1.4 {
|
||||
sqlite3_snapshot_free $snapshot
|
||||
execsql COMMIT
|
||||
} {}
|
||||
|
||||
do_test 4.2.1 {
|
||||
execsql {
|
||||
INSERT INTO t3 VALUES('s', 'e');
|
||||
INSERT INTO t3 VALUES('n', 't');
|
||||
BEGIN;
|
||||
SELECT * FROM t3;
|
||||
}
|
||||
} {o t t f f s s e n t}
|
||||
do_test 4.2.2 {
|
||||
set snapshot [sqlite3_snapshot_get db main]
|
||||
execsql {
|
||||
COMMIT;
|
||||
PRAGMA wal_checkpoint;
|
||||
BEGIN;
|
||||
}
|
||||
sqlite3_snapshot_open db main $snapshot
|
||||
execsql { SELECT * FROM t3 }
|
||||
} {o t t f f s s e n t}
|
||||
do_test 4.2.3 {
|
||||
execsql {
|
||||
COMMIT;
|
||||
INSERT INTO t3 VALUES('e', 't');
|
||||
BEGIN;
|
||||
}
|
||||
list [catch {sqlite3_snapshot_open db main $snapshot} msg] $msg
|
||||
} {1 SQLITE_BUSY_SNAPSHOT}
|
||||
do_test 4.2.4 {
|
||||
sqlite3_snapshot_free $snapshot
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that SQLITE_BUSY is returned if a checkpoint is running when
|
||||
# sqlite3_snapshot_open() is called.
|
||||
#
|
||||
reset_db
|
||||
db close
|
||||
testvfs tvfs
|
||||
sqlite3 db test.db -vfs tvfs
|
||||
|
||||
do_execsql_test 5.1 {
|
||||
PRAGMA journal_mode = wal;
|
||||
CREATE TABLE x1(x, xx, xxx);
|
||||
INSERT INTO x1 VALUES('z', 'zz', 'zzz');
|
||||
BEGIN;
|
||||
SELECT * FROM x1;
|
||||
} {wal z zz zzz}
|
||||
|
||||
do_test 5.2 {
|
||||
set ::snapshot [sqlite3_snapshot_get db main]
|
||||
sqlite3 db2 test.db -vfs tvfs
|
||||
execsql {
|
||||
INSERT INTO x1 VALUES('a', 'aa', 'aaa');
|
||||
COMMIT;
|
||||
}
|
||||
} {}
|
||||
|
||||
set t53 0
|
||||
proc write_callback {args} {
|
||||
do_test 5.3.[incr ::t53] {
|
||||
execsql BEGIN
|
||||
list [catch { sqlite3_snapshot_open db main $::snapshot } msg] $msg
|
||||
} {1 SQLITE_BUSY}
|
||||
catchsql COMMIT
|
||||
}
|
||||
|
||||
tvfs filter xWrite
|
||||
tvfs script write_callback
|
||||
db2 eval { PRAGMA wal_checkpoint }
|
||||
db close
|
||||
db2 close
|
||||
tvfs delete
|
||||
sqlite3_snapshot_free $snapshot
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that sqlite3_snapshot_get() may be called immediately after
|
||||
# "BEGIN; PRAGMA user_version;". And that sqlite3_snapshot_open() may
|
||||
# be called after opening the db handle and running the script
|
||||
# "PRAGMA user_version; BEGIN".
|
||||
reset_db
|
||||
do_execsql_test 6.1 {
|
||||
PRAGMA journal_mode = wal;
|
||||
CREATE TABLE x1(x, xx, xxx);
|
||||
INSERT INTO x1 VALUES('z', 'zz', 'zzz');
|
||||
BEGIN;
|
||||
PRAGMA user_version;
|
||||
} {wal 0}
|
||||
do_test 6.2 {
|
||||
set ::snapshot [sqlite3_snapshot_get db main]
|
||||
execsql {
|
||||
INSERT INTO x1 VALUES('a', 'aa', 'aaa');
|
||||
COMMIT;
|
||||
}
|
||||
} {}
|
||||
do_test 6.3 {
|
||||
sqlite3 db2 test.db
|
||||
db2 eval "PRAGMA user_version ; BEGIN"
|
||||
sqlite3_snapshot_open db2 main $::snapshot
|
||||
db2 eval { SELECT * FROM x1 }
|
||||
} {z zz zzz}
|
||||
sqlite3_snapshot_free $snapshot
|
||||
|
||||
finish_test
|
||||
@@ -0,0 +1,164 @@
|
||||
# 2015 December 10
|
||||
#
|
||||
# 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 the sqlite3_snapshot_xxx() APIs.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !snapshot {finish_test; return}
|
||||
set testprefix snapshot_fault
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that an sqlite3_snapshot_open() client cannot be tricked into
|
||||
# reading a corrupt snapshot even if a second client fails while
|
||||
# checkpointing the db.
|
||||
#
|
||||
do_faultsim_test 1.0 -prep {
|
||||
faultsim_delete_and_reopen
|
||||
sqlite3 db2 test.db
|
||||
db2 eval {
|
||||
CREATE TABLE t1(a, b UNIQUE, c UNIQUE);
|
||||
INSERT INTO t1 VALUES(1, randomblob(500), randomblob(500));
|
||||
INSERT INTO t1 VALUES(2, randomblob(500), randomblob(500));
|
||||
PRAGMA journal_mode = wal;
|
||||
INSERT INTO t1 VALUES(3, randomblob(500), randomblob(500));
|
||||
BEGIN;
|
||||
SELECT a FROM t1;
|
||||
}
|
||||
set ::snapshot [sqlite3_snapshot_get db2 main]
|
||||
db2 eval COMMIT
|
||||
db2 eval {
|
||||
UPDATE t1 SET b=randomblob(501), c=randomblob(501) WHERE a=1;
|
||||
INSERT INTO t1 VALUES(4, randomblob(500), randomblob(500));
|
||||
INSERT INTO t1 VALUES(5, randomblob(500), randomblob(500));
|
||||
INSERT INTO t1 VALUES(6, randomblob(500), randomblob(500));
|
||||
}
|
||||
} -body {
|
||||
db eval { PRAGMA wal_checkpoint }
|
||||
} -test {
|
||||
db2 eval BEGIN
|
||||
if {[catch { sqlite3_snapshot_open db2 main $::snapshot } msg]} {
|
||||
if {$msg != "SQLITE_BUSY_SNAPSHOT" && $msg != "SQLITE_BUSY"} {
|
||||
error "error is $msg"
|
||||
}
|
||||
} else {
|
||||
set res [db2 eval {
|
||||
SELECT a FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
}]
|
||||
if {$res != "1 2 3 ok"} { error "res is $res" }
|
||||
}
|
||||
|
||||
sqlite3_snapshot_free $::snapshot
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# This test is similar to the previous one. Except, after the
|
||||
# "PRAGMA wal_checkpoint" command fails the db is closed and reopened
|
||||
# so as to require wal file recovery. It should not be possible to open
|
||||
# a snapshot that is part of the body of a recovered wal file.
|
||||
#
|
||||
do_faultsim_test 2.0 -prep {
|
||||
faultsim_delete_and_reopen
|
||||
db eval {
|
||||
CREATE TABLE t1(a, b UNIQUE, c UNIQUE);
|
||||
INSERT INTO t1 VALUES(1, randomblob(500), randomblob(500));
|
||||
INSERT INTO t1 VALUES(2, randomblob(500), randomblob(500));
|
||||
PRAGMA journal_mode = wal;
|
||||
INSERT INTO t1 VALUES(3, randomblob(500), randomblob(500));
|
||||
BEGIN;
|
||||
SELECT a FROM t1;
|
||||
}
|
||||
set ::snapshot [sqlite3_snapshot_get db main]
|
||||
db eval COMMIT
|
||||
|
||||
db eval {
|
||||
UPDATE t1 SET b=randomblob(501), c=randomblob(501) WHERE a=1;
|
||||
INSERT INTO t1 VALUES(4, randomblob(500), randomblob(500));
|
||||
INSERT INTO t1 VALUES(5, randomblob(500), randomblob(500));
|
||||
INSERT INTO t1 VALUES(6, randomblob(500), randomblob(500));
|
||||
}
|
||||
} -body {
|
||||
db eval { PRAGMA wal_checkpoint }
|
||||
} -test {
|
||||
|
||||
db_save
|
||||
db close
|
||||
db_restore_and_reopen
|
||||
db eval { SELECT * FROM t1 }
|
||||
|
||||
db eval BEGIN
|
||||
if {[catch { sqlite3_snapshot_open db main $::snapshot } msg]} {
|
||||
if {$msg != "SQLITE_BUSY_SNAPSHOT" && $msg != "SQLITE_BUSY"} {
|
||||
error "error is $msg"
|
||||
}
|
||||
} else {
|
||||
# This branch should actually never be taken. But it was useful in
|
||||
# determining whether or not this test was actually working (by
|
||||
# running a modified version of SQLite that allowed snapshots to be
|
||||
# opened following a recovery).
|
||||
error "TEST HAS FAILED"
|
||||
|
||||
set res [db eval {
|
||||
SELECT a FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
}]
|
||||
if {$res != "1 2 3 ok"} { error "res is $res" }
|
||||
}
|
||||
|
||||
sqlite3_snapshot_free $::snapshot
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test the handling of faults that occur within sqlite3_snapshot_open().
|
||||
#
|
||||
do_faultsim_test 3.0 -prep {
|
||||
faultsim_delete_and_reopen
|
||||
db eval {
|
||||
CREATE TABLE t1(a, b UNIQUE, c UNIQUE);
|
||||
INSERT INTO t1 VALUES(1, randomblob(500), randomblob(500));
|
||||
INSERT INTO t1 VALUES(2, randomblob(500), randomblob(500));
|
||||
PRAGMA journal_mode = wal;
|
||||
INSERT INTO t1 VALUES(3, randomblob(500), randomblob(500));
|
||||
BEGIN;
|
||||
SELECT a FROM t1;
|
||||
}
|
||||
set ::snapshot [sqlite3_snapshot_get db main]
|
||||
db eval COMMIT
|
||||
db eval {
|
||||
UPDATE t1 SET b=randomblob(501), c=randomblob(501) WHERE a=1;
|
||||
INSERT INTO t1 VALUES(4, randomblob(500), randomblob(500));
|
||||
INSERT INTO t1 VALUES(5, randomblob(500), randomblob(500));
|
||||
INSERT INTO t1 VALUES(6, randomblob(500), randomblob(500));
|
||||
BEGIN;
|
||||
}
|
||||
} -body {
|
||||
if { [catch { sqlite3_snapshot_open db main $::snapshot } msg] } {
|
||||
error $msg
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}} {1 SQLITE_IOERR} \
|
||||
{1 SQLITE_IOERR_NOMEM} {1 SQLITE_IOERR_READ}
|
||||
if {$testrc==0} {
|
||||
set res [db eval {
|
||||
SELECT a FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
}]
|
||||
if {$res != "1 2 3 ok"} { error "res is $res" }
|
||||
}
|
||||
|
||||
sqlite3_snapshot_free $::snapshot
|
||||
}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -226,6 +226,7 @@ do_faultsim_test 3 -faults vfsfault-* -prep {
|
||||
faultsim_delete_and_reopen
|
||||
file_control_chunksize_test db main 8192
|
||||
execsql {
|
||||
PRAGMA synchronous=OFF;
|
||||
CREATE TABLE t1(a, b);
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
|
||||
+32
-2
@@ -88,6 +88,13 @@
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "test_multiplex.h"
|
||||
|
||||
/* Required to link test_multiplex.c */
|
||||
#ifndef SQLITE_OMIT_WSD
|
||||
int sqlite3PendingByte = 0x40000000;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This code implements the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
@@ -1460,13 +1467,36 @@ int main(int argc, char **argv){
|
||||
argc = 2;
|
||||
argv = substArgv;
|
||||
}
|
||||
|
||||
/* Loop through the command-line arguments to ensure that each argument
|
||||
** selects at least one test. If not, assume there is a typo on the
|
||||
** command-line and bail out with the usage message. */
|
||||
for(iArg=1; iArg<argc; iArg++){
|
||||
const char *zArg = argv[iArg];
|
||||
if( zArg[0]=='-' ){
|
||||
if( sqlite3_stricmp(zArg, "-multiplexor")==0 ){
|
||||
/* Install the multiplexor VFS as the default */
|
||||
int rc = sqlite3_multiplex_initialize(0, 1);
|
||||
if( rc!=SQLITE_OK ){
|
||||
fprintf(stderr, "Failed to install multiplexor VFS (%d)\n", rc);
|
||||
return 253;
|
||||
}
|
||||
}
|
||||
else {
|
||||
goto usage;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
|
||||
if( sqlite3_strglob(argv[iArg],aTest[i].zTest)==0 ) break;
|
||||
if( sqlite3_strglob(zArg, aTest[i].zTest)==0 ) break;
|
||||
}
|
||||
if( i>=sizeof(aTest)/sizeof(aTest[0]) ) goto usage;
|
||||
}
|
||||
|
||||
for(iArg=1; iArg<argc; iArg++){
|
||||
if( argv[iArg][0]=='-' ) continue;
|
||||
for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
|
||||
char const *z = aTest[i].zTest;
|
||||
if( sqlite3_strglob(argv[iArg],z)==0 ){
|
||||
@@ -1483,7 +1513,7 @@ int main(int argc, char **argv){
|
||||
return (nGlobalErr>0 ? 255 : 0);
|
||||
|
||||
usage:
|
||||
printf("Usage: %s [testname|testprefix*]...\n", argv[0]);
|
||||
printf("Usage: %s [-multiplexor] [testname|testprefix*]...\n", argv[0]);
|
||||
printf("Available tests are:\n");
|
||||
for(i=0; i<sizeof(aTest)/sizeof(aTest[0]); i++){
|
||||
printf(" %s\n", aTest[i].zTest);
|
||||
|
||||
+1
-3
@@ -125,7 +125,7 @@ if {1} {
|
||||
}
|
||||
return $res
|
||||
} else {
|
||||
return [exec ls -U /]
|
||||
return [string map {/ {}} [glob /*]]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,5 +214,3 @@ if {1} {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -47,6 +47,18 @@ do_test where7-1.1 {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1 2 3 4 2 3 4 5 3 4 6 8 4 5 10 15 5 10 100 1000}
|
||||
do_execsql_test where7-1.1.1 {
|
||||
CREATE TABLE t(a);
|
||||
CREATE INDEX ta ON t(a);
|
||||
INSERT INTO t(a) VALUES(1),(2);
|
||||
SELECT * FROM t ORDER BY a;
|
||||
SELECT * FROM t WHERE a<2 OR a<3 ORDER BY a;
|
||||
PRAGMA count_changes=ON;
|
||||
DELETE FROM t WHERE a<2 OR a<3;
|
||||
SELECT * FROM t;
|
||||
PRAGMA count_changes=OFF;
|
||||
DROP TABLE t;
|
||||
} {1 2 1 2 2}
|
||||
do_test where7-1.2 {
|
||||
count_steps {
|
||||
SELECT a FROM t1 WHERE b=3 OR c=6 ORDER BY a
|
||||
|
||||
@@ -975,4 +975,20 @@ do_execsql_test 17.9 {
|
||||
SELECT * FROM x4;
|
||||
} {10 11}
|
||||
|
||||
# Added to test a fix to a faulty assert() discovered by libFuzzer.
|
||||
#
|
||||
do_execsql_test 18.1 {
|
||||
WITH xyz(x) AS (VALUES(NULL) UNION SELECT round(1<x) FROM xyz ORDER BY 1)
|
||||
SELECT quote(x) FROM xyz;
|
||||
} {NULL}
|
||||
do_execsql_test 18.2 {
|
||||
WITH xyz(x) AS (
|
||||
SELECT printf('%d', 5) * NULL
|
||||
UNION SELECT round(1<1+x)
|
||||
FROM xyz ORDER BY 1
|
||||
)
|
||||
SELECT 1 FROM xyz;
|
||||
} 1
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ IF NOT DEFINED TEMP (
|
||||
%_VECHO% Temp = '%TEMP%'
|
||||
|
||||
IF NOT DEFINED TCLKIT_URI (
|
||||
SET TCLKIT_URI=http://tclsh.com/
|
||||
SET TCLKIT_URI=https://tclsh.com/
|
||||
)
|
||||
|
||||
%_VECHO% TclKitUri = '%TCLKIT_URI%'
|
||||
|
||||
@@ -320,7 +320,7 @@ REM
|
||||
IF DEFINED UCRTVersion (
|
||||
SET NUCRTVER=%UCRTVersion%
|
||||
) ELSE (
|
||||
SET NUCRTVER=10.0.10240.0
|
||||
SET NUCRTVER=10.0.10586.0
|
||||
)
|
||||
|
||||
REM
|
||||
|
||||
+6
-10
@@ -43,20 +43,16 @@ cp $TOP/sqlite3.1 $TMPSPACE
|
||||
cp $TOP/sqlite3.pc.in $TMPSPACE
|
||||
cp $TOP/src/shell.c $TMPSPACE
|
||||
|
||||
chmod 755 $TMPSPACE/install-sh
|
||||
chmod 755 $TMPSPACE/missing
|
||||
chmod 755 $TMPSPACE/depcomp
|
||||
chmod 755 $TMPSPACE/config.sub
|
||||
chmod 755 $TMPSPACE/config.guess
|
||||
|
||||
cat $TMPSPACE/configure.ac |
|
||||
sed "s/AC_INIT(sqlite, .*, http:\/\/www.sqlite.org)/AC_INIT(sqlite, $VERSION, http:\/\/www.sqlite.org)/" > $TMPSPACE/tmp
|
||||
sed "s/--SQLITE-VERSION--/$VERSION/" > $TMPSPACE/tmp
|
||||
mv $TMPSPACE/tmp $TMPSPACE/configure.ac
|
||||
|
||||
cd $TMPSPACE
|
||||
aclocal
|
||||
autoconf
|
||||
automake --add-missing
|
||||
autoreconf -i
|
||||
#libtoolize
|
||||
#aclocal
|
||||
#autoconf
|
||||
#automake --add-missing
|
||||
|
||||
mkdir -p tea/generic
|
||||
echo "#ifdef USE_SYSTEM_SQLITE" > tea/generic/tclsqlite3.c
|
||||
|
||||
@@ -238,7 +238,7 @@ set pragma_def {
|
||||
IF: !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
|
||||
|
||||
NAME: parser_trace
|
||||
IF: defined(SQLITE_DEBUG)
|
||||
IF: defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE)
|
||||
|
||||
NAME: case_sensitive_like
|
||||
|
||||
|
||||
Reference in New Issue
Block a user