Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 426504965c |
+1
-2
@@ -402,7 +402,6 @@ TESTSRC = \
|
||||
$(TOP)/src/test_tclvar.c \
|
||||
$(TOP)/src/test_thread.c \
|
||||
$(TOP)/src/test_vfs.c \
|
||||
$(TOP)/src/test_windirent.c \
|
||||
$(TOP)/src/test_wsd.c \
|
||||
$(TOP)/ext/fts3/fts3_term.c \
|
||||
$(TOP)/ext/fts3/fts3_test.c \
|
||||
@@ -1156,7 +1155,7 @@ THREADTEST3_SRC = $(TOP)/test/threadtest3.c \
|
||||
$(TOP)/test/tt3_lookaside1.c
|
||||
|
||||
threadtest3$(TEXE): sqlite3.lo $(THREADTEST3_SRC)
|
||||
$(LTLINK) $(TOP)/test/threadtest3.c $(TOP)/src/test_multiplex.c sqlite3.lo -o $@ $(TLIBS)
|
||||
$(LTLINK) $(TOP)/test/threadtest3.c sqlite3.lo -o $@ $(TLIBS)
|
||||
|
||||
threadtest: threadtest3$(TEXE)
|
||||
./threadtest3$(TEXE)
|
||||
|
||||
+1
-2
@@ -50,7 +50,7 @@ API_ARMOR = 0
|
||||
!IFNDEF NO_WARN
|
||||
!IF $(USE_FULLWARN)!=0
|
||||
NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206
|
||||
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706
|
||||
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
@@ -1071,7 +1071,6 @@ TESTSRC = \
|
||||
$(TOP)\src\test_tclvar.c \
|
||||
$(TOP)\src\test_thread.c \
|
||||
$(TOP)\src\test_vfs.c \
|
||||
$(TOP)\src\test_windirent.c \
|
||||
$(TOP)\src\test_wsd.c \
|
||||
$(TOP)\ext\fts3\fts3_term.c \
|
||||
$(TOP)\ext\fts3\fts3_test.c \
|
||||
|
||||
+1530
File diff suppressed because it is too large
Load Diff
+1773
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@
|
||||
#
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT(sqlite, --SQLITE-VERSION--, http://www.sqlite.org)
|
||||
AC_INIT(sqlite, 3.7.5, http://www.sqlite.org)
|
||||
AC_CONFIG_SRCDIR([sqlite3.c])
|
||||
|
||||
# Use automake.
|
||||
|
||||
Executable
+708
@@ -0,0 +1,708 @@
|
||||
#! /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:
|
||||
Executable
+527
@@ -0,0 +1,527 @@
|
||||
#!/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
Executable
+331
@@ -0,0 +1,331 @@
|
||||
#! /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:
|
||||
@@ -398,7 +398,7 @@ static void showSegmentStats(sqlite3 *db, const char *zTab){
|
||||
if( sqlite3_step(pStmt)==SQLITE_ROW
|
||||
&& (nLeaf = sqlite3_column_int(pStmt, 0))>0
|
||||
){
|
||||
nIdx = sqlite3_column_int(pStmt, 5);
|
||||
int nIdx = sqlite3_column_int(pStmt, 5);
|
||||
sqlite3_int64 sz;
|
||||
printf("For level %d:\n", i);
|
||||
printf(" Number of indexes...................... %9d\n", nIdx);
|
||||
|
||||
+1
-1
@@ -544,7 +544,7 @@ int sqlite3Fts5AuxInit(fts5_api *pApi){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int i; /* To iterate through builtin functions */
|
||||
|
||||
for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){
|
||||
for(i=0; rc==SQLITE_OK && i<sizeof(aBuiltin)/sizeof(aBuiltin[0]); i++){
|
||||
rc = pApi->xCreateFunction(pApi,
|
||||
aBuiltin[i].zFunc,
|
||||
aBuiltin[i].pUserData,
|
||||
|
||||
+14
-33
@@ -216,53 +216,34 @@ static int fts5ConfigParseSpecial(
|
||||
if( sqlite3_strnicmp("prefix", zCmd, nCmd)==0 ){
|
||||
const int nByte = sizeof(int) * FTS5_MAX_PREFIX_INDEXES;
|
||||
const char *p;
|
||||
int bFirst = 1;
|
||||
if( pConfig->aPrefix==0 ){
|
||||
if( pConfig->aPrefix ){
|
||||
*pzErr = sqlite3_mprintf("multiple prefix=... directives");
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
pConfig->aPrefix = sqlite3Fts5MallocZero(&rc, nByte);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
|
||||
p = zArg;
|
||||
while( 1 ){
|
||||
while( rc==SQLITE_OK && p[0] ){
|
||||
int nPre = 0;
|
||||
|
||||
while( p[0]==' ' ) p++;
|
||||
if( bFirst==0 && p[0]==',' ){
|
||||
p++;
|
||||
while( p[0]==' ' ) p++;
|
||||
}else if( p[0]=='\0' ){
|
||||
break;
|
||||
}
|
||||
if( p[0]<'0' || p[0]>'9' ){
|
||||
*pzErr = sqlite3_mprintf("malformed prefix=... directive");
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if( pConfig->nPrefix==FTS5_MAX_PREFIX_INDEXES ){
|
||||
*pzErr = sqlite3_mprintf(
|
||||
"too many prefix indexes (max %d)", FTS5_MAX_PREFIX_INDEXES
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
while( p[0]>='0' && p[0]<='9' && nPre<1000 ){
|
||||
nPre = nPre*10 + (p[0] - '0');
|
||||
p++;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && (nPre<=0 || nPre>=1000) ){
|
||||
*pzErr = sqlite3_mprintf("prefix length out of range (max 999)");
|
||||
while( p[0]==' ' ) p++;
|
||||
if( p[0]==',' ){
|
||||
p++;
|
||||
}else if( p[0] ){
|
||||
*pzErr = sqlite3_mprintf("malformed prefix=... directive");
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
if( rc==SQLITE_OK && (nPre==0 || nPre>=1000) ){
|
||||
*pzErr = sqlite3_mprintf("prefix length out of range: %d", nPre);
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
pConfig->aPrefix[pConfig->nPrefix] = nPre;
|
||||
pConfig->nPrefix++;
|
||||
bFirst = 0;
|
||||
}
|
||||
assert( pConfig->nPrefix<=FTS5_MAX_PREFIX_INDEXES );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -407,7 +407,7 @@ static int fts5ExprPhraseIsMatch(
|
||||
|
||||
/* If the aStatic[] array is not large enough, allocate a large array
|
||||
** using sqlite3_malloc(). This approach could be improved upon. */
|
||||
if( pPhrase->nTerm>(int)ArraySize(aStatic) ){
|
||||
if( pPhrase->nTerm>(sizeof(aStatic) / sizeof(aStatic[0])) ){
|
||||
int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
|
||||
aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte);
|
||||
if( !aIter ) return SQLITE_NOMEM;
|
||||
@@ -430,7 +430,7 @@ static int fts5ExprPhraseIsMatch(
|
||||
}
|
||||
if( rc!=SQLITE_OK ) goto ismatch_out;
|
||||
sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]);
|
||||
aIter[i].bFlag = (u8)bFlag;
|
||||
aIter[i].bFlag = bFlag;
|
||||
if( aIter[i].bEof ) goto ismatch_out;
|
||||
}
|
||||
|
||||
@@ -543,7 +543,7 @@ static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){
|
||||
|
||||
/* If the aStatic[] array is not large enough, allocate a large array
|
||||
** using sqlite3_malloc(). This approach could be improved upon. */
|
||||
if( pNear->nPhrase>(int)ArraySize(aStatic) ){
|
||||
if( pNear->nPhrase>(sizeof(aStatic) / sizeof(aStatic[0])) ){
|
||||
int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
|
||||
a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte);
|
||||
}else{
|
||||
@@ -2190,7 +2190,7 @@ int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){
|
||||
int rc = SQLITE_OK;
|
||||
void *pCtx = (void*)pGlobal;
|
||||
|
||||
for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aFunc); i++){
|
||||
for(i=0; rc==SQLITE_OK && i<(sizeof(aFunc) / sizeof(aFunc[0])); i++){
|
||||
struct Fts5ExprFunc *p = &aFunc[i];
|
||||
rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ static void fts5HashAddPoslistSize(Fts5HashEntry *p){
|
||||
|
||||
assert( p->bDel==0 || p->bDel==1 );
|
||||
if( nPos<=127 ){
|
||||
pPtr[p->iSzPoslist] = (u8)nPos;
|
||||
pPtr[p->iSzPoslist] = nPos;
|
||||
}else{
|
||||
int nByte = sqlite3Fts5GetVarintLen((u32)nPos);
|
||||
memmove(&pPtr[p->iSzPoslist + nByte], &pPtr[p->iSzPoslist + 1], nSz);
|
||||
|
||||
+9
-10
@@ -2393,7 +2393,7 @@ static int fts5MultiIterDoCompare(Fts5IndexIter *pIter, int iOut){
|
||||
}
|
||||
}
|
||||
|
||||
pRes->iFirst = (u16)iRes;
|
||||
pRes->iFirst = iRes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2560,7 +2560,7 @@ static int fts5MultiIterAdvanceRowid(
|
||||
pIter->iSwitchRowid = pOther->iRowid;
|
||||
}
|
||||
}
|
||||
pRes->iFirst = (u16)(pNew - pIter->aSeg);
|
||||
pRes->iFirst = (pNew - pIter->aSeg);
|
||||
if( i==1 ) break;
|
||||
|
||||
pOther = &pIter->aSeg[ pIter->aFirst[i ^ 0x0001].iFirst ];
|
||||
@@ -2711,7 +2711,7 @@ static void fts5MultiIterNew(
|
||||
*ppOut = pNew = fts5MultiIterAlloc(p, nSeg);
|
||||
if( pNew==0 ) return;
|
||||
pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC));
|
||||
pNew->bSkipEmpty = (u8)bSkipEmpty;
|
||||
pNew->bSkipEmpty = bSkipEmpty;
|
||||
pNew->pStruct = pStruct;
|
||||
fts5StructureRef(pStruct);
|
||||
|
||||
@@ -3174,7 +3174,7 @@ static void fts5WriteFlushLeaf(Fts5Index *p, Fts5SegWriter *pWriter){
|
||||
|
||||
/* Set the szLeaf header field. */
|
||||
assert( 0==fts5GetU16(&pPage->buf.p[2]) );
|
||||
fts5PutU16(&pPage->buf.p[2], (u16)pPage->buf.n);
|
||||
fts5PutU16(&pPage->buf.p[2], pPage->buf.n);
|
||||
|
||||
if( pWriter->bFirstTermInPage ){
|
||||
/* No term was written to this page. */
|
||||
@@ -3306,7 +3306,7 @@ static void fts5WriteAppendRowid(
|
||||
** rowid-pointer in the page-header. Also append a value to the dlidx
|
||||
** buffer, in case a doclist-index is required. */
|
||||
if( pWriter->bFirstRowidInPage ){
|
||||
fts5PutU16(pPage->buf.p, (u16)pPage->buf.n);
|
||||
fts5PutU16(pPage->buf.p, pPage->buf.n);
|
||||
fts5WriteDlidxAppend(p, pWriter, iRowid);
|
||||
}
|
||||
|
||||
@@ -3464,7 +3464,7 @@ static void fts5TrimSegments(Fts5Index *p, Fts5IndexIter *pIter){
|
||||
fts5BufferAppendBlob(&p->rc, &buf, pData->szLeaf-iOff, &pData->p[iOff]);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
/* Set the szLeaf field */
|
||||
fts5PutU16(&buf.p[2], (u16)buf.n);
|
||||
fts5PutU16(&buf.p[2], buf.n);
|
||||
}
|
||||
|
||||
/* Set up the new page-index array */
|
||||
@@ -3830,7 +3830,7 @@ static void fts5FlushOneHash(Fts5Index *p){
|
||||
iRowid += iDelta;
|
||||
|
||||
if( writer.bFirstRowidInPage ){
|
||||
fts5PutU16(&pBuf->p[0], (u16)pBuf->n); /* first rowid on page */
|
||||
fts5PutU16(&pBuf->p[0], pBuf->n); /* first rowid on page */
|
||||
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid);
|
||||
writer.bFirstRowidInPage = 0;
|
||||
fts5WriteDlidxAppend(p, &writer, iRowid);
|
||||
@@ -4627,8 +4627,7 @@ int sqlite3Fts5IndexWrite(
|
||||
int nByte = fts5IndexCharlenToBytelen(pToken, nToken, pConfig->aPrefix[i]);
|
||||
if( nByte ){
|
||||
rc = sqlite3Fts5HashWrite(p->pHash,
|
||||
p->iWriteRowid, iCol, iPos, (char)(FTS5_MAIN_PREFIX+i+1), pToken,
|
||||
nByte
|
||||
p->iWriteRowid, iCol, iPos, FTS5_MAIN_PREFIX+i+1, pToken, nByte
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4678,7 +4677,7 @@ int sqlite3Fts5IndexQuery(
|
||||
|
||||
if( iIdx<=pConfig->nPrefix ){
|
||||
Fts5Structure *pStruct = fts5StructureRead(p);
|
||||
buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx);
|
||||
buf.p[0] = FTS5_MAIN_PREFIX + iIdx;
|
||||
if( pStruct ){
|
||||
fts5MultiIterNew(p, pStruct, 1, flags, buf.p, nToken+1, -1, 0, &pRet);
|
||||
fts5StructureRelease(pStruct);
|
||||
|
||||
@@ -537,7 +537,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
for(i=0; i<pInfo->nConstraint; i++){
|
||||
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
|
||||
int j;
|
||||
for(j=0; j<(int)ArraySize(aConstraint); j++){
|
||||
for(j=0; j<sizeof(aConstraint)/sizeof(aConstraint[0]); j++){
|
||||
struct Constraint *pC = &aConstraint[j];
|
||||
if( p->iColumn==aColMap[pC->iCol] && p->op & pC->op ){
|
||||
if( p->usable ){
|
||||
@@ -584,11 +584,11 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
|
||||
/* Assign argvIndex values to each constraint in use. */
|
||||
iNext = 1;
|
||||
for(i=0; i<(int)ArraySize(aConstraint); i++){
|
||||
for(i=0; i<sizeof(aConstraint)/sizeof(aConstraint[0]); i++){
|
||||
struct Constraint *pC = &aConstraint[i];
|
||||
if( pC->iConsIndex>=0 ){
|
||||
pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++;
|
||||
pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit;
|
||||
pInfo->aConstraintUsage[pC->iConsIndex].omit = pC->omit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -338,7 +338,7 @@ int sqlite3Fts5StorageClose(Fts5Storage *p){
|
||||
int i;
|
||||
|
||||
/* Finalize all SQL statements */
|
||||
for(i=0; i<(int)ArraySize(p->aStmt); i++){
|
||||
for(i=0; i<ArraySize(p->aStmt); i++){
|
||||
sqlite3_finalize(p->aStmt[i]);
|
||||
}
|
||||
|
||||
|
||||
@@ -256,7 +256,7 @@ static int fts5UnicodeAddExceptions(
|
||||
int bToken;
|
||||
READ_UTF8(zCsr, zTerm, iCode);
|
||||
if( iCode<128 ){
|
||||
p->aTokenChar[iCode] = (unsigned char)bTokenChars;
|
||||
p->aTokenChar[iCode] = bTokenChars;
|
||||
}else{
|
||||
bToken = sqlite3Fts5UnicodeIsalnum(iCode);
|
||||
assert( (bToken==0 || bToken==1) );
|
||||
@@ -1220,7 +1220,7 @@ int sqlite3Fts5TokenizerInit(fts5_api *pApi){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int i; /* To iterate through builtin functions */
|
||||
|
||||
for(i=0; rc==SQLITE_OK && i<(int)ArraySize(aBuiltin); i++){
|
||||
for(i=0; rc==SQLITE_OK && i<sizeof(aBuiltin)/sizeof(aBuiltin[0]); i++){
|
||||
rc = pApi->xCreateTokenizer(pApi,
|
||||
aBuiltin[i].zName,
|
||||
(void*)pApi,
|
||||
|
||||
@@ -42,8 +42,6 @@ foreach {tn opt} {
|
||||
1 {prefix=x}
|
||||
2 {prefix='x'}
|
||||
3 {prefix='$'}
|
||||
4 {prefix='1,2,'}
|
||||
5 {prefix=',1'}
|
||||
} {
|
||||
set res [list 1 {malformed prefix=... directive}]
|
||||
do_catchsql_test 2.$tn "CREATE VIRTUAL TABLE f1 USING fts5(x, $opt)" $res
|
||||
@@ -120,15 +118,18 @@ do_catchsql_test 5.3 {
|
||||
#-------------------------------------------------------------------------
|
||||
# Errors in prefix= directives.
|
||||
#
|
||||
do_catchsql_test 6.1 {
|
||||
CREATE VIRTUAL TABLE abc USING fts5(a, prefix=1, prefix=2);
|
||||
} {1 {multiple prefix=... directives}}
|
||||
do_catchsql_test 6.2 {
|
||||
CREATE VIRTUAL TABLE abc USING fts5(a, prefix='1, 2, 1001');
|
||||
} {1 {prefix length out of range (max 999)}}
|
||||
} {1 {prefix length out of range: 1001}}
|
||||
do_catchsql_test 6.3 {
|
||||
CREATE VIRTUAL TAbLE abc USING fts5(a, prefix='1, 2, 0000');
|
||||
} {1 {prefix length out of range (max 999)}}
|
||||
} {1 {prefix length out of range: 0}}
|
||||
do_catchsql_test 6.4 {
|
||||
CREATE VIRTUAL TABLE abc USING fts5(a, prefix='1 , 1000000');
|
||||
} {1 {prefix length out of range (max 999)}}
|
||||
} {1 {malformed prefix=... directive}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Duplicate tokenize= and other options.
|
||||
@@ -203,16 +204,5 @@ do_catchsql_test 9.4.1 {
|
||||
INSERT INTO abc(abc, rank) VALUES('nosuchoption', 1);
|
||||
} {1 {SQL logic error or missing database}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Too many prefix indexes. Maximum allowed is 31.
|
||||
#
|
||||
foreach {tn spec} {
|
||||
1 {prefix="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32"}
|
||||
2 {prefix="1 2 3 4", prefix="5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32"}
|
||||
} {
|
||||
set sql "CREATE VIRTUAL TABLE xyz USING fts5(x, $spec)"
|
||||
do_catchsql_test 10.$tn $sql {1 {too many prefix indexes (max 31)}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -298,48 +298,6 @@ foreach {tn col pattern} {
|
||||
do_execsql_test 6.$tn { SELECT rowid FROM t5($query) } $res
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that the various ways of creating prefix indexes produce the
|
||||
# same database on disk.
|
||||
#
|
||||
save_prng_state
|
||||
foreach {tn create} {
|
||||
1 { CREATE VIRTUAL TABLE tt USING fts5(x, y, prefix="1,2,3") }
|
||||
2 { CREATE VIRTUAL TABLE tt USING fts5(x, y, prefix="1 2 3") }
|
||||
3 { CREATE VIRTUAL TABLE tt USING fts5(x, y, prefix=1, prefix=2, prefix=3) }
|
||||
4 { CREATE VIRTUAL TABLE tt USING fts5(x, y, prefix="1 2", prefix=3) }
|
||||
} {
|
||||
execsql { DROP TABLE IF EXISTS tt }
|
||||
restore_prng_state
|
||||
execsql $create
|
||||
execsql {
|
||||
INSERT INTO tt VALUES('cc b ggg ccc aa eee hh', 'aa g b hh a e');
|
||||
INSERT INTO tt VALUES('cc bb cc gg j g cc', 'ii jjj ggg jjj cc cc');
|
||||
INSERT INTO tt VALUES('h eee cc h iii', 'aaa iii dd iii dd');
|
||||
INSERT INTO tt VALUES('jjj hh eee c e b gg', 'j bbb jj ddd jj');
|
||||
INSERT INTO tt VALUES('ii hhh aaa ff c hhh iii', 'j cc hh bb e');
|
||||
INSERT INTO tt VALUES('e fff hhh i aaa', 'g b aa gg c aa dd');
|
||||
INSERT INTO tt VALUES('i aaa ccc gg hhh aa h', 'j bbb bbb d ff');
|
||||
INSERT INTO tt VALUES('g f gg ff ff jjj d', 'jjj d j fff fff ee j');
|
||||
INSERT INTO tt VALUES('a cc e ccc jjj c', 'ccc iii d bb a eee g');
|
||||
INSERT INTO tt VALUES('jj hh hh bb bbb gg', 'j c jjj bb iii f');
|
||||
INSERT INTO tt VALUES('a ggg g cc ccc aa', 'jjj j j aaa c');
|
||||
INSERT INTO tt VALUES('ddd j dd b i', 'aaa bbb iii ggg ff ccc ddd');
|
||||
INSERT INTO tt VALUES('jj ii hh c ii h gg', 'hhh bbb ddd bbb hh g ggg');
|
||||
INSERT INTO tt VALUES('aa hhh ccc h ggg ccc', 'iii d jj a ff ii');
|
||||
}
|
||||
|
||||
#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM tt_data} {puts $r}
|
||||
|
||||
if {$tn==1} {
|
||||
set ::checksum [execsql {SELECT md5sum(id, block) FROM tt_data}]
|
||||
} else {
|
||||
do_execsql_test 7.$tn {
|
||||
SELECT md5sum(id, block) FROM tt_data
|
||||
} [list $::checksum]
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
+1
-111
@@ -1181,7 +1181,7 @@ static void jsonTest1Func(
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
/****************************************************************************
|
||||
** Scalar SQL function implementations
|
||||
** SQL function implementations
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
@@ -1514,102 +1514,6 @@ static void jsonValidFunc(
|
||||
sqlite3_result_int(ctx, rc);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
** Aggregate SQL function implementations
|
||||
****************************************************************************/
|
||||
/*
|
||||
** json_group_array(VALUE)
|
||||
**
|
||||
** Return a JSON array composed of all values in the aggregate.
|
||||
*/
|
||||
static void jsonArrayStep(
|
||||
sqlite3_context *ctx,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
JsonString *pStr;
|
||||
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
|
||||
if( pStr ){
|
||||
if( pStr->zBuf==0 ){
|
||||
jsonInit(pStr, ctx);
|
||||
jsonAppendChar(pStr, '[');
|
||||
}else{
|
||||
jsonAppendChar(pStr, ',');
|
||||
pStr->pCtx = ctx;
|
||||
}
|
||||
jsonAppendValue(pStr, argv[0]);
|
||||
}
|
||||
}
|
||||
static void jsonArrayFinal(sqlite3_context *ctx){
|
||||
JsonString *pStr;
|
||||
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
|
||||
if( pStr ){
|
||||
pStr->pCtx = ctx;
|
||||
jsonAppendChar(pStr, ']');
|
||||
if( pStr->bErr ){
|
||||
sqlite3_result_error_nomem(ctx);
|
||||
if( !pStr->bStatic ) sqlite3_free(pStr->zBuf);
|
||||
}else{
|
||||
sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed,
|
||||
pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
|
||||
pStr->bStatic = 1;
|
||||
}
|
||||
}else{
|
||||
sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC);
|
||||
}
|
||||
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
** json_group_obj(NAME,VALUE)
|
||||
**
|
||||
** Return a JSON object composed of all names and values in the aggregate.
|
||||
*/
|
||||
static void jsonObjectStep(
|
||||
sqlite3_context *ctx,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
JsonString *pStr;
|
||||
const char *z;
|
||||
u32 n;
|
||||
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
|
||||
if( pStr ){
|
||||
if( pStr->zBuf==0 ){
|
||||
jsonInit(pStr, ctx);
|
||||
jsonAppendChar(pStr, '{');
|
||||
}else{
|
||||
jsonAppendChar(pStr, ',');
|
||||
pStr->pCtx = ctx;
|
||||
}
|
||||
z = (const char*)sqlite3_value_text(argv[0]);
|
||||
n = (u32)sqlite3_value_bytes(argv[0]);
|
||||
jsonAppendString(pStr, z, n);
|
||||
jsonAppendChar(pStr, ':');
|
||||
jsonAppendValue(pStr, argv[1]);
|
||||
}
|
||||
}
|
||||
static void jsonObjectFinal(sqlite3_context *ctx){
|
||||
JsonString *pStr;
|
||||
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
|
||||
if( pStr ){
|
||||
jsonAppendChar(pStr, '}');
|
||||
if( pStr->bErr ){
|
||||
sqlite3_result_error_nomem(ctx);
|
||||
if( !pStr->bStatic ) sqlite3_free(pStr->zBuf);
|
||||
}else{
|
||||
sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed,
|
||||
pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
|
||||
pStr->bStatic = 1;
|
||||
}
|
||||
}else{
|
||||
sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
|
||||
}
|
||||
sqlite3_result_subtype(ctx, JSON_SUBTYPE);
|
||||
}
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/****************************************************************************
|
||||
** The json_each virtual table
|
||||
@@ -2108,15 +2012,6 @@ int sqlite3Json1Init(sqlite3 *db){
|
||||
{ "json_test1", 1, 0, jsonTest1Func },
|
||||
#endif
|
||||
};
|
||||
static const struct {
|
||||
const char *zName;
|
||||
int nArg;
|
||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**);
|
||||
void (*xFinal)(sqlite3_context*);
|
||||
} aAgg[] = {
|
||||
{ "json_group_array", 1, jsonArrayStep, jsonArrayFinal },
|
||||
{ "json_group_object", 2, jsonObjectStep, jsonObjectFinal },
|
||||
};
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
static const struct {
|
||||
const char *zName;
|
||||
@@ -2132,11 +2027,6 @@ int sqlite3Json1Init(sqlite3 *db){
|
||||
(void*)&aFunc[i].flag,
|
||||
aFunc[i].xFunc, 0, 0);
|
||||
}
|
||||
for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
|
||||
rc = sqlite3_create_function(db, aAgg[i].zName, aAgg[i].nArg,
|
||||
SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
|
||||
0, aAgg[i].xStep, aAgg[i].xFinal);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){
|
||||
rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0);
|
||||
|
||||
+1
-9
@@ -1717,23 +1717,17 @@ static void scriptCodeSqlFunc(
|
||||
# define SCRIPT_LATIN 0x0001
|
||||
# define SCRIPT_CYRILLIC 0x0002
|
||||
# define SCRIPT_GREEK 0x0004
|
||||
# define SCRIPT_HEBREW 0x0008
|
||||
# define SCRIPT_ARABIC 0x0010
|
||||
|
||||
while( nIn>0 ){
|
||||
c = utf8Read(zIn, nIn, &sz);
|
||||
zIn += sz;
|
||||
nIn -= sz;
|
||||
if( c<0x02af && (c>=0x80 || midClass[c&0x7f]<CCLASS_DIGIT) ){
|
||||
if( c<0x02af ){
|
||||
scriptMask |= SCRIPT_LATIN;
|
||||
}else if( c>=0x0400 && c<=0x04ff ){
|
||||
scriptMask |= SCRIPT_CYRILLIC;
|
||||
}else if( c>=0x0386 && c<=0x03ce ){
|
||||
scriptMask |= SCRIPT_GREEK;
|
||||
}else if( c>=0x0590 && c<=0x05ff ){
|
||||
scriptMask |= SCRIPT_HEBREW;
|
||||
}else if( c>=0x0600 && c<=0x06ff ){
|
||||
scriptMask |= SCRIPT_ARABIC;
|
||||
}
|
||||
}
|
||||
switch( scriptMask ){
|
||||
@@ -1741,8 +1735,6 @@ static void scriptCodeSqlFunc(
|
||||
case SCRIPT_LATIN: res = 215; break;
|
||||
case SCRIPT_CYRILLIC: res = 220; break;
|
||||
case SCRIPT_GREEK: res = 200; break;
|
||||
case SCRIPT_HEBREW: res = 125; break;
|
||||
case SCRIPT_ARABIC: res = 160; break;
|
||||
default: res = 998; break;
|
||||
}
|
||||
sqlite3_result_int(context, res);
|
||||
|
||||
@@ -312,7 +312,6 @@ TESTSRC = \
|
||||
$(TOP)/src/test_tclvar.c \
|
||||
$(TOP)/src/test_thread.c \
|
||||
$(TOP)/src/test_vfs.c \
|
||||
$(TOP)/src/test_windirent.c \
|
||||
$(TOP)/src/test_wsd.c
|
||||
|
||||
# Extensions to be statically loaded.
|
||||
@@ -795,8 +794,8 @@ THREADTEST3_SRC = $(TOP)/test/threadtest3.c \
|
||||
$(TOP)/test/tt3_stress.c \
|
||||
$(TOP)/test/tt3_lookaside1.c
|
||||
|
||||
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)
|
||||
threadtest3$(EXE): sqlite3.o $(THREADTEST3_SRC)
|
||||
$(TCCX) $(TOP)/test/threadtest3.c sqlite3.o -o $@ $(THREADLIB)
|
||||
|
||||
threadtest: threadtest3$(EXE)
|
||||
./threadtest3$(EXE)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
C Use\sthe\sOvflOffset()\smacro\sto\stry\sto\sremove\ssome\smagic\snumbers\sfrom\sbtree.c.
|
||||
D 2015-12-30T20:50:11.553
|
||||
F Makefile.in 28bcd6149e050dff35d4dcfd97e890cd387a499d
|
||||
C Add\sa\snew\sOP_BColumn\sopcode\swhere\sthe\scursor\sis\sguaranteed\sto\sbe\sof\stype\nCURTYPE_BTREE\sand\sis\sthus\sable\sto\sskip\ssome\schecks\sand\srun\sslightly\sfaster.
|
||||
D 2015-11-21T17:53:06.758
|
||||
F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 5fff077fcc46de7714ed6eebb6159a4c00eab751
|
||||
F Makefile.msc e928e68168df69b353300ac87c10105206653a03
|
||||
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
|
||||
F VERSION 8b9d3ac6f1962f94e06ba05462422a544f9c4e36
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
@@ -13,7 +13,13 @@ F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am 089e5ecdb5761e64ea1013ded02feb4d8b29927d
|
||||
F autoconf/README 14458f1046c118efa721aadec5f227e876d3cd38
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/configure.ac 82c628c68f0f204d57343dc345b6dbd1789fb1bd
|
||||
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/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
|
||||
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
|
||||
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
|
||||
@@ -90,7 +96,7 @@ F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057
|
||||
F ext/fts3/fts3_write.c f442223e4a1914dc1fc12b65af7e4f2c255fa47c
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3view.c 5d78b668f4e9598af9147f8999632599fb0d9dd5
|
||||
F ext/fts3/tool/fts3view.c 8e53d0190a7b3443764bbd32ad47be2bd852026d
|
||||
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
|
||||
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252
|
||||
@@ -98,17 +104,17 @@ F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
|
||||
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
|
||||
F ext/fts5/fts5.h 8b9a13b309b180e9fb88ea5666c0d8d73c6102d9
|
||||
F ext/fts5/fts5Int.h acf968e43d57b6b1caf7554d34ec35d6ed3b4fe8
|
||||
F ext/fts5/fts5_aux.c 2dafc3aee0c70d643140c77d8d70daffa51a9e9e
|
||||
F ext/fts5/fts5_aux.c 1f384972d606375b8fa078319f25ab4b5feb1b35
|
||||
F ext/fts5/fts5_buffer.c 1e49512a535045e621246dc7f4f65f3593fa0fc2
|
||||
F ext/fts5/fts5_config.c 0ee66188609a62342e9f9aeefa3c3e44518a4dd6
|
||||
F ext/fts5/fts5_expr.c 8228aca3e9af626a1ca9b093d4d24b4f2488ad23
|
||||
F ext/fts5/fts5_hash.c 25838d525e97f8662ff3504be94d0bad24f9a37e
|
||||
F ext/fts5/fts5_index.c 578f46697080f11a1e26cd45a1c039c043a3111d
|
||||
F ext/fts5/fts5_main.c e11b525778e6fce416d916bfa96926bd1ce4616d
|
||||
F ext/fts5/fts5_storage.c 57c636d87cbb829d6147c8c8bf78fa53b9ebb526
|
||||
F ext/fts5/fts5_config.c 6fc92c0b1bda5244c28a54c9ba740736bd5513d9
|
||||
F ext/fts5/fts5_expr.c 28b15c9ae296204bc0a2e5cf7a667d840a9d2900
|
||||
F ext/fts5/fts5_hash.c a9d4c1efebc2a91d26ad7ebdfcbf2678ceac405f
|
||||
F ext/fts5/fts5_index.c b622a0a70f57a96469e6828da2dd70e0872aeb37
|
||||
F ext/fts5/fts5_main.c 7581280ee242785477df67402f2853c66f77d45b
|
||||
F ext/fts5/fts5_storage.c 9ea3d92178743758b6c54d9fe8836bbbdcc92e3b
|
||||
F ext/fts5/fts5_tcl.c 3bf445e66de32137d4693694ff7b1fd6074e32bd
|
||||
F ext/fts5/fts5_test_mi.c e96be827aa8f571031e65e481251dc1981d608bf
|
||||
F ext/fts5/fts5_tokenize.c 504984ac6993323247221eebe3cd55bead01b5f8
|
||||
F ext/fts5/fts5_tokenize.c 12c5d925286491a71bb3dad7c8924ce9cfd18320
|
||||
F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c
|
||||
F ext/fts5/fts5_varint.c 3f86ce09cab152e3d45490d7586b7ed2e40c13f1
|
||||
F ext/fts5/fts5_vocab.c 3742d0abfe8aa8c3cb4a7df56aa38f2e3c3fb1c2
|
||||
@@ -133,7 +139,7 @@ F ext/fts5/test/fts5aux.test 8c687c948cc98e9a94be014df7d518acc1b3b74f
|
||||
F ext/fts5/test/fts5auxdata.test 141a7cbffcceb1bd2799b4b29c183ff8780d586e
|
||||
F ext/fts5/test/fts5bigpl.test 04ee0d7eebbebf17c31f5a0b5c5f9494eac3a0cb
|
||||
F ext/fts5/test/fts5columnsize.test a8cfef21ffa1c264b9f670a7d94eeaccb5341c07
|
||||
F ext/fts5/test/fts5config.test 42c1336cc6ed33d7e9c4a05dbce81721b765e7d0
|
||||
F ext/fts5/test/fts5config.test ad2ff42ddc856aed2d05bf89dc1c578c8a39ea3b
|
||||
F ext/fts5/test/fts5conflict.test 26f4e46c4d31e16221794832a990dc4e30e18de5
|
||||
F ext/fts5/test/fts5content.test 9a952c95518a14182dc3b59e3c8fa71cda82a4e1
|
||||
F ext/fts5/test/fts5corrupt.test c2ad090192708150d50d961278df10ae7a4b8b62
|
||||
@@ -162,7 +168,7 @@ F ext/fts5/test/fts5phrase.test f6d1d464da5beb25dc56277aa4f1d6102f0d9a2f
|
||||
F ext/fts5/test/fts5plan.test 6a55ecbac9890765b0e16f8c421c7e0888cfe436
|
||||
F ext/fts5/test/fts5porter.test 7cdc07bef301d70eebbfa75dcaf45c3680e1d0e1
|
||||
F ext/fts5/test/fts5porter2.test 2e65633d58a1c525d5af0f6c01e5a59155bb3487
|
||||
F ext/fts5/test/fts5prefix.test efd42e00bb8e8a36383f25c838185508681c093f
|
||||
F ext/fts5/test/fts5prefix.test 7ccbdf180ed561a912acef520519e85af8642239
|
||||
F ext/fts5/test/fts5query.test f5ec25f5f2fbb70033424113cdffc101b1985a40
|
||||
F ext/fts5/test/fts5rank.test 7e9e64eac7245637f6f2033aec4b292aaf611aab
|
||||
F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b
|
||||
@@ -191,14 +197,14 @@ F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
|
||||
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
|
||||
F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767
|
||||
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
|
||||
F ext/misc/json1.c b7ed42db00f7429c0f0b5068209c95c41b531596
|
||||
F ext/misc/json1.c 4f45afd9dbcd6feca8c528251efbb7fc09299a09
|
||||
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
|
||||
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
|
||||
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
|
||||
F ext/misc/series.c b8fb7befd85b3a9b4a10e701b30b2b79ca92b6d4
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c df6efb90eb668d1860c9b59e4320e985e46dffa7
|
||||
F ext/misc/spellfix.c b9065af7ab1f2597b505a8aa9892620866d502fc
|
||||
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
|
||||
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
|
||||
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
|
||||
@@ -257,119 +263,119 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk ed77cbb97848c8dae1ab928245432f74b0580162
|
||||
F main.mk ae99be5eb22933b1ecf80f94d41d25a3ea80aaf3
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
|
||||
F mptest/crash02.subtest f4ef05adcd15d60e5d2bd654204f2c008b519df8
|
||||
F mptest/mptest.c 0d3f2eb8e373cb692ab362a6dddedd53e0978502
|
||||
F mptest/mptest.c e7b499cb0cf8c3de65eaf24dec9b36daa4e013e4
|
||||
F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
|
||||
F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 9d649e46c780166e416fb11dbd23f8d49aab8267
|
||||
F src/analyze.c 977bd50c751bb939ef52917892e12bedbfcea7ce
|
||||
F src/analyze.c 4c308880cf53c558070cb8513bdff4ffb1a38a77
|
||||
F src/attach.c e944d0052b577703b9b83aac1638452ff42a8395
|
||||
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
||||
F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc
|
||||
F src/bitvec.c 1a78d450a17c5016710eec900bedfc5729bf9bdf
|
||||
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
||||
F src/btree.c ec6627fbb483526e0f6e095c0a438191fe6386b3
|
||||
F src/btree.c d3bdd8462a86492e2ebc9aca4a0168429017de25
|
||||
F src/btree.h 2d76dee44704c47eed323356a758662724b674a0
|
||||
F src/btreeInt.h dc698b04ae266bcce5f2eebba007133bf2339ef5
|
||||
F src/build.c 5a8611a01cbf67c736d81304e054ec361ef8963d
|
||||
F src/btreeInt.h 3ab435ed27adea54d040584b0bcc488ee7db1e38
|
||||
F src/build.c 19f7585c9747d5043dae64bc82f9cac759f69700
|
||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
|
||||
F src/ctime.c 60e135af364d777a9ab41c97e5e89cd224da6198
|
||||
F src/date.c e4655393bb403fa310eef66cc4583d75d4d7fd93
|
||||
F src/ctime.c 509ef9c64d1321f42448f111da86400b1799218a
|
||||
F src/date.c fb1c99172017dcc8e237339132c91a21a0788584
|
||||
F src/dbstat.c ffd63fc8ba7541476ced189b95e95d7f2bc63f78
|
||||
F src/delete.c 00af9f08a15ddc5cba5962d3d3e5bf2d67b2e7da
|
||||
F src/expr.c 38790e65d1219f2b7dc26458f39a5252fe7c60cd
|
||||
F src/expr.c dfccb439a2a981d71970ce3d15effeb59b258798
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c e18b3dff7d47c7bcac5ac4fc178a89b9fd322b44
|
||||
F src/func.c cf5e10af9125b245f1b962e8ba4d520a37818795
|
||||
F src/global.c bd5a0af3f30b0c01be6db756c626cd3c33a3d260
|
||||
F src/fkey.c 31900763094a3736a5fc887469202eb579fef2d0
|
||||
F src/func.c ecdd69ec6a1e406f04cc73324be2ebbf6354197f
|
||||
F src/global.c 508e4087f7b41d688e4762dcf4d4fe28cfbc87f9
|
||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 6b45cc86967da11aa024d034745f93f66d53f650
|
||||
F src/insert.c e1d20ae8979e25519c2670233718676bedcfedc9
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||
F src/loadext.c 84996d7d70a605597d79c1f1d7b2012a5fd34f2b
|
||||
F src/main.c b9641a4f650230bfc5dbb0bebf7b33ff4d27586a
|
||||
F src/malloc.c 8f787669e79de26efc42272b5797bc00fff527c6
|
||||
F src/loadext.c 18586e45a215325f15096821e9c082035d4fb810
|
||||
F src/main.c 91feb5c7e393ad8f0c434754114a3493c3b0617a
|
||||
F src/malloc.c 337bbe9c7d436ef9b7d06b5dd10bbfc8f3025972
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
|
||||
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
|
||||
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
|
||||
F src/mem5.c 262055c242fa7db59c5f07ad77fdc4e97888c054
|
||||
F src/mem5.c 5c267678ba9f745a2ee58102a9f482d64a58577a
|
||||
F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85
|
||||
F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495
|
||||
F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c
|
||||
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
|
||||
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
|
||||
F src/mutex_unix.c 27bb6cc49485ee46711a6580ab7b3f1402211d23
|
||||
F src/mutex_unix.c fc54f25b2a750d53b32512a4a728cec28039ae2a
|
||||
F src/mutex_w32.c 5e6fe1c298fb5a8a15aaed4161d5759311431c17
|
||||
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
|
||||
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 0ca6d8710366fbb01a275160f018334cd347cbda
|
||||
F src/os_unix.c bddde71dc024574ace03ffee859abb99d152fd4a
|
||||
F src/os_win.c 386fba30419e8458b13209781c2af5590eab2811
|
||||
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
|
||||
F src/pager.c 58d2593612acb6b542de6715b4af397ea1fa0a35
|
||||
F src/pager.h bf25005b4656cd805af43487c3139fca9678d0cc
|
||||
F src/pager.c 18341e2b759b447cbc82fb9215d08d9c5864e92e
|
||||
F src/pager.h 87c4118a71ba3965184148b379a6d93179071091
|
||||
F src/parse.y 23737e649c26ce327603799e57f5c2ff50e5e6ba
|
||||
F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23
|
||||
F src/pcache.h 1ff11adce609ba7de139b6abfabaf9a2bac947b5
|
||||
F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051
|
||||
F src/pcache1.c 902e1bc7bdaa81b40f8543407c5e2ac8ef4dc035
|
||||
F src/pragma.c f3e7147299ca05ef4304a36f1fd6e002729c72c6
|
||||
F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
|
||||
F src/pragma.h 3d94aebbebd2089899fecc01909bf2608b39507d
|
||||
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
|
||||
F src/printf.c af589a27b7d40f6f4f704e9eea99f02f18ad6d32
|
||||
F src/printf.c f8fc8f04e75b1e983ef2793c27ec7a43b287e94a
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c a83b41104e6ff69855d03cd0aaa09e93927ec39f
|
||||
F src/resolve.c f4c897ca76ca6d5e0b3f0499c627392ffe657c8e
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c f8fded11fc443a9f5a73cc5db069d06b34460e2f
|
||||
F src/shell.c ace08b69cd9702143cf87b5bd20b744a56f832fd
|
||||
F src/sqlite.h.in 7d87d71b9a4689c51fa092f48f16590ff71558e3
|
||||
F src/select.c 0495e86f8377026fbd529a1a5bf62046cbb6eec5
|
||||
F src/shell.c f0f59ea60ad297f671b7ae0fb957a736ad17c92c
|
||||
F src/sqlite.h.in fa62718f73553f06b2f2e362fd09ccb4e1cbb626
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d
|
||||
F src/sqliteInt.h 526c8514d0cb0768d014d04445c6eebd1d0b1a2c
|
||||
F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924
|
||||
F src/sqliteInt.h 64256d193a16a147d9f6317cc4e095fdd3e0a2e9
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
|
||||
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
|
||||
F src/tclsqlite.c d9439b6a910985b7fff43ba6756bcef00de22649
|
||||
F src/test1.c 4f1b42699068b7806af3111786f5ad760c2c1ff7
|
||||
F src/test1.c 4004bcc1b3b361a9137acd1d875599ecbdd6f961
|
||||
F src/test2.c 5586f43fcd9a1be0830793cf9d354082c261b25b
|
||||
F src/test3.c a8887dabbbee3059af338f20d290084a63ed1b0f
|
||||
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
|
||||
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
|
||||
F src/test6.c 41cacf3b0dd180823919bf9e1fbab287c9266723
|
||||
F src/test7.c 9c89a4f1ed6bb13af0ed805b8d782bd83fcd57e3
|
||||
F src/test8.c fa262391d3edea6490a71bfaa8fed477ccbbac75
|
||||
F src/test8.c 610e3d523018ca63b08081795e76794a2121ec38
|
||||
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
|
||||
F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
|
||||
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
|
||||
F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803
|
||||
F src/test_blob.c e5a7a81d61a780da79101aeb1e60d300af169e07
|
||||
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
|
||||
F src/test_config.c 0dee90328e3dedf8ba002ee94b6a7e7ea7726fe4
|
||||
F src/test_config.c f2824de39f59d8d621e2d6ec5cc67006d000b2eb
|
||||
F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_fs.c 993c7eab65bed6add4bb48cca29775e963f710cf
|
||||
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
|
||||
F src/test_func.c 0d9c25956152adefee8881c6fadc8354793764d0
|
||||
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
|
||||
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
|
||||
F src/test_intarray.c 870124b95ec4c645d4eb84f15efb7133528fb1a5
|
||||
F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202
|
||||
F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa
|
||||
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
|
||||
F src/test_malloc.c 96df9381a1ff1f6d3805ff7231b9baf1386aaabf
|
||||
F src/test_multiplex.c 6a088d8d9d4aad4bec45dd8878af11b15900702d
|
||||
F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4
|
||||
F src/test_malloc.c 27d9e11b6e9d30267465d41ad81edbe24256408b
|
||||
F src/test_multiplex.c 9fefd23f6cc3fa9bf0748a5e453167e7b9f193ce
|
||||
F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3
|
||||
F src/test_mutex.c dbdfaff8580071f2212a0deae3325a93a737819c
|
||||
F src/test_onefile.c 38f7cbe79d5bafe95bde683cc3a53b8ca16daf10
|
||||
@@ -383,39 +389,37 @@ F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
|
||||
F src/test_sqllog.c 0d138a8180a312bf996b37fa66da5c5799d4d57b
|
||||
F src/test_superlock.c 06797157176eb7085027d9dd278c0d7a105e3ec9
|
||||
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
|
||||
F src/test_tclvar.c d86412527da65468ee6fa1b8607c65d0af736bc4
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c af391ec03d23486dffbcc250b7e58e073f172af9
|
||||
F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_windirent.c 8f5fada630348558d5745b334702f301da1ffc61
|
||||
F src/test_windirent.h b12055cab6227f7be10f5c19296f67c60cc5e2a5
|
||||
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 de3ed31ad3218a20d7d7e18bf1b3b734e78bda66
|
||||
F src/update.c 17332f9fe818cbc0444c36a811800af8498af4c3
|
||||
F src/utf.c 32d7f82aa921322f3e1c956f4b58f019ebd2c6b3
|
||||
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
|
||||
F src/update.c 40e51cd0883cb5bfd6abb7d8a7cd8aa47fab2945
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
F src/util.c e802e8e311a0d6c48cd1b3e89db164f6f0248d70
|
||||
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
||||
F src/vdbe.c 984c2be6691d3f67deb2e6747c2132150d776f32
|
||||
F src/vdbe.c 8694c0e6497cd21e19e30ac059f933ac5d9abea2
|
||||
F src/vdbe.h efb7a8c1459e31f3ea4377824c6a7e4cb5068637
|
||||
F src/vdbeInt.h 75c2e82ee3357e9210c06474f8d9bdf12c81105d
|
||||
F src/vdbeapi.c 020681b943e77766b32ae1cddf86d7831b7374ca
|
||||
F src/vdbeaux.c 68082d9991fc1b8625d34c8b5db1775c9dee426e
|
||||
F src/vdbeaux.c 16e21a6ae0c290f17f6e7395d80686622cafeaa2
|
||||
F src/vdbeblob.c fdc4a81605ae7a35ae94a55bd768b66d6be16f15
|
||||
F src/vdbemem.c fdd1578e47bea61390d472de53c565781d81e045
|
||||
F src/vdbesort.c a7ec02da4494c59dfd071126dd3726be5a11459d
|
||||
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
|
||||
F src/vtab.c 2a8b44aa372c33f6154208e7a7f6c44254549806
|
||||
F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
|
||||
F src/wal.c 974928c988681c5157202c79dd9f26afaa7b5086
|
||||
F src/wal.h 907943dfdef10b583e81906679a347e0ec6f1b1b
|
||||
F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba
|
||||
F src/where.c c6d3d2f6af57d574a7365ee2b225a5024f2a6bec
|
||||
F src/whereInt.h 78b6b4de94db84aecbdc07fe3e38f648eb391e9a
|
||||
F src/wherecode.c dfbfe198e418b01f208b489e088edd230c91a4e7
|
||||
F src/whereexpr.c eebba8340c90de73b3d3bbe8c43b84559b8e6e2c
|
||||
F src/where.c 6aceb72cc58dc06922a9e1604d559c8ca4c3e728
|
||||
F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647
|
||||
F src/wherecode.c 4c96182e7b25e4be54008dee2da5b9c2f8480b9b
|
||||
F src/whereexpr.c bd4877cd4dd11f6ab551ef0054535ca3c6224950
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@@ -429,7 +433,7 @@ F test/alter4.test c461150723ac957f3b2214aa0b11552cd72023ec
|
||||
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
F test/analyze.test 3eb35a4af972f98422e5dc0586501b17d103d321
|
||||
F test/analyze3.test 1dccda46a6c374018af617fba00bfe297a61d442
|
||||
F test/analyze3.test 0f0ee6135b293a0e5af471a8423b80b688469d71
|
||||
F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213
|
||||
F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
|
||||
F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f
|
||||
@@ -502,7 +506,7 @@ F test/cacheflush.test a755c93482ce2e20c04825304bef27e7b7ea0111
|
||||
F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738
|
||||
F test/capi3.test bf6f0308bbbba1e770dac13aa08e5c2ac61c7324
|
||||
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
|
||||
F test/capi3c.test 06f6261f9e9b4ef6f76afcd9900f3665408af1c8
|
||||
F test/capi3c.test fdc0d67a2cb8e8fc400d5b7735e330161ea057a2
|
||||
F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
|
||||
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
|
||||
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
|
||||
@@ -563,7 +567,7 @@ F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
|
||||
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
|
||||
F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
|
||||
F test/cursorhint.test 432811b62bd5ffb812729f49bba3b9ad687550bb
|
||||
F test/date.test 984ac1e3e5e031386866f034006148d3972b4a65
|
||||
F test/date.test 42973251b9429f2c41b77eb98a7b0b0ba2d3b2c0
|
||||
F test/dbstatus.test 8de104bb5606f19537d23cd553b41349b5ab1204
|
||||
F test/dbstatus2.test 10418e62b3db5dca070f0c3eef3ea13946f339c2
|
||||
F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
|
||||
@@ -575,7 +579,7 @@ F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240
|
||||
F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
|
||||
F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
|
||||
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
|
||||
F test/distinct.test a1783b960ad8c15a77cd9f207be072898db1026c
|
||||
F test/distinct.test 175d49ee783febaf368192dfe7f5afbc68910230
|
||||
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
|
||||
F test/e_blobbytes.test 9bea1d3e2b20f3010b04abba58f6ba172301f49f
|
||||
F test/e_blobclose.test df756753f571bc30e42e3a6cba2807576e49e716
|
||||
@@ -604,7 +608,7 @@ F test/e_walckpt.test 65e29b6631e51f210f83e4ff11571e647ba93608
|
||||
F test/e_walhook.test da3ea8b3483d1af72190337bda50155a91a4b664
|
||||
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
|
||||
F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6
|
||||
F test/enc3.test 90683ad0e6ea587b9d5542ca93568af9a9858c40
|
||||
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
|
||||
F test/eqp.test 85873fa5816c48915c82c4e74cb5c35a5b48160f
|
||||
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
|
||||
@@ -724,7 +728,7 @@ F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
|
||||
F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e
|
||||
F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb
|
||||
F test/fts4check.test 9d9e818fd6cb29c0e007cd6d00447739d4fde430
|
||||
F test/fts4content.test 8707425b926663f8ca81de866c007900442b5ec0
|
||||
F test/fts4content.test abb0c77bc3da3df64fec72e00844d2257a90025d
|
||||
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
|
||||
F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53
|
||||
F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d
|
||||
@@ -749,7 +753,7 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
|
||||
F test/fuzz3.test 53fabcd5f0f430f8b221282f6c12c4d0903c21eb
|
||||
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
|
||||
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
|
||||
F test/fuzzcheck.c ccdcdc28579b2c9744696bca8726bdbd729eea11
|
||||
F test/fuzzcheck.c 7c61352f20a28429b221f406f3854cf9c912f63b
|
||||
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
|
||||
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
@@ -757,7 +761,7 @@ F test/fuzzdata4.db 1882f0055fb63214d8407ddc7aca9b0b1c59af21
|
||||
F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
|
||||
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
|
||||
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
|
||||
F test/hexlit.test d7b0a5f41123df1e43985b91b8b2e70f95282d21
|
||||
F test/hexlit.test 1d312fa816dfd3650a3bb488093bc09a0c927f67
|
||||
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
|
||||
F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f
|
||||
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
|
||||
@@ -787,7 +791,7 @@ F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
|
||||
F test/index6.test 7102ec371414c42dfb1d5ca37eb4519aa9edc23a
|
||||
F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c
|
||||
F test/indexedby.test 9c4cd331224e57f79fbf411ae245e6272d415985
|
||||
F test/indexexpr1.test cb71b6586177b840e28110dd952178bb2bdfedc2
|
||||
F test/indexexpr1.test bbb52b5d5717d9f23853826963b0af5110009366
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
|
||||
@@ -820,13 +824,12 @@ F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
|
||||
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
|
||||
F test/json101.test f0178422b3a2418f423fd0d3caf3571c8d1b9863
|
||||
F test/json102.test bf3fe7a706d30936a76a0f7a0375e1e8e73aff5a
|
||||
F test/json103.test 923b288a0610ec86c0951778f7db19cbcca36ad1
|
||||
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
|
||||
F test/like.test edcf6d0a055816fd793eab92454597c1be91f720
|
||||
F test/like.test 4f2a71d36a536233727f71995fef900756705e56
|
||||
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
|
||||
F test/like3.test 3608a2042b6f922f900fbfd5d3ce4e7eca57f7c4
|
||||
F test/like3.test 7b0525a39e4f25c4fd113de7e2e28eb712dcdedf
|
||||
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
|
||||
F test/loadext.test 648cb95f324d1775c54a55c12271b2d1156b633b
|
||||
F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
|
||||
@@ -929,7 +932,7 @@ F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test 4ea119731c62d2f7d0aa86dd5b184cbb61ca411b
|
||||
F test/pragma.test a44253f911e7d50127d4a08f927f47c861a4c772
|
||||
F test/pragma2.test a9400a7289605280576098b97f5cde3f204075c0
|
||||
F test/pragma2.test 00065068eeab2d15ea55465ec0f1e0a70e2c369e
|
||||
F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
|
||||
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
|
||||
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054
|
||||
@@ -1015,8 +1018,6 @@ 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
|
||||
@@ -1036,9 +1037,8 @@ F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/speedtest1.c f8bf04214e7b5f745feea99f7bde68b1c4870666
|
||||
F test/spellfix.test 0597065ff57042df1f138e6a2611ae19c2698135
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test f7bf7b3482971473d32b6b00f6944c5c066cff97
|
||||
F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5
|
||||
F test/sqllimits1.test a74ee2a3740b9f9c2437c246d8fb77354862a142
|
||||
F test/sqllimits1.test 89b3d5aad05b99f707ee3786bdd4416dccf83304
|
||||
F test/sqllog.test a8faa2df39610a037dd372ed872d124260d32953
|
||||
F test/stat.test 8de91498c99f5298b303f70f1d1f3b9557af91bf
|
||||
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
|
||||
@@ -1049,10 +1049,10 @@ F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
|
||||
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
|
||||
F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
|
||||
F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
|
||||
F test/symlink.test cbf6cb8c6c4b63a39e9f0f6b0d5c99e249dbc102
|
||||
F test/symlink.test 2513f7c030df0f435c6415687ba8b739f3d312df
|
||||
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
|
||||
F test/syscall.test 2aa9e111b79fb385681ff8940124def6f8faab87
|
||||
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
|
||||
F test/syscall.test fba9ebdc6905d05bba6a835e691f20ed9ea2cc88
|
||||
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
|
||||
F test/tabfunc01.test cc33684f9480fcf1fd5ce287ac28d22971cad1cc
|
||||
F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
|
||||
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
@@ -1072,7 +1072,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 7ca82330041456afa52e4968196bb0867371f91b
|
||||
F test/threadtest3.c 9ab4b168681c3a6f70f6c833ba08e0d48dd4af9b
|
||||
F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
|
||||
F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c
|
||||
F test/tkt-26ff0c2d1e.test 888324e751512972c6e0d1a09df740d8f5aaf660
|
||||
@@ -1204,7 +1204,7 @@ F test/tkt3824.test 150aa00bb6220672e5f0eb14dc8eaa36750425f0
|
||||
F test/tkt3832.test 2300d10d57562b89875b72148338ac3e14f8847d
|
||||
F test/tkt3838.test 292e72489101cd1320d7278dc111c173ebf334d4
|
||||
F test/tkt3841.test 4659845bc53f809a5932c61c6ce8c5bb9d6b947f
|
||||
F test/tkt3871.test d921703d07c68f4fd5312073215a17fa34b0401d
|
||||
F test/tkt3871.test 43ecbc8d90dc83908e2a454aef345acc9d160c6f
|
||||
F test/tkt3879.test 2ad5bef2c87e9991ce941e054c31abe26ef7fb90
|
||||
F test/tkt3911.test 74cd324f3ba653040cc6d94cc4857b290d12d633
|
||||
F test/tkt3918.test ea78bf164e4d55cbde0d83c671ef6fbe930a0032
|
||||
@@ -1259,10 +1259,10 @@ F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
|
||||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
F test/view.test f6c3a39e0c819891265e1d0754e99960d81ef6c9
|
||||
F test/vtab1.test 7c4b81abd88361ada9cbe414c459efca26be6bda
|
||||
F test/vtab1.test 6210e076997f176bedc300a87ad6404651b601dd
|
||||
F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad
|
||||
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
|
||||
F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3
|
||||
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
|
||||
F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391
|
||||
F test/vtab6.test d2986cf418dc51e7fb81d12366bea2caa8b812df
|
||||
F test/vtab7.test ae560ebea870ed04e9aa4177cc302f910faaabb5
|
||||
@@ -1272,10 +1272,8 @@ F test/vtabA.test 1317f06a03597eee29f40a49b6c21e1aaba4285f
|
||||
F test/vtabB.test 04df5dc531b9f44d9ca65b9c1b79f12b5922a796
|
||||
F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292
|
||||
F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96
|
||||
F test/vtabE.test d5024aa42754962f6bb0afd261681686488e7afe
|
||||
F test/vtabE.test 7c4693638d7797ce2eda17af74292b97e705cc61
|
||||
F test/vtabF.test fd5ad376f5a34fe0891df1f3cddb4fe7c3eb077e
|
||||
F test/vtabH.test f77296bbf55675b72817cc10fbbcb236ac986abf
|
||||
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
|
||||
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
|
||||
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
|
||||
F test/vtab_shared.test ea8778d5b0df200adef2ca7c00c3c37d4375f772
|
||||
@@ -1312,8 +1310,8 @@ F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e
|
||||
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
|
||||
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
|
||||
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
|
||||
F test/where7.test f520bcec2c3d12dc4615623b06b2aec7c2d67e94
|
||||
F test/where8.test 98eedca0d375fb400b8377269c4b4686582dfb45
|
||||
F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8
|
||||
F test/where8.test 2eafe74e01cc10355985874e1ff868ac03dbae5e
|
||||
F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739
|
||||
F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2
|
||||
F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
|
||||
@@ -1332,7 +1330,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 cef099a491eac9874f2c28bd2dc86394fb3e47b3
|
||||
F test/with1.test 05c8fc7f809f178a8a0519f02c21fe430948c895
|
||||
F test/with2.test 2b40da883658eb74ad8ad06afabe11a408e7fb87
|
||||
F test/with3.test 511bacdbe41c49cf34f9fd1bd3245fe1575bca98
|
||||
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
|
||||
@@ -1346,9 +1344,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 629d87562e0487c386db630033931d12d62e6372
|
||||
F tool/GetTclKit.bat 8606413d3035c05373a0d7fae82ebf59ae9e16c3
|
||||
F tool/addopcodes.tcl 4ca9c3ef196f08da30add5d07ce0c9458dc8c633
|
||||
F tool/build-all-msvc.bat 204a039f985d5a4f4f9df3a3aa594fd17848c37e x
|
||||
F tool/build-all-msvc.bat e42141ca3c3812315432f9813ef9eb78aa8d99c9 x
|
||||
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
|
||||
F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x
|
||||
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
|
||||
@@ -1363,12 +1361,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 5a5441280b509d2bb3bdc71bfb63781b0d570373
|
||||
F tool/mkautoconfamal.sh 4bdf61548a143e5977bd86ab93d68b694d10c8fa
|
||||
F tool/mkkeywordhash.c 06ec0b78bd4fa68c12d90ef2bdfe76b039133ff8
|
||||
F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b
|
||||
F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl f0d5bb266d1d388cf86fce5ba01a891e95d72d41
|
||||
F tool/mkpragmatab.tcl e94e55d247d4fe3be34f2a4f4edb03fdcd09ce5b
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 87240b09c20042999b41d5fabe091b7111287835
|
||||
F tool/mksqlite3c.tcl b66b4170f693602cd6985aed15d9509fe2f18c84
|
||||
@@ -1382,7 +1380,7 @@ F tool/replace.tcl 7727c60a04299b65a92f5e1590896fea0f25b9e0
|
||||
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
|
||||
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
|
||||
F tool/run-speed-test.sh 0ae485af4fe9f826e2b494be8c81f8ca9e222a4a
|
||||
F tool/showdb.c 82dca79a999b2701c62417636345e9974151fdad
|
||||
F tool/showdb.c d4476e000a64eca9f5e2c2f68741e747b9778e8d
|
||||
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
|
||||
F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
|
||||
F tool/showstat4.c bda40d6e395df7edb6e9ea630784d3d762c35b4b
|
||||
@@ -1395,7 +1393,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
|
||||
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
||||
F tool/sqldiff.c 653db1a9294e0b34849c4504599c282a18d8b8c6
|
||||
F tool/sqldiff.c db1232df457fdd4cbf2a919a497fc44bb18fb933
|
||||
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
|
||||
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
|
||||
F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f
|
||||
@@ -1406,10 +1404,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 6a4cfc7ab62046eb718ce59eff6b632f239312ac
|
||||
R c06b170488f3c7c74619bb001be96ae6
|
||||
T *branch * ovfloffset-macro
|
||||
T *sym-ovfloffset-macro *
|
||||
P 198d191b2f5ef7d63ac0093c701955c9052fd734
|
||||
R 047e676af06478b15f87435c78af3c91
|
||||
T *branch * btree-column-opcode
|
||||
T *sym-btree-column-opcode *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z bc33053752556a2a7906fec188dea6ee
|
||||
Z d7290cc1ec32ea2c40df94d6965d7340
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1541607d458069f5db890b4ebe1c7e14ddf4e360
|
||||
093e0d10a81adc078dcb3e08e33ce89bdbe53789
|
||||
+3
-3
@@ -422,9 +422,9 @@ static void stringAppend(String *p, const char *z, int n){
|
||||
if( n<0 ) n = (int)strlen(z);
|
||||
if( p->n+n>=p->nAlloc ){
|
||||
int nAlloc = p->nAlloc*2 + n + 100;
|
||||
char *zNew = sqlite3_realloc(p->z, nAlloc);
|
||||
if( zNew==0 ) fatalError("out of memory");
|
||||
p->z = zNew;
|
||||
char *z = sqlite3_realloc(p->z, nAlloc);
|
||||
if( z==0 ) fatalError("out of memory");
|
||||
p->z = z;
|
||||
p->nAlloc = nAlloc;
|
||||
}
|
||||
memcpy(p->z+p->n, z, n);
|
||||
|
||||
+1
-1
@@ -990,7 +990,7 @@ static void analyzeOneTable(
|
||||
/* Do not gather statistics on views or virtual tables */
|
||||
return;
|
||||
}
|
||||
if( sqlite3_strlike("sqlite_%", pTab->zName, 0)==0 ){
|
||||
if( sqlite3_strnicmp(pTab->zName, "sqlite_", 7)==0 ){
|
||||
/* Do not gather statistics on system tables */
|
||||
return;
|
||||
}
|
||||
|
||||
+23
-17
@@ -1051,7 +1051,8 @@ static SQLITE_NOINLINE void btreeParseCellAdjustSizeForOverflow(
|
||||
}else{
|
||||
pInfo->nLocal = (u16)minLocal;
|
||||
}
|
||||
pInfo->nSize = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell) + 4;
|
||||
pInfo->iOverflow = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell);
|
||||
pInfo->nSize = pInfo->iOverflow + 4;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1083,6 +1084,7 @@ static void btreeParseCellPtrNoPayload(
|
||||
pInfo->nSize = 4 + getVarint(&pCell[4], (u64*)&pInfo->nKey);
|
||||
pInfo->nPayload = 0;
|
||||
pInfo->nLocal = 0;
|
||||
pInfo->iOverflow = 0;
|
||||
pInfo->pPayload = 0;
|
||||
return;
|
||||
}
|
||||
@@ -1152,6 +1154,7 @@ static void btreeParseCellPtr(
|
||||
pInfo->nSize = nPayload + (u16)(pIter - pCell);
|
||||
if( pInfo->nSize<4 ) pInfo->nSize = 4;
|
||||
pInfo->nLocal = (u16)nPayload;
|
||||
pInfo->iOverflow = 0;
|
||||
}else{
|
||||
btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo);
|
||||
}
|
||||
@@ -1190,6 +1193,7 @@ static void btreeParseCellPtrIndex(
|
||||
pInfo->nSize = nPayload + (u16)(pIter - pCell);
|
||||
if( pInfo->nSize<4 ) pInfo->nSize = 4;
|
||||
pInfo->nLocal = (u16)nPayload;
|
||||
pInfo->iOverflow = 0;
|
||||
}else{
|
||||
btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo);
|
||||
}
|
||||
@@ -1305,8 +1309,8 @@ static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
|
||||
if( *pRC ) return;
|
||||
assert( pCell!=0 );
|
||||
pPage->xParseCell(pPage, pCell, &info);
|
||||
if( info.nLocal<info.nPayload ){
|
||||
Pgno ovfl = get4byte(&pCell[OvflOffset(&info)]);
|
||||
if( info.iOverflow ){
|
||||
Pgno ovfl = get4byte(&pCell[info.iOverflow]);
|
||||
ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC);
|
||||
}
|
||||
}
|
||||
@@ -3344,11 +3348,11 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
|
||||
if( eType==PTRMAP_OVERFLOW1 ){
|
||||
CellInfo info;
|
||||
pPage->xParseCell(pPage, pCell, &info);
|
||||
if( info.nLocal<info.nPayload
|
||||
&& pCell+info.nSize-1<=pPage->aData+pPage->maskPage
|
||||
&& iFrom==get4byte(pCell+OvflOffset(&info))
|
||||
if( info.iOverflow
|
||||
&& pCell+info.iOverflow+3<=pPage->aData+pPage->maskPage
|
||||
&& iFrom==get4byte(&pCell[info.iOverflow])
|
||||
){
|
||||
put4byte(pCell+OvflOffset(&info), iTo);
|
||||
put4byte(&pCell[info.iOverflow], iTo);
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
@@ -5990,13 +5994,13 @@ static int clearCell(
|
||||
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||
pPage->xParseCell(pPage, pCell, &info);
|
||||
*pnSize = info.nSize;
|
||||
if( info.nLocal==info.nPayload ){
|
||||
if( info.iOverflow==0 ){
|
||||
return SQLITE_OK; /* No overflow pages. Return without doing anything */
|
||||
}
|
||||
if( pCell+info.nSize-1 > pPage->aData+pPage->maskPage ){
|
||||
if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){
|
||||
return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */
|
||||
}
|
||||
ovflPgno = get4byte(pCell + info.nSize - 4);
|
||||
ovflPgno = get4byte(&pCell[info.iOverflow]);
|
||||
assert( pBt->usableSize > 4 );
|
||||
ovflPageSize = pBt->usableSize - 4;
|
||||
nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
|
||||
@@ -6145,6 +6149,7 @@ static int fillInCell(
|
||||
assert( info.nKey==nKey );
|
||||
assert( *pnSize == info.nSize );
|
||||
assert( spaceLeft == info.nLocal );
|
||||
assert( pPrior == &pCell[info.iOverflow] );
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6465,7 +6470,7 @@ static int rebuildPage(
|
||||
pData = pEnd;
|
||||
for(i=0; i<nCell; i++){
|
||||
u8 *pCell = apCell[i];
|
||||
if( SQLITE_WITHIN(pCell,aData,pEnd) ){
|
||||
if( pCell>aData && pCell<pEnd ){
|
||||
pCell = &pTmp[pCell - aData];
|
||||
}
|
||||
pData -= szCell[i];
|
||||
@@ -6576,7 +6581,7 @@ static int pageFreeArray(
|
||||
|
||||
for(i=iFirst; i<iEnd; i++){
|
||||
u8 *pCell = pCArray->apCell[i];
|
||||
if( SQLITE_WITHIN(pCell, pStart, pEnd) ){
|
||||
if( pCell>=pStart && pCell<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
|
||||
@@ -6854,8 +6859,8 @@ static int ptrmapCheckPages(MemPage **apPage, int nPage){
|
||||
|
||||
z = findCell(pPage, j);
|
||||
pPage->xParseCell(pPage, z, &info);
|
||||
if( info.nLocal<info.nPayload ){
|
||||
Pgno ovfl = get4byte(&z[OvflOffset(&info)]);
|
||||
if( info.iOverflow ){
|
||||
Pgno ovfl = get4byte(&z[info.iOverflow]);
|
||||
ptrmapGet(pBt, ovfl, &e, &n);
|
||||
assert( n==pPage->pgno && e==PTRMAP_OVERFLOW1 );
|
||||
}
|
||||
@@ -7516,7 +7521,8 @@ static int balance_nonroot(
|
||||
** overflow cell), we can skip updating the pointer map entries. */
|
||||
if( iOld>=nNew
|
||||
|| pNew->pgno!=aPgno[iOld]
|
||||
|| !SQLITE_WITHIN(pCell,aOld,&aOld[usableSize])
|
||||
|| pCell<aOld
|
||||
|| pCell>=&aOld[usableSize]
|
||||
){
|
||||
if( !leafCorrection ){
|
||||
ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc);
|
||||
@@ -9161,9 +9167,9 @@ static int checkTreePage(
|
||||
if( info.nPayload>info.nLocal ){
|
||||
int nPage; /* Number of pages on the overflow chain */
|
||||
Pgno pgnoOvfl; /* First page of the overflow chain */
|
||||
assert( pc + info.nSize - 4 <= usableSize );
|
||||
assert( pc + info.iOverflow <= usableSize );
|
||||
nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
|
||||
pgnoOvfl = get4byte(&pCell[info.nSize - 4]);
|
||||
pgnoOvfl = get4byte(&pCell[info.iOverflow]);
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( pBt->autoVacuum ){
|
||||
checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage);
|
||||
|
||||
+1
-7
@@ -470,16 +470,10 @@ struct CellInfo {
|
||||
u8 *pPayload; /* Pointer to the start of payload */
|
||||
u32 nPayload; /* Bytes of payload */
|
||||
u16 nLocal; /* Amount of payload held locally, not on overflow */
|
||||
u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */
|
||||
u16 nSize; /* Size of the cell content on the main b-tree page */
|
||||
};
|
||||
|
||||
/* If X is a pointer to a CellInfo object for a cell, then OvflOffset(X) is
|
||||
** the offset from the start of that cell to the first overflow page number
|
||||
** for for that cell.
|
||||
*/
|
||||
#define OvflOffset(X) ((X)->nSize-4)
|
||||
|
||||
|
||||
/*
|
||||
** Maximum depth of an SQLite B-Tree structure. Any B-Tree deeper than
|
||||
** this will be declared corrupt. This value is calculated based on a
|
||||
|
||||
+15
-9
@@ -376,7 +376,12 @@ Table *sqlite3LocateTable(
|
||||
}
|
||||
pParse->checkSchema = 1;
|
||||
}
|
||||
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
else if( pParse->db->auth.authLevel<UAUTH_User ){
|
||||
sqlite3ErrorMsg(pParse, "user not authenticated");
|
||||
p = 0;
|
||||
}
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -1635,7 +1640,7 @@ static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){
|
||||
zExtra = sqlite3DbMallocZero(db, nByte);
|
||||
if( zExtra==0 ) return SQLITE_NOMEM;
|
||||
memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn);
|
||||
pIdx->azColl = (const char**)zExtra;
|
||||
pIdx->azColl = (char**)zExtra;
|
||||
zExtra += sizeof(char*)*N;
|
||||
memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn);
|
||||
pIdx->aiColumn = (i16*)zExtra;
|
||||
@@ -1816,7 +1821,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
|
||||
if( !hasColumn(pPk->aiColumn, j, i) ){
|
||||
assert( j<pPk->nColumn );
|
||||
pPk->aiColumn[j] = i;
|
||||
pPk->azColl[j] = sqlite3StrBINARY;
|
||||
pPk->azColl[j] = "BINARY";
|
||||
j++;
|
||||
}
|
||||
}
|
||||
@@ -2866,7 +2871,7 @@ Index *sqlite3AllocateIndexObject(
|
||||
p = sqlite3DbMallocZero(db, nByte + nExtra);
|
||||
if( p ){
|
||||
char *pExtra = ((char*)p)+ROUND8(sizeof(Index));
|
||||
p->azColl = (const char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol);
|
||||
p->azColl = (char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol);
|
||||
p->aiRowLogEst = (LogEst*)pExtra; pExtra += sizeof(LogEst)*(nCol+1);
|
||||
p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol;
|
||||
p->aSortOrder = (u8*)pExtra;
|
||||
@@ -3143,7 +3148,7 @@ Index *sqlite3CreateIndex(
|
||||
for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
|
||||
Expr *pCExpr; /* The i-th index expression */
|
||||
int requestedSortOrder; /* ASC or DESC on the i-th expression */
|
||||
const char *zColl; /* Collation sequence name */
|
||||
char *zColl; /* Collation sequence name */
|
||||
|
||||
sqlite3StringToId(pListItem->pExpr);
|
||||
sqlite3ResolveSelfReference(pParse, pTab, NC_IdxExpr, pListItem->pExpr, 0);
|
||||
@@ -3189,7 +3194,7 @@ Index *sqlite3CreateIndex(
|
||||
}else if( j>=0 ){
|
||||
zColl = pTab->aCol[j].zColl;
|
||||
}
|
||||
if( !zColl ) zColl = sqlite3StrBINARY;
|
||||
if( !zColl ) zColl = "BINARY";
|
||||
if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
|
||||
goto exit_create_index;
|
||||
}
|
||||
@@ -3218,7 +3223,7 @@ Index *sqlite3CreateIndex(
|
||||
assert( i==pIndex->nColumn );
|
||||
}else{
|
||||
pIndex->aiColumn[i] = XN_ROWID;
|
||||
pIndex->azColl[i] = sqlite3StrBINARY;
|
||||
pIndex->azColl[i] = "BINARY";
|
||||
}
|
||||
sqlite3DefaultRowEst(pIndex);
|
||||
if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex);
|
||||
@@ -4342,8 +4347,9 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
|
||||
if( pKey ){
|
||||
assert( sqlite3KeyInfoIsWriteable(pKey) );
|
||||
for(i=0; i<nCol; i++){
|
||||
const char *zColl = pIdx->azColl[i];
|
||||
pKey->aColl[i] = zColl==sqlite3StrBINARY ? 0 :
|
||||
char *zColl = pIdx->azColl[i];
|
||||
assert( zColl!=0 );
|
||||
pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 :
|
||||
sqlite3LocateCollSeq(pParse, zColl);
|
||||
pKey->aSortOrder[i] = pIdx->aSortOrder[i];
|
||||
}
|
||||
|
||||
@@ -63,9 +63,6 @@ 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
|
||||
@@ -161,9 +158,6 @@ static const char * const azCompileOpt[] = {
|
||||
#ifdef SQLITE_INT64_TYPE
|
||||
"INT64_TYPE",
|
||||
#endif
|
||||
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
"LIKE_DOESNT_MATCH_BLOBS",
|
||||
#endif
|
||||
#if SQLITE_LOCK_TRACE
|
||||
"LOCK_TRACE",
|
||||
#endif
|
||||
|
||||
+7
-14
@@ -65,7 +65,6 @@ struct DateTime {
|
||||
char validHMS; /* True (1) if h,m,s are valid */
|
||||
char validJD; /* True (1) if iJD is valid */
|
||||
char validTZ; /* True (1) if tz is valid */
|
||||
char tzSet; /* Timezone was set explicitly */
|
||||
};
|
||||
|
||||
|
||||
@@ -159,7 +158,6 @@ static int parseTimezone(const char *zDate, DateTime *p){
|
||||
p->tz = sgn*(nMn + nHr*60);
|
||||
zulu_time:
|
||||
while( sqlite3Isspace(*zDate) ){ zDate++; }
|
||||
p->tzSet = 1;
|
||||
return *zDate!=0;
|
||||
}
|
||||
|
||||
@@ -592,18 +590,13 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
|
||||
}
|
||||
#ifndef SQLITE_OMIT_LOCALTIME
|
||||
else if( strcmp(z, "utc")==0 ){
|
||||
if( p->tzSet==0 ){
|
||||
sqlite3_int64 c1;
|
||||
computeJD(p);
|
||||
c1 = localtimeOffset(p, pCtx, &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->iJD -= c1;
|
||||
clearYMD_HMS_TZ(p);
|
||||
p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
|
||||
}
|
||||
p->tzSet = 1;
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
sqlite3_int64 c1;
|
||||
computeJD(p);
|
||||
c1 = localtimeOffset(p, pCtx, &rc);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->iJD -= c1;
|
||||
clearYMD_HMS_TZ(p);
|
||||
p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+5
-21
@@ -853,7 +853,6 @@ 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;
|
||||
@@ -888,11 +887,9 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
||||
assert( ExprHasProperty(p, EP_Reduced)==0 );
|
||||
memcpy(zAlloc, p, nNewSize);
|
||||
}else{
|
||||
u32 nSize = (u32)exprStructSize(p);
|
||||
int nSize = exprStructSize(p);
|
||||
memcpy(zAlloc, p, nSize);
|
||||
if( nSize<EXPR_FULLSIZE ){
|
||||
memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
|
||||
}
|
||||
memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
|
||||
}
|
||||
|
||||
/* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
|
||||
@@ -982,7 +979,6 @@ 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){
|
||||
@@ -2468,7 +2464,7 @@ void sqlite3ExprCodeLoadIndexColumn(
|
||||
assert( pIdx->aColExpr );
|
||||
assert( pIdx->aColExpr->nExpr>iIdxCol );
|
||||
pParse->iSelfTab = iTabCur;
|
||||
sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut);
|
||||
sqlite3ExprCode(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut);
|
||||
}else{
|
||||
sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur,
|
||||
iTabCol, regOut);
|
||||
@@ -3321,25 +3317,13 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
||||
sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target);
|
||||
}else{
|
||||
inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
|
||||
assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
|
||||
assert( pParse->pVdbe || pParse->db->mallocFailed );
|
||||
if( inReg!=target && pParse->pVdbe ){
|
||||
sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Make a transient copy of expression pExpr and then code it using
|
||||
** sqlite3ExprCode(). This routine works just like sqlite3ExprCode()
|
||||
** except that the input expression is guaranteed to be unchanged.
|
||||
*/
|
||||
void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){
|
||||
sqlite3 *db = pParse->db;
|
||||
pExpr = sqlite3ExprDup(db, pExpr, 0);
|
||||
if( !db->mallocFailed ) sqlite3ExprCode(pParse, pExpr, target);
|
||||
sqlite3ExprDelete(db, pExpr);
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code that will evaluate expression pExpr and store the
|
||||
** results in register target. The results are guaranteed to appear
|
||||
@@ -3834,7 +3818,7 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){
|
||||
if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken ){
|
||||
if( pA->op==TK_FUNCTION ){
|
||||
if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
|
||||
}else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
|
||||
|
||||
+4
-2
@@ -249,7 +249,7 @@ int sqlite3FkLocateIndex(
|
||||
int i, j;
|
||||
for(i=0; i<nCol; i++){
|
||||
i16 iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */
|
||||
const char *zDfltColl; /* Def. collation for column */
|
||||
char *zDfltColl; /* Def. collation for column */
|
||||
char *zIdxCol; /* Name of indexed column */
|
||||
|
||||
if( iCol<0 ) break; /* No foreign keys against expression indexes */
|
||||
@@ -258,7 +258,9 @@ int sqlite3FkLocateIndex(
|
||||
** the default collation sequence for the column, this index is
|
||||
** unusable. Bail out early in this case. */
|
||||
zDfltColl = pParent->aCol[iCol].zColl;
|
||||
if( !zDfltColl ) zDfltColl = sqlite3StrBINARY;
|
||||
if( !zDfltColl ){
|
||||
zDfltColl = "BINARY";
|
||||
}
|
||||
if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break;
|
||||
|
||||
zIdxCol = pParent->aCol[iCol].zName;
|
||||
|
||||
+1
-19
@@ -747,7 +747,7 @@ static int patternCompare(
|
||||
}
|
||||
c2 = Utf8Read(zString);
|
||||
if( c==c2 ) continue;
|
||||
if( noCase && sqlite3Tolower(c)==sqlite3Tolower(c2) ){
|
||||
if( noCase && c<0x80 && c2<0x80 && sqlite3Tolower(c)==sqlite3Tolower(c2) ){
|
||||
continue;
|
||||
}
|
||||
if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue;
|
||||
@@ -763,13 +763,6 @@ int sqlite3_strglob(const char *zGlobPattern, const char *zString){
|
||||
return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, 0)==0;
|
||||
}
|
||||
|
||||
/*
|
||||
** The sqlite3_strlike() interface.
|
||||
*/
|
||||
int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){
|
||||
return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc)==0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Count the number of times that the LIKE operator (or GLOB which is
|
||||
** just a variation of LIKE) gets called. This is used for testing
|
||||
@@ -802,17 +795,6 @@ static void likeFunc(
|
||||
int nPat;
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
|
||||
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_BLOB
|
||||
|| sqlite3_value_type(argv[1])==SQLITE_BLOB
|
||||
){
|
||||
#ifdef SQLITE_TEST
|
||||
sqlite3_like_count++;
|
||||
#endif
|
||||
sqlite3_result_int(context, 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
zB = sqlite3_value_text(argv[0]);
|
||||
zA = sqlite3_value_text(argv[1]);
|
||||
|
||||
|
||||
@@ -260,8 +260,3 @@ int sqlite3PendingByte = 0x40000000;
|
||||
** the vdbe.c file.
|
||||
*/
|
||||
const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
|
||||
|
||||
/*
|
||||
** Name of the default collating sequence
|
||||
*/
|
||||
const char sqlite3StrBINARY[] = "BINARY";
|
||||
|
||||
+20
-7
@@ -1408,7 +1408,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
int x;
|
||||
if( iField==XN_EXPR ){
|
||||
pParse->ckBase = regNewData+1;
|
||||
sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i);
|
||||
sqlite3ExprCode(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i);
|
||||
pParse->ckBase = 0;
|
||||
VdbeComment((v, "%s column %d", pIdx->zName, i));
|
||||
}else{
|
||||
@@ -1709,6 +1709,20 @@ int sqlite3_xferopt_count;
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_XFER_OPT
|
||||
/*
|
||||
** Check to collation names to see if they are compatible.
|
||||
*/
|
||||
static int xferCompatibleCollation(const char *z1, const char *z2){
|
||||
if( z1==0 ){
|
||||
return z2==0;
|
||||
}
|
||||
if( z2==0 ){
|
||||
return 0;
|
||||
}
|
||||
return sqlite3StrICmp(z1, z2)==0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Check to see if index pSrc is compatible as a source of data
|
||||
** for index pDest in an insert transfer optimization. The rules
|
||||
@@ -1744,7 +1758,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
|
||||
if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){
|
||||
return 0; /* Different sort orders */
|
||||
}
|
||||
if( sqlite3_stricmp(pSrc->azColl[i],pDest->azColl[i])!=0 ){
|
||||
if( !xferCompatibleCollation(pSrc->azColl[i],pDest->azColl[i]) ){
|
||||
return 0; /* Different collating sequences */
|
||||
}
|
||||
}
|
||||
@@ -1905,7 +1919,7 @@ static int xferOptimization(
|
||||
if( pDestCol->affinity!=pSrcCol->affinity ){
|
||||
return 0; /* Affinity must be the same on all columns */
|
||||
}
|
||||
if( sqlite3_stricmp(pDestCol->zColl, pSrcCol->zColl)!=0 ){
|
||||
if( !xferCompatibleCollation(pDestCol->zColl, pSrcCol->zColl) ){
|
||||
return 0; /* Collating sequence must be the same on all columns */
|
||||
}
|
||||
if( pDestCol->notNull && !pSrcCol->notNull ){
|
||||
@@ -2052,10 +2066,9 @@ static int xferOptimization(
|
||||
** a VACUUM command. In that case keys may not be written in strictly
|
||||
** sorted order. */
|
||||
for(i=0; i<pSrcIdx->nColumn; i++){
|
||||
const char *zColl = pSrcIdx->azColl[i];
|
||||
assert( sqlite3_stricmp(sqlite3StrBINARY, zColl)!=0
|
||||
|| sqlite3StrBINARY==zColl );
|
||||
if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break;
|
||||
char *zColl = pSrcIdx->azColl[i];
|
||||
assert( zColl!=0 );
|
||||
if( sqlite3_stricmp("BINARY", zColl) ) break;
|
||||
}
|
||||
if( i==pSrcIdx->nColumn ){
|
||||
idxInsFlags = OPFLAG_USESEEKRESULT;
|
||||
|
||||
+1
-5
@@ -410,11 +410,7 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
sqlite3_bind_zeroblob64,
|
||||
/* Version 3.9.0 and later */
|
||||
sqlite3_value_subtype,
|
||||
sqlite3_result_subtype,
|
||||
/* Version 3.10.0 and later */
|
||||
sqlite3_status64,
|
||||
sqlite3_strlike,
|
||||
sqlite3_db_cacheflush
|
||||
sqlite3_result_subtype
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+8
-94
@@ -445,10 +445,9 @@ int sqlite3_config(int op, ...){
|
||||
break;
|
||||
}
|
||||
case SQLITE_CONFIG_PAGECACHE: {
|
||||
/* 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). */
|
||||
/* 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). */
|
||||
sqlite3GlobalConfig.pPage = va_arg(ap, void*);
|
||||
sqlite3GlobalConfig.szPage = va_arg(ap, int);
|
||||
sqlite3GlobalConfig.nPage = va_arg(ap, int);
|
||||
@@ -2829,9 +2828,9 @@ static int openDatabase(
|
||||
** EVIDENCE-OF: R-52786-44878 SQLite defines three built-in collating
|
||||
** functions:
|
||||
*/
|
||||
createCollation(db, sqlite3StrBINARY, SQLITE_UTF8, 0, binCollFunc, 0);
|
||||
createCollation(db, sqlite3StrBINARY, SQLITE_UTF16BE, 0, binCollFunc, 0);
|
||||
createCollation(db, sqlite3StrBINARY, SQLITE_UTF16LE, 0, binCollFunc, 0);
|
||||
createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0);
|
||||
createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0);
|
||||
createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0);
|
||||
createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0);
|
||||
createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0);
|
||||
if( db->mallocFailed ){
|
||||
@@ -2840,7 +2839,7 @@ static int openDatabase(
|
||||
/* EVIDENCE-OF: R-08308-17224 The default collating function for all
|
||||
** strings is BINARY.
|
||||
*/
|
||||
db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, sqlite3StrBINARY, 0);
|
||||
db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0);
|
||||
assert( db->pDfltColl!=0 );
|
||||
|
||||
/* Parse the filename/URI argument. */
|
||||
@@ -3340,7 +3339,7 @@ int sqlite3_table_column_metadata(
|
||||
primarykey = 1;
|
||||
}
|
||||
if( !zCollSeq ){
|
||||
zCollSeq = sqlite3StrBINARY;
|
||||
zCollSeq = "BINARY";
|
||||
}
|
||||
|
||||
error_out:
|
||||
@@ -3421,9 +3420,6 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
|
||||
if( op==SQLITE_FCNTL_FILE_POINTER ){
|
||||
*(sqlite3_file**)pArg = fd;
|
||||
rc = SQLITE_OK;
|
||||
}else if( op==SQLITE_FCNTL_VFS_POINTER ){
|
||||
*(sqlite3_vfs**)pArg = sqlite3PagerVfs(pPager);
|
||||
rc = SQLITE_OK;
|
||||
}else if( fd->pMethods ){
|
||||
rc = sqlite3OsFileControl(fd, op, pArg);
|
||||
}else{
|
||||
@@ -3866,85 +3862,3 @@ 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( SQLITE_WITHIN(p, sqlite3GlobalConfig.pScratch, mem0.pScratchEnd) ){
|
||||
if( p>=sqlite3GlobalConfig.pScratch && p<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 SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pEnd);
|
||||
return p>=db->lookaside.pStart && p<db->lookaside.pEnd;
|
||||
}
|
||||
#else
|
||||
#define isLookaside(A,B) 0
|
||||
|
||||
+19
-10
@@ -25,7 +25,7 @@
|
||||
**
|
||||
** This memory allocator uses the following algorithm:
|
||||
**
|
||||
** 1. All memory allocation sizes are rounded up to a power of 2.
|
||||
** 1. All memory allocations sizes are rounded up to a power of 2.
|
||||
**
|
||||
** 2. If two adjacent free blocks are the halves of a larger block,
|
||||
** then the two blocks are coalesced into the single larger block.
|
||||
@@ -117,7 +117,7 @@ static SQLITE_WSD struct Mem5Global {
|
||||
/*
|
||||
** Lists of free blocks. aiFreelist[0] is a list of free blocks of
|
||||
** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2.
|
||||
** aiFreelist[2] holds free blocks of size szAtom*4. And so forth.
|
||||
** and so forth.
|
||||
*/
|
||||
int aiFreelist[LOGMAX+1];
|
||||
|
||||
@@ -183,7 +183,9 @@ static void memsys5Link(int i, int iLogsize){
|
||||
}
|
||||
|
||||
/*
|
||||
** Obtain or release the mutex needed to access global data structures.
|
||||
** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
|
||||
** will already be held (obtained by code in malloc.c) if
|
||||
** sqlite3GlobalConfig.bMemStat is true.
|
||||
*/
|
||||
static void memsys5Enter(void){
|
||||
sqlite3_mutex_enter(mem5.mutex);
|
||||
@@ -193,8 +195,9 @@ static void memsys5Leave(void){
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the size of an outstanding allocation, in bytes.
|
||||
** This only works for chunks that are currently checked out.
|
||||
** Return the size of an outstanding allocation, in bytes. The
|
||||
** size returned omits the 8-byte header overhead. This only
|
||||
** works for chunks that are currently checked out.
|
||||
*/
|
||||
static int memsys5Size(void *p){
|
||||
int iSize, i;
|
||||
@@ -227,12 +230,16 @@ static void *memsys5MallocUnsafe(int nByte){
|
||||
/* Keep track of the maximum allocation request. Even unfulfilled
|
||||
** requests are counted */
|
||||
if( (u32)nByte>mem5.maxRequest ){
|
||||
/* Abort if the requested allocation size is larger than the largest
|
||||
** power of two that we can represent using 32-bit signed integers. */
|
||||
if( nByte > 0x40000000 ) return 0;
|
||||
mem5.maxRequest = nByte;
|
||||
}
|
||||
|
||||
/* Abort if the requested allocation size is larger than the largest
|
||||
** power of two that we can represent using 32-bit signed integers.
|
||||
*/
|
||||
if( nByte > 0x40000000 ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Round nByte up to the next valid power of two */
|
||||
for(iFullSz=mem5.szAtom,iLogsize=0; iFullSz<nByte; iFullSz*=2,iLogsize++){}
|
||||
|
||||
@@ -391,11 +398,13 @@ static void *memsys5Realloc(void *pPrior, int nBytes){
|
||||
if( nBytes<=nOld ){
|
||||
return pPrior;
|
||||
}
|
||||
p = memsys5Malloc(nBytes);
|
||||
memsys5Enter();
|
||||
p = memsys5MallocUnsafe(nBytes);
|
||||
if( p ){
|
||||
memcpy(p, pPrior, nOld);
|
||||
memsys5Free(pPrior);
|
||||
memsys5FreeUnsafe(pPrior);
|
||||
}
|
||||
memsys5Leave();
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,8 +51,6 @@ struct sqlite3_mutex {
|
||||
};
|
||||
#if SQLITE_MUTEX_NREF
|
||||
#define SQLITE3_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER,0,0,(pthread_t)0,0}
|
||||
#elif defined(SQLITE_ENABLE_API_ARMOR)
|
||||
#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0 }
|
||||
#else
|
||||
#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
|
||||
#endif
|
||||
|
||||
+263
-163
@@ -258,6 +258,8 @@ static pid_t randomnessPid = 0;
|
||||
#define UNIXFILE_DELETE 0x20 /* Delete on close */
|
||||
#define UNIXFILE_URI 0x40 /* Filename might have query parameters */
|
||||
#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
|
||||
#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings issued */
|
||||
#define UNIXFILE_BLOCK 0x0200 /* Next SHM lock might block */
|
||||
|
||||
/*
|
||||
** Include code that is common to all os_*.c files
|
||||
@@ -322,6 +324,19 @@ static int posixOpen(const char *zFile, int flags, int mode){
|
||||
return open(zFile, flags, mode);
|
||||
}
|
||||
|
||||
/*
|
||||
** On some systems, calls to fchown() will trigger a message in a security
|
||||
** log if they come from non-root processes. So avoid calling fchown() if
|
||||
** we are not running as root.
|
||||
*/
|
||||
static int posixFchown(int fd, uid_t uid, gid_t gid){
|
||||
#if OS_VXWORKS
|
||||
return 0;
|
||||
#else
|
||||
return geteuid() ? 0 : fchown(fd,uid,gid);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Forward reference */
|
||||
static int openDirectory(const char*, int*);
|
||||
static int unixGetpagesize(void);
|
||||
@@ -408,7 +423,7 @@ static struct unix_syscall {
|
||||
#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
|
||||
aSyscall[13].pCurrent)
|
||||
|
||||
{ "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
|
||||
{ "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
|
||||
#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
|
||||
|
||||
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
|
||||
@@ -430,50 +445,32 @@ static struct unix_syscall {
|
||||
{ "rmdir", (sqlite3_syscall_ptr)rmdir, 0 },
|
||||
#define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent)
|
||||
|
||||
{ "fchown", (sqlite3_syscall_ptr)fchown, 0 },
|
||||
{ "fchown", (sqlite3_syscall_ptr)posixFchown, 0 },
|
||||
#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
|
||||
|
||||
{ "geteuid", (sqlite3_syscall_ptr)geteuid, 0 },
|
||||
#define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent)
|
||||
|
||||
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
|
||||
{ "mmap", (sqlite3_syscall_ptr)mmap, 0 },
|
||||
#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[22].pCurrent)
|
||||
#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent)
|
||||
|
||||
{ "munmap", (sqlite3_syscall_ptr)munmap, 0 },
|
||||
#define osMunmap ((void*(*)(void*,size_t))aSyscall[23].pCurrent)
|
||||
#define osMunmap ((void*(*)(void*,size_t))aSyscall[22].pCurrent)
|
||||
|
||||
#if HAVE_MREMAP
|
||||
{ "mremap", (sqlite3_syscall_ptr)mremap, 0 },
|
||||
#else
|
||||
{ "mremap", (sqlite3_syscall_ptr)0, 0 },
|
||||
#endif
|
||||
#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[24].pCurrent)
|
||||
|
||||
#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)
|
||||
{ "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 },
|
||||
#define osGetpagesize ((int(*)(void))aSyscall[25].pCurrent)
|
||||
#define osGetpagesize ((int(*)(void))aSyscall[24].pCurrent)
|
||||
|
||||
{ "readlink", (sqlite3_syscall_ptr)readlink, 0 },
|
||||
#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent)
|
||||
#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[25].pCurrent)
|
||||
|
||||
#endif
|
||||
|
||||
}; /* End of the overrideable system calls */
|
||||
|
||||
|
||||
/*
|
||||
** On some systems, calls to fchown() will trigger a message in a security
|
||||
** log if they come from non-root processes. So avoid calling fchown() if
|
||||
** we are not running as root.
|
||||
*/
|
||||
static int robustFchown(int fd, uid_t uid, gid_t gid){
|
||||
#if OS_VXWORKS
|
||||
return 0;
|
||||
#else
|
||||
return osGeteuid() ? 0 : osFchown(fd,uid,gid);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
|
||||
** "unix" VFSes. Return SQLITE_OK opon successfully updating the
|
||||
@@ -758,12 +755,23 @@ static int robust_ftruncate(int h, sqlite3_int64 sz){
|
||||
** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
|
||||
*/
|
||||
static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
|
||||
assert( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) );
|
||||
switch (posixError) {
|
||||
case EACCES:
|
||||
#if 0
|
||||
/* At one point this code was not commented out. In theory, this branch
|
||||
** should never be hit, as this function should only be called after
|
||||
** a locking-related function (i.e. fcntl()) has returned non-zero with
|
||||
** the value of errno as the first argument. Since a system call has failed,
|
||||
** errno should be non-zero.
|
||||
**
|
||||
** Despite this, if errno really is zero, we still don't want to return
|
||||
** SQLITE_OK. The system call failed, and *some* SQLite error should be
|
||||
** propagated back to the caller. Commenting this branch out means errno==0
|
||||
** will be handled by the "default:" case below.
|
||||
*/
|
||||
case 0:
|
||||
return SQLITE_OK;
|
||||
#endif
|
||||
|
||||
case EAGAIN:
|
||||
case ETIMEDOUT:
|
||||
case EBUSY:
|
||||
@@ -773,9 +781,41 @@ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
|
||||
* introspection, in which it actually means what it says */
|
||||
return SQLITE_BUSY;
|
||||
|
||||
case EACCES:
|
||||
/* EACCES is like EAGAIN during locking operations, but not any other time*/
|
||||
if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
|
||||
(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
|
||||
return SQLITE_BUSY;
|
||||
}
|
||||
/* else fall through */
|
||||
case EPERM:
|
||||
return SQLITE_PERM;
|
||||
|
||||
#if EOPNOTSUPP!=ENOTSUP
|
||||
case EOPNOTSUPP:
|
||||
/* something went terribly awry, unless during file system support
|
||||
* introspection, in which it actually means what it says */
|
||||
#endif
|
||||
#ifdef ENOTSUP
|
||||
case ENOTSUP:
|
||||
/* invalid fd, unless during file system support introspection, in which
|
||||
* it actually means what it says */
|
||||
#endif
|
||||
case EIO:
|
||||
case EBADF:
|
||||
case EINVAL:
|
||||
case ENOTCONN:
|
||||
case ENODEV:
|
||||
case ENXIO:
|
||||
case ENOENT:
|
||||
#ifdef ESTALE /* ESTALE is not defined on Interix systems */
|
||||
case ESTALE:
|
||||
#endif
|
||||
case ENOSYS:
|
||||
/* these should force the client to close the file and reconnect */
|
||||
|
||||
default:
|
||||
return sqliteIOErr;
|
||||
}
|
||||
@@ -1059,7 +1099,7 @@ static unixInodeInfo *inodeList = 0;
|
||||
|
||||
/*
|
||||
**
|
||||
** This function - unixLogErrorAtLine(), is only ever called via the macro
|
||||
** This function - unixLogError_x(), is only ever called via the macro
|
||||
** unixLogError().
|
||||
**
|
||||
** It is invoked after an error occurs in an OS function and errno has been
|
||||
@@ -1228,7 +1268,7 @@ static int findInodeInfo(
|
||||
rc = osFstat(fd, &statbuf);
|
||||
if( rc!=0 ){
|
||||
storeLastErrno(pFile, errno);
|
||||
#if defined(EOVERFLOW) && defined(SQLITE_DISABLE_LFS)
|
||||
#ifdef EOVERFLOW
|
||||
if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS;
|
||||
#endif
|
||||
return SQLITE_IOERR;
|
||||
@@ -1315,21 +1355,30 @@ static int fileHasMoved(unixFile *pFile){
|
||||
static void verifyDbFile(unixFile *pFile){
|
||||
struct stat buf;
|
||||
int rc;
|
||||
if( pFile->ctrlFlags & UNIXFILE_WARNED ){
|
||||
/* One or more of the following warnings have already been issued. Do not
|
||||
** repeat them so as not to clutter the error log */
|
||||
return;
|
||||
}
|
||||
rc = osFstat(pFile->h, &buf);
|
||||
if( rc!=0 ){
|
||||
sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath);
|
||||
pFile->ctrlFlags |= UNIXFILE_WARNED;
|
||||
return;
|
||||
}
|
||||
if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){
|
||||
sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath);
|
||||
pFile->ctrlFlags |= UNIXFILE_WARNED;
|
||||
return;
|
||||
}
|
||||
if( buf.st_nlink>1 ){
|
||||
sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath);
|
||||
pFile->ctrlFlags |= UNIXFILE_WARNED;
|
||||
return;
|
||||
}
|
||||
if( fileHasMoved(pFile) ){
|
||||
sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
|
||||
pFile->ctrlFlags |= UNIXFILE_WARNED;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1349,7 +1398,6 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
|
||||
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
|
||||
|
||||
assert( pFile );
|
||||
assert( pFile->eFileLock<=SHARED_LOCK );
|
||||
unixEnterMutex(); /* Because pFile->pInode is shared across threads */
|
||||
|
||||
/* Check if a thread in this process holds such a lock */
|
||||
@@ -1406,7 +1454,9 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
|
||||
unixInodeInfo *pInode = pFile->pInode;
|
||||
assert( unixMutexHeld() );
|
||||
assert( pInode!=0 );
|
||||
if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){
|
||||
if( ((pFile->ctrlFlags & UNIXFILE_EXCL)!=0 || pInode->bProcessLock)
|
||||
&& ((pFile->ctrlFlags & UNIXFILE_RDONLY)==0)
|
||||
){
|
||||
if( pInode->bProcessLock==0 ){
|
||||
struct flock lock;
|
||||
assert( pInode->nLock==0 );
|
||||
@@ -1758,7 +1808,9 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
||||
if( unixFileLock(pFile, &lock)==(-1) ){
|
||||
tErrno = errno;
|
||||
rc = SQLITE_IOERR_UNLOCK;
|
||||
storeLastErrno(pFile, tErrno);
|
||||
if( IS_LOCK_ERROR(rc) ){
|
||||
storeLastErrno(pFile, tErrno);
|
||||
}
|
||||
goto end_unlock;
|
||||
}
|
||||
lock.l_type = F_RDLCK;
|
||||
@@ -1780,7 +1832,9 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
||||
if( unixFileLock(pFile, &lock)==(-1) ){
|
||||
tErrno = errno;
|
||||
rc = SQLITE_IOERR_UNLOCK;
|
||||
storeLastErrno(pFile, tErrno);
|
||||
if( IS_LOCK_ERROR(rc) ){
|
||||
storeLastErrno(pFile, tErrno);
|
||||
}
|
||||
goto end_unlock;
|
||||
}
|
||||
}else
|
||||
@@ -2031,7 +2085,17 @@ static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
|
||||
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
|
||||
|
||||
assert( pFile );
|
||||
reserved = osAccess((const char*)pFile->lockingContext, 0)==0;
|
||||
|
||||
/* Check if a thread in this process holds such a lock */
|
||||
if( pFile->eFileLock>SHARED_LOCK ){
|
||||
/* Either this connection or some other connection in the same process
|
||||
** holds a lock on the file. No need to check further. */
|
||||
reserved = 1;
|
||||
}else{
|
||||
/* The lock is held if and only if the lockfile exists */
|
||||
const char *zLockFile = (const char*)pFile->lockingContext;
|
||||
reserved = osAccess(zLockFile, 0)==0;
|
||||
}
|
||||
OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
|
||||
*pResOut = reserved;
|
||||
return rc;
|
||||
@@ -2093,7 +2157,7 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) {
|
||||
rc = SQLITE_BUSY;
|
||||
} else {
|
||||
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
|
||||
if( rc!=SQLITE_BUSY ){
|
||||
if( IS_LOCK_ERROR(rc) ){
|
||||
storeLastErrno(pFile, tErrno);
|
||||
}
|
||||
}
|
||||
@@ -2140,12 +2204,14 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
|
||||
/* To fully unlock the database, delete the lock file */
|
||||
assert( eFileLock==NO_LOCK );
|
||||
rc = osRmdir(zLockFile);
|
||||
if( rc<0 && errno==ENOTDIR ) rc = osUnlink(zLockFile);
|
||||
if( rc<0 ){
|
||||
int tErrno = errno;
|
||||
if( tErrno==ENOENT ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
rc = 0;
|
||||
if( ENOENT != tErrno ){
|
||||
rc = SQLITE_IOERR_UNLOCK;
|
||||
}
|
||||
if( IS_LOCK_ERROR(rc) ){
|
||||
storeLastErrno(pFile, tErrno);
|
||||
}
|
||||
return rc;
|
||||
@@ -2158,11 +2224,14 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
|
||||
** Close a file. Make sure the lock has been released before closing.
|
||||
*/
|
||||
static int dotlockClose(sqlite3_file *id) {
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
assert( id!=0 );
|
||||
dotlockUnlock(id, NO_LOCK);
|
||||
sqlite3_free(pFile->lockingContext);
|
||||
return closeUnixFile(id);
|
||||
int rc = SQLITE_OK;
|
||||
if( id ){
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
dotlockUnlock(id, NO_LOCK);
|
||||
sqlite3_free(pFile->lockingContext);
|
||||
rc = closeUnixFile(id);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
/****************** End of the dot-file lock implementation *******************
|
||||
******************************************************************************/
|
||||
@@ -2228,8 +2297,10 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
|
||||
int tErrno = errno;
|
||||
/* unlock failed with an error */
|
||||
lrc = SQLITE_IOERR_UNLOCK;
|
||||
storeLastErrno(pFile, tErrno);
|
||||
rc = lrc;
|
||||
if( IS_LOCK_ERROR(lrc) ){
|
||||
storeLastErrno(pFile, tErrno);
|
||||
rc = lrc;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int tErrno = errno;
|
||||
@@ -2362,9 +2433,12 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) {
|
||||
** Close a file.
|
||||
*/
|
||||
static int flockClose(sqlite3_file *id) {
|
||||
assert( id!=0 );
|
||||
flockUnlock(id, NO_LOCK);
|
||||
return closeUnixFile(id);
|
||||
int rc = SQLITE_OK;
|
||||
if( id ){
|
||||
flockUnlock(id, NO_LOCK);
|
||||
rc = closeUnixFile(id);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
|
||||
@@ -2989,22 +3063,23 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
|
||||
*/
|
||||
static int afpClose(sqlite3_file *id) {
|
||||
int rc = SQLITE_OK;
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
assert( id!=0 );
|
||||
afpUnlock(id, NO_LOCK);
|
||||
unixEnterMutex();
|
||||
if( pFile->pInode && pFile->pInode->nLock ){
|
||||
/* If there are outstanding locks, do not actually close the file just
|
||||
** yet because that would clear those locks. Instead, add the file
|
||||
** descriptor to pInode->aPending. It will be automatically closed when
|
||||
** the last lock is cleared.
|
||||
*/
|
||||
setPendingFd(pFile);
|
||||
if( id ){
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
afpUnlock(id, NO_LOCK);
|
||||
unixEnterMutex();
|
||||
if( pFile->pInode && pFile->pInode->nLock ){
|
||||
/* If there are outstanding locks, do not actually close the file just
|
||||
** yet because that would clear those locks. Instead, add the file
|
||||
** descriptor to pInode->aPending. It will be automatically closed when
|
||||
** the last lock is cleared.
|
||||
*/
|
||||
setPendingFd(pFile);
|
||||
}
|
||||
releaseInodeInfo(pFile);
|
||||
sqlite3_free(pFile->lockingContext);
|
||||
rc = closeUnixFile(id);
|
||||
unixLeaveMutex();
|
||||
}
|
||||
releaseInodeInfo(pFile);
|
||||
sqlite3_free(pFile->lockingContext);
|
||||
rc = closeUnixFile(id);
|
||||
unixLeaveMutex();
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3083,9 +3158,13 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
|
||||
SimulateIOError( got = -1 );
|
||||
#else
|
||||
newOffset = lseek(id->h, offset, SEEK_SET);
|
||||
SimulateIOError( newOffset = -1 );
|
||||
if( newOffset<0 ){
|
||||
storeLastErrno((unixFile*)id, errno);
|
||||
SimulateIOError( newOffset-- );
|
||||
if( newOffset!=offset ){
|
||||
if( newOffset == -1 ){
|
||||
storeLastErrno((unixFile*)id, errno);
|
||||
}else{
|
||||
storeLastErrno((unixFile*)id, 0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
got = osRead(id->h, pBuf, cnt);
|
||||
@@ -3184,7 +3263,6 @@ static int seekAndWriteFd(
|
||||
|
||||
assert( nBuf==(nBuf&0x1ffff) );
|
||||
assert( fd>2 );
|
||||
assert( piErrno!=0 );
|
||||
nBuf &= 0x1ffff;
|
||||
TIMER_START;
|
||||
|
||||
@@ -3195,10 +3273,11 @@ static int seekAndWriteFd(
|
||||
#else
|
||||
do{
|
||||
i64 iSeek = lseek(fd, iOff, SEEK_SET);
|
||||
SimulateIOError( iSeek = -1 );
|
||||
if( iSeek<0 ){
|
||||
rc = -1;
|
||||
break;
|
||||
SimulateIOError( iSeek-- );
|
||||
|
||||
if( iSeek!=iOff ){
|
||||
if( piErrno ) *piErrno = (iSeek==-1 ? errno : 0);
|
||||
return -1;
|
||||
}
|
||||
rc = osWrite(fd, pBuf, nBuf);
|
||||
}while( rc<0 && errno==EINTR );
|
||||
@@ -3207,7 +3286,7 @@ static int seekAndWriteFd(
|
||||
TIMER_END;
|
||||
OSTRACE(("WRITE %-3d %5d %7lld %llu\n", fd, rc, iOff, TIMER_ELAPSED));
|
||||
|
||||
if( rc<0 ) *piErrno = errno;
|
||||
if( rc<0 && piErrno ) *piErrno = errno;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3391,15 +3470,10 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
|
||||
#endif
|
||||
|
||||
/* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
|
||||
** no-op. But go ahead and call fstat() to validate the file
|
||||
** descriptor as we need a method to provoke a failure during
|
||||
** coverate testing.
|
||||
** no-op
|
||||
*/
|
||||
#ifdef SQLITE_NO_SYNC
|
||||
{
|
||||
struct stat buf;
|
||||
rc = osFstat(fd, &buf);
|
||||
}
|
||||
rc = SQLITE_OK;
|
||||
#elif HAVE_FULLFSYNC
|
||||
if( fullSync ){
|
||||
rc = osFcntl(fd, F_FULLFSYNC, 0);
|
||||
@@ -3465,20 +3539,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>0 && zDirname[ii]!='/'; ii--);
|
||||
for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
|
||||
if( ii>0 ){
|
||||
zDirname[ii] = '\0';
|
||||
}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));
|
||||
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;
|
||||
return unixLogError(SQLITE_CANTOPEN_BKPT, "openDirectory", zDirname);
|
||||
return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3531,11 +3601,10 @@ static int unixSync(sqlite3_file *id, int flags){
|
||||
OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
|
||||
HAVE_FULLFSYNC, isFullsync));
|
||||
rc = osOpenDirectory(pFile->zPath, &dirfd);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( rc==SQLITE_OK && dirfd>=0 ){
|
||||
full_fsync(dirfd, 0, 0);
|
||||
robust_close(pFile, dirfd, __LINE__);
|
||||
}else{
|
||||
assert( rc==SQLITE_CANTOPEN );
|
||||
}else if( rc==SQLITE_CANTOPEN ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
|
||||
@@ -3667,14 +3736,18 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
|
||||
int nWrite = 0; /* Number of bytes written by seekAndWrite */
|
||||
i64 iWrite; /* Next offset to write to */
|
||||
|
||||
iWrite = (buf.st_size/nBlk)*nBlk + nBlk - 1;
|
||||
iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
|
||||
assert( iWrite>=buf.st_size );
|
||||
assert( (iWrite/nBlk)==((buf.st_size+nBlk-1)/nBlk) );
|
||||
assert( ((iWrite+1)%nBlk)==0 );
|
||||
for(/*no-op*/; iWrite<nSize+nBlk-1; iWrite+=nBlk ){
|
||||
if( iWrite>=nSize ) iWrite = nSize - 1;
|
||||
for(/*no-op*/; iWrite<nSize; iWrite+=nBlk ){
|
||||
nWrite = seekAndWrite(pFile, iWrite, "", 1);
|
||||
if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
|
||||
}
|
||||
if( nWrite==0 || (nSize%nBlk) ){
|
||||
nWrite = seekAndWrite(pFile, nSize-1, "", 1);
|
||||
if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -3722,6 +3795,10 @@ static int unixGetTempname(int nBuf, char *zBuf);
|
||||
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
switch( op ){
|
||||
case SQLITE_FCNTL_WAL_BLOCK: {
|
||||
/* pFile->ctrlFlags |= UNIXFILE_BLOCK; // Deferred feature */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_LOCKSTATE: {
|
||||
*(int*)pArg = pFile->eFileLock;
|
||||
return SQLITE_OK;
|
||||
@@ -4048,9 +4125,10 @@ static int unixShmSystemLock(
|
||||
assert( n==1 || lockType!=F_RDLCK );
|
||||
|
||||
/* Locks are within range */
|
||||
assert( n>=1 && n<=SQLITE_SHM_NLOCK );
|
||||
assert( n>=1 && n<SQLITE_SHM_NLOCK );
|
||||
|
||||
if( pShmNode->h>=0 ){
|
||||
int lkType;
|
||||
/* Initialize the locking parameters */
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.l_type = lockType;
|
||||
@@ -4058,8 +4136,10 @@ static int unixShmSystemLock(
|
||||
f.l_start = ofst;
|
||||
f.l_len = n;
|
||||
|
||||
rc = osFcntl(pShmNode->h, F_SETLK, &f);
|
||||
lkType = (pFile->ctrlFlags & UNIXFILE_BLOCK)!=0 ? F_SETLKW : F_SETLK;
|
||||
rc = osFcntl(pShmNode->h, lkType, &f);
|
||||
rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
|
||||
pFile->ctrlFlags &= ~UNIXFILE_BLOCK;
|
||||
}
|
||||
|
||||
/* Update the global lock state and do debug tracing */
|
||||
@@ -4126,7 +4206,7 @@ static int unixShmRegionPerMap(void){
|
||||
static void unixShmPurge(unixFile *pFd){
|
||||
unixShmNode *p = pFd->pInode->pShmNode;
|
||||
assert( unixMutexHeld() );
|
||||
if( p && ALWAYS(p->nRef==0) ){
|
||||
if( p && p->nRef==0 ){
|
||||
int nShmPerMap = unixShmRegionPerMap();
|
||||
int i;
|
||||
assert( p->pInode==pFd->pInode );
|
||||
@@ -4213,7 +4293,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
|
||||
** a new *-shm file is created, an attempt will be made to create it
|
||||
** with the same permissions.
|
||||
*/
|
||||
if( osFstat(pDbFd->h, &sStat) ){
|
||||
if( osFstat(pDbFd->h, &sStat) && pInode->bProcessLock==0 ){
|
||||
rc = SQLITE_IOERR_FSTAT;
|
||||
goto shm_open_err;
|
||||
}
|
||||
@@ -4263,7 +4343,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
|
||||
** is owned by the same user that owns the original database. Otherwise,
|
||||
** the original owner will not be able to connect.
|
||||
*/
|
||||
robustFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
|
||||
osFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
|
||||
|
||||
/* Check to see if another process is holding the dead-man switch.
|
||||
** If not, truncate the file to zero length.
|
||||
@@ -4400,8 +4480,7 @@ static int unixShmMap(
|
||||
/* Write to the last byte of each newly allocated or extended page */
|
||||
assert( (nByte % pgsz)==0 );
|
||||
for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){
|
||||
int x = 0;
|
||||
if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, &x)!=1 ){
|
||||
if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, 0)!=1 ){
|
||||
const char *zFile = pShmNode->zFilename;
|
||||
rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile);
|
||||
goto shmpage_out;
|
||||
@@ -4769,14 +4848,17 @@ static void unixRemapfile(
|
||||
** recreated as a result of outstanding references) or an SQLite error
|
||||
** code otherwise.
|
||||
*/
|
||||
static int unixMapfile(unixFile *pFd, i64 nMap){
|
||||
static int unixMapfile(unixFile *pFd, i64 nByte){
|
||||
i64 nMap = nByte;
|
||||
int rc;
|
||||
|
||||
assert( nMap>=0 || pFd->nFetchOut==0 );
|
||||
assert( nMap>0 || (pFd->mmapSize==0 && pFd->pMapRegion==0) );
|
||||
if( pFd->nFetchOut>0 ) return SQLITE_OK;
|
||||
|
||||
if( nMap<0 ){
|
||||
struct stat statbuf; /* Low-level file information */
|
||||
if( osFstat(pFd->h, &statbuf) ){
|
||||
rc = osFstat(pFd->h, &statbuf);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return SQLITE_IOERR_FSTAT;
|
||||
}
|
||||
nMap = statbuf.st_size;
|
||||
@@ -4785,9 +4867,12 @@ static int unixMapfile(unixFile *pFd, i64 nMap){
|
||||
nMap = pFd->mmapSizeMax;
|
||||
}
|
||||
|
||||
assert( nMap>0 || (pFd->mmapSize==0 && pFd->pMapRegion==0) );
|
||||
if( nMap!=pFd->mmapSize ){
|
||||
unixRemapfile(pFd, nMap);
|
||||
if( nMap>0 ){
|
||||
unixRemapfile(pFd, nMap);
|
||||
}else{
|
||||
unixUnmapfile(pFd);
|
||||
}
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
@@ -5356,19 +5441,21 @@ static int fillInUnixFile(
|
||||
*/
|
||||
static const char *unixTempFileDir(void){
|
||||
static const char *azDirs[] = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"/var/tmp",
|
||||
"/usr/tmp",
|
||||
"/tmp",
|
||||
"."
|
||||
0 /* List terminator */
|
||||
};
|
||||
unsigned int i;
|
||||
struct stat buf;
|
||||
const char *zDir = sqlite3_temp_directory;
|
||||
const char *zDir = 0;
|
||||
|
||||
if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
|
||||
if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
|
||||
azDirs[0] = sqlite3_temp_directory;
|
||||
if( !azDirs[1] ) azDirs[1] = getenv("SQLITE_TMPDIR");
|
||||
if( !azDirs[2] ) azDirs[2] = getenv("TMPDIR");
|
||||
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
|
||||
if( zDir==0 ) continue;
|
||||
if( osStat(zDir, &buf) ) continue;
|
||||
@@ -5385,8 +5472,12 @@ static const char *unixTempFileDir(void){
|
||||
** pVfs->mxPathname bytes.
|
||||
*/
|
||||
static int unixGetTempname(int nBuf, char *zBuf){
|
||||
static const unsigned char zChars[] =
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789";
|
||||
unsigned int i, j;
|
||||
const char *zDir;
|
||||
int iLimit = 0;
|
||||
|
||||
/* It's odd to simulate an io-error here, but really this is just
|
||||
** using the io-error infrastructure to test that SQLite handles this
|
||||
@@ -5395,14 +5486,24 @@ static int unixGetTempname(int nBuf, char *zBuf){
|
||||
SimulateIOError( return SQLITE_IOERR );
|
||||
|
||||
zDir = unixTempFileDir();
|
||||
if( zDir==0 ) zDir = ".";
|
||||
|
||||
/* Check that the output buffer is large enough for the temporary file
|
||||
** name. If it is not, return SQLITE_ERROR.
|
||||
*/
|
||||
if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 18) >= (size_t)nBuf ){
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
do{
|
||||
u64 r;
|
||||
sqlite3_randomness(sizeof(r), &r);
|
||||
assert( nBuf>2 );
|
||||
zBuf[nBuf-2] = 0;
|
||||
sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c",
|
||||
zDir, r, 0);
|
||||
if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ) return SQLITE_ERROR;
|
||||
sqlite3_snprintf(nBuf-18, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
|
||||
j = (int)strlen(zBuf);
|
||||
sqlite3_randomness(15, &zBuf[j]);
|
||||
for(i=0; i<15; i++, j++){
|
||||
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
|
||||
}
|
||||
zBuf[j] = 0;
|
||||
zBuf[j+1] = 0;
|
||||
}while( osAccess(zBuf,0)==0 );
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -5524,19 +5625,16 @@ static int findCreateFileMode(
|
||||
** used by the test_multiplex.c module.
|
||||
*/
|
||||
nDb = sqlite3Strlen30(zPath) - 1;
|
||||
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( sqlite3Isalnum(zPath[nDb]) );
|
||||
#ifdef SQLITE_ENABLE_8_3_NAMES
|
||||
while( nDb>0 && sqlite3Isalnum(zPath[nDb]) ) nDb--;
|
||||
if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK;
|
||||
#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
|
||||
while( zPath[nDb]!='-' ){
|
||||
assert( nDb>0 );
|
||||
assert( zPath[nDb]!='\n' );
|
||||
nDb--;
|
||||
}
|
||||
#endif
|
||||
memcpy(zDb, zPath, nDb);
|
||||
zDb[nDb] = '\0';
|
||||
|
||||
@@ -5677,7 +5775,7 @@ static int unixOpen(
|
||||
}else if( !zName ){
|
||||
/* If zName is NULL, the upper layer is requesting a temp file. */
|
||||
assert(isDelete && !syncDir);
|
||||
rc = unixGetTempname(pVfs->mxPathname, zTmpname);
|
||||
rc = unixGetTempname(MAX_PATHNAME+2, zTmpname);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
@@ -5710,8 +5808,7 @@ static int unixOpen(
|
||||
}
|
||||
fd = robust_open(zName, openFlags, openMode);
|
||||
OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags));
|
||||
assert( !isExclusive || (openFlags & O_CREAT)!=0 );
|
||||
if( fd<0 && errno!=EISDIR && isReadWrite ){
|
||||
if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
|
||||
/* Failed to open the file for read/write access. Try read-only. */
|
||||
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
|
||||
openFlags &= ~(O_RDWR|O_CREAT);
|
||||
@@ -5730,7 +5827,7 @@ static int unixOpen(
|
||||
** the same as the original database.
|
||||
*/
|
||||
if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
|
||||
robustFchown(fd, uid, gid);
|
||||
osFchown(fd, uid, gid);
|
||||
}
|
||||
}
|
||||
assert( fd>=0 );
|
||||
@@ -5867,8 +5964,7 @@ static int unixDelete(
|
||||
rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
|
||||
}
|
||||
robust_close(0, fd, __LINE__);
|
||||
}else{
|
||||
assert( rc==SQLITE_CANTOPEN );
|
||||
}else if( rc==SQLITE_CANTOPEN ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
}
|
||||
@@ -5892,19 +5988,29 @@ static int unixAccess(
|
||||
int flags, /* What do we want to learn about the zPath file? */
|
||||
int *pResOut /* Write result boolean here */
|
||||
){
|
||||
int amode = 0;
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
SimulateIOError( return SQLITE_IOERR_ACCESS; );
|
||||
assert( pResOut!=0 );
|
||||
switch( flags ){
|
||||
case SQLITE_ACCESS_EXISTS:
|
||||
amode = F_OK;
|
||||
break;
|
||||
case SQLITE_ACCESS_READWRITE:
|
||||
amode = W_OK|R_OK;
|
||||
break;
|
||||
case SQLITE_ACCESS_READ:
|
||||
amode = R_OK;
|
||||
break;
|
||||
|
||||
/* The spec says there are three possible values for flags. But only
|
||||
** two of them are actually used */
|
||||
assert( flags==SQLITE_ACCESS_EXISTS || flags==SQLITE_ACCESS_READWRITE );
|
||||
|
||||
if( flags==SQLITE_ACCESS_EXISTS ){
|
||||
default:
|
||||
assert(!"Invalid flags argument");
|
||||
}
|
||||
*pResOut = (osAccess(zPath, amode)==0);
|
||||
if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
|
||||
struct stat buf;
|
||||
*pResOut = (0==osStat(zPath, &buf) && buf.st_size>0);
|
||||
}else{
|
||||
*pResOut = osAccess(zPath, W_OK|R_OK)==0;
|
||||
if( 0==osStat(zPath, &buf) && buf.st_size==0 ){
|
||||
*pResOut = 0;
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -5947,7 +6053,8 @@ static int unixFullPathname(
|
||||
if( errno!=EINVAL && errno!=ENOENT ){
|
||||
return unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zPath);
|
||||
}
|
||||
sqlite3_snprintf(nOut, zOut, "%s", zPath);
|
||||
zOut[nOut-1] = '\0';
|
||||
sqlite3_snprintf(nOut-1, zOut, "%s", zPath);
|
||||
nByte = sqlite3Strlen30(zOut);
|
||||
}else{
|
||||
zOut[nByte] = '\0';
|
||||
@@ -5969,9 +6076,7 @@ static int unixFullPathname(
|
||||
** truncated to make it fit. This is Ok, as SQLite refuses to open any
|
||||
** file for which this function returns a full path larger than (nOut-8)
|
||||
** bytes in size. */
|
||||
testcase( nByte==nOut-5 );
|
||||
testcase( nByte==nOut-4 );
|
||||
if( zOut[0]!='/' && nByte<nOut-4 ){
|
||||
if( zOut[0]!='/' ){
|
||||
int nCwd;
|
||||
int nRem = nOut-nByte-1;
|
||||
memmove(&zOut[nRem], zOut, nByte+1);
|
||||
@@ -6154,8 +6259,11 @@ static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
|
||||
*piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000;
|
||||
#else
|
||||
struct timeval sNow;
|
||||
(void)gettimeofday(&sNow, 0); /* Cannot fail given valid arguments */
|
||||
*piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
|
||||
if( gettimeofday(&sNow, 0)==0 ){
|
||||
*piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
|
||||
}else{
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
@@ -6167,7 +6275,6 @@ static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if 0 /* Not used */
|
||||
/*
|
||||
** Find the current time (in Universal Coordinated Time). Write the
|
||||
** current time and date as a Julian Day number into *prNow and
|
||||
@@ -6181,11 +6288,7 @@ static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
|
||||
*prNow = i/86400000.0;
|
||||
return rc;
|
||||
}
|
||||
#else
|
||||
# define unixCurrentTime 0
|
||||
#endif
|
||||
|
||||
#if 0 /* Not used */
|
||||
/*
|
||||
** We added the xGetLastError() method with the intention of providing
|
||||
** better low-level error messages when operating-system problems come up
|
||||
@@ -6199,9 +6302,6 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
|
||||
UNUSED_PARAMETER(NotUsed3);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
# define unixGetLastError 0
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
@@ -7340,7 +7440,7 @@ static int proxyUnlock(sqlite3_file *id, int eFileLock) {
|
||||
** Close a file that uses proxy locks.
|
||||
*/
|
||||
static int proxyClose(sqlite3_file *id) {
|
||||
if( ALWAYS(id) ){
|
||||
if( id ){
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
|
||||
unixFile *lockProxy = pCtx->lockProxy;
|
||||
@@ -7484,7 +7584,7 @@ int sqlite3_os_init(void){
|
||||
|
||||
/* Double-check that the aSyscall[] array has been constructed
|
||||
** correctly. See ticket [bb3a86e890c8e96ab] */
|
||||
assert( ArraySize(aSyscall)==27 );
|
||||
assert( ArraySize(aSyscall)==26 );
|
||||
|
||||
/* Register all VFSes defined in the aVfs[] array */
|
||||
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
|
||||
|
||||
+1
-29
@@ -6679,7 +6679,7 @@ const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){
|
||||
/*
|
||||
** Return the VFS structure for the pager.
|
||||
*/
|
||||
sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){
|
||||
const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){
|
||||
return pPager->pVfs;
|
||||
}
|
||||
|
||||
@@ -7301,34 +7301,6 @@ 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
|
||||
|
||||
+1
-5
@@ -168,10 +168,6 @@ 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
|
||||
@@ -186,7 +182,7 @@ u32 sqlite3PagerDataVersion(Pager*);
|
||||
#endif
|
||||
int sqlite3PagerMemUsed(Pager*);
|
||||
const char *sqlite3PagerFilename(Pager*, int);
|
||||
sqlite3_vfs *sqlite3PagerVfs(Pager*);
|
||||
const sqlite3_vfs *sqlite3PagerVfs(Pager*);
|
||||
sqlite3_file *sqlite3PagerFile(Pager*);
|
||||
const char *sqlite3PagerJournalname(Pager*);
|
||||
int sqlite3PagerNosync(Pager*);
|
||||
|
||||
+2
-2
@@ -65,7 +65,7 @@
|
||||
** that is allocated when the page cache is created. The size of the local
|
||||
** bulk allocation can be adjusted using
|
||||
**
|
||||
** sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, N).
|
||||
** sqlite3_config(SQLITE_CONFIG_PAGECACHE, 0, 0, N).
|
||||
**
|
||||
** If N is positive, then N pages worth of memory are allocated using a single
|
||||
** sqlite3Malloc() call and that memory is used for the first N pages allocated.
|
||||
@@ -350,7 +350,7 @@ static void *pcache1Alloc(int nByte){
|
||||
static void pcache1Free(void *p){
|
||||
int nFreed = 0;
|
||||
if( p==0 ) return;
|
||||
if( SQLITE_WITHIN(p, pcache1.pStart, pcache1.pEnd) ){
|
||||
if( p>=pcache1.pStart && p<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) && !defined(SQLITE_OMIT_PARSER_TRACE)
|
||||
#if defined(SQLITE_DEBUG)
|
||||
{ /* zName: */ "parser_trace",
|
||||
/* ePragTyp: */ PragTyp_PARSER_TRACE,
|
||||
/* ePragFlag: */ 0,
|
||||
|
||||
+4
-27
@@ -270,12 +270,6 @@ void sqlite3VXPrintf(
|
||||
testcase( wx>0x7fffffff );
|
||||
width = wx & 0x7fffffff;
|
||||
}
|
||||
assert( width>=0 );
|
||||
#ifdef SQLITE_PRINTF_PRECISION_LIMIT
|
||||
if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
|
||||
width = SQLITE_PRINTF_PRECISION_LIMIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the precision */
|
||||
if( c=='.' ){
|
||||
@@ -302,14 +296,6 @@ void sqlite3VXPrintf(
|
||||
}else{
|
||||
precision = -1;
|
||||
}
|
||||
assert( precision>=(-1) );
|
||||
#ifdef SQLITE_PRINTF_PRECISION_LIMIT
|
||||
if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){
|
||||
precision = SQLITE_PRINTF_PRECISION_LIMIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Get the conversion type modifier */
|
||||
if( c=='l' ){
|
||||
flag_long = 1;
|
||||
@@ -766,9 +752,8 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
setStrAccumError(p, STRACCUM_TOOBIG);
|
||||
return N;
|
||||
}else{
|
||||
char *zOld = p->bMalloced ? p->zText : 0;
|
||||
char *zOld = (p->zText==p->zBase ? 0 : p->zText);
|
||||
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,
|
||||
@@ -789,10 +774,9 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
}
|
||||
if( zNew ){
|
||||
assert( p->zText!=0 || p->nChar==0 );
|
||||
if( !p->bMalloced && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
|
||||
if( zOld==0 && 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);
|
||||
@@ -810,7 +794,6 @@ 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;
|
||||
}
|
||||
|
||||
@@ -828,7 +811,6 @@ 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) );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -864,13 +846,11 @@ 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->bMalloced==0 ){
|
||||
if( p->mxAlloc>0 && p->zText==p->zBase ){
|
||||
p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
|
||||
if( p->zText ){
|
||||
memcpy(p->zText, p->zBase, p->nChar+1);
|
||||
p->bMalloced = 1;
|
||||
}else{
|
||||
setStrAccumError(p, STRACCUM_NOMEM);
|
||||
}
|
||||
@@ -883,10 +863,8 @@ char *sqlite3StrAccumFinish(StrAccum *p){
|
||||
** Reset an StrAccum string. Reclaim all malloced memory.
|
||||
*/
|
||||
void sqlite3StrAccumReset(StrAccum *p){
|
||||
assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) );
|
||||
if( p->bMalloced ){
|
||||
if( p->zText!=p->zBase ){
|
||||
sqlite3DbFree(p->db, p->zText);
|
||||
p->bMalloced = 0;
|
||||
}
|
||||
p->zText = 0;
|
||||
}
|
||||
@@ -912,7 +890,6 @@ void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){
|
||||
p->nAlloc = n;
|
||||
p->mxAlloc = mx;
|
||||
p->accError = 0;
|
||||
p->bMalloced = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+2
-1
@@ -328,6 +328,7 @@ 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 ){
|
||||
@@ -362,7 +363,7 @@ static int lookupName(
|
||||
&& VisibleRowid(pMatch->pTab)
|
||||
){
|
||||
cnt = 1;
|
||||
pExpr->iColumn = -1;
|
||||
pExpr->iColumn = -1; /* IMP: R-44911-55124 */
|
||||
pExpr->affinity = SQLITE_AFF_INTEGER;
|
||||
}
|
||||
|
||||
|
||||
+6
-11
@@ -1340,8 +1340,7 @@ static const char *columnTypeImpl(
|
||||
char const *zOrigCol = 0;
|
||||
#endif
|
||||
|
||||
assert( pExpr!=0 );
|
||||
assert( pNC->pSrcList!=0 );
|
||||
if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
|
||||
switch( pExpr->op ){
|
||||
case TK_AGG_COLUMN:
|
||||
case TK_COLUMN: {
|
||||
@@ -1529,9 +1528,7 @@ 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;
|
||||
@@ -1543,7 +1540,7 @@ static void generateColumnNames(
|
||||
if( pEList->a[i].zName ){
|
||||
char *zName = pEList->a[i].zName;
|
||||
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
|
||||
}else if( p->op==TK_COLUMN || p->op==TK_AGG_COLUMN ){
|
||||
}else if( (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) && pTabList ){
|
||||
Table *pTab;
|
||||
char *zCol;
|
||||
int iCol = p->iColumn;
|
||||
@@ -1616,7 +1613,6 @@ int sqlite3ColumnsFromExprList(
|
||||
nCol = 0;
|
||||
aCol = 0;
|
||||
}
|
||||
assert( nCol==(i16)nCol );
|
||||
*pnCol = nCol;
|
||||
*paCol = aCol;
|
||||
|
||||
@@ -2372,7 +2368,7 @@ static int multiSelect(
|
||||
if( dest.eDest==SRT_Output ){
|
||||
Select *pFirst = p;
|
||||
while( pFirst->pPrior ) pFirst = pFirst->pPrior;
|
||||
generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList);
|
||||
generateColumnNames(pParse, 0, pFirst->pEList);
|
||||
}
|
||||
iBreak = sqlite3VdbeMakeLabel(v);
|
||||
iCont = sqlite3VdbeMakeLabel(v);
|
||||
@@ -2447,7 +2443,7 @@ static int multiSelect(
|
||||
if( dest.eDest==SRT_Output ){
|
||||
Select *pFirst = p;
|
||||
while( pFirst->pPrior ) pFirst = pFirst->pPrior;
|
||||
generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList);
|
||||
generateColumnNames(pParse, 0, pFirst->pEList);
|
||||
}
|
||||
iBreak = sqlite3VdbeMakeLabel(v);
|
||||
iCont = sqlite3VdbeMakeLabel(v);
|
||||
@@ -3062,7 +3058,7 @@ static int multiSelectOrderBy(
|
||||
if( pDest->eDest==SRT_Output ){
|
||||
Select *pFirst = pPrior;
|
||||
while( pFirst->pPrior ) pFirst = pFirst->pPrior;
|
||||
generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList);
|
||||
generateColumnNames(pParse, 0, pFirst->pEList);
|
||||
}
|
||||
|
||||
/* Reassembly the compound query so that it will be freed correctly
|
||||
@@ -4459,7 +4455,6 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
#if SQLITE_MAX_COLUMN
|
||||
if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
|
||||
sqlite3ErrorMsg(pParse, "too many columns in result set");
|
||||
return WRC_Abort;
|
||||
}
|
||||
#endif
|
||||
return WRC_Continue;
|
||||
|
||||
+59
-143
@@ -329,13 +329,6 @@ static int bail_on_error = 0;
|
||||
*/
|
||||
static int stdin_is_interactive = 1;
|
||||
|
||||
/*
|
||||
** On Windows systems we have to know if standard output is a console
|
||||
** in order to translate UTF-8 into MBCS. The following variable is
|
||||
** true if translation is required.
|
||||
*/
|
||||
static int stdout_is_console = 1;
|
||||
|
||||
/*
|
||||
** The following is the open SQLite database. We make a pointer
|
||||
** to this database a static variable so that it can be accessed
|
||||
@@ -437,16 +430,6 @@ static void shellstaticFunc(
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Compute a string length that is limited to what can be stored in
|
||||
** lower 30 bits of a 32-bit signed integer.
|
||||
*/
|
||||
static int strlen30(const char *z){
|
||||
const char *z2 = z;
|
||||
while( *z2 ){ z2++; }
|
||||
return 0x3fffffff & (int)(z2 - z);
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine reads a line of text from FILE in, stores
|
||||
** the text in memory obtained from malloc() and returns a pointer
|
||||
@@ -482,26 +465,6 @@ static char *local_getline(char *zLine, FILE *in){
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
/* For interactive input on Windows systems, translate the
|
||||
** multi-byte characterset characters into UTF-8. */
|
||||
if( stdin_is_interactive ){
|
||||
extern char *sqlite3_win32_mbcs_to_utf8(const char*);
|
||||
char *zTrans = sqlite3_win32_mbcs_to_utf8(zLine);
|
||||
if( zTrans ){
|
||||
int nTrans = strlen30(zTrans)+1;
|
||||
if( nTrans>nLine ){
|
||||
zLine = realloc(zLine, nTrans);
|
||||
if( zLine==0 ){
|
||||
sqlite3_free(zTrans);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
memcpy(zLine, zTrans, nTrans);
|
||||
sqlite3_free(zTrans);
|
||||
}
|
||||
}
|
||||
#endif /* defined(_WIN32) || defined(WIN32) */
|
||||
return zLine;
|
||||
}
|
||||
|
||||
@@ -539,31 +502,6 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
|
||||
return zResult;
|
||||
}
|
||||
|
||||
/*
|
||||
** Render output like fprintf(). Except, if the output is going to the
|
||||
** console and if this is running on a Windows machine, translate the
|
||||
** output from UTF-8 into MBCS.
|
||||
*/
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
void utf8_printf(FILE *out, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
va_start(ap, zFormat);
|
||||
if( stdout_is_console && out==stdout ){
|
||||
extern char *sqlite3_win32_utf8_to_mbcs(const char*);
|
||||
char *z1 = sqlite3_vmprintf(zFormat, ap);
|
||||
char *z2 = sqlite3_win32_utf8_to_mbcs(z1);
|
||||
sqlite3_free(z1);
|
||||
fputs(z2, out);
|
||||
sqlite3_free(z2);
|
||||
}else{
|
||||
vfprintf(out, zFormat, ap);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
#else
|
||||
# define utf8_printf fprintf
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Shell output mode information from before ".explain on",
|
||||
** saved so that it can be restored by ".explain off"
|
||||
@@ -587,7 +525,6 @@ 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 */
|
||||
@@ -669,6 +606,16 @@ static const char *modeDescr[] = {
|
||||
*/
|
||||
#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
|
||||
|
||||
/*
|
||||
** Compute a string length that is limited to what can be stored in
|
||||
** lower 30 bits of a 32-bit signed integer.
|
||||
*/
|
||||
static int strlen30(const char *z){
|
||||
const char *z2 = z;
|
||||
while( *z2 ){ z2++; }
|
||||
return 0x3fffffff & (int)(z2 - z);
|
||||
}
|
||||
|
||||
/*
|
||||
** A callback for the sqlite3_log() interface.
|
||||
*/
|
||||
@@ -701,7 +648,7 @@ static void output_quoted_string(FILE *out, const char *z){
|
||||
if( z[i]=='\'' ) nSingle++;
|
||||
}
|
||||
if( nSingle==0 ){
|
||||
utf8_printf(out,"'%s'",z);
|
||||
fprintf(out,"'%s'",z);
|
||||
}else{
|
||||
fprintf(out,"'");
|
||||
while( *z ){
|
||||
@@ -710,10 +657,10 @@ static void output_quoted_string(FILE *out, const char *z){
|
||||
fprintf(out,"''");
|
||||
z++;
|
||||
}else if( z[i]=='\'' ){
|
||||
utf8_printf(out,"%.*s''",i,z);
|
||||
fprintf(out,"%.*s''",i,z);
|
||||
z += i+1;
|
||||
}else{
|
||||
utf8_printf(out,"%s",z);
|
||||
fprintf(out,"%s",z);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -769,7 +716,7 @@ static void output_html_string(FILE *out, const char *z){
|
||||
&& z[i]!='\'';
|
||||
i++){}
|
||||
if( i>0 ){
|
||||
utf8_printf(out,"%.*s",i,z);
|
||||
fprintf(out,"%.*s",i,z);
|
||||
}
|
||||
if( z[i]=='<' ){
|
||||
fprintf(out,"<");
|
||||
@@ -820,7 +767,7 @@ static const char needCsvQuote[] = {
|
||||
static void output_csv(ShellState *p, const char *z, int bSep){
|
||||
FILE *out = p->out;
|
||||
if( z==0 ){
|
||||
utf8_printf(out,"%s",p->nullValue);
|
||||
fprintf(out,"%s",p->nullValue);
|
||||
}else{
|
||||
int i;
|
||||
int nSep = strlen30(p->colSeparator);
|
||||
@@ -840,11 +787,11 @@ static void output_csv(ShellState *p, const char *z, int bSep){
|
||||
}
|
||||
putc('"', out);
|
||||
}else{
|
||||
utf8_printf(out, "%s", z);
|
||||
fprintf(out, "%s", z);
|
||||
}
|
||||
}
|
||||
if( bSep ){
|
||||
utf8_printf(p->out, "%s", p->colSeparator);
|
||||
fprintf(p->out, "%s", p->colSeparator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -882,9 +829,9 @@ static int shell_callback(
|
||||
int len = strlen30(azCol[i] ? azCol[i] : "");
|
||||
if( len>w ) w = len;
|
||||
}
|
||||
if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
|
||||
if( p->cnt++>0 ) fprintf(p->out, "%s", p->rowSeparator);
|
||||
for(i=0; i<nArg; i++){
|
||||
utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
|
||||
fprintf(p->out,"%*s = %s%s", w, azCol[i],
|
||||
azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
|
||||
}
|
||||
break;
|
||||
@@ -910,10 +857,10 @@ static int shell_callback(
|
||||
}
|
||||
if( p->showHeader ){
|
||||
if( w<0 ){
|
||||
utf8_printf(p->out,"%*.*s%s",-w,-w,azCol[i],
|
||||
fprintf(p->out,"%*.*s%s",-w,-w,azCol[i],
|
||||
i==nArg-1 ? p->rowSeparator : " ");
|
||||
}else{
|
||||
utf8_printf(p->out,"%-*.*s%s",w,w,azCol[i],
|
||||
fprintf(p->out,"%-*.*s%s",w,w,azCol[i],
|
||||
i==nArg-1 ? p->rowSeparator : " ");
|
||||
}
|
||||
}
|
||||
@@ -927,8 +874,7 @@ static int shell_callback(
|
||||
}else{
|
||||
w = 10;
|
||||
}
|
||||
fprintf(p->out,"%-*.*s%s",w,w,
|
||||
"----------------------------------------------------------"
|
||||
fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------"
|
||||
"----------------------------------------------------------",
|
||||
i==nArg-1 ? p->rowSeparator : " ");
|
||||
}
|
||||
@@ -952,11 +898,11 @@ static int shell_callback(
|
||||
p->iIndent++;
|
||||
}
|
||||
if( w<0 ){
|
||||
utf8_printf(p->out,"%*.*s%s",-w,-w,
|
||||
fprintf(p->out,"%*.*s%s",-w,-w,
|
||||
azArg[i] ? azArg[i] : p->nullValue,
|
||||
i==nArg-1 ? p->rowSeparator : " ");
|
||||
}else{
|
||||
utf8_printf(p->out,"%-*.*s%s",w,w,
|
||||
fprintf(p->out,"%-*.*s%s",w,w,
|
||||
azArg[i] ? azArg[i] : p->nullValue,
|
||||
i==nArg-1 ? p->rowSeparator : " ");
|
||||
}
|
||||
@@ -967,7 +913,7 @@ static int shell_callback(
|
||||
case MODE_List: {
|
||||
if( p->cnt++==0 && p->showHeader ){
|
||||
for(i=0; i<nArg; i++){
|
||||
utf8_printf(p->out,"%s%s",azCol[i],
|
||||
fprintf(p->out,"%s%s",azCol[i],
|
||||
i==nArg-1 ? p->rowSeparator : p->colSeparator);
|
||||
}
|
||||
}
|
||||
@@ -975,13 +921,13 @@ static int shell_callback(
|
||||
for(i=0; i<nArg; i++){
|
||||
char *z = azArg[i];
|
||||
if( z==0 ) z = p->nullValue;
|
||||
utf8_printf(p->out, "%s", z);
|
||||
fprintf(p->out, "%s", z);
|
||||
if( i<nArg-1 ){
|
||||
utf8_printf(p->out, "%s", p->colSeparator);
|
||||
fprintf(p->out, "%s", p->colSeparator);
|
||||
}else if( p->mode==MODE_Semi ){
|
||||
utf8_printf(p->out, ";%s", p->rowSeparator);
|
||||
fprintf(p->out, ";%s", p->rowSeparator);
|
||||
}else{
|
||||
utf8_printf(p->out, "%s", p->rowSeparator);
|
||||
fprintf(p->out, "%s", p->rowSeparator);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1010,16 +956,16 @@ static int shell_callback(
|
||||
if( p->cnt++==0 && p->showHeader ){
|
||||
for(i=0; i<nArg; i++){
|
||||
output_c_string(p->out,azCol[i] ? azCol[i] : "");
|
||||
if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
|
||||
if(i<nArg-1) fprintf(p->out, "%s", p->colSeparator);
|
||||
}
|
||||
utf8_printf(p->out, "%s", p->rowSeparator);
|
||||
fprintf(p->out, "%s", p->rowSeparator);
|
||||
}
|
||||
if( azArg==0 ) break;
|
||||
for(i=0; i<nArg; i++){
|
||||
output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
|
||||
if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
|
||||
if(i<nArg-1) fprintf(p->out, "%s", p->colSeparator);
|
||||
}
|
||||
utf8_printf(p->out, "%s", p->rowSeparator);
|
||||
fprintf(p->out, "%s", p->rowSeparator);
|
||||
break;
|
||||
}
|
||||
case MODE_Csv: {
|
||||
@@ -1028,13 +974,13 @@ static int shell_callback(
|
||||
for(i=0; i<nArg; i++){
|
||||
output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
|
||||
}
|
||||
utf8_printf(p->out, "%s", p->rowSeparator);
|
||||
fprintf(p->out, "%s", p->rowSeparator);
|
||||
}
|
||||
if( nArg>0 ){
|
||||
for(i=0; i<nArg; i++){
|
||||
output_csv(p, azArg[i], i<nArg-1);
|
||||
}
|
||||
utf8_printf(p->out, "%s", p->rowSeparator);
|
||||
fprintf(p->out, "%s", p->rowSeparator);
|
||||
}
|
||||
setTextMode(p->out);
|
||||
break;
|
||||
@@ -1042,12 +988,12 @@ static int shell_callback(
|
||||
case MODE_Insert: {
|
||||
p->cnt++;
|
||||
if( azArg==0 ) break;
|
||||
utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
|
||||
fprintf(p->out,"INSERT INTO %s",p->zDestTable);
|
||||
if( p->showHeader ){
|
||||
fprintf(p->out,"(");
|
||||
for(i=0; i<nArg; i++){
|
||||
char *zSep = i>0 ? ",": "";
|
||||
utf8_printf(p->out, "%s%s", zSep, azCol[i]);
|
||||
fprintf(p->out, "%s%s", zSep, azCol[i]);
|
||||
}
|
||||
fprintf(p->out,")");
|
||||
}
|
||||
@@ -1061,14 +1007,14 @@ static int shell_callback(
|
||||
output_quoted_string(p->out, azArg[i]);
|
||||
}else if( aiType && (aiType[i]==SQLITE_INTEGER
|
||||
|| aiType[i]==SQLITE_FLOAT) ){
|
||||
utf8_printf(p->out,"%s%s",zSep, azArg[i]);
|
||||
fprintf(p->out,"%s%s",zSep, azArg[i]);
|
||||
}else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
|
||||
const void *pBlob = sqlite3_column_blob(p->pStmt, i);
|
||||
int nBlob = sqlite3_column_bytes(p->pStmt, i);
|
||||
if( zSep[0] ) fprintf(p->out,"%s",zSep);
|
||||
output_hex_blob(p->out, pBlob, nBlob);
|
||||
}else if( isNumber(azArg[i], 0) ){
|
||||
utf8_printf(p->out,"%s%s",zSep, azArg[i]);
|
||||
fprintf(p->out,"%s%s",zSep, azArg[i]);
|
||||
}else{
|
||||
if( zSep[0] ) fprintf(p->out,"%s",zSep);
|
||||
output_quoted_string(p->out, azArg[i]);
|
||||
@@ -1080,17 +1026,17 @@ static int shell_callback(
|
||||
case MODE_Ascii: {
|
||||
if( p->cnt++==0 && p->showHeader ){
|
||||
for(i=0; i<nArg; i++){
|
||||
if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
|
||||
utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
|
||||
if( i>0 ) fprintf(p->out, "%s", p->colSeparator);
|
||||
fprintf(p->out,"%s",azCol[i] ? azCol[i] : "");
|
||||
}
|
||||
utf8_printf(p->out, "%s", p->rowSeparator);
|
||||
fprintf(p->out, "%s", p->rowSeparator);
|
||||
}
|
||||
if( azArg==0 ) break;
|
||||
for(i=0; i<nArg; i++){
|
||||
if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
|
||||
utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
|
||||
if( i>0 ) fprintf(p->out, "%s", p->colSeparator);
|
||||
fprintf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
|
||||
}
|
||||
utf8_printf(p->out, "%s", p->rowSeparator);
|
||||
fprintf(p->out, "%s", p->rowSeparator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1220,13 +1166,13 @@ static int run_table_dump_query(
|
||||
nResult = sqlite3_column_count(pSelect);
|
||||
while( rc==SQLITE_ROW ){
|
||||
if( zFirstRow ){
|
||||
utf8_printf(p->out, "%s", zFirstRow);
|
||||
fprintf(p->out, "%s", zFirstRow);
|
||||
zFirstRow = 0;
|
||||
}
|
||||
z = (const char*)sqlite3_column_text(pSelect, 0);
|
||||
utf8_printf(p->out, "%s", z);
|
||||
fprintf(p->out, "%s", z);
|
||||
for(i=1; i<nResult; i++){
|
||||
utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
|
||||
fprintf(p->out, ",%s", sqlite3_column_text(pSelect, i));
|
||||
}
|
||||
if( z==0 ) z = "";
|
||||
while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
|
||||
@@ -1414,7 +1360,7 @@ static void display_scanstats(
|
||||
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
|
||||
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
|
||||
sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
|
||||
utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
|
||||
fprintf(pArg->out, "Loop %2d: %s\n", n, zExplain);
|
||||
rEstLoop *= rEst;
|
||||
fprintf(pArg->out,
|
||||
" nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
|
||||
@@ -1575,7 +1521,7 @@ static int shell_exec(
|
||||
/* echo the sql statement if echo on */
|
||||
if( pArg && pArg->echoOn ){
|
||||
const char *zStmtSql = sqlite3_sql(pStmt);
|
||||
utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
|
||||
fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
|
||||
}
|
||||
|
||||
/* Show the EXPLAIN QUERY PLAN if .eqp is on */
|
||||
@@ -1589,7 +1535,7 @@ static int shell_exec(
|
||||
fprintf(pArg->out,"--EQP-- %d,", sqlite3_column_int(pExplain, 0));
|
||||
fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1));
|
||||
fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2));
|
||||
utf8_printf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
|
||||
fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pExplain);
|
||||
@@ -1730,11 +1676,11 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
|
||||
"INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
|
||||
"VALUES('table','%q','%q',0,'%q');",
|
||||
zTable, zTable, zSql);
|
||||
utf8_printf(p->out, "%s\n", zIns);
|
||||
fprintf(p->out, "%s\n", zIns);
|
||||
sqlite3_free(zIns);
|
||||
return 0;
|
||||
}else{
|
||||
utf8_printf(p->out, "%s;\n", zSql);
|
||||
fprintf(p->out, "%s;\n", zSql);
|
||||
}
|
||||
|
||||
if( strcmp(zType, "table")==0 ){
|
||||
@@ -1839,7 +1785,6 @@ 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"
|
||||
@@ -1902,7 +1847,6 @@ static char zHelp[] =
|
||||
".timeout MS Try opening locked tables for MS milliseconds\n"
|
||||
".timer on|off Turn SQL timer on or off\n"
|
||||
".trace FILE|off Output each SQL statement as it is run\n"
|
||||
".vfsinfo ?AUX? Information about the top-level VFS\n"
|
||||
".vfsname ?AUX? Print the name of the VFS stack\n"
|
||||
".width NUM1 NUM2 ... Set column widths for \"column\" mode\n"
|
||||
" Negative values right-justify\n"
|
||||
@@ -2179,7 +2123,7 @@ static void sql_trace_callback(void *pArg, const char *z){
|
||||
if( f ){
|
||||
int i = (int)strlen(z);
|
||||
while( i>0 && z[i-1]==';' ){ i--; }
|
||||
utf8_printf(f, "%.*s;\n", i, z);
|
||||
fprintf(f, "%.*s;\n", i, z);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2662,7 +2606,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
|
||||
char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
|
||||
int val = db_int(p, zSql);
|
||||
sqlite3_free(zSql);
|
||||
utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
|
||||
fprintf(p->out, "%-20s %d\n", aQuery[i].zName, val);
|
||||
}
|
||||
sqlite3_free(zSchemaTab);
|
||||
return 0;
|
||||
@@ -2812,15 +2756,6 @@ 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]);
|
||||
@@ -3502,7 +3437,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
int i;
|
||||
for(i=1; i<nArg; i++){
|
||||
if( i>1 ) fprintf(p->out, " ");
|
||||
utf8_printf(p->out, "%s", azArg[i]);
|
||||
fprintf(p->out, "%s", azArg[i]);
|
||||
}
|
||||
fprintf(p->out, "\n");
|
||||
}else
|
||||
@@ -3696,7 +3631,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
int i, v;
|
||||
for(i=1; i<nArg; i++){
|
||||
v = booleanValue(azArg[i]);
|
||||
utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
|
||||
fprintf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
|
||||
}
|
||||
}
|
||||
if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
|
||||
@@ -3705,7 +3640,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
char zBuf[200];
|
||||
v = integerValue(azArg[i]);
|
||||
sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
|
||||
utf8_printf(p->out, "%s", zBuf);
|
||||
fprintf(p->out, "%s", zBuf);
|
||||
}
|
||||
}
|
||||
}else
|
||||
@@ -3879,8 +3814,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
for(i=0; i<nPrintRow; i++){
|
||||
for(j=i; j<nRow; j+=nPrintRow){
|
||||
char *zSp = j<nPrintRow ? "" : " ";
|
||||
utf8_printf(p->out, "%s%-*s", zSp, maxlen,
|
||||
azResult[j] ? azResult[j]:"");
|
||||
fprintf(p->out, "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:"");
|
||||
}
|
||||
fprintf(p->out, "\n");
|
||||
}
|
||||
@@ -4133,20 +4067,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3_libversion(), sqlite3_sourceid());
|
||||
}else
|
||||
|
||||
if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
|
||||
const char *zDbName = nArg==2 ? azArg[1] : "main";
|
||||
sqlite3_vfs *pVfs;
|
||||
if( p->db ){
|
||||
sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
|
||||
if( pVfs ){
|
||||
fprintf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
|
||||
fprintf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
|
||||
fprintf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
|
||||
fprintf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
|
||||
}
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
|
||||
const char *zDbName = nArg==2 ? azArg[1] : "main";
|
||||
char *zVfsName = 0;
|
||||
@@ -4351,9 +4271,6 @@ 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 ){
|
||||
@@ -4601,7 +4518,6 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
Argv0 = argv[0];
|
||||
main_init(&data);
|
||||
stdin_is_interactive = isatty(0);
|
||||
stdout_is_console = isatty(1);
|
||||
|
||||
/* Make sure we have a valid signal handler early, before anything
|
||||
** else is done.
|
||||
|
||||
+25
-170
@@ -882,15 +882,6 @@ struct sqlite3_io_methods {
|
||||
** pointer in case this file-control is not implemented. This file-control
|
||||
** is intended for diagnostic use only.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_VFS_POINTER]]
|
||||
** ^The [SQLITE_FCNTL_VFS_POINTER] opcode finds a pointer to the top-level
|
||||
** [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.)^
|
||||
** ^When there are multiple VFS shims in the stack, this opcode finds the
|
||||
** upper-most shim only.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_PRAGMA]]
|
||||
** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA]
|
||||
** file control is sent to the open [sqlite3_file] object corresponding
|
||||
@@ -1009,7 +1000,6 @@ struct sqlite3_io_methods {
|
||||
#define SQLITE_FCNTL_WAL_BLOCK 24
|
||||
#define SQLITE_FCNTL_ZIPVFS 25
|
||||
#define SQLITE_FCNTL_RBU 26
|
||||
#define SQLITE_FCNTL_VFS_POINTER 27
|
||||
|
||||
/* deprecated names */
|
||||
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
||||
@@ -4405,8 +4395,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.
|
||||
*/
|
||||
sqlite3_value *sqlite3_value_dup(const sqlite3_value*);
|
||||
void sqlite3_value_free(sqlite3_value*);
|
||||
SQLITE_EXPERIMENTAL sqlite3_value *sqlite3_value_dup(const sqlite3_value*);
|
||||
SQLITE_EXPERIMENTAL void sqlite3_value_free(sqlite3_value*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtain Aggregate Function Context
|
||||
@@ -5625,17 +5615,6 @@ struct sqlite3_module {
|
||||
** ^Information about the ORDER BY clause is stored in aOrderBy[].
|
||||
** ^Each term of aOrderBy records a column of the ORDER BY clause.
|
||||
**
|
||||
** The colUsed field indicates which columns of the virtual table may be
|
||||
** required by the current scan. Virtual table columns are numbered from
|
||||
** zero in the order in which they appear within the CREATE TABLE statement
|
||||
** passed to sqlite3_declare_vtab(). For the first 63 columns (columns 0-62),
|
||||
** the corresponding bit is set within the colUsed mask if the column may be
|
||||
** required by SQLite. If the table has at least 64 columns and any column
|
||||
** to the right of the first 63 is required, then bit 63 of colUsed is also
|
||||
** set. In other words, column iCol may be required if the expression
|
||||
** (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) evaluates to
|
||||
** non-zero.
|
||||
**
|
||||
** The [xBestIndex] method must fill aConstraintUsage[] with information
|
||||
** about what parameters to pass to xFilter. ^If argvIndex>0 then
|
||||
** the right-hand side of the corresponding aConstraint[] is evaluated
|
||||
@@ -5715,8 +5694,6 @@ struct sqlite3_index_info {
|
||||
sqlite3_int64 estimatedRows; /* Estimated number of rows returned */
|
||||
/* Fields below are only available in SQLite 3.9.0 and later */
|
||||
int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */
|
||||
/* Fields below are only available in SQLite 3.10.0 and later */
|
||||
sqlite3_uint64 colUsed; /* Input: Mask of columns used by statement */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -5732,15 +5709,12 @@ struct sqlite3_index_info {
|
||||
** an operator that is part of a constraint term in the wHERE clause of
|
||||
** a query that uses a [virtual table].
|
||||
*/
|
||||
#define SQLITE_INDEX_CONSTRAINT_EQ 2
|
||||
#define SQLITE_INDEX_CONSTRAINT_GT 4
|
||||
#define SQLITE_INDEX_CONSTRAINT_LE 8
|
||||
#define SQLITE_INDEX_CONSTRAINT_LT 16
|
||||
#define SQLITE_INDEX_CONSTRAINT_GE 32
|
||||
#define SQLITE_INDEX_CONSTRAINT_MATCH 64
|
||||
#define SQLITE_INDEX_CONSTRAINT_LIKE 65
|
||||
#define SQLITE_INDEX_CONSTRAINT_GLOB 66
|
||||
#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
|
||||
#define SQLITE_INDEX_CONSTRAINT_EQ 2
|
||||
#define SQLITE_INDEX_CONSTRAINT_GT 4
|
||||
#define SQLITE_INDEX_CONSTRAINT_LE 8
|
||||
#define SQLITE_INDEX_CONSTRAINT_LT 16
|
||||
#define SQLITE_INDEX_CONSTRAINT_GE 32
|
||||
#define SQLITE_INDEX_CONSTRAINT_MATCH 64
|
||||
|
||||
/*
|
||||
** CAPI3REF: Register A Virtual Table Implementation
|
||||
@@ -7391,43 +7365,18 @@ int sqlite3_strnicmp(const char *, const char *, int);
|
||||
/*
|
||||
** CAPI3REF: String Globbing
|
||||
*
|
||||
** ^The [sqlite3_strglob(P,X)] interface returns zero if and only if
|
||||
** string X matches the [GLOB] pattern P.
|
||||
** ^The definition of [GLOB] pattern matching used in
|
||||
** ^The [sqlite3_strglob(P,X)] interface returns zero if string X matches
|
||||
** the glob pattern P, and it returns non-zero if string X does not match
|
||||
** the glob pattern P. ^The definition of glob pattern matching used in
|
||||
** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the
|
||||
** SQL dialect understood by SQLite. ^The [sqlite3_strglob(P,X)] function
|
||||
** is case sensitive.
|
||||
** SQL dialect used by SQLite. ^The sqlite3_strglob(P,X) function is case
|
||||
** sensitive.
|
||||
**
|
||||
** Note that this routine returns zero on a match and non-zero if the strings
|
||||
** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()].
|
||||
**
|
||||
** See also: [sqlite3_strlike()].
|
||||
*/
|
||||
int sqlite3_strglob(const char *zGlob, const char *zStr);
|
||||
|
||||
/*
|
||||
** CAPI3REF: String LIKE Matching
|
||||
*
|
||||
** ^The [sqlite3_strlike(P,X,E)] interface returns zero if and only if
|
||||
** string X matches the [LIKE] pattern P with escape character E.
|
||||
** ^The definition of [LIKE] pattern matching used in
|
||||
** [sqlite3_strlike(P,X,E)] is the same as for the "X LIKE P ESCAPE E"
|
||||
** operator in the SQL dialect understood by SQLite. ^For "X LIKE P" without
|
||||
** the ESCAPE clause, set the E parameter of [sqlite3_strlike(P,X,E)] to 0.
|
||||
** ^As with the LIKE operator, the [sqlite3_strlike(P,X,E)] function is case
|
||||
** insensitive - equivalent upper and lower case ASCII characters match
|
||||
** one another.
|
||||
**
|
||||
** ^The [sqlite3_strlike(P,X,E)] function matches Unicode characters, though
|
||||
** only ASCII characters are case folded.
|
||||
**
|
||||
** Note that this routine returns zero on a match and non-zero if the strings
|
||||
** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()].
|
||||
**
|
||||
** See also: [sqlite3_strglob()].
|
||||
*/
|
||||
int sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Error Logging Interface
|
||||
**
|
||||
@@ -7851,127 +7800,33 @@ void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
|
||||
/*
|
||||
** CAPI3REF: Flush caches to disk mid-transaction
|
||||
**
|
||||
** ^If a write-transaction is open on [database connection] D when the
|
||||
** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
|
||||
** If a write-transaction is open when this function is called, any dirty
|
||||
** pages in the pager-cache that are not currently in use are written out
|
||||
** to disk. A dirty page may be in use if a database cursor created by an
|
||||
** active SQL statement is reading from it, or if it is page 1 of a database
|
||||
** file (page 1 is always "in use"). ^The [sqlite3_db_cacheflush(D)]
|
||||
** interface flushes caches for all schemas - "main", "temp", and
|
||||
** any [attached] databases.
|
||||
** file (page 1 is always "in use"). Dirty pages are flushed for all
|
||||
** databases - "main", "temp" and any attached databases.
|
||||
**
|
||||
** ^If this function needs to obtain extra database locks before dirty pages
|
||||
** can be flushed to disk, it does so. ^If those 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 said locks cannot be obtained
|
||||
** immediately and there is a busy-handler callback configured, it is invoked
|
||||
** in the usual manner. ^If the required lock still cannot be obtained, then
|
||||
** 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] is returned to the caller immediately.
|
||||
** abandoned and an SQLite error code returned to the caller immediately.
|
||||
**
|
||||
** ^Otherwise, if no error occurs, [sqlite3_db_cacheflush()] returns SQLITE_OK.
|
||||
** Otherwise, if no error occurs, SQLITE_OK is returned.
|
||||
**
|
||||
** ^This function does not set the database handle error code or message
|
||||
** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions.
|
||||
** 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*);
|
||||
|
||||
/*
|
||||
** 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.
|
||||
|
||||
@@ -275,10 +275,6 @@ struct sqlite3_api_routines {
|
||||
/* Version 3.9.0 and later */
|
||||
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*);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -518,10 +514,6 @@ struct sqlite3_api_routines {
|
||||
/* Version 3.9.0 and later */
|
||||
#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)
|
||||
|
||||
+6
-24
@@ -173,21 +173,6 @@
|
||||
# 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.
|
||||
@@ -692,6 +677,11 @@ typedef INT16_TYPE LogEst;
|
||||
** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
|
||||
** at run-time.
|
||||
*/
|
||||
#ifdef SQLITE_AMALGAMATION
|
||||
const int sqlite3one = 1;
|
||||
#else
|
||||
extern const int sqlite3one;
|
||||
#endif
|
||||
#if (defined(i386) || defined(__i386__) || defined(_M_IX86) || \
|
||||
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
|
||||
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
|
||||
@@ -709,11 +699,6 @@ typedef INT16_TYPE LogEst;
|
||||
# define SQLITE_UTF16NATIVE SQLITE_UTF16BE
|
||||
#endif
|
||||
#if !defined(SQLITE_BYTEORDER)
|
||||
# ifdef SQLITE_AMALGAMATION
|
||||
const int sqlite3one = 1;
|
||||
# else
|
||||
extern const int sqlite3one;
|
||||
# endif
|
||||
# define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */
|
||||
# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0)
|
||||
# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
|
||||
@@ -1932,7 +1917,7 @@ struct Index {
|
||||
Index *pNext; /* The next index associated with the same table */
|
||||
Schema *pSchema; /* Schema containing this index */
|
||||
u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
|
||||
const char **azColl; /* Array of collation sequence names for index */
|
||||
char **azColl; /* Array of collation sequence names for index */
|
||||
Expr *pPartIdxWhere; /* WHERE clause for partial indices */
|
||||
ExprList *aColExpr; /* Column expressions */
|
||||
int tnum; /* DB Page containing root of this index */
|
||||
@@ -2967,7 +2952,6 @@ 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
|
||||
@@ -3461,7 +3445,6 @@ void sqlite3ExprCacheRemove(Parse*, int, int);
|
||||
void sqlite3ExprCacheClear(Parse*);
|
||||
void sqlite3ExprCacheAffinityChange(Parse*, int, int);
|
||||
void sqlite3ExprCode(Parse*, Expr*, int);
|
||||
void sqlite3ExprCodeCopy(Parse*, Expr*, int);
|
||||
void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
|
||||
void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8);
|
||||
int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
|
||||
@@ -3699,7 +3682,6 @@ int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
|
||||
void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
extern const unsigned char sqlite3OpcodeProperty[];
|
||||
extern const char sqlite3StrBINARY[];
|
||||
extern const unsigned char sqlite3UpperToLower[];
|
||||
extern const unsigned char sqlite3CtypeMap[];
|
||||
extern const Token sqlite3IntTokens[];
|
||||
|
||||
+2
-95
@@ -2269,94 +2269,6 @@ 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
|
||||
**
|
||||
@@ -5994,13 +5906,13 @@ static int test_sqlite3_log(
|
||||
Tcl_DecrRefCount(logcallback.pObj);
|
||||
logcallback.pObj = 0;
|
||||
logcallback.pInterp = 0;
|
||||
sqlite3_config(SQLITE_CONFIG_LOG, (void*)0, (void*)0);
|
||||
sqlite3_config(SQLITE_CONFIG_LOG, 0, 0);
|
||||
}
|
||||
if( objc>1 ){
|
||||
logcallback.pObj = objv[1];
|
||||
Tcl_IncrRefCount(logcallback.pObj);
|
||||
logcallback.pInterp = interp;
|
||||
sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, (void*)0);
|
||||
sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, 0);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -7171,11 +7083,6 @@ 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);
|
||||
|
||||
+9
-52
@@ -745,34 +745,6 @@ static void string_concat(char **pzStr, char *zAppend, int doFree, int *pRc){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This function returns a pointer to an sqlite3_malloc()ed buffer
|
||||
** containing the select-list (the thing between keywords SELECT and FROM)
|
||||
** to query the underlying real table with for the scan described by
|
||||
** argument pIdxInfo.
|
||||
**
|
||||
** If the current SQLite version is earlier than 3.10.0, this is just "*"
|
||||
** (select all columns). Or, for version 3.10.0 and greater, the list of
|
||||
** columns identified by the pIdxInfo->colUsed mask.
|
||||
*/
|
||||
static char *echoSelectList(echo_vtab *pTab, sqlite3_index_info *pIdxInfo){
|
||||
char *zRet = 0;
|
||||
if( sqlite3_libversion_number()<3010000 ){
|
||||
zRet = sqlite3_mprintf(", *");
|
||||
}else{
|
||||
int i;
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( pIdxInfo->colUsed & ((sqlite3_uint64)1 << (i>=63 ? 63 : i)) ){
|
||||
zRet = sqlite3_mprintf("%z, %s", zRet, pTab->aCol[i]);
|
||||
}else{
|
||||
zRet = sqlite3_mprintf("%z, NULL", zRet);
|
||||
}
|
||||
if( !zRet ) break;
|
||||
}
|
||||
}
|
||||
return zRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** The echo module implements the subset of query constraints and sort
|
||||
** orders that may take advantage of SQLite indices on the underlying
|
||||
@@ -798,7 +770,6 @@ static char *echoSelectList(echo_vtab *pTab, sqlite3_index_info *pIdxInfo){
|
||||
static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
int ii;
|
||||
char *zQuery = 0;
|
||||
char *zCol = 0;
|
||||
char *zNew;
|
||||
int nArg = 0;
|
||||
const char *zSep = "WHERE";
|
||||
@@ -846,11 +817,10 @@ static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
}
|
||||
}
|
||||
|
||||
zCol = echoSelectList(pVtab, pIdxInfo);
|
||||
if( !zCol ) return SQLITE_NOMEM;
|
||||
zQuery = sqlite3_mprintf("SELECT rowid%z FROM %Q", zCol, pVtab->zTableName);
|
||||
if( !zQuery ) return SQLITE_NOMEM;
|
||||
|
||||
zQuery = sqlite3_mprintf("SELECT rowid, * FROM %Q", pVtab->zTableName);
|
||||
if( !zQuery ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
for(ii=0; ii<pIdxInfo->nConstraint; ii++){
|
||||
const struct sqlite3_index_constraint *pConstraint;
|
||||
struct sqlite3_index_constraint_usage *pUsage;
|
||||
@@ -863,7 +833,7 @@ static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
|
||||
iCol = pConstraint->iColumn;
|
||||
if( iCol<0 || pVtab->aIndex[iCol] ){
|
||||
char *zNewCol = iCol>=0 ? pVtab->aCol[iCol] : "rowid";
|
||||
char *zCol = iCol>=0 ? pVtab->aCol[iCol] : "rowid";
|
||||
char *zOp = 0;
|
||||
useIdx = 1;
|
||||
switch( pConstraint->op ){
|
||||
@@ -878,26 +848,13 @@ static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
case SQLITE_INDEX_CONSTRAINT_GE:
|
||||
zOp = ">="; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_MATCH:
|
||||
/* Purposely translate the MATCH operator into a LIKE, which
|
||||
** will be used by the next block of code to construct a new
|
||||
** query. It should also be noted here that the next block
|
||||
** of code requires the first letter of this operator to be
|
||||
** in upper-case to trigger the special MATCH handling (i.e.
|
||||
** wrapping the bound parameter with literal '%'s).
|
||||
*/
|
||||
zOp = "LIKE"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_LIKE:
|
||||
zOp = "like"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_GLOB:
|
||||
zOp = "glob"; break;
|
||||
case SQLITE_INDEX_CONSTRAINT_REGEXP:
|
||||
zOp = "regexp"; break;
|
||||
}
|
||||
if( zOp[0]=='L' ){
|
||||
zNew = sqlite3_mprintf(" %s %s LIKE (SELECT '%%'||?||'%%')",
|
||||
zSep, zNewCol);
|
||||
zSep, zCol);
|
||||
} else {
|
||||
zNew = sqlite3_mprintf(" %s %s %s ?", zSep, zNewCol, zOp);
|
||||
zNew = sqlite3_mprintf(" %s %s %s ?", zSep, zCol, zOp);
|
||||
}
|
||||
string_concat(&zQuery, zNew, 1, &rc);
|
||||
|
||||
@@ -915,9 +872,9 @@ static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
pIdxInfo->aOrderBy->iColumn<0 ||
|
||||
pVtab->aIndex[pIdxInfo->aOrderBy->iColumn]) ){
|
||||
int iCol = pIdxInfo->aOrderBy->iColumn;
|
||||
char *zNewCol = iCol>=0 ? pVtab->aCol[iCol] : "rowid";
|
||||
char *zCol = iCol>=0 ? pVtab->aCol[iCol] : "rowid";
|
||||
char *zDir = pIdxInfo->aOrderBy->desc?"DESC":"ASC";
|
||||
zNew = sqlite3_mprintf(" ORDER BY %s %s", zNewCol, zDir);
|
||||
zNew = sqlite3_mprintf(" ORDER BY %s %s", zCol, zDir);
|
||||
string_concat(&zQuery, zNew, 1, &rc);
|
||||
pIdxInfo->orderByConsumed = 1;
|
||||
}
|
||||
|
||||
@@ -143,12 +143,6 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "mem5", "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
|
||||
@@ -191,12 +185,6 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "json1", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
Tcl_SetVar2(interp, "sqlite_options", "like_match_blobs", "0", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "like_match_blobs", "1", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_OMIT_ATTACH
|
||||
Tcl_SetVar2(interp, "sqlite_options", "attach", "0", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
|
||||
+3
-575
@@ -29,37 +29,6 @@
|
||||
** Adding the row to the idx table automatically creates a row in the
|
||||
** virtual table with rowid=4, path=/etc/passwd and a text field that
|
||||
** contains data read from file /etc/passwd on disk.
|
||||
**
|
||||
*************************************************************************
|
||||
** Virtual table module "fsdir"
|
||||
**
|
||||
** This module is designed to be used as a read-only eponymous virtual table.
|
||||
** Its schema is as follows:
|
||||
**
|
||||
** CREATE TABLE fsdir(dir TEXT, name TEXT);
|
||||
**
|
||||
** When queried, a WHERE term of the form "dir = $dir" must be provided. The
|
||||
** virtual table then appears to have one row for each entry in file-system
|
||||
** directory $dir. Column dir contains a copy of $dir, and column "name"
|
||||
** contains the name of the directory entry.
|
||||
**
|
||||
** If the specified $dir cannot be opened or is not a directory, it is not
|
||||
** an error. The virtual table appears to be empty in this case.
|
||||
**
|
||||
*************************************************************************
|
||||
** Virtual table module "fstree"
|
||||
**
|
||||
** This module is also a read-only eponymous virtual table with the
|
||||
** following schema:
|
||||
**
|
||||
** CREATE TABLE fstree(path TEXT, size INT, data BLOB);
|
||||
**
|
||||
** Running a "SELECT * FROM fstree" query on this table returns the entire
|
||||
** contents of the file-system, starting at "/". To restrict the search
|
||||
** space, the virtual table supports LIKE and GLOB constraints on the
|
||||
** 'path' column. For example:
|
||||
**
|
||||
** SELECT * FROM fstree WHERE path LIKE '/home/dan/sqlite/%'
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
@@ -72,17 +41,9 @@
|
||||
|
||||
#if SQLITE_OS_UNIX
|
||||
# include <unistd.h>
|
||||
# include <dirent.h>
|
||||
# ifndef DIRENT
|
||||
# define DIRENT dirent
|
||||
# endif
|
||||
#endif
|
||||
#if SQLITE_OS_WIN
|
||||
# include <io.h>
|
||||
# include "test_windirent.h"
|
||||
# ifndef S_ISREG
|
||||
# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
@@ -109,491 +70,6 @@ struct fs_cursor {
|
||||
int nAlloc;
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
** Start of fsdir implementation.
|
||||
*/
|
||||
typedef struct FsdirVtab FsdirVtab;
|
||||
typedef struct FsdirCsr FsdirCsr;
|
||||
struct FsdirVtab {
|
||||
sqlite3_vtab base;
|
||||
};
|
||||
|
||||
struct FsdirCsr {
|
||||
sqlite3_vtab_cursor base;
|
||||
char *zDir; /* Buffer containing directory scanned */
|
||||
DIR *pDir; /* Open directory */
|
||||
sqlite3_int64 iRowid;
|
||||
struct DIRENT entry; /* Current entry */
|
||||
};
|
||||
|
||||
/*
|
||||
** This function is the implementation of both the xConnect and xCreate
|
||||
** methods of the fsdir virtual table.
|
||||
**
|
||||
** The argv[] array contains the following:
|
||||
**
|
||||
** argv[0] -> module name ("fs")
|
||||
** argv[1] -> database name
|
||||
** argv[2] -> table name
|
||||
** argv[...] -> other module argument fields.
|
||||
*/
|
||||
static int fsdirConnect(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
FsdirVtab *pTab;
|
||||
|
||||
if( argc!=3 ){
|
||||
*pzErr = sqlite3_mprintf("wrong number of arguments");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
pTab = (FsdirVtab *)sqlite3_malloc(sizeof(FsdirVtab));
|
||||
if( !pTab ) return SQLITE_NOMEM;
|
||||
memset(pTab, 0, sizeof(FsdirVtab));
|
||||
|
||||
*ppVtab = &pTab->base;
|
||||
sqlite3_declare_vtab(db, "CREATE TABLE xyz(dir, name);");
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** xDestroy/xDisconnect implementation.
|
||||
*/
|
||||
static int fsdirDisconnect(sqlite3_vtab *pVtab){
|
||||
sqlite3_free(pVtab);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** xBestIndex implementation. The only constraint supported is:
|
||||
**
|
||||
** (dir = ?)
|
||||
*/
|
||||
static int fsdirBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
int ii;
|
||||
|
||||
pIdxInfo->estimatedCost = 1000000000.0;
|
||||
|
||||
for(ii=0; ii<pIdxInfo->nConstraint; ii++){
|
||||
struct sqlite3_index_constraint const *p = &pIdxInfo->aConstraint[ii];
|
||||
if( p->iColumn==0 && p->usable && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||
struct sqlite3_index_constraint_usage *pUsage;
|
||||
pUsage = &pIdxInfo->aConstraintUsage[ii];
|
||||
pUsage->omit = 1;
|
||||
pUsage->argvIndex = 1;
|
||||
pIdxInfo->idxNum = 1;
|
||||
pIdxInfo->estimatedCost = 1.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** xOpen implementation.
|
||||
**
|
||||
** Open a new fsdir cursor.
|
||||
*/
|
||||
static int fsdirOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
|
||||
FsdirCsr *pCur;
|
||||
/* 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;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Close a fsdir cursor.
|
||||
*/
|
||||
static int fsdirClose(sqlite3_vtab_cursor *cur){
|
||||
FsdirCsr *pCur = (FsdirCsr*)cur;
|
||||
if( pCur->pDir ) closedir(pCur->pDir);
|
||||
sqlite3_free(pCur->zDir);
|
||||
sqlite3_free(pCur);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Skip the cursor to the next entry.
|
||||
*/
|
||||
static int fsdirNext(sqlite3_vtab_cursor *cur){
|
||||
FsdirCsr *pCsr = (FsdirCsr*)cur;
|
||||
|
||||
if( pCsr->pDir ){
|
||||
struct DIRENT *pRes = 0;
|
||||
readdir_r(pCsr->pDir, &pCsr->entry, &pRes);
|
||||
if( pRes==0 ){
|
||||
closedir(pCsr->pDir);
|
||||
pCsr->pDir = 0;
|
||||
}
|
||||
pCsr->iRowid++;
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** xFilter method implementation.
|
||||
*/
|
||||
static int fsdirFilter(
|
||||
sqlite3_vtab_cursor *pVtabCursor,
|
||||
int idxNum, const char *idxStr,
|
||||
int argc, sqlite3_value **argv
|
||||
){
|
||||
FsdirCsr *pCsr = (FsdirCsr*)pVtabCursor;
|
||||
const char *zDir;
|
||||
int nDir;
|
||||
|
||||
|
||||
if( idxNum!=1 || argc!=1 ){
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
pCsr->iRowid = 0;
|
||||
sqlite3_free(pCsr->zDir);
|
||||
if( pCsr->pDir ){
|
||||
closedir(pCsr->pDir);
|
||||
pCsr->pDir = 0;
|
||||
}
|
||||
|
||||
zDir = (const char*)sqlite3_value_text(argv[0]);
|
||||
nDir = sqlite3_value_bytes(argv[0]);
|
||||
pCsr->zDir = sqlite3_malloc(nDir+1);
|
||||
if( pCsr->zDir==0 ) return SQLITE_NOMEM;
|
||||
memcpy(pCsr->zDir, zDir, nDir+1);
|
||||
|
||||
pCsr->pDir = opendir(pCsr->zDir);
|
||||
return fsdirNext(pVtabCursor);
|
||||
}
|
||||
|
||||
/*
|
||||
** xEof method implementation.
|
||||
*/
|
||||
static int fsdirEof(sqlite3_vtab_cursor *cur){
|
||||
FsdirCsr *pCsr = (FsdirCsr*)cur;
|
||||
return pCsr->pDir==0;
|
||||
}
|
||||
|
||||
/*
|
||||
** xColumn method implementation.
|
||||
*/
|
||||
static int fsdirColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
|
||||
FsdirCsr *pCsr = (FsdirCsr*)cur;
|
||||
switch( i ){
|
||||
case 0: /* dir */
|
||||
sqlite3_result_text(ctx, pCsr->zDir, -1, SQLITE_STATIC);
|
||||
break;
|
||||
|
||||
case 1: /* name */
|
||||
sqlite3_result_text(ctx, pCsr->entry.d_name, -1, SQLITE_TRANSIENT);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( 0 );
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** xRowid method implementation.
|
||||
*/
|
||||
static int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
FsdirCsr *pCsr = (FsdirCsr*)cur;
|
||||
*pRowid = pCsr->iRowid;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
/*
|
||||
** End of fsdir implementation.
|
||||
*************************************************************************/
|
||||
|
||||
/*************************************************************************
|
||||
** Start of fstree implementation.
|
||||
*/
|
||||
typedef struct FstreeVtab FstreeVtab;
|
||||
typedef struct FstreeCsr FstreeCsr;
|
||||
struct FstreeVtab {
|
||||
sqlite3_vtab base;
|
||||
sqlite3 *db;
|
||||
};
|
||||
|
||||
struct FstreeCsr {
|
||||
sqlite3_vtab_cursor base;
|
||||
sqlite3_stmt *pStmt; /* Statement to list paths */
|
||||
int fd; /* File descriptor open on current path */
|
||||
};
|
||||
|
||||
/*
|
||||
** This function is the implementation of both the xConnect and xCreate
|
||||
** methods of the fstree virtual table.
|
||||
**
|
||||
** The argv[] array contains the following:
|
||||
**
|
||||
** argv[0] -> module name ("fs")
|
||||
** argv[1] -> database name
|
||||
** argv[2] -> table name
|
||||
** argv[...] -> other module argument fields.
|
||||
*/
|
||||
static int fstreeConnect(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
FstreeVtab *pTab;
|
||||
|
||||
if( argc!=3 ){
|
||||
*pzErr = sqlite3_mprintf("wrong number of arguments");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
pTab = (FstreeVtab *)sqlite3_malloc(sizeof(FstreeVtab));
|
||||
if( !pTab ) return SQLITE_NOMEM;
|
||||
memset(pTab, 0, sizeof(FstreeVtab));
|
||||
pTab->db = db;
|
||||
|
||||
*ppVtab = &pTab->base;
|
||||
sqlite3_declare_vtab(db, "CREATE TABLE xyz(path, size, data);");
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** xDestroy/xDisconnect implementation.
|
||||
*/
|
||||
static int fstreeDisconnect(sqlite3_vtab *pVtab){
|
||||
sqlite3_free(pVtab);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** xBestIndex implementation. The only constraint supported is:
|
||||
**
|
||||
** (dir = ?)
|
||||
*/
|
||||
static int fstreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
int ii;
|
||||
|
||||
for(ii=0; ii<pIdxInfo->nConstraint; ii++){
|
||||
struct sqlite3_index_constraint const *p = &pIdxInfo->aConstraint[ii];
|
||||
if( p->iColumn==0 && p->usable && (
|
||||
p->op==SQLITE_INDEX_CONSTRAINT_GLOB
|
||||
|| p->op==SQLITE_INDEX_CONSTRAINT_LIKE
|
||||
|| p->op==SQLITE_INDEX_CONSTRAINT_EQ
|
||||
)){
|
||||
struct sqlite3_index_constraint_usage *pUsage;
|
||||
pUsage = &pIdxInfo->aConstraintUsage[ii];
|
||||
pIdxInfo->idxNum = p->op;
|
||||
pUsage->argvIndex = 1;
|
||||
pIdxInfo->estimatedCost = 100000.0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
pIdxInfo->estimatedCost = 1000000000.0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** xOpen implementation.
|
||||
**
|
||||
** Open a new fstree cursor.
|
||||
*/
|
||||
static int fstreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
|
||||
FstreeCsr *pCur;
|
||||
pCur = (FstreeCsr*)sqlite3_malloc(sizeof(FstreeCsr));
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, sizeof(FstreeCsr));
|
||||
pCur->fd = -1;
|
||||
*ppCursor = &pCur->base;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static void fstreeCloseFd(FstreeCsr *pCsr){
|
||||
if( pCsr->fd>=0 ){
|
||||
close(pCsr->fd);
|
||||
pCsr->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Close a fstree cursor.
|
||||
*/
|
||||
static int fstreeClose(sqlite3_vtab_cursor *cur){
|
||||
FstreeCsr *pCsr = (FstreeCsr*)cur;
|
||||
sqlite3_finalize(pCsr->pStmt);
|
||||
fstreeCloseFd(pCsr);
|
||||
sqlite3_free(pCsr);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Skip the cursor to the next entry.
|
||||
*/
|
||||
static int fstreeNext(sqlite3_vtab_cursor *cur){
|
||||
FstreeCsr *pCsr = (FstreeCsr*)cur;
|
||||
int rc;
|
||||
|
||||
fstreeCloseFd(pCsr);
|
||||
rc = sqlite3_step(pCsr->pStmt);
|
||||
if( rc!=SQLITE_ROW ){
|
||||
rc = sqlite3_finalize(pCsr->pStmt);
|
||||
pCsr->pStmt = 0;
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
pCsr->fd = open((const char*)sqlite3_column_text(pCsr->pStmt, 0), O_RDONLY);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** xFilter method implementation.
|
||||
*/
|
||||
static int fstreeFilter(
|
||||
sqlite3_vtab_cursor *pVtabCursor,
|
||||
int idxNum, const char *idxStr,
|
||||
int argc, sqlite3_value **argv
|
||||
){
|
||||
FstreeCsr *pCsr = (FstreeCsr*)pVtabCursor;
|
||||
FstreeVtab *pTab = (FstreeVtab*)(pCsr->base.pVtab);
|
||||
int rc;
|
||||
const char *zSql =
|
||||
"WITH r(d) AS ("
|
||||
" SELECT CASE WHEN dir=?2 THEN ?3 ELSE dir END || '/' || name "
|
||||
" FROM fsdir WHERE dir=?1 AND name NOT LIKE '.%'"
|
||||
" UNION ALL"
|
||||
" SELECT dir || '/' || name FROM r, fsdir WHERE dir=d AND name NOT LIKE '.%'"
|
||||
") SELECT d FROM r;";
|
||||
|
||||
char *zRoot;
|
||||
int nRoot;
|
||||
char *zPrefix;
|
||||
int nPrefix;
|
||||
const char *zDir;
|
||||
int nDir;
|
||||
char aWild[2] = { '\0', '\0' };
|
||||
|
||||
#if SQLITE_OS_WIN
|
||||
zRoot = sqlite3_mprintf("%s%c", getenv("SystemDrive"), '/');
|
||||
nRoot = strlen(zRoot);
|
||||
zPrefix = sqlite3_mprintf("%s", getenv("SystemDrive"));
|
||||
nPrefix = strlen(zPrefix);
|
||||
#else
|
||||
zRoot = "/";
|
||||
nRoot = 1;
|
||||
zPrefix = "";
|
||||
nPrefix = 0;
|
||||
#endif
|
||||
|
||||
zDir = zRoot;
|
||||
nDir = nRoot;
|
||||
|
||||
fstreeCloseFd(pCsr);
|
||||
sqlite3_finalize(pCsr->pStmt);
|
||||
pCsr->pStmt = 0;
|
||||
rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
if( idxNum ){
|
||||
const char *zQuery = (const char*)sqlite3_value_text(argv[0]);
|
||||
switch( idxNum ){
|
||||
case SQLITE_INDEX_CONSTRAINT_GLOB:
|
||||
aWild[0] = '*';
|
||||
aWild[1] = '?';
|
||||
break;
|
||||
case SQLITE_INDEX_CONSTRAINT_LIKE:
|
||||
aWild[0] = '_';
|
||||
aWild[1] = '%';
|
||||
break;
|
||||
}
|
||||
|
||||
if( sqlite3_strnicmp(zQuery, zPrefix, nPrefix)==0 ){
|
||||
int i;
|
||||
for(i=nPrefix; zQuery[i]; i++){
|
||||
if( zQuery[i]==aWild[0] || zQuery[i]==aWild[1] ) break;
|
||||
if( zQuery[i]=='/' ) nDir = i;
|
||||
}
|
||||
zDir = zQuery;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_bind_text(pCsr->pStmt, 1, zDir, nDir, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(pCsr->pStmt, 2, zRoot, nRoot, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(pCsr->pStmt, 3, zPrefix, nPrefix, SQLITE_TRANSIENT);
|
||||
|
||||
#if SQLITE_OS_WIN
|
||||
sqlite3_free(zPrefix);
|
||||
sqlite3_free(zRoot);
|
||||
#endif
|
||||
|
||||
return fstreeNext(pVtabCursor);
|
||||
}
|
||||
|
||||
/*
|
||||
** xEof method implementation.
|
||||
*/
|
||||
static int fstreeEof(sqlite3_vtab_cursor *cur){
|
||||
FstreeCsr *pCsr = (FstreeCsr*)cur;
|
||||
return pCsr->pStmt==0;
|
||||
}
|
||||
|
||||
/*
|
||||
** xColumn method implementation.
|
||||
*/
|
||||
static int fstreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
|
||||
FstreeCsr *pCsr = (FstreeCsr*)cur;
|
||||
if( i==0 ){ /* path */
|
||||
sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, 0));
|
||||
}else{
|
||||
struct stat sBuf;
|
||||
fstat(pCsr->fd, &sBuf);
|
||||
|
||||
if( S_ISREG(sBuf.st_mode) ){
|
||||
if( i==1 ){
|
||||
sqlite3_result_int64(ctx, sBuf.st_size);
|
||||
}else{
|
||||
int nRead;
|
||||
char *aBuf = sqlite3_malloc(sBuf.st_mode+1);
|
||||
if( !aBuf ) return SQLITE_NOMEM;
|
||||
nRead = read(pCsr->fd, aBuf, sBuf.st_mode);
|
||||
if( nRead!=sBuf.st_mode ){
|
||||
return SQLITE_IOERR;
|
||||
}
|
||||
sqlite3_result_blob(ctx, aBuf, nRead, SQLITE_TRANSIENT);
|
||||
sqlite3_free(aBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** xRowid method implementation.
|
||||
*/
|
||||
static int fstreeRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
*pRowid = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
/*
|
||||
** End of fstree implementation.
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** This function is the implementation of both the xConnect and xCreate
|
||||
** methods of the fs virtual table.
|
||||
@@ -633,7 +109,7 @@ static int fsConnect(
|
||||
memcpy(pVtab->zTbl, zTbl, strlen(zTbl));
|
||||
memcpy(pVtab->zDb, zDb, strlen(zDb));
|
||||
*ppVtab = &pVtab->base;
|
||||
sqlite3_declare_vtab(db, "CREATE TABLE x(path TEXT, data TEXT)");
|
||||
sqlite3_declare_vtab(db, "CREATE TABLE xyz(path TEXT, data TEXT)");
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -712,15 +188,15 @@ static int fsFilter(
|
||||
static int fsColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
|
||||
fs_cursor *pCur = (fs_cursor*)cur;
|
||||
|
||||
assert( i==0 || i==1 || i==2 );
|
||||
assert( i==0 || i==1 );
|
||||
if( i==0 ){
|
||||
sqlite3_result_value(ctx, sqlite3_column_value(pCur->pStmt, 0));
|
||||
}else{
|
||||
const char *zFile = (const char *)sqlite3_column_text(pCur->pStmt, 1);
|
||||
struct stat sbuf;
|
||||
int fd;
|
||||
|
||||
int n;
|
||||
|
||||
fd = open(zFile, O_RDONLY);
|
||||
if( fd<0 ) return SQLITE_IOERR;
|
||||
fstat(fd, &sbuf);
|
||||
@@ -808,52 +284,6 @@ static sqlite3_module fsModule = {
|
||||
0, /* xRename */
|
||||
};
|
||||
|
||||
static sqlite3_module fsdirModule = {
|
||||
0, /* iVersion */
|
||||
fsdirConnect, /* xCreate */
|
||||
fsdirConnect, /* xConnect */
|
||||
fsdirBestIndex, /* xBestIndex */
|
||||
fsdirDisconnect, /* xDisconnect */
|
||||
fsdirDisconnect, /* xDestroy */
|
||||
fsdirOpen, /* xOpen - open a cursor */
|
||||
fsdirClose, /* xClose - close a cursor */
|
||||
fsdirFilter, /* xFilter - configure scan constraints */
|
||||
fsdirNext, /* xNext - advance a cursor */
|
||||
fsdirEof, /* xEof - check for end of scan */
|
||||
fsdirColumn, /* xColumn - read data */
|
||||
fsdirRowid, /* xRowid - read data */
|
||||
0, /* xUpdate */
|
||||
0, /* xBegin */
|
||||
0, /* xSync */
|
||||
0, /* xCommit */
|
||||
0, /* xRollback */
|
||||
0, /* xFindMethod */
|
||||
0, /* xRename */
|
||||
};
|
||||
|
||||
static sqlite3_module fstreeModule = {
|
||||
0, /* iVersion */
|
||||
fstreeConnect, /* xCreate */
|
||||
fstreeConnect, /* xConnect */
|
||||
fstreeBestIndex, /* xBestIndex */
|
||||
fstreeDisconnect, /* xDisconnect */
|
||||
fstreeDisconnect, /* xDestroy */
|
||||
fstreeOpen, /* xOpen - open a cursor */
|
||||
fstreeClose, /* xClose - close a cursor */
|
||||
fstreeFilter, /* xFilter - configure scan constraints */
|
||||
fstreeNext, /* xNext - advance a cursor */
|
||||
fstreeEof, /* xEof - check for end of scan */
|
||||
fstreeColumn, /* xColumn - read data */
|
||||
fstreeRowid, /* xRowid - read data */
|
||||
0, /* xUpdate */
|
||||
0, /* xBegin */
|
||||
0, /* xSync */
|
||||
0, /* xCommit */
|
||||
0, /* xRollback */
|
||||
0, /* xFindMethod */
|
||||
0, /* xRename */
|
||||
};
|
||||
|
||||
/*
|
||||
** Decode a pointer to an sqlite3 object.
|
||||
*/
|
||||
@@ -876,8 +306,6 @@ static int register_fs_module(
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
sqlite3_create_module(db, "fs", &fsModule, (void *)interp);
|
||||
sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
|
||||
sqlite3_create_module(db, "fstree", &fstreeModule, 0);
|
||||
#endif
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ static void statusFunc(
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
int op = 0, mx, cur, resetFlag, rc;
|
||||
int op, mx, cur, resetFlag, rc;
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){
|
||||
op = sqlite3_value_int(argv[0]);
|
||||
}else if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){
|
||||
|
||||
+3
-4
@@ -222,8 +222,7 @@ 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,
|
||||
(void*)0, (void*)0);
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 0, 0);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -911,7 +910,7 @@ static int test_config_scratch(
|
||||
free(buf);
|
||||
if( sz<0 ){
|
||||
buf = 0;
|
||||
rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, (void*)0, 0, 0);
|
||||
rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, 0, 0, 0);
|
||||
}else{
|
||||
buf = malloc( sz*N + 1 );
|
||||
rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, buf, sz, N);
|
||||
@@ -958,7 +957,7 @@ static int test_config_pagecache(
|
||||
Tcl_SetObjResult(interp, pRes);
|
||||
|
||||
if( sz<0 ){
|
||||
sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, 0);
|
||||
sqlite3_config(SQLITE_CONFIG_PAGECACHE, 0, 0, 0);
|
||||
}else{
|
||||
buf = malloc( sz*N );
|
||||
sqlite3_config(SQLITE_CONFIG_PAGECACHE, buf, sz, N);
|
||||
|
||||
+11
-6
@@ -189,11 +189,8 @@ static struct {
|
||||
int isInitialized;
|
||||
|
||||
/* For run-time access any of the other global data structures in this
|
||||
** 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. */
|
||||
** shim, the following mutex must be held.
|
||||
*/
|
||||
sqlite3_mutex *pMutex;
|
||||
|
||||
/* List of multiplexGroup objects.
|
||||
@@ -761,8 +758,11 @@ 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,7 +772,9 @@ 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;
|
||||
@@ -789,7 +791,8 @@ static int multiplexRead(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert( nMutex==0 || nMutex==1 );
|
||||
if( nMutex ) multiplexLeave();
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -806,6 +809,7 @@ 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 ){
|
||||
@@ -830,6 +834,7 @@ static int multiplexWrite(
|
||||
}
|
||||
}
|
||||
}
|
||||
multiplexLeave();
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
+28
-168
@@ -23,15 +23,6 @@
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
/*
|
||||
** Characters that make up the idxStr created by xBestIndex for xFilter.
|
||||
*/
|
||||
#define TCLVAR_NAME_EQ 'e'
|
||||
#define TCLVAR_NAME_MATCH 'm'
|
||||
#define TCLVAR_VALUE_GLOB 'g'
|
||||
#define TCLVAR_VALUE_REGEXP 'r'
|
||||
#define TCLVAR_VALUE_LIKE 'l'
|
||||
|
||||
typedef struct tclvar_vtab tclvar_vtab;
|
||||
typedef struct tclvar_cursor tclvar_cursor;
|
||||
|
||||
@@ -164,44 +155,15 @@ static int tclvarFilter(
|
||||
){
|
||||
tclvar_cursor *pCur = (tclvar_cursor *)pVtabCursor;
|
||||
Tcl_Interp *interp = ((tclvar_vtab *)(pVtabCursor->pVtab))->interp;
|
||||
Tcl_Obj *p = Tcl_NewStringObj("tclvar_filter_cmd", -1);
|
||||
|
||||
const char *zEq = "";
|
||||
const char *zMatch = "";
|
||||
const char *zGlob = "";
|
||||
const char *zRegexp = "";
|
||||
const char *zLike = "";
|
||||
int i;
|
||||
|
||||
for(i=0; idxStr[i]; i++){
|
||||
switch( idxStr[i] ){
|
||||
case TCLVAR_NAME_EQ:
|
||||
zEq = (const char*)sqlite3_value_text(argv[i]);
|
||||
break;
|
||||
case TCLVAR_NAME_MATCH:
|
||||
zMatch = (const char*)sqlite3_value_text(argv[i]);
|
||||
break;
|
||||
case TCLVAR_VALUE_GLOB:
|
||||
zGlob = (const char*)sqlite3_value_text(argv[i]);
|
||||
break;
|
||||
case TCLVAR_VALUE_REGEXP:
|
||||
zRegexp = (const char*)sqlite3_value_text(argv[i]);
|
||||
break;
|
||||
case TCLVAR_VALUE_LIKE:
|
||||
zLike = (const char*)sqlite3_value_text(argv[i]);
|
||||
break;
|
||||
default:
|
||||
assert( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
Tcl_Obj *p = Tcl_NewStringObj("info vars", -1);
|
||||
Tcl_IncrRefCount(p);
|
||||
Tcl_ListObjAppendElement(0, p, Tcl_NewStringObj(zEq, -1));
|
||||
Tcl_ListObjAppendElement(0, p, Tcl_NewStringObj(zMatch, -1));
|
||||
Tcl_ListObjAppendElement(0, p, Tcl_NewStringObj(zGlob, -1));
|
||||
Tcl_ListObjAppendElement(0, p, Tcl_NewStringObj(zRegexp, -1));
|
||||
Tcl_ListObjAppendElement(0, p, Tcl_NewStringObj(zLike, -1));
|
||||
|
||||
assert( argc==0 || argc==1 );
|
||||
if( argc==1 ){
|
||||
Tcl_Obj *pArg = Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1);
|
||||
Tcl_ListObjAppendElement(0, p, pArg);
|
||||
}
|
||||
Tcl_EvalObjEx(interp, p, TCL_EVAL_GLOBAL);
|
||||
if( pCur->pList1 ){
|
||||
Tcl_DecrRefCount(pCur->pList1);
|
||||
@@ -214,6 +176,7 @@ static int tclvarFilter(
|
||||
pCur->i2 = 0;
|
||||
pCur->pList1 = Tcl_GetObjResult(interp);
|
||||
Tcl_IncrRefCount(pCur->pList1);
|
||||
assert( pCur->i1==0 && pCur->i2==0 && pCur->pList2==0 );
|
||||
|
||||
Tcl_DecrRefCount(p);
|
||||
return tclvarNext(pVtabCursor);
|
||||
@@ -261,113 +224,32 @@ static int tclvarEof(sqlite3_vtab_cursor *cur){
|
||||
return (pCur->pList2?0:1);
|
||||
}
|
||||
|
||||
/*
|
||||
** If nul-terminated string zStr does not already contain the character
|
||||
** passed as the second argument, append it and return 0. Or, if there is
|
||||
** already an instance of x in zStr, do nothing return 1;
|
||||
**
|
||||
** There is guaranteed to be enough room in the buffer pointed to by zStr
|
||||
** for the new character and nul-terminator.
|
||||
*/
|
||||
static int tclvarAddToIdxstr(char *zStr, char x){
|
||||
int i;
|
||||
for(i=0; zStr[i]; i++){
|
||||
if( zStr[i]==x ) return 1;
|
||||
}
|
||||
zStr[i] = x;
|
||||
zStr[i+1] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if variable $::tclvar_set_omit exists and is set to true.
|
||||
** False otherwise.
|
||||
*/
|
||||
static int tclvarSetOmit(Tcl_Interp *interp){
|
||||
int rc;
|
||||
int res = 0;
|
||||
Tcl_Obj *pRes;
|
||||
rc = Tcl_Eval(interp,
|
||||
"expr {[info exists ::tclvar_set_omit] && $::tclvar_set_omit}"
|
||||
);
|
||||
if( rc==TCL_OK ){
|
||||
pRes = Tcl_GetObjResult(interp);
|
||||
rc = Tcl_GetBooleanFromObj(0, pRes, &res);
|
||||
}
|
||||
return (rc==TCL_OK && res);
|
||||
}
|
||||
|
||||
/*
|
||||
** The xBestIndex() method. This virtual table supports the following
|
||||
** operators:
|
||||
**
|
||||
** name = ? (omit flag clear)
|
||||
** name MATCH ? (omit flag set)
|
||||
** value GLOB ? (omit flag set iff $::tclvar_set_omit)
|
||||
** value REGEXP ? (omit flag set iff $::tclvar_set_omit)
|
||||
** value LIKE ? (omit flag set iff $::tclvar_set_omit)
|
||||
**
|
||||
** For each constraint present, the corresponding TCLVAR_XXX character is
|
||||
** appended to the idxStr value.
|
||||
*/
|
||||
static int tclvarBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
tclvar_vtab *pTab = (tclvar_vtab*)tab;
|
||||
int ii;
|
||||
char *zStr = sqlite3_malloc(32);
|
||||
int iStr = 0;
|
||||
|
||||
if( zStr==0 ) return SQLITE_NOMEM;
|
||||
zStr[0] = '\0';
|
||||
|
||||
for(ii=0; ii<pIdxInfo->nConstraint; ii++){
|
||||
struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii];
|
||||
struct sqlite3_index_constraint_usage *pUsage;
|
||||
|
||||
pUsage = &pIdxInfo->aConstraintUsage[ii];
|
||||
if( pCons->usable ){
|
||||
/* name = ? */
|
||||
if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && pCons->iColumn==0 ){
|
||||
if( 0==tclvarAddToIdxstr(zStr, TCLVAR_NAME_EQ) ){
|
||||
pUsage->argvIndex = ++iStr;
|
||||
pUsage->omit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* name MATCH ? */
|
||||
if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH && pCons->iColumn==0 ){
|
||||
if( 0==tclvarAddToIdxstr(zStr, TCLVAR_NAME_MATCH) ){
|
||||
pUsage->argvIndex = ++iStr;
|
||||
pUsage->omit = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* value GLOB ? */
|
||||
if( pCons->op==SQLITE_INDEX_CONSTRAINT_GLOB && pCons->iColumn==2 ){
|
||||
if( 0==tclvarAddToIdxstr(zStr, TCLVAR_VALUE_GLOB) ){
|
||||
pUsage->argvIndex = ++iStr;
|
||||
pUsage->omit = tclvarSetOmit(pTab->interp);
|
||||
}
|
||||
}
|
||||
|
||||
/* value REGEXP ? */
|
||||
if( pCons->op==SQLITE_INDEX_CONSTRAINT_REGEXP && pCons->iColumn==2 ){
|
||||
if( 0==tclvarAddToIdxstr(zStr, TCLVAR_VALUE_REGEXP) ){
|
||||
pUsage->argvIndex = ++iStr;
|
||||
pUsage->omit = tclvarSetOmit(pTab->interp);
|
||||
}
|
||||
}
|
||||
|
||||
/* value LIKE ? */
|
||||
if( pCons->op==SQLITE_INDEX_CONSTRAINT_LIKE && pCons->iColumn==2 ){
|
||||
if( 0==tclvarAddToIdxstr(zStr, TCLVAR_VALUE_LIKE) ){
|
||||
pUsage->argvIndex = ++iStr;
|
||||
pUsage->omit = tclvarSetOmit(pTab->interp);
|
||||
}
|
||||
}
|
||||
if( pCons->iColumn==0 && pCons->usable
|
||||
&& pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||
struct sqlite3_index_constraint_usage *pUsage;
|
||||
pUsage = &pIdxInfo->aConstraintUsage[ii];
|
||||
pUsage->omit = 0;
|
||||
pUsage->argvIndex = 1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
for(ii=0; ii<pIdxInfo->nConstraint; ii++){
|
||||
struct sqlite3_index_constraint const *pCons = &pIdxInfo->aConstraint[ii];
|
||||
if( pCons->iColumn==0 && pCons->usable
|
||||
&& pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH ){
|
||||
struct sqlite3_index_constraint_usage *pUsage;
|
||||
pUsage = &pIdxInfo->aConstraintUsage[ii];
|
||||
pUsage->omit = 1;
|
||||
pUsage->argvIndex = 1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
pIdxInfo->idxStr = zStr;
|
||||
pIdxInfo->needToFreeIdxStr = 1;
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -413,7 +295,6 @@ static int register_tclvar_module(
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *CONST objv[] /* Command arguments */
|
||||
){
|
||||
int rc = TCL_OK;
|
||||
sqlite3 *db;
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
||||
@@ -421,30 +302,9 @@ static int register_tclvar_module(
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
sqlite3_create_module(db, "tclvar", &tclvarModule, (void*)interp);
|
||||
rc = Tcl_Eval(interp,
|
||||
"proc like {pattern str} {\n"
|
||||
" set p [string map {% * _ ?} $pattern]\n"
|
||||
" string match $p $str\n"
|
||||
"}\n"
|
||||
"proc tclvar_filter_cmd {eq match glob regexp like} {\n"
|
||||
" set res {}\n"
|
||||
" set pattern $eq\n"
|
||||
" if {$pattern=={}} { set pattern $match }\n"
|
||||
" if {$pattern=={}} { set pattern * }\n"
|
||||
" foreach v [uplevel #0 info vars $pattern] {\n"
|
||||
" if {($glob=={} || [string match $glob [uplevel #0 set $v]])\n"
|
||||
" && ($like=={} || [like $like [uplevel #0 set $v]])\n"
|
||||
" && ($regexp=={} || [regexp $regexp [uplevel #0 set $v]])\n"
|
||||
" } {\n"
|
||||
" lappend res $v\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" set res\n"
|
||||
"}\n"
|
||||
);
|
||||
sqlite3_create_module(db, "tclvar", &tclvarModule, (void *)interp);
|
||||
#endif
|
||||
return rc;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
** 2015 November 30
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This file contains code to implement most of the opendir() family of
|
||||
** POSIX functions on Win32 using the MSVCRT.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
|
||||
#include "test_windirent.h"
|
||||
|
||||
/*
|
||||
** Implementation of the POSIX opendir() function using the MSVCRT.
|
||||
*/
|
||||
LPDIR opendir(
|
||||
const char *dirname
|
||||
){
|
||||
struct _finddata_t data;
|
||||
LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
|
||||
SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
|
||||
|
||||
if( dirp==NULL ) return NULL;
|
||||
memset(dirp, 0, sizeof(DIR));
|
||||
|
||||
/* TODO: Remove this if Unix-style root paths are not used. */
|
||||
if( sqlite3_stricmp(dirname, "/")==0 ){
|
||||
dirname = getenv("SystemDrive");
|
||||
}
|
||||
|
||||
_snprintf(data.name, namesize, "%s\\*", dirname);
|
||||
dirp->d_handle = _findfirst(data.name, &data);
|
||||
|
||||
if( dirp->d_handle==BAD_INTPTR_T ){
|
||||
closedir(dirp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* TODO: Remove this block to allow hidden and system files. */
|
||||
if( data.attrib&_A_HIDDEN || data.attrib&_A_SYSTEM ){
|
||||
if( _findnext(dirp->d_handle, &data)==-1 ){
|
||||
closedir(dirp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
dirp->d_first.d_attributes = data.attrib;
|
||||
strncpy(dirp->d_first.d_name, data.name, NAME_MAX);
|
||||
dirp->d_first.d_name[NAME_MAX] = '\0';
|
||||
|
||||
return dirp;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the POSIX readdir() function using the MSVCRT.
|
||||
*/
|
||||
LPDIRENT readdir(
|
||||
LPDIR dirp
|
||||
){
|
||||
struct _finddata_t data;
|
||||
|
||||
if( dirp==NULL ) return NULL;
|
||||
|
||||
if( dirp->d_first.d_ino==0 ){
|
||||
dirp->d_first.d_ino++;
|
||||
dirp->d_next.d_ino++;
|
||||
|
||||
return &dirp->d_first;
|
||||
}
|
||||
|
||||
next:
|
||||
|
||||
if( _findnext(dirp->d_handle, &data)==-1 ) return NULL;
|
||||
|
||||
/* TODO: Remove this block to allow hidden and system files. */
|
||||
if( data.attrib&_A_HIDDEN ) goto next;
|
||||
if( data.attrib&_A_SYSTEM ) goto next;
|
||||
|
||||
dirp->d_next.d_ino++;
|
||||
dirp->d_next.d_attributes = data.attrib;
|
||||
strncpy(dirp->d_next.d_name, data.name, NAME_MAX);
|
||||
dirp->d_next.d_name[NAME_MAX] = '\0';
|
||||
|
||||
return &dirp->d_next;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the POSIX readdir_r() function using the MSVCRT.
|
||||
*/
|
||||
INT readdir_r(
|
||||
LPDIR dirp,
|
||||
LPDIRENT entry,
|
||||
LPDIRENT *result
|
||||
){
|
||||
struct _finddata_t data;
|
||||
|
||||
if( dirp==NULL ) return EBADF;
|
||||
|
||||
if( dirp->d_first.d_ino==0 ){
|
||||
dirp->d_first.d_ino++;
|
||||
dirp->d_next.d_ino++;
|
||||
|
||||
entry->d_ino = dirp->d_first.d_ino;
|
||||
entry->d_attributes = dirp->d_first.d_attributes;
|
||||
strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX);
|
||||
entry->d_name[NAME_MAX] = '\0';
|
||||
|
||||
*result = entry;
|
||||
return 0;
|
||||
}
|
||||
|
||||
next:
|
||||
|
||||
if( _findnext(dirp->d_handle, &data)==-1 ){
|
||||
*result = NULL;
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
/* TODO: Remove this block to allow hidden and system files. */
|
||||
if( data.attrib&_A_HIDDEN ) goto next;
|
||||
if( data.attrib&_A_SYSTEM ) goto next;
|
||||
|
||||
entry->d_ino = (ino_t)-1; /* not available */
|
||||
entry->d_attributes = data.attrib;
|
||||
strncpy(entry->d_name, data.name, NAME_MAX);
|
||||
entry->d_name[NAME_MAX] = '\0';
|
||||
|
||||
*result = entry;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the POSIX closedir() function using the MSVCRT.
|
||||
*/
|
||||
INT closedir(
|
||||
LPDIR dirp
|
||||
){
|
||||
INT result = 0;
|
||||
|
||||
if( dirp==NULL ) return EINVAL;
|
||||
|
||||
if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){
|
||||
result = _findclose(dirp->d_handle);
|
||||
}
|
||||
|
||||
sqlite3_free(dirp);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* defined(WIN32) && defined(_MSC_VER) */
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
** 2015 November 30
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This file contains declarations for most of the opendir() family of
|
||||
** POSIX functions on Win32 using the MSVCRT.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
|
||||
/*
|
||||
** We need several data types from the Windows SDK header.
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include "windows.h"
|
||||
|
||||
/*
|
||||
** We need several support functions from the SQLite core.
|
||||
*/
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
/*
|
||||
** We need several things from the ANSI and MSVCRT headers.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <io.h>
|
||||
#include <limits.h>
|
||||
|
||||
/*
|
||||
** We may need to provide the "ino_t" type.
|
||||
*/
|
||||
|
||||
#ifndef INO_T_DEFINED
|
||||
#define INO_T_DEFINED
|
||||
typedef unsigned short ino_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** We need to define "NAME_MAX" if it was not present in "limits.h".
|
||||
*/
|
||||
|
||||
#ifndef NAME_MAX
|
||||
# ifdef FILENAME_MAX
|
||||
# define NAME_MAX (FILENAME_MAX)
|
||||
# else
|
||||
# define NAME_MAX (260)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T".
|
||||
*/
|
||||
|
||||
#ifndef NULL_INTPTR_T
|
||||
# define NULL_INTPTR_T ((intptr_t)(0))
|
||||
#endif
|
||||
|
||||
#ifndef BAD_INTPTR_T
|
||||
# define BAD_INTPTR_T ((intptr_t)(-1))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** We need to provide the necessary structures and related types.
|
||||
*/
|
||||
|
||||
typedef struct DIRENT DIRENT;
|
||||
typedef struct DIR DIR;
|
||||
typedef DIRENT *LPDIRENT;
|
||||
typedef DIR *LPDIR;
|
||||
|
||||
struct DIRENT {
|
||||
ino_t d_ino; /* Sequence number, do not use. */
|
||||
unsigned d_attributes; /* Win32 file attributes. */
|
||||
char d_name[NAME_MAX + 1]; /* Name within the directory. */
|
||||
};
|
||||
|
||||
struct DIR {
|
||||
intptr_t d_handle; /* Value returned by "_findfirst". */
|
||||
DIRENT d_first; /* DIRENT constructed based on "_findfirst". */
|
||||
DIRENT d_next; /* DIRENT constructed based on "_findnext". */
|
||||
};
|
||||
|
||||
/*
|
||||
** Finally, we can provide the function prototypes for the opendir(),
|
||||
** readdir(), readdir_r(), and closedir() POSIX functions.
|
||||
*/
|
||||
|
||||
extern LPDIR opendir(const char *dirname);
|
||||
extern LPDIRENT readdir(LPDIR dirp);
|
||||
extern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result);
|
||||
extern INT closedir(LPDIR dirp);
|
||||
|
||||
#endif /* defined(WIN32) && defined(_MSC_VER) */
|
||||
+23
-4
@@ -559,12 +559,31 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
|
||||
*/
|
||||
assert( pTable!=0 );
|
||||
if( (v = sqlite3GetVdbe(pParse))!=0 ){
|
||||
sqlite3NestedParse(pParse,
|
||||
"DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'",
|
||||
db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrigger->zName
|
||||
);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-5
@@ -263,12 +263,10 @@ void sqlite3Update(
|
||||
assert( chngPk==0 || chngPk==1 );
|
||||
chngKey = chngRowid + chngPk;
|
||||
|
||||
/* The SET expressions are not actually used inside the WHERE loop.
|
||||
** So reset the colUsed mask. Unless this is a virtual table. In that
|
||||
** case, set all bits of the colUsed mask (to ensure that the virtual
|
||||
** table implementation makes all columns available).
|
||||
/* The SET expressions are not actually used inside the WHERE loop.
|
||||
** So reset the colUsed mask
|
||||
*/
|
||||
pTabList->a[0].colUsed = IsVirtual(pTab) ? (Bitmask)-1 : 0;
|
||||
pTabList->a[0].colUsed = 0;
|
||||
|
||||
hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey);
|
||||
|
||||
|
||||
@@ -37,13 +37,13 @@
|
||||
#include <assert.h>
|
||||
#include "vdbeInt.h"
|
||||
|
||||
#if !defined(SQLITE_AMALGAMATION) && SQLITE_BYTEORDER==0
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
/*
|
||||
** The following constant value is used by the SQLITE_BIGENDIAN and
|
||||
** SQLITE_LITTLEENDIAN macros.
|
||||
*/
|
||||
const int sqlite3one = 1;
|
||||
#endif /* SQLITE_AMALGAMATION && SQLITE_BYTEORDER==0 */
|
||||
#endif /* SQLITE_AMALGAMATION */
|
||||
|
||||
/*
|
||||
** This lookup table is used to help decode the first byte of
|
||||
|
||||
+9
-8
@@ -1088,7 +1088,6 @@ case OP_String: { /* out2 */
|
||||
pOut->n = pOp->p1;
|
||||
pOut->enc = encoding;
|
||||
UPDATE_MAX_BLOBSIZE(pOut);
|
||||
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
if( pOp->p5 ){
|
||||
assert( pOp->p3>0 );
|
||||
assert( pOp->p3<=(p->nMem-p->nCursor) );
|
||||
@@ -1096,7 +1095,6 @@ case OP_String: { /* out2 */
|
||||
assert( pIn3->flags & MEM_Int );
|
||||
if( pIn3->u.i ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1981,7 +1979,6 @@ 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{
|
||||
@@ -2378,12 +2375,20 @@ case OP_Column: {
|
||||
u16 fx; /* pDest->flags value */
|
||||
Mem *pReg; /* PseudoTable input register */
|
||||
|
||||
pC = p->apCsr[pOp->p1];
|
||||
if( pC->eCurType==CURTYPE_PSEUDO ) goto skip_moveto;
|
||||
pOp->opcode = OP_BColumn;
|
||||
|
||||
case OP_BColumn:
|
||||
pC = p->apCsr[pOp->p1];
|
||||
rc = sqlite3VdbeCursorMoveto(pC);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
skip_moveto:
|
||||
p2 = pOp->p2;
|
||||
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
||||
pDest = &aMem[pOp->p3];
|
||||
memAboutToChange(p, pDest);
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
assert( p2<pC->nField );
|
||||
aOffset = pC->aOffset;
|
||||
@@ -2393,8 +2398,6 @@ case OP_Column: {
|
||||
pCrsr = pC->uc.pCursor;
|
||||
|
||||
/* If the cursor cache is stale, bring it up-to-date */
|
||||
rc = sqlite3VdbeCursorMoveto(pC);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
if( pC->cacheStatus!=p->cacheCtr ){
|
||||
if( pC->nullRow ){
|
||||
if( pC->eCurType==CURTYPE_PSEUDO ){
|
||||
@@ -2524,8 +2527,6 @@ case OP_Column: {
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto op_column_error;
|
||||
}
|
||||
}else{
|
||||
VVA_ONLY( t = 0; ) /* Only needed by assert() statements */
|
||||
}
|
||||
|
||||
/* If after trying to extract new entries from the header, nHdrParsed is
|
||||
|
||||
+49
-45
@@ -349,7 +349,7 @@ int sqlite3VdbeMakeLabel(Vdbe *v){
|
||||
if( p->aLabel ){
|
||||
p->aLabel[i] = -1;
|
||||
}
|
||||
return ADDR(i);
|
||||
return -1-i;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -359,7 +359,7 @@ int sqlite3VdbeMakeLabel(Vdbe *v){
|
||||
*/
|
||||
void sqlite3VdbeResolveLabel(Vdbe *v, int x){
|
||||
Parse *p = v->pParse;
|
||||
int j = ADDR(x);
|
||||
int j = -1-x;
|
||||
assert( v->magic==VDBE_MAGIC_INIT );
|
||||
assert( j<p->nLabel );
|
||||
assert( j>=0 );
|
||||
@@ -586,8 +586,8 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
|
||||
|
||||
pOp->opflags = sqlite3OpcodeProperty[opcode];
|
||||
if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
|
||||
assert( ADDR(pOp->p2)<pParse->nLabel );
|
||||
pOp->p2 = aLabel[ADDR(pOp->p2)];
|
||||
assert( -1-pOp->p2<pParse->nLabel );
|
||||
pOp->p2 = aLabel[-1-pOp->p2];
|
||||
}
|
||||
}
|
||||
sqlite3DbFree(p->db, pParse->aLabel);
|
||||
@@ -644,10 +644,15 @@ 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;
|
||||
pOut->p2 = aOp->p2;
|
||||
assert( aOp->p2>=0 );
|
||||
if( p2<0 ){
|
||||
assert( sqlite3OpcodeProperty[pOut->opcode] & OPFLG_JUMP );
|
||||
pOut->p2 = addr + ADDR(p2);
|
||||
}else{
|
||||
pOut->p2 = p2;
|
||||
}
|
||||
pOut->p3 = aOp->p3;
|
||||
pOut->p4type = P4_NOTUSED;
|
||||
pOut->p4.p = 0;
|
||||
@@ -832,6 +837,7 @@ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
|
||||
freeP4(db, pOp->p4type, pOp->p4.p);
|
||||
memset(pOp, 0, sizeof(pOp[0]));
|
||||
pOp->opcode = OP_Noop;
|
||||
if( addr==p->nOp-1 ) p->nOp--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1720,31 +1726,30 @@ void sqlite3VdbeIOTraceSql(Vdbe *p){
|
||||
**
|
||||
** nByte is the number of bytes of space needed.
|
||||
**
|
||||
** pFrom points to *pnFrom bytes of available space. New space is allocated
|
||||
** from the end of the pFrom buffer and *pnFrom is decremented.
|
||||
** *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.
|
||||
**
|
||||
** *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.
|
||||
** *pnByte is a counter of the number of bytes of space that have failed
|
||||
** to allocate. If there is insufficient space in *ppFrom to satisfy the
|
||||
** request, then increment *pnByte by the amount of the request.
|
||||
*/
|
||||
static void *allocSpace(
|
||||
void *pBuf, /* Where return pointer will be stored */
|
||||
int nByte, /* Number of bytes to allocate */
|
||||
u8 *pFrom, /* Memory available for allocation */
|
||||
int *pnFrom, /* IN/OUT: Space available at pFrom */
|
||||
int *pnNeeded /* If allocation cannot be made, increment *pnByte */
|
||||
u8 **ppFrom, /* IN/OUT: Allocate from *ppFrom */
|
||||
u8 *pEnd, /* Pointer to 1 byte past the end of *ppFrom buffer */
|
||||
int *pnByte /* If allocation cannot be made, increment *pnByte */
|
||||
){
|
||||
assert( EIGHT_BYTE_ALIGNMENT(pFrom) );
|
||||
if( pBuf==0 ){
|
||||
nByte = ROUND8(nByte);
|
||||
if( nByte <= *pnFrom ){
|
||||
*pnFrom -= nByte;
|
||||
pBuf = &pFrom[*pnFrom];
|
||||
}else{
|
||||
*pnNeeded += nByte;
|
||||
}
|
||||
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(pBuf) );
|
||||
return pBuf;
|
||||
}
|
||||
|
||||
@@ -1817,8 +1822,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 );
|
||||
@@ -1850,16 +1855,16 @@ void sqlite3VdbeMakeReady(
|
||||
** an array to marshal SQL function arguments in.
|
||||
*/
|
||||
zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */
|
||||
assert( pParse->nOpAlloc*sizeof(Op) <= 0x7fffff00 );
|
||||
nFree = (pParse->nOpAlloc - p->nOp)*sizeof(p->aOp[0]); /* Available space */
|
||||
zEnd = (u8*)&p->aOp[pParse->nOpAlloc]; /* First byte past end of zCsr[] */
|
||||
|
||||
resolveP2Values(p, &nArg);
|
||||
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
|
||||
if( pParse->explain && nMem<10 ){
|
||||
nMem = 10;
|
||||
}
|
||||
memset(zCsr, 0, nFree);
|
||||
assert( EIGHT_BYTE_ALIGNMENT(&zCsr[nFree]) );
|
||||
memset(zCsr, 0, zEnd-zCsr);
|
||||
zCsr += (zCsr - (u8*)0)&7;
|
||||
assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
|
||||
p->expired = 0;
|
||||
|
||||
/* Memory for registers, parameters, cursor, etc, is allocated in two
|
||||
@@ -1874,21 +1879,21 @@ void sqlite3VdbeMakeReady(
|
||||
*/
|
||||
do {
|
||||
nByte = 0;
|
||||
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->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte);
|
||||
p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte);
|
||||
p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte);
|
||||
p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
|
||||
p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
|
||||
zCsr, &nFree, &nByte);
|
||||
p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, zCsr, &nFree, &nByte);
|
||||
&zCsr, zEnd, &nByte);
|
||||
p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, &zCsr, zEnd, &nByte);
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), zCsr, &nFree, &nByte);
|
||||
p->anExec = allocSpace(p->anExec, p->nOp*sizeof(i64), &zCsr, zEnd, &nByte);
|
||||
#endif
|
||||
if( nByte ){
|
||||
p->pFree = sqlite3DbMallocZero(db, nByte);
|
||||
}
|
||||
zCsr = p->pFree;
|
||||
nFree = nByte;
|
||||
zEnd = &zCsr[nByte];
|
||||
}while( nByte && !db->mallocFailed );
|
||||
|
||||
p->nCursor = nCursor;
|
||||
@@ -2995,13 +3000,12 @@ int sqlite3VdbeCursorRestore(VdbeCursor *p){
|
||||
** not been deleted out from under the cursor, then this routine is a no-op.
|
||||
*/
|
||||
int sqlite3VdbeCursorMoveto(VdbeCursor *p){
|
||||
if( p->eCurType==CURTYPE_BTREE ){
|
||||
if( p->deferredMoveto ){
|
||||
return handleDeferredMoveto(p);
|
||||
}
|
||||
if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
|
||||
return handleMovedCursor(p);
|
||||
}
|
||||
assert( p->eCurType==CURTYPE_BTREE );
|
||||
if( p->deferredMoveto ){
|
||||
return handleDeferredMoveto(p);
|
||||
}
|
||||
if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
|
||||
return handleMovedCursor(p);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -3231,7 +3235,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;
|
||||
if( len>0 ) memcpy(buf, pMem->z, len);
|
||||
memcpy(buf, pMem->z, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
@@ -272,8 +272,7 @@ int sqlite3WalTrace = 0;
|
||||
|
||||
/*
|
||||
** Indices of various locking bytes. WAL_NREADER is the number
|
||||
** of available reader locks and should be at least 3. The default
|
||||
** is SQLITE_SHM_NLOCK==8 and WAL_NREADER==5.
|
||||
** of available reader locks and should be at least 3.
|
||||
*/
|
||||
#define WAL_WRITE_LOCK 0
|
||||
#define WAL_ALL_BUT_WRITE 1
|
||||
@@ -293,10 +292,7 @@ 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 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.
|
||||
** object.
|
||||
**
|
||||
** 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
|
||||
@@ -329,16 +325,6 @@ 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)
|
||||
@@ -378,9 +364,6 @@ 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
|
||||
|
||||
@@ -390,8 +373,9 @@ 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+offsetof(WalCkptInfo,aLock))
|
||||
#define WALINDEX_HDR_SIZE (sizeof(WalIndexHdr)*2+sizeof(WalCkptInfo))
|
||||
#define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2 + sizeof(WalCkptInfo))
|
||||
#define WALINDEX_LOCK_RESERVED 16
|
||||
#define WALINDEX_HDR_SIZE (WALINDEX_LOCK_OFFSET+WALINDEX_LOCK_RESERVED)
|
||||
|
||||
/* Size of header before each frame in wal */
|
||||
#define WAL_FRAME_HDRSIZE 24
|
||||
@@ -450,9 +434,6 @@ 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
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -808,9 +789,10 @@ static void walUnlockShared(Wal *pWal, int lockIdx){
|
||||
SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED);
|
||||
WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx)));
|
||||
}
|
||||
static int walLockExclusive(Wal *pWal, int lockIdx, int n){
|
||||
static int walLockExclusive(Wal *pWal, int lockIdx, int n, int fBlock){
|
||||
int rc;
|
||||
if( pWal->exclusiveMode ) return SQLITE_OK;
|
||||
if( fBlock ) sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_WAL_BLOCK, 0);
|
||||
rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
|
||||
SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
|
||||
WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
|
||||
@@ -1096,7 +1078,7 @@ static int walIndexRecover(Wal *pWal){
|
||||
assert( pWal->writeLock );
|
||||
iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
|
||||
nLock = SQLITE_SHM_NLOCK - iLock;
|
||||
rc = walLockExclusive(pWal, iLock, nLock);
|
||||
rc = walLockExclusive(pWal, iLock, nLock, 0);
|
||||
if( rc ){
|
||||
return rc;
|
||||
}
|
||||
@@ -1217,7 +1199,6 @@ 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;
|
||||
@@ -1289,11 +1270,7 @@ 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
|
||||
@@ -1639,7 +1616,7 @@ static int walBusyLock(
|
||||
){
|
||||
int rc;
|
||||
do {
|
||||
rc = walLockExclusive(pWal, lockIdx, n);
|
||||
rc = walLockExclusive(pWal, lockIdx, n, 0);
|
||||
}while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) );
|
||||
return rc;
|
||||
}
|
||||
@@ -1679,7 +1656,6 @@ 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 );
|
||||
@@ -1789,8 +1765,6 @@ 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);
|
||||
@@ -2083,7 +2057,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
|
||||
walUnlockShared(pWal, WAL_WRITE_LOCK);
|
||||
rc = SQLITE_READONLY_RECOVERY;
|
||||
}
|
||||
}else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
|
||||
}else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1, 1)) ){
|
||||
pWal->writeLock = 1;
|
||||
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
|
||||
badHdr = walIndexTryHdr(pWal, pChanged);
|
||||
@@ -2174,7 +2148,6 @@ 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 */
|
||||
|
||||
@@ -2238,12 +2211,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
}
|
||||
|
||||
pInfo = walCkptInfo(pWal);
|
||||
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
|
||||
){
|
||||
if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame ){
|
||||
/* The WAL has been completely backfilled (or it is empty).
|
||||
** and can be safely ignored.
|
||||
*/
|
||||
@@ -2281,88 +2249,85 @@ 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<=mxFrame ){
|
||||
if( mxReadMark<=thisMark && thisMark<=pWal->hdr.mxFrame ){
|
||||
assert( thisMark!=READMARK_NOT_USED );
|
||||
mxReadMark = thisMark;
|
||||
mxI = i;
|
||||
}
|
||||
}
|
||||
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;
|
||||
/* 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, 0);
|
||||
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( 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;
|
||||
}
|
||||
@@ -2385,14 +2350,6 @@ 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 );
|
||||
@@ -2400,66 +2357,6 @@ 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;
|
||||
}
|
||||
|
||||
@@ -2640,7 +2537,7 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){
|
||||
/* Only one writer allowed at a time. Get the write lock. Return
|
||||
** SQLITE_BUSY if unable.
|
||||
*/
|
||||
rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
|
||||
rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1, 0);
|
||||
if( rc ){
|
||||
return rc;
|
||||
}
|
||||
@@ -2785,7 +2682,7 @@ static int walRestartLog(Wal *pWal){
|
||||
if( pInfo->nBackfill>0 ){
|
||||
u32 salt1;
|
||||
sqlite3_randomness(4, &salt1);
|
||||
rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
|
||||
rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* If all readers are using WAL_READ_LOCK(0) (in other words if no
|
||||
** readers are currently using the WAL), then the transactions
|
||||
@@ -3110,7 +3007,7 @@ int sqlite3WalCheckpoint(
|
||||
|
||||
/* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
|
||||
** "checkpoint" lock on the database file. */
|
||||
rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
|
||||
rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1, 0);
|
||||
if( rc ){
|
||||
/* EVIDENCE-OF: R-10421-19736 If any other process is running a
|
||||
** checkpoint operation at the same time, the lock cannot be obtained and
|
||||
@@ -3269,35 +3166,6 @@ 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,11 +126,6 @@ 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).
|
||||
|
||||
+4
-10
@@ -718,7 +718,7 @@ static void constructAutomaticIndex(
|
||||
idxCols |= cMask;
|
||||
pIdx->aiColumn[n] = pTerm->u.leftColumn;
|
||||
pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
|
||||
pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
|
||||
pIdx->azColl[n] = pColl ? pColl->zName : "BINARY";
|
||||
n++;
|
||||
}
|
||||
}
|
||||
@@ -730,20 +730,20 @@ static void constructAutomaticIndex(
|
||||
for(i=0; i<mxBitCol; i++){
|
||||
if( extraCols & MASKBIT(i) ){
|
||||
pIdx->aiColumn[n] = i;
|
||||
pIdx->azColl[n] = sqlite3StrBINARY;
|
||||
pIdx->azColl[n] = "BINARY";
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if( pSrc->colUsed & MASKBIT(BMS-1) ){
|
||||
for(i=BMS-1; i<pTable->nCol; i++){
|
||||
pIdx->aiColumn[n] = i;
|
||||
pIdx->azColl[n] = sqlite3StrBINARY;
|
||||
pIdx->azColl[n] = "BINARY";
|
||||
n++;
|
||||
}
|
||||
}
|
||||
assert( n==nKeyCol );
|
||||
pIdx->aiColumn[n] = XN_ROWID;
|
||||
pIdx->azColl[n] = sqlite3StrBINARY;
|
||||
pIdx->azColl[n] = "BINARY";
|
||||
|
||||
/* Create the automatic index */
|
||||
assert( pLevel->iIdxCur>=0 );
|
||||
@@ -893,9 +893,6 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
pIdxCons[j].iTermOffset = i;
|
||||
op = (u8)pTerm->eOperator & WO_ALL;
|
||||
if( op==WO_IN ) op = WO_EQ;
|
||||
if( op==WO_MATCH ){
|
||||
op = pTerm->eMatchOp;
|
||||
}
|
||||
pIdxCons[j].op = op;
|
||||
/* The direct assignment in the previous line is possible only because
|
||||
** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
|
||||
@@ -2864,7 +2861,6 @@ static int whereLoopAddVirtual(
|
||||
pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
|
||||
pIdxInfo->estimatedRows = 25;
|
||||
pIdxInfo->idxFlags = 0;
|
||||
pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed;
|
||||
rc = vtabBestIndex(pParse, pTab, pIdxInfo);
|
||||
if( rc ) goto whereLoopAddVtab_exit;
|
||||
pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
|
||||
@@ -4492,7 +4488,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
sqlite3VdbeJumpHere(v, pLevel->addrSkip);
|
||||
sqlite3VdbeJumpHere(v, pLevel->addrSkip-2);
|
||||
}
|
||||
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
if( pLevel->addrLikeRep ){
|
||||
int op;
|
||||
if( sqlite3VdbeGetOp(v, pLevel->addrLikeRep-1)->p1 ){
|
||||
@@ -4503,7 +4498,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
sqlite3VdbeAddOp2(v, op, pLevel->iLikeRepCntr, pLevel->addrLikeRep);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
#endif
|
||||
if( pLevel->iLeftJoin ){
|
||||
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
|
||||
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
|
||||
|
||||
+1
-4
@@ -69,10 +69,8 @@ struct WhereLevel {
|
||||
int addrCont; /* Jump here to continue with the next loop cycle */
|
||||
int addrFirst; /* First instruction of interior of the loop */
|
||||
int addrBody; /* Beginning of the body of this loop */
|
||||
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
int iLikeRepCntr; /* LIKE range processing counter register */
|
||||
int addrLikeRep; /* LIKE range processing address */
|
||||
#endif
|
||||
u8 iFrom; /* Which entry in the FROM clause */
|
||||
u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
|
||||
int p1, p2; /* Operands of the opcode used to ends the loop */
|
||||
@@ -255,7 +253,6 @@ struct WhereTerm {
|
||||
u16 eOperator; /* A WO_xx value describing <op> */
|
||||
u16 wtFlags; /* TERM_xxx bit flags. See below */
|
||||
u8 nChild; /* Number of children that must disable us */
|
||||
u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
|
||||
WhereClause *pWC; /* The clause this term is part of */
|
||||
Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
|
||||
Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */
|
||||
@@ -288,7 +285,7 @@ struct WhereTerm {
|
||||
struct WhereScan {
|
||||
WhereClause *pOrigWC; /* Original, innermost WhereClause */
|
||||
WhereClause *pWC; /* WhereClause currently being scanned */
|
||||
const char *zCollName; /* Required collating sequence, if not NULL */
|
||||
char *zCollName; /* Required collating sequence, if not NULL */
|
||||
Expr *pIdxExpr; /* Search for this index expression */
|
||||
char idxaff; /* Must match this affinity, if zCollName!=NULL */
|
||||
unsigned char nEquiv; /* Number of entries in aEquiv[] */
|
||||
|
||||
@@ -561,7 +561,6 @@ static int codeAllEqualityTerms(
|
||||
return regBase;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
/*
|
||||
** If the most recently coded instruction is a constant range contraint
|
||||
** that originated from the LIKE optimization, then change the P3 to be
|
||||
@@ -573,10 +572,6 @@ static int codeAllEqualityTerms(
|
||||
** The OP_String opcodes on the second pass convert the upper and lower
|
||||
** bound string contants to blobs. This routine makes the necessary changes
|
||||
** to the OP_String opcodes for that to happen.
|
||||
**
|
||||
** Except, of course, if SQLITE_LIKE_DOESNT_MATCH_BLOBS is defined, then
|
||||
** only the one pass through the string space is required, so this routine
|
||||
** becomes a no-op.
|
||||
*/
|
||||
static void whereLikeOptimizationStringFixup(
|
||||
Vdbe *v, /* prepared statement under construction */
|
||||
@@ -594,9 +589,6 @@ static void whereLikeOptimizationStringFixup(
|
||||
pOp->p5 = 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define whereLikeOptimizationStringFixup(A,B,C)
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
/*
|
||||
@@ -1083,7 +1075,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
if( pLoop->wsFlags & WHERE_TOP_LIMIT ){
|
||||
pRangeEnd = pLoop->aLTerm[j++];
|
||||
nExtraReg = 1;
|
||||
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
if( (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0 ){
|
||||
assert( pRangeStart!=0 ); /* LIKE opt constraints */
|
||||
assert( pRangeStart->wtFlags & TERM_LIKEOPT ); /* occur in pairs */
|
||||
@@ -1096,7 +1087,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
VdbeComment((v, "LIKE loop counter"));
|
||||
pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v);
|
||||
}
|
||||
#endif
|
||||
if( pRangeStart==0
|
||||
&& (j = pIdx->aiColumn[nEq])>=0
|
||||
&& pIdx->pTable->aCol[j].notNull==0
|
||||
@@ -1600,13 +1590,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
continue;
|
||||
}
|
||||
if( pTerm->wtFlags & TERM_LIKECOND ){
|
||||
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
continue;
|
||||
#else
|
||||
assert( pLevel->iLikeRepCntr>0 );
|
||||
skipLikeAddr = sqlite3VdbeAddOp1(v, OP_IfNot, pLevel->iLikeRepCntr);
|
||||
VdbeCoverage(v);
|
||||
#endif
|
||||
}
|
||||
sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
|
||||
if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr);
|
||||
|
||||
+9
-30
@@ -277,48 +277,29 @@ static int isLikeOrGlob(
|
||||
/*
|
||||
** Check to see if the given expression is of the form
|
||||
**
|
||||
** column OP expr
|
||||
**
|
||||
** where OP is one of MATCH, GLOB, LIKE or REGEXP and "column" is a
|
||||
** column of a virtual table.
|
||||
** column MATCH expr
|
||||
**
|
||||
** If it is then return TRUE. If not, return FALSE.
|
||||
*/
|
||||
static int isMatchOfColumn(
|
||||
Expr *pExpr, /* Test this expression */
|
||||
unsigned char *peOp2 /* OUT: 0 for MATCH, or else an op2 value */
|
||||
Expr *pExpr /* Test this expression */
|
||||
){
|
||||
struct Op2 {
|
||||
const char *zOp;
|
||||
unsigned char eOp2;
|
||||
} aOp[] = {
|
||||
{ "match", SQLITE_INDEX_CONSTRAINT_MATCH },
|
||||
{ "glob", SQLITE_INDEX_CONSTRAINT_GLOB },
|
||||
{ "like", SQLITE_INDEX_CONSTRAINT_LIKE },
|
||||
{ "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP }
|
||||
};
|
||||
ExprList *pList;
|
||||
Expr *pCol; /* Column reference */
|
||||
int i;
|
||||
|
||||
if( pExpr->op!=TK_FUNCTION ){
|
||||
return 0;
|
||||
}
|
||||
if( sqlite3StrICmp(pExpr->u.zToken,"match")!=0 ){
|
||||
return 0;
|
||||
}
|
||||
pList = pExpr->x.pList;
|
||||
if( pList==0 || pList->nExpr!=2 ){
|
||||
if( pList->nExpr!=2 ){
|
||||
return 0;
|
||||
}
|
||||
pCol = pList->a[1].pExpr;
|
||||
if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){
|
||||
if( pList->a[1].pExpr->op != TK_COLUMN ){
|
||||
return 0;
|
||||
}
|
||||
for(i=0; i<ArraySize(aOp); i++){
|
||||
if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
|
||||
*peOp2 = aOp[i].eOp2;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
@@ -895,7 +876,6 @@ static void exprAnalyze(
|
||||
int op; /* Top-level operator. pExpr->op */
|
||||
Parse *pParse = pWInfo->pParse; /* Parsing context */
|
||||
sqlite3 *db = pParse->db; /* Database connection */
|
||||
unsigned char eOp2; /* op2 value for LIKE/REGEXP/GLOB */
|
||||
|
||||
if( db->mallocFailed ){
|
||||
return;
|
||||
@@ -1119,7 +1099,7 @@ static void exprAnalyze(
|
||||
** virtual tables. The native query optimizer does not attempt
|
||||
** to do anything with MATCH functions.
|
||||
*/
|
||||
if( isMatchOfColumn(pExpr, &eOp2) ){
|
||||
if( isMatchOfColumn(pExpr) ){
|
||||
int idxNew;
|
||||
Expr *pRight, *pLeft;
|
||||
WhereTerm *pNewTerm;
|
||||
@@ -1140,7 +1120,6 @@ static void exprAnalyze(
|
||||
pNewTerm->leftCursor = pLeft->iTable;
|
||||
pNewTerm->u.leftColumn = pLeft->iColumn;
|
||||
pNewTerm->eOperator = WO_MATCH;
|
||||
pNewTerm->eMatchOp = eOp2;
|
||||
markTermAsChild(pWC, idxNew, idxTerm);
|
||||
pTerm = &pWC->a[idxTerm];
|
||||
pTerm->wtFlags |= TERM_COPIED;
|
||||
|
||||
+6
-14
@@ -283,17 +283,9 @@ do_eqp_test analyze3-2.3 {
|
||||
SELECT count(a) FROM t1 WHERE b LIKE '%a'
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
|
||||
# Return the first argument if like_match_blobs is true (the default)
|
||||
# or the second argument if not
|
||||
#
|
||||
proc ilmb {a b} {
|
||||
ifcapable like_match_blobs {return $a}
|
||||
return $b
|
||||
}
|
||||
|
||||
do_test analyze3-2.4 {
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE 'a%' }
|
||||
} [list [ilmb 102 101] 0 100]
|
||||
} {102 0 100}
|
||||
do_test analyze3-2.5 {
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE '%a' }
|
||||
} {999 999 100}
|
||||
@@ -301,7 +293,7 @@ do_test analyze3-2.5 {
|
||||
do_test analyze3-2.6 {
|
||||
set like "a%"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} [list [ilmb 102 101] 0 100]
|
||||
} {102 0 100}
|
||||
do_test analyze3-2.7 {
|
||||
set like "%a"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
@@ -309,19 +301,19 @@ do_test analyze3-2.7 {
|
||||
do_test analyze3-2.8 {
|
||||
set like "a"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} [list [ilmb 102 101] 0 0]
|
||||
} {102 0 0}
|
||||
do_test analyze3-2.9 {
|
||||
set like "ab"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} [list [ilmb 12 11] 0 0]
|
||||
} {12 0 0}
|
||||
do_test analyze3-2.10 {
|
||||
set like "abc"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} [list [ilmb 3 2] 0 1]
|
||||
} {3 0 1}
|
||||
do_test analyze3-2.11 {
|
||||
set like "a_c"
|
||||
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
|
||||
} [list [ilmb 102 101] 0 10]
|
||||
} {102 0 10}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix capi3c
|
||||
|
||||
# Do not use a codec for tests in this file, as the database file is
|
||||
# manipulated directly using tcl scripts (using the [hexio_write] command).
|
||||
@@ -1376,26 +1375,4 @@ do_test capi3c-24.3 {
|
||||
decltype {SELECT (SELECT x FROM (SELECT t5.a AS x)) FROM t5}
|
||||
} {INTEGER}
|
||||
|
||||
|
||||
# Further tests of sqlite3_column_decltype():
|
||||
#
|
||||
do_execsql_test 25.0 {
|
||||
CREATE TABLE t11(a VARCHAR(10), b INTEGER);
|
||||
CREATE TABLE t12(a VARCHAR(15), b FLOAT);
|
||||
}
|
||||
|
||||
foreach {tn sql} {
|
||||
1 "SELECT * FROM t11 UNION ALL SELECT * FROM t12"
|
||||
2 "SELECT * FROM t11 UNION SELECT * FROM t12"
|
||||
3 "SELECT * FROM t11 EXCEPT SELECT * FROM t12"
|
||||
4 "SELECT * FROM t11 INTERSECT SELECT * FROM t12"
|
||||
|
||||
5 "SELECT * FROM t11 UNION ALL SELECT * FROM t12 ORDER BY 1"
|
||||
6 "SELECT * FROM t11 UNION SELECT * FROM t12 ORDER BY 1"
|
||||
7 "SELECT * FROM t11 EXCEPT SELECT * FROM t12 ORDER BY 1"
|
||||
8 "SELECT * FROM t11 INTERSECT SELECT * FROM t12 ORDER BY 1"
|
||||
} {
|
||||
do_test 25.$tn { decltype $sql } {VARCHAR(10) INTEGER}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -336,15 +336,6 @@ if {$tzoffset_new==4} {
|
||||
datetest 6.8.1 {datetime('2006-04-02 02:00:00','utc')} {2006-04-02 06:00:00}
|
||||
datetest 6.8.2 {datetime('2007-03-11 02:00:00','utc')} {2007-03-11 06:00:00}
|
||||
|
||||
# The 'utc' modifier is a no-op if the LHS is known to already be in UTC
|
||||
datetest 6.9.1 {datetime('2015-12-23 12:00:00','utc')} {2015-12-23 17:00:00}
|
||||
datetest 6.9.2 {datetime('2015-12-23 12:00:00z','utc')} {2015-12-23 12:00:00}
|
||||
datetest 6.9.3 {datetime('2015-12-23 12:00:00-03:00','utc')} \
|
||||
{2015-12-23 15:00:00}
|
||||
datetest 6.9.4 {datetime('2015-12-23 12:00:00','utc','utc','utc')} \
|
||||
{2015-12-23 17:00:00}
|
||||
|
||||
|
||||
datetest 6.10 {datetime('2000-01-01 12:00:00','localtime')} \
|
||||
{2000-01-01 07:00:00}
|
||||
datetest 6.11 {datetime('1969-01-01 12:00:00','localtime')} \
|
||||
|
||||
@@ -252,21 +252,4 @@ do_execsql_test 5.6 {
|
||||
SELECT DISTINCT x FROM t1 ORDER BY x;
|
||||
} {1 2 3 4 5 6}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# 2015-11-23. Problem discovered by Kostya Serebryany using libFuzzer
|
||||
#
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
do_execsql_test 6.1 {
|
||||
CREATE TABLE jjj(x);
|
||||
SELECT (SELECT 'mmm' UNION SELECT DISTINCT max(name) ORDER BY 1)
|
||||
FROM sqlite_master;
|
||||
} {jjj}
|
||||
do_execsql_test 6.2 {
|
||||
CREATE TABLE nnn(x);
|
||||
SELECT (SELECT 'mmm' UNION SELECT DISTINCT max(name) ORDER BY 1)
|
||||
FROM sqlite_master;
|
||||
} {mmm}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+2
-3
@@ -62,7 +62,7 @@ ifcapable {bloblit && utf16} {
|
||||
execsql {
|
||||
CREATE TABLE t2(a);
|
||||
INSERT INTO t2 VALUES(x'61006200630064006500');
|
||||
SELECT CAST(a AS text) FROM t2 WHERE CAST(a AS text) LIKE 'abc%';
|
||||
SELECT CAST(a AS text) FROM t2 WHERE a LIKE 'abc%';
|
||||
}
|
||||
} {abcde}
|
||||
do_test enc3-2.3 {
|
||||
@@ -72,8 +72,7 @@ ifcapable {bloblit && utf16} {
|
||||
} {abcde}
|
||||
do_test enc3-2.4 {
|
||||
execsql {
|
||||
SELECT rowid FROM t2
|
||||
WHERE CAST(a AS text) LIKE CAST(x'610062002500' AS text);
|
||||
SELECT rowid FROM t2 WHERE a LIKE x'610062002500';
|
||||
}
|
||||
} {1}
|
||||
}
|
||||
|
||||
@@ -587,7 +587,7 @@ do_execsql_test 10.1 {
|
||||
INSERT INTO idx VALUES (3, 't3.txt');
|
||||
|
||||
CREATE VIRTUAL TABLE vt USING fs(idx);
|
||||
SELECT path, data FROM vt;
|
||||
SELECT * FROM vt;
|
||||
} {
|
||||
1 {a b c d e f g h i j k l m n o p q r s t u v w x y z}
|
||||
2 {a b c d e f g h i j k l m a b c d e f g h i j k l m}
|
||||
@@ -595,7 +595,7 @@ do_execsql_test 10.1 {
|
||||
}
|
||||
|
||||
do_execsql_test 10.2 {
|
||||
SELECT path, data FROM vt WHERE rowid = 2;
|
||||
SELECT * FROM vt WHERE rowid = 2;
|
||||
} {
|
||||
2 {a b c d e f g h i j k l m a b c d e f g h i j k l m}
|
||||
}
|
||||
|
||||
+8
-2
@@ -588,13 +588,18 @@ static int inmemFullPathname(
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* GetLastError() is never used */
|
||||
static int inmemGetLastError(sqlite3_vfs *pVfs, int n, char *z){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Register the VFS that reads from the g.aFile[] set of files.
|
||||
*/
|
||||
static void inmemVfsRegister(void){
|
||||
static sqlite3_vfs inmemVfs;
|
||||
sqlite3_vfs *pDefault = sqlite3_vfs_find(0);
|
||||
inmemVfs.iVersion = 3;
|
||||
inmemVfs.iVersion = 1;
|
||||
inmemVfs.szOsFile = sizeof(VHandle);
|
||||
inmemVfs.mxPathname = 200;
|
||||
inmemVfs.zName = "inmem";
|
||||
@@ -604,7 +609,8 @@ static void inmemVfsRegister(void){
|
||||
inmemVfs.xFullPathname = inmemFullPathname;
|
||||
inmemVfs.xRandomness = pDefault->xRandomness;
|
||||
inmemVfs.xSleep = pDefault->xSleep;
|
||||
inmemVfs.xCurrentTimeInt64 = pDefault->xCurrentTimeInt64;
|
||||
inmemVfs.xCurrentTime = pDefault->xCurrentTime;
|
||||
inmemVfs.xGetLastError = inmemGetLastError;
|
||||
sqlite3_vfs_register(&inmemVfs, 0);
|
||||
};
|
||||
|
||||
|
||||
@@ -109,9 +109,6 @@ do_execsql_test hexlit-301 {
|
||||
do_catchsql_test hexlist-400 {
|
||||
SELECT 0x10000000000000000;
|
||||
} {1 {hex literal too big: 0x10000000000000000}}
|
||||
do_catchsql_test hexlist-401 {
|
||||
SELECT DISTINCT 0x10000000000000000;
|
||||
} {1 {hex literal too big: 0x10000000000000000}}
|
||||
do_catchsql_test hexlist-410 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(x);
|
||||
|
||||
@@ -307,21 +307,5 @@ do_catchsql_test indexexpr1-910 {
|
||||
INSERT INTO t9(a,b,c,d) VALUES(5,6,7,-8);
|
||||
} {1 {UNIQUE constraint failed: index 't9x1'}}
|
||||
|
||||
# Test cases derived from a NEVER() maro failure discovered by
|
||||
# Jonathan Metzman using AFL
|
||||
#
|
||||
do_execsql_test indexexpr1-1000 {
|
||||
DROP TABLE IF EXISTS t0;
|
||||
CREATE TABLE t0(a,b,t);
|
||||
CREATE INDEX i ON t0(a in(0,1));
|
||||
INSERT INTO t0 VALUES(0,1,2),(2,3,4),(5,6,7);
|
||||
UPDATE t0 SET b=99 WHERE (a in(0,1))=0;
|
||||
SELECT *, '|' FROM t0 ORDER BY +a;
|
||||
} {0 1 2 | 2 99 4 | 5 99 7 |}
|
||||
do_execsql_test indexexpr1-1010 {
|
||||
UPDATE t0 SET b=88 WHERE (a in(0,1))=1;
|
||||
SELECT *, '|' FROM t0 ORDER BY +a;
|
||||
} {0 88 2 | 2 99 4 | 5 99 7 |}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
# 2015-12-30
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements tests for JSON aggregate SQL functions
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !json1 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test json103-100 {
|
||||
CREATE TABLE t1(a,b,c);
|
||||
WITH RECURSIVE c(x) AS (VALUES(1) UNION SELECT x+1 FROM c WHERE x<100)
|
||||
INSERT INTO t1(a,b,c) SELECT x, x%3, printf('n%d',x) FROM c;
|
||||
UPDATE t1 SET a='orange' WHERE rowid=39;
|
||||
UPDATE t1 SET a=32.5 WHERE rowid=31;
|
||||
UPDATE t1 SET a=x'303132' WHERE rowid=29;
|
||||
UPDATE t1 SET a=NULL WHERE rowid=37;
|
||||
SELECT json_group_array(a) FROM t1 WHERE a<0 AND typeof(a)!='blob';
|
||||
} {{[]}}
|
||||
do_catchsql_test json103-101 {
|
||||
SELECT json_group_array(a) FROM t1;
|
||||
} {1 {JSON cannot hold BLOB values}}
|
||||
do_execsql_test json103-110 {
|
||||
SELECT json_group_array(a) FROM t1
|
||||
WHERE rowid BETWEEN 31 AND 39;
|
||||
} {{[32.5,32,33,34,35,36,null,38,"orange"]}}
|
||||
do_execsql_test json103-111 {
|
||||
SELECT json_array_length(json_group_array(a)) FROM t1
|
||||
WHERE rowid BETWEEN 31 AND 39;
|
||||
} {9}
|
||||
do_execsql_test json103-120 {
|
||||
SELECT b, json_group_array(a) FROM t1 WHERE rowid<10 GROUP BY b ORDER BY b;
|
||||
} {0 {[3,6,9]} 1 {[1,4,7]} 2 {[2,5,8]}}
|
||||
|
||||
do_execsql_test json103-200 {
|
||||
SELECT json_group_object(c,a) FROM t1 WHERE a<0 AND typeof(a)!='blob';
|
||||
} {{{}}}
|
||||
do_catchsql_test json103-201 {
|
||||
SELECT json_group_object(c,a) FROM t1;
|
||||
} {1 {JSON cannot hold BLOB values}}
|
||||
|
||||
do_execsql_test json103-210 {
|
||||
SELECT json_group_object(c,a) FROM t1
|
||||
WHERE rowid BETWEEN 31 AND 39 AND rowid%2==1;
|
||||
} {{{"n31":32.5,"n33":33,"n35":35,"n37":null,"n39":"orange"}}}
|
||||
do_execsql_test json103-220 {
|
||||
SELECT b, json_group_object(c,a) FROM t1
|
||||
WHERE rowid<7 GROUP BY b ORDER BY b;
|
||||
} {0 {{"n3":3,"n6":6}} 1 {{"n1":1,"n4":4}} 2 {{"n2":2,"n5":5}}}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
+10
-26
@@ -745,19 +745,11 @@ ifcapable like_opt&&!icu {
|
||||
SELECT a FROM t10 WHERE e LIKE '12%' ORDER BY +a;
|
||||
}
|
||||
} {12 123 scan 5 like 6}
|
||||
ifcapable like_match_blobs {
|
||||
do_test like-10.5a {
|
||||
count {
|
||||
SELECT a FROM t10 WHERE f LIKE '12%' ORDER BY +a;
|
||||
}
|
||||
} {12 123 scan 4 like 0}
|
||||
} else {
|
||||
do_test like-10.5b {
|
||||
count {
|
||||
SELECT a FROM t10 WHERE f LIKE '12%' ORDER BY +a;
|
||||
}
|
||||
} {12 123 scan 3 like 0}
|
||||
}
|
||||
do_test like-10.5 {
|
||||
count {
|
||||
SELECT a FROM t10 WHERE f LIKE '12%' ORDER BY +a;
|
||||
}
|
||||
} {12 123 scan 4 like 0}
|
||||
do_test like-10.6 {
|
||||
count {
|
||||
SELECT a FROM t10 WHERE a LIKE '12%' ORDER BY +a;
|
||||
@@ -794,19 +786,11 @@ ifcapable like_opt&&!icu {
|
||||
SELECT a FROM t10b WHERE e GLOB '12*' ORDER BY +a;
|
||||
}
|
||||
} {12 123 scan 5 like 6}
|
||||
ifcapable like_match_blobs {
|
||||
do_test like-10.14 {
|
||||
count {
|
||||
SELECT a FROM t10b WHERE f GLOB '12*' ORDER BY +a;
|
||||
}
|
||||
} {12 123 scan 4 like 0}
|
||||
} else {
|
||||
do_test like-10.14 {
|
||||
count {
|
||||
SELECT a FROM t10b WHERE f GLOB '12*' ORDER BY +a;
|
||||
}
|
||||
} {12 123 scan 3 like 0}
|
||||
}
|
||||
do_test like-10.14 {
|
||||
count {
|
||||
SELECT a FROM t10b WHERE f GLOB '12*' ORDER BY +a;
|
||||
}
|
||||
} {12 123 scan 4 like 0}
|
||||
do_test like-10.15 {
|
||||
count {
|
||||
SELECT a FROM t10b WHERE a GLOB '12*' ORDER BY +a;
|
||||
|
||||
+2
-5
@@ -29,11 +29,6 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !like_match_blobs {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test like3-1.1 {
|
||||
PRAGMA encoding=UTF8;
|
||||
CREATE TABLE t1(a,b TEXT COLLATE nocase);
|
||||
@@ -112,4 +107,6 @@ do_execsql_test like3-4.2ck {
|
||||
SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY +x ASC;
|
||||
} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+2
-7
@@ -125,8 +125,8 @@ ifcapable attach {
|
||||
|
||||
# Default setting of PRAGMA cache_spill is always ON
|
||||
#
|
||||
# EVIDENCE-OF: R-63549-59887 PRAGMA cache_spill; PRAGMA
|
||||
# cache_spill=boolean; PRAGMA schema.cache_spill=N;
|
||||
# EVIDENCE-OF: R-51036-62828 PRAGMA cache_spill; PRAGMA
|
||||
# cache_spill=boolean;
|
||||
#
|
||||
# EVIDENCE-OF: R-23955-02765 Cache_spill is enabled by default
|
||||
#
|
||||
@@ -190,11 +190,6 @@ 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;
|
||||
|
||||
@@ -1,340 +0,0 @@
|
||||
# 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
|
||||
@@ -1,164 +0,0 @@
|
||||
# 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
|
||||
@@ -1,43 +0,0 @@
|
||||
# 2015-12-17
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix spellfix3
|
||||
|
||||
ifcapable !vtab { finish_test ; return }
|
||||
|
||||
load_static_extension db spellfix
|
||||
|
||||
do_execsql_test 100 {
|
||||
SELECT spellfix1_scriptcode('And God said, “Let there be light”');
|
||||
} {215}
|
||||
do_execsql_test 110 {
|
||||
SELECT spellfix1_scriptcode('Бог сказал: "Да будет свет"');
|
||||
} {220}
|
||||
do_execsql_test 120 {
|
||||
SELECT spellfix1_scriptcode('και ειπεν ο θεος γενηθητω φως και εγενετο φως');
|
||||
} {200}
|
||||
do_execsql_test 130 {
|
||||
SELECT spellfix1_scriptcode('וַיֹּ֥אמֶר אֱלֹהִ֖ים יְהִ֣י א֑וֹר וַֽיְהִי־אֽוֹר׃');
|
||||
} {125}
|
||||
do_execsql_test 140 {
|
||||
SELECT spellfix1_scriptcode('فِي ذَلِكَ الوَقتِ، قالَ اللهُ: لِيَكُنْ نُورٌ. فَصَارَ نُورٌ.');
|
||||
} {160}
|
||||
do_execsql_test 200 {
|
||||
SELECT spellfix1_scriptcode('+3.14159');
|
||||
} {999}
|
||||
do_execsql_test 210 {
|
||||
SELECT spellfix1_scriptcode('And God said: "Да будет свет"');
|
||||
} {998}
|
||||
|
||||
finish_test
|
||||
@@ -874,17 +874,6 @@ do_test sqllimits1-16.2 {
|
||||
}
|
||||
} {1 {string or blob too big}}
|
||||
|
||||
do_catchsql_test sqllimits1.17.0 {
|
||||
SELECT *,*,*,*,*,*,*,* FROM (
|
||||
SELECT *,*,*,*,*,*,*,* FROM (
|
||||
SELECT *,*,*,*,*,*,*,* FROM (
|
||||
SELECT *,*,*,*,*,*,*,* FROM (
|
||||
SELECT *,*,*,*,*,*,*,* FROM (
|
||||
SELECT 1,2,3,4,5,6,7,8,9,10
|
||||
)
|
||||
))))
|
||||
} "1 {too many columns in result set}"
|
||||
|
||||
|
||||
foreach {key value} [array get saved] {
|
||||
catch {set $key $value}
|
||||
|
||||
@@ -116,14 +116,4 @@ do_execsql_test 2.5 {
|
||||
SELECT * FROM t1;
|
||||
} {1 2}
|
||||
|
||||
# Try to open a ridiculously long pathname. Bug found by
|
||||
# Kostya Serebryany using libFuzzer on 2015-11-30.
|
||||
#
|
||||
do_test 3.1 {
|
||||
db close
|
||||
catch {sqlite3 db [string repeat [string repeat x 100]/ 6]} res
|
||||
set res
|
||||
} {unable to open database file}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ foreach s {
|
||||
open close access getcwd stat fstat ftruncate
|
||||
fcntl read pread write pwrite fchmod fallocate
|
||||
pread64 pwrite64 unlink openDirectory mkdir rmdir
|
||||
statvfs fchown geteuid umask mmap munmap mremap
|
||||
statvfs fchown umask mmap munmap mremap
|
||||
getpagesize readlink
|
||||
} {
|
||||
if {[test_syscall exists $s]} {lappend syscall_list $s}
|
||||
|
||||
@@ -226,7 +226,6 @@ 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;
|
||||
|
||||
+20
-50
@@ -88,13 +88,6 @@
|
||||
#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
|
||||
@@ -875,28 +868,22 @@ static void filecopy_x(
|
||||
** Used by setstoptime() and timetostop().
|
||||
*/
|
||||
static double timelimit = 0.0;
|
||||
|
||||
static double currentTime(void){
|
||||
double t;
|
||||
static sqlite3_vfs *pTimelimitVfs = 0;
|
||||
if( pTimelimitVfs==0 ) pTimelimitVfs = sqlite3_vfs_find(0);
|
||||
if( pTimelimitVfs->iVersion>=1 && pTimelimitVfs->xCurrentTimeInt64!=0 ){
|
||||
sqlite3_int64 tm;
|
||||
pTimelimitVfs->xCurrentTimeInt64(pTimelimitVfs, &tm);
|
||||
t = tm/86400000.0;
|
||||
}else{
|
||||
pTimelimitVfs->xCurrentTime(pTimelimitVfs, &t);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
static sqlite3_vfs *pTimelimitVfs = 0;
|
||||
|
||||
static void setstoptime_x(
|
||||
Error *pErr, /* IN/OUT: Error code */
|
||||
int nMs /* Milliseconds until "stop time" */
|
||||
){
|
||||
if( pErr->rc==SQLITE_OK ){
|
||||
double t = currentTime();
|
||||
timelimit = t + ((double)nMs)/(1000.0*60.0*60.0*24.0);
|
||||
double t;
|
||||
int rc;
|
||||
pTimelimitVfs = sqlite3_vfs_find(0);
|
||||
rc = pTimelimitVfs->xCurrentTime(pTimelimitVfs, &t);
|
||||
if( rc!=SQLITE_OK ){
|
||||
pErr->rc = rc;
|
||||
}else{
|
||||
timelimit = t + ((double)nMs)/(1000.0*60.0*60.0*24.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -905,8 +892,14 @@ static int timetostop_x(
|
||||
){
|
||||
int ret = 1;
|
||||
if( pErr->rc==SQLITE_OK ){
|
||||
double t = currentTime();
|
||||
ret = (t >= timelimit);
|
||||
double t;
|
||||
int rc;
|
||||
rc = pTimelimitVfs->xCurrentTime(pTimelimitVfs, &t);
|
||||
if( rc!=SQLITE_OK ){
|
||||
pErr->rc = rc;
|
||||
}else{
|
||||
ret = (t >= timelimit);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1467,36 +1460,13 @@ 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(zArg, aTest[i].zTest)==0 ) break;
|
||||
if( sqlite3_strglob(argv[iArg],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 ){
|
||||
@@ -1513,7 +1483,7 @@ int main(int argc, char **argv){
|
||||
return (nGlobalErr>0 ? 255 : 0);
|
||||
|
||||
usage:
|
||||
printf("Usage: %s [-multiplexor] [testname|testprefix*]...\n", argv[0]);
|
||||
printf("Usage: %s [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);
|
||||
|
||||
+5
-5
@@ -32,8 +32,8 @@ do_test tkt3871-1.3 {
|
||||
execsql { SELECT * FROM e WHERE a = 1 OR a = 2 }
|
||||
set echo_module
|
||||
} [list \
|
||||
xFilter {SELECT rowid, a, b FROM 't1' WHERE a = ?} 1 \
|
||||
xFilter {SELECT rowid, a, b FROM 't1' WHERE a = ?} 2 \
|
||||
xFilter {SELECT rowid, * FROM 't1' WHERE a = ?} 1 \
|
||||
xFilter {SELECT rowid, * FROM 't1' WHERE a = ?} 2 \
|
||||
]
|
||||
|
||||
do_test tkt3871-1.4 {
|
||||
@@ -44,9 +44,9 @@ do_test tkt3871-1.5 {
|
||||
execsql { SELECT * FROM e WHERE a = 1 OR a = 2 OR b = 9 }
|
||||
set echo_module
|
||||
} [list \
|
||||
xFilter {SELECT rowid, a, b FROM 't1' WHERE a = ?} 1 \
|
||||
xFilter {SELECT rowid, a, b FROM 't1' WHERE a = ?} 2 \
|
||||
xFilter {SELECT rowid, a, b FROM 't1' WHERE b = ?} 9
|
||||
xFilter {SELECT rowid, * FROM 't1' WHERE a = ?} 1 \
|
||||
xFilter {SELECT rowid, * FROM 't1' WHERE a = ?} 2 \
|
||||
xFilter {SELECT rowid, * FROM 't1' WHERE b = ?} 9
|
||||
]
|
||||
|
||||
|
||||
|
||||
+41
-45
@@ -393,7 +393,7 @@ do_test vtab1-3.7 {
|
||||
SELECT rowid, * FROM t1;
|
||||
}
|
||||
} {1 1 2 3 2 4 5 6}
|
||||
do_test vtab1-3.8.1 {
|
||||
do_test vtab1-3.8 {
|
||||
execsql {
|
||||
SELECT a AS d, b AS e, c AS f FROM t1;
|
||||
}
|
||||
@@ -404,14 +404,14 @@ do_test vtab1-3.8.1 {
|
||||
# in test8.c) to make sure the xBestIndex() and xFilter() methods were
|
||||
# called correctly.
|
||||
#
|
||||
do_test vtab1-3.8.2 {
|
||||
do_test vtab1-3.8 {
|
||||
set echo_module ""
|
||||
execsql {
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
set echo_module
|
||||
} [list xBestIndex {SELECT rowid, a, b, c FROM 'treal'} \
|
||||
xFilter {SELECT rowid, a, b, c FROM 'treal'} ]
|
||||
} [list xBestIndex {SELECT rowid, * FROM 'treal'} \
|
||||
xFilter {SELECT rowid, * FROM 'treal'} ]
|
||||
do_test vtab1-3.9 {
|
||||
set echo_module ""
|
||||
execsql {
|
||||
@@ -420,8 +420,8 @@ do_test vtab1-3.9 {
|
||||
} {4 5 6}
|
||||
do_test vtab1-3.10 {
|
||||
set echo_module
|
||||
} [list xBestIndex {SELECT rowid, a, b, c FROM 'treal' WHERE b = ?} \
|
||||
xFilter {SELECT rowid, a, b, c FROM 'treal' WHERE b = ?} 5 ]
|
||||
} [list xBestIndex {SELECT rowid, * FROM 'treal' WHERE b = ?} \
|
||||
xFilter {SELECT rowid, * FROM 'treal' WHERE b = ?} 5 ]
|
||||
do_test vtab1-3.10 {
|
||||
set echo_module ""
|
||||
execsql {
|
||||
@@ -430,9 +430,8 @@ do_test vtab1-3.10 {
|
||||
} {4 5 6}
|
||||
do_test vtab1-3.11 {
|
||||
set echo_module
|
||||
} [list xBestIndex {SELECT rowid, a, b, c FROM 'treal' WHERE b >= ? AND b <= ?}\
|
||||
xFilter {SELECT rowid, a, b, c FROM 'treal' WHERE b >= ? AND b <= ?}\
|
||||
5 10 ]
|
||||
} [list xBestIndex {SELECT rowid, * FROM 'treal' WHERE b >= ? AND b <= ?} \
|
||||
xFilter {SELECT rowid, * FROM 'treal' WHERE b >= ? AND b <= ?} 5 10 ]
|
||||
do_test vtab1-3.12 {
|
||||
set echo_module ""
|
||||
execsql {
|
||||
@@ -441,9 +440,8 @@ do_test vtab1-3.12 {
|
||||
} {1 2 3 4 5 6}
|
||||
do_test vtab1-3.13 {
|
||||
set echo_module
|
||||
} [list xBestIndex {SELECT rowid, a, b, c FROM 'treal' WHERE b >= ? AND b <= ?}\
|
||||
xFilter {SELECT rowid, a, b, c FROM 'treal' WHERE b >= ? AND b <= ?}\
|
||||
2 10 ]
|
||||
} [list xBestIndex {SELECT rowid, * FROM 'treal' WHERE b >= ? AND b <= ?} \
|
||||
xFilter {SELECT rowid, * FROM 'treal' WHERE b >= ? AND b <= ?} 2 10 ]
|
||||
|
||||
# Add a function for the MATCH operator. Everything always matches!
|
||||
#proc test_match {lhs rhs} {
|
||||
@@ -461,8 +459,8 @@ do_test vtab1-3.12 {
|
||||
} {1 {unable to use function MATCH in the requested context}}
|
||||
do_test vtab1-3.13 {
|
||||
set echo_module
|
||||
} [list xBestIndex {SELECT rowid, a, b, c FROM 'treal'} \
|
||||
xFilter {SELECT rowid, a, b, c FROM 'treal'}]
|
||||
} [list xBestIndex {SELECT rowid, * FROM 'treal'} \
|
||||
xFilter {SELECT rowid, * FROM 'treal'}]
|
||||
ifcapable subquery {
|
||||
# The echo module uses a subquery internally to implement the MATCH operator.
|
||||
do_test vtab1-3.14 {
|
||||
@@ -474,9 +472,9 @@ do_test vtab1-3.14 {
|
||||
do_test vtab1-3.15 {
|
||||
set echo_module
|
||||
} [list xBestIndex \
|
||||
{SELECT rowid, a, b, c FROM 'treal' WHERE b LIKE (SELECT '%'||?||'%')} \
|
||||
{SELECT rowid, * FROM 'treal' WHERE b LIKE (SELECT '%'||?||'%')} \
|
||||
xFilter \
|
||||
{SELECT rowid, a, b, c FROM 'treal' WHERE b LIKE (SELECT '%'||?||'%')} \
|
||||
{SELECT rowid, * FROM 'treal' WHERE b LIKE (SELECT '%'||?||'%')} \
|
||||
string ]
|
||||
}; #ifcapable subquery
|
||||
|
||||
@@ -507,8 +505,8 @@ do_test vtab1-4.1 {
|
||||
} {2 5 nosort}
|
||||
do_test vtab1-4.2 {
|
||||
set echo_module
|
||||
} [list xBestIndex {SELECT rowid, NULL, b, NULL FROM 'treal' ORDER BY b ASC} \
|
||||
xFilter {SELECT rowid, NULL, b, NULL FROM 'treal' ORDER BY b ASC} ]
|
||||
} [list xBestIndex {SELECT rowid, * FROM 'treal' ORDER BY b ASC} \
|
||||
xFilter {SELECT rowid, * FROM 'treal' ORDER BY b ASC} ]
|
||||
do_test vtab1-4.3 {
|
||||
set echo_module ""
|
||||
cksort {
|
||||
@@ -517,8 +515,8 @@ do_test vtab1-4.3 {
|
||||
} {5 2 nosort}
|
||||
do_test vtab1-4.4 {
|
||||
set echo_module
|
||||
} [list xBestIndex {SELECT rowid, NULL, b, NULL FROM 'treal' ORDER BY b DESC} \
|
||||
xFilter {SELECT rowid, NULL, b, NULL FROM 'treal' ORDER BY b DESC} ]
|
||||
} [list xBestIndex {SELECT rowid, * FROM 'treal' ORDER BY b DESC} \
|
||||
xFilter {SELECT rowid, * FROM 'treal' ORDER BY b DESC} ]
|
||||
do_test vtab1-4.3 {
|
||||
set echo_module ""
|
||||
cksort {
|
||||
@@ -527,8 +525,8 @@ do_test vtab1-4.3 {
|
||||
} {2 5 sort}
|
||||
do_test vtab1-4.4 {
|
||||
set echo_module
|
||||
} [list xBestIndex {SELECT rowid, NULL, b, NULL FROM 'treal'} \
|
||||
xFilter {SELECT rowid, NULL, b, NULL FROM 'treal'} ]
|
||||
} [list xBestIndex {SELECT rowid, * FROM 'treal'} \
|
||||
xFilter {SELECT rowid, * FROM 'treal'} ]
|
||||
|
||||
execsql {
|
||||
DROP TABLE t1;
|
||||
@@ -577,9 +575,9 @@ do_test vtab1-5-2 {
|
||||
do_test vtab1-5-3 {
|
||||
filter $echo_module
|
||||
} [list \
|
||||
xFilter {SELECT rowid, a, b, c FROM 't1'} \
|
||||
xFilter {SELECT rowid, d, e, f FROM 't2'} \
|
||||
xFilter {SELECT rowid, d, e, f FROM 't2'} \
|
||||
xFilter {SELECT rowid, * FROM 't1'} \
|
||||
xFilter {SELECT rowid, * FROM 't2'} \
|
||||
xFilter {SELECT rowid, * FROM 't2'} \
|
||||
]
|
||||
do_test vtab1-5-4 {
|
||||
set echo_module ""
|
||||
@@ -593,9 +591,9 @@ do_test vtab1-5-4 {
|
||||
do_test vtab1-5-5 {
|
||||
filter $echo_module
|
||||
} [list \
|
||||
xFilter {SELECT rowid, a, b, c FROM 't1'} \
|
||||
xFilter {SELECT rowid, d, e, f FROM 't2'} \
|
||||
xFilter {SELECT rowid, d, e, f FROM 't2'} \
|
||||
xFilter {SELECT rowid, * FROM 't1'} \
|
||||
xFilter {SELECT rowid, * FROM 't2'} \
|
||||
xFilter {SELECT rowid, * FROM 't2'} \
|
||||
]
|
||||
do_test vtab1-5-6 {
|
||||
execsql {
|
||||
@@ -617,9 +615,9 @@ do_test vtab1-5-6 {
|
||||
do_test vtab1-5-7 {
|
||||
filter $::echo_module
|
||||
} [list \
|
||||
xFilter {SELECT rowid, a, b, c FROM 't1'} \
|
||||
xFilter {SELECT rowid, d, e, f FROM 't2' WHERE d = ?} \
|
||||
xFilter {SELECT rowid, d, e, f FROM 't2' WHERE d = ?} \
|
||||
xFilter {SELECT rowid, * FROM 't1'} \
|
||||
xFilter {SELECT rowid, * FROM 't2' WHERE d = ?} \
|
||||
xFilter {SELECT rowid, * FROM 't2' WHERE d = ?} \
|
||||
]
|
||||
|
||||
execsql {
|
||||
@@ -969,8 +967,8 @@ do_test vtab1.10-5 {
|
||||
}
|
||||
set echo_module
|
||||
} [list \
|
||||
xBestIndex {SELECT rowid, a, b, c FROM 'r'} \
|
||||
xFilter {SELECT rowid, a, b, c FROM 'r'} \
|
||||
xBestIndex {SELECT rowid, * FROM 'r'} \
|
||||
xFilter {SELECT rowid, * FROM 'r'} \
|
||||
]
|
||||
proc match_func {args} {return ""}
|
||||
do_test vtab1.10-6 {
|
||||
@@ -981,8 +979,8 @@ do_test vtab1.10-6 {
|
||||
}
|
||||
set echo_module
|
||||
} [list \
|
||||
xBestIndex {SELECT rowid, a, b, c FROM 'r'} \
|
||||
xFilter {SELECT rowid, a, b, c FROM 'r'} \
|
||||
xBestIndex {SELECT rowid, * FROM 'r'} \
|
||||
xFilter {SELECT rowid, * FROM 'r'} \
|
||||
]
|
||||
|
||||
|
||||
@@ -1155,15 +1153,13 @@ do_test vtab1-14.2 {
|
||||
set echo_module ""
|
||||
execsql { SELECT * FROM echo_c WHERE rowid = 1 }
|
||||
set echo_module
|
||||
} [list xBestIndex {SELECT rowid, a, b, c FROM 'c' WHERE rowid = ?} \
|
||||
xFilter {SELECT rowid, a, b, c FROM 'c' WHERE rowid = ?} 1]
|
||||
} [list xBestIndex {SELECT rowid, * FROM 'c' WHERE rowid = ?} xFilter {SELECT rowid, * FROM 'c' WHERE rowid = ?} 1]
|
||||
|
||||
do_test vtab1-14.3 {
|
||||
set echo_module ""
|
||||
execsql { SELECT * FROM echo_c WHERE a = 1 }
|
||||
set echo_module
|
||||
} [list xBestIndex {SELECT rowid, a, b, c FROM 'c' WHERE a = ?} \
|
||||
xFilter {SELECT rowid, a, b, c FROM 'c' WHERE a = ?} 1]
|
||||
} [list xBestIndex {SELECT rowid, * FROM 'c' WHERE a = ?} xFilter {SELECT rowid, * FROM 'c' WHERE a = ?} 1]
|
||||
|
||||
#do_test vtab1-14.4 {
|
||||
# set echo_module ""
|
||||
@@ -1304,16 +1300,16 @@ do_execsql_test 18.1.0 {
|
||||
|
||||
foreach {tn sql res filter} {
|
||||
1.1 "SELECT a FROM e6 WHERE b>'James'" {4 1 5}
|
||||
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b > ?} James}
|
||||
{xFilter {SELECT rowid, * FROM 't6' WHERE b > ?} James}
|
||||
|
||||
1.2 "SELECT a FROM e6 WHERE b>='J' AND b<'K'" {3 4}
|
||||
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ?} J K}
|
||||
{xFilter {SELECT rowid, * FROM 't6' WHERE b >= ? AND b < ?} J K}
|
||||
|
||||
1.3 "SELECT a FROM e6 WHERE b LIKE 'J%'" {3 4}
|
||||
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} J%}
|
||||
{xFilter {SELECT rowid, * FROM 't6'}}
|
||||
|
||||
1.4 "SELECT a FROM e6 WHERE b LIKE 'j%'" {3 4}
|
||||
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} j%}
|
||||
{xFilter {SELECT rowid, * FROM 't6'}}
|
||||
} {
|
||||
set echo_module {}
|
||||
do_execsql_test 18.$tn.1 $sql $res
|
||||
@@ -1323,10 +1319,10 @@ foreach {tn sql res filter} {
|
||||
do_execsql_test 18.2.0 { PRAGMA case_sensitive_like = ON }
|
||||
foreach {tn sql res filter} {
|
||||
2.1 "SELECT a FROM e6 WHERE b LIKE 'J%'" {3 4}
|
||||
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} J%}
|
||||
{xFilter {SELECT rowid, * FROM 't6'}}
|
||||
|
||||
2.2 "SELECT a FROM e6 WHERE b LIKE 'j%'" {}
|
||||
{xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} j%}
|
||||
{xFilter {SELECT rowid, * FROM 't6'}}
|
||||
} {
|
||||
set echo_module {}
|
||||
do_execsql_test 18.$tn.1 $sql $res
|
||||
|
||||
+16
-16
@@ -57,9 +57,9 @@ do_test vtab4-1.3 {
|
||||
UPDATE techo SET a = 2;
|
||||
}
|
||||
set echo_module
|
||||
} [list xBestIndex {SELECT rowid, a, b, c FROM 'treal'} \
|
||||
} [list xBestIndex {SELECT rowid, * FROM 'treal'} \
|
||||
xBegin echo(treal) \
|
||||
xFilter {SELECT rowid, a, b, c FROM 'treal'} \
|
||||
xFilter {SELECT rowid, * FROM 'treal'} \
|
||||
xSync echo(treal) \
|
||||
xCommit echo(treal) \
|
||||
]
|
||||
@@ -69,9 +69,9 @@ do_test vtab4-1.4 {
|
||||
DELETE FROM techo;
|
||||
}
|
||||
set echo_module
|
||||
} [list xBestIndex {SELECT rowid, NULL, NULL, NULL FROM 'treal'} \
|
||||
} [list xBestIndex {SELECT rowid, * FROM 'treal'} \
|
||||
xBegin echo(treal) \
|
||||
xFilter {SELECT rowid, NULL, NULL, NULL FROM 'treal'} \
|
||||
xFilter {SELECT rowid, * FROM 'treal'} \
|
||||
xSync echo(treal) \
|
||||
xCommit echo(treal) \
|
||||
]
|
||||
@@ -105,12 +105,12 @@ do_test vtab4-2.2 {
|
||||
COMMIT;
|
||||
}
|
||||
set echo_module
|
||||
} [list xBestIndex {SELECT rowid, a, b, c FROM 'treal'} \
|
||||
} [list xBestIndex {SELECT rowid, * FROM 'treal'} \
|
||||
xBegin echo(sreal) \
|
||||
xFilter {SELECT rowid, a, b, c FROM 'treal'} \
|
||||
xBestIndex {SELECT rowid, NULL, NULL, NULL FROM 'treal'} \
|
||||
xFilter {SELECT rowid, * FROM 'treal'} \
|
||||
xBestIndex {SELECT rowid, * FROM 'treal'} \
|
||||
xBegin echo(treal) \
|
||||
xFilter {SELECT rowid, NULL, NULL, NULL FROM 'treal'} \
|
||||
xFilter {SELECT rowid, * FROM 'treal'} \
|
||||
xSync echo(sreal) \
|
||||
xSync echo(treal) \
|
||||
xCommit echo(sreal) \
|
||||
@@ -137,12 +137,12 @@ do_test vtab4-2.5 {
|
||||
ROLLBACK;
|
||||
}
|
||||
set echo_module
|
||||
} [list xBestIndex {SELECT rowid, a, b, c FROM 'sreal'} \
|
||||
} [list xBestIndex {SELECT rowid, * FROM 'sreal'} \
|
||||
xBegin echo(treal) \
|
||||
xFilter {SELECT rowid, a, b, c FROM 'sreal'} \
|
||||
xBestIndex {SELECT rowid, NULL, NULL, NULL FROM 'sreal'} \
|
||||
xFilter {SELECT rowid, * FROM 'sreal'} \
|
||||
xBestIndex {SELECT rowid, * FROM 'sreal'} \
|
||||
xBegin echo(sreal) \
|
||||
xFilter {SELECT rowid, NULL, NULL, NULL FROM 'sreal'} \
|
||||
xFilter {SELECT rowid, * FROM 'sreal'} \
|
||||
xRollback echo(treal) \
|
||||
xRollback echo(sreal) \
|
||||
]
|
||||
@@ -178,12 +178,12 @@ do_test vtab4-3.3 {
|
||||
COMMIT;
|
||||
}
|
||||
set echo_module
|
||||
} [list xBestIndex {SELECT rowid, a, b, c FROM 'sreal'} \
|
||||
} [list xBestIndex {SELECT rowid, * FROM 'sreal'} \
|
||||
xBegin echo(treal) \
|
||||
xFilter {SELECT rowid, a, b, c FROM 'sreal'} \
|
||||
xBestIndex {SELECT rowid, NULL, NULL, NULL FROM 'sreal'} \
|
||||
xFilter {SELECT rowid, * FROM 'sreal'} \
|
||||
xBestIndex {SELECT rowid, * FROM 'sreal'} \
|
||||
xBegin echo(sreal) \
|
||||
xFilter {SELECT rowid, NULL, NULL, NULL FROM 'sreal'} \
|
||||
xFilter {SELECT rowid, * FROM 'sreal'} \
|
||||
xSync echo(treal) \
|
||||
xSync echo(sreal) \
|
||||
xRollback echo(treal) \
|
||||
|
||||
@@ -46,5 +46,3 @@ do_test vtabE-1 {
|
||||
ORDER BY t1.value, t2.value;
|
||||
}
|
||||
} {vtabE vtabE1 11 vtabE1 w x {} vtabE vtabE1 11 vtabE1 y z {} vtabE vtabE2 22 vtabE2 a b {} vtabE vtabE2 22 vtabE2 c d {}}
|
||||
|
||||
finish_test
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user