Index: Makefile.msc
==================================================================
--- Makefile.msc
+++ Makefile.msc
@@ -28,10 +28,17 @@
# has no effect if (any) optimizations are enabled.
#
!IFNDEF USE_RUNTIME_CHECKS
USE_RUNTIME_CHECKS = 0
!ENDIF
+
+# Set this non-0 to create a SQLite amalgamation file that excludes the
+# various built-in extensions.
+#
+!IFNDEF MINIMAL_AMALGAMATION
+MINIMAL_AMALGAMATION = 0
+!ENDIF
# Set this non-0 to use "stdcall" calling convention for the core library
# and shell executable.
#
!IFNDEF USE_STDCALL
@@ -268,16 +275,43 @@
!ELSE
SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
!ENDIF
!ENDIF
+# <>
+# These are the names of the customized Tcl header files used by various parts
+# of this makefile when the stdcall calling convention is in use. It is not
+# used for any other purpose.
+#
+!IFNDEF SQLITETCLH
+SQLITETCLH = sqlite_tcl.h
+!ENDIF
+
+!IFNDEF SQLITETCLDECLSH
+SQLITETCLDECLSH = sqlite_tclDecls.h
+!ENDIF
+
+# These are the additional targets that the targets that integrate with the
+# Tcl library should depend on when compiling, etc.
+#
+!IFNDEF SQLITE_TCL_DEP
+!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
+SQLITE_TCL_DEP = $(SQLITETCLDECLSH) $(SQLITETCLH)
+!ELSE
+SQLITE_TCL_DEP =
+!ENDIF
+!ENDIF
+# <>
+
# These are the "standard" SQLite compilation options used when compiling for
# the Windows platform.
#
!IFNDEF OPT_FEATURE_FLAGS
+!IF $(MINIMAL_AMALGAMATION)==0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
+!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
# Should the session extension be enabled? If so, add compilation options
# to enable it.
@@ -469,24 +503,36 @@
# to how the Tcl library functions are declared and exported (i.e. without
# an explicit calling convention, which results in "cdecl").
#
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
!IF "$(PLATFORM)"=="x86"
-CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
-SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
+CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
+SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
+# <>
+TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
+# <>
!ELSE
!IFNDEF PLATFORM
-CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
-SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
+CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
+SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
+# <>
+TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
+# <>
!ELSE
CORE_CCONV_OPTS =
SHELL_CCONV_OPTS =
+# <>
+TEST_CCONV_OPTS =
+# <>
!ENDIF
!ENDIF
!ELSE
CORE_CCONV_OPTS =
SHELL_CCONV_OPTS =
+# <>
+TEST_CCONV_OPTS =
+# <>
!ENDIF
# These are additional compiler options used for the core library.
#
!IFNDEF CORE_COMPILE_OPTS
@@ -635,15 +681,38 @@
# The mksqlite3c.tcl script accepts some options on the command
# line. When compiling with debugging enabled, some of these
# options are necessary in order to allow debugging symbols to
# work correctly with Visual Studio when using the amalgamation.
#
+!IFNDEF MKSQLITE3C_TOOL
+!IF $(MINIMAL_AMALGAMATION)!=0
+MKSQLITE3C_TOOL = $(TOP)\tool\mksqlite3c-noext.tcl
+!ELSE
+MKSQLITE3C_TOOL = $(TOP)\tool\mksqlite3c.tcl
+!ENDIF
+!ENDIF
+
!IFNDEF MKSQLITE3C_ARGS
!IF $(DEBUG)>1
MKSQLITE3C_ARGS = --linemacros
!ELSE
MKSQLITE3C_ARGS =
+!ENDIF
+!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
+MKSQLITE3C_ARGS = $(MKSQLITE3C_ARGS) --useapicall
+!ENDIF
+!ENDIF
+
+# The mksqlite3h.tcl script accepts some options on the command line.
+# When compiling with stdcall support, some of these options are
+# necessary.
+#
+!IFNDEF MKSQLITE3H_ARGS
+!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
+MKSQLITE3H_ARGS = --useapicall
+!ELSE
+MKSQLITE3H_ARGS =
!ENDIF
!ENDIF
# <>
# Define -DNDEBUG to compile without debugging (i.e., for production usage)
@@ -1243,10 +1312,20 @@
SRC11 = \
keywordhash.h \
opcodes.h \
parse.h \
$(SQLITE3H)
+
+# Generated Tcl header files
+#
+!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
+SRC12 = \
+ $(SQLITETCLH) \
+ $(SQLITETCLDECLSH)
+!ELSE
+SRC12 =
+!ENDIF
# All source code files.
#
SRC = $(SRC00) $(SRC01) $(SRC02) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11)
@@ -1350,11 +1429,11 @@
$(TOP)\src\pager.h \
$(TOP)\src\pcache.h \
parse.h \
$(TOP)\src\pragma.h \
$(SQLITE3H) \
- $(TOP)\src\sqlite3ext.h \
+ sqlite3ext.h \
$(TOP)\src\sqliteInt.h \
$(TOP)\src\sqliteLimit.h \
$(TOP)\src\vdbe.h \
$(TOP)\src\vdbeInt.h \
$(TOP)\src\vxworks.h \
@@ -1508,11 +1587,11 @@
# copies of all of the C source code and header files needed to
# build on the target system. Some of the C source code and header
# files are automatically generated. This target takes care of
# all that automatic generation.
#
-.target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl fts5.c
+.target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl fts5.c $(SQLITE_TCL_DEP)
-rmdir /Q/S tsrc 2>NUL
-mkdir tsrc
for %i in ($(SRC00)) do copy /Y %i tsrc
for %i in ($(SRC01)) do copy /Y %i tsrc
for %i in ($(SRC02)) do copy /Y %i tsrc
@@ -1523,19 +1602,20 @@
for %i in ($(SRC07)) do copy /Y %i tsrc
for %i in ($(SRC08)) do copy /Y %i tsrc
for %i in ($(SRC09)) do copy /Y %i tsrc
for %i in ($(SRC10)) do copy /Y %i tsrc
for %i in ($(SRC11)) do copy /Y %i tsrc
+ for %i in ($(SRC12)) do copy /Y %i tsrc
copy /Y fts5.c tsrc
copy /Y fts5.h tsrc
del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL
$(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new
move vdbe.new tsrc\vdbe.c
echo > .target_source
-sqlite3.c: .target_source sqlite3ext.h $(TOP)\tool\mksqlite3c.tcl
- $(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl $(MKSQLITE3C_ARGS)
+sqlite3.c: .target_source sqlite3ext.h $(MKSQLITE3C_TOOL)
+ $(TCLSH_CMD) $(MKSQLITE3C_TOOL) $(MKSQLITE3C_ARGS)
copy tsrc\shell.c .
copy $(TOP)\ext\session\sqlite3session.h .
sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl
$(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl
@@ -1804,14 +1884,14 @@
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\wherecode.c
whereexpr.lo: $(TOP)\src\whereexpr.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\whereexpr.c
-tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR)
+tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR) $(SQLITE_TCL_DEP)
$(LTCOMPILE) $(NO_WARN) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
-tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR)
+tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR) $(SQLITE_TCL_DEP)
$(LTCOMPILE) $(NO_WARN) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
$(LTLINK) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
@@ -1833,14 +1913,20 @@
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) parse.y
move parse.h parse.h.temp
$(TCLSH_CMD) $(TOP)\tool\addopcodes.tcl parse.h.temp > parse.h
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
- $(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H)
+ $(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H) $(MKSQLITE3H_ARGS)
sqlite3ext.h: .target_source
- copy tsrc\sqlite3ext.h .
+!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
+ type tsrc\sqlite3ext.h | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*\)" "(SQLITE_CALLBACK *)" \
+ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*" "(SQLITE_APICALL *" > sqlite3ext.h
+ copy /Y sqlite3ext.h tsrc\sqlite3ext.h
+!ELSE
+ copy /Y tsrc\sqlite3ext.h sqlite3ext.h
+!ENDIF
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
$(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) \
$(TOP)\tool\mkkeywordhash.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
@@ -1969,20 +2055,41 @@
TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE=""
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN)
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
+TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C)
!IF $(USE_AMALGAMATION)==0
TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0)
!ELSE
TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC1)
!ENDIF
-testfixture.exe: $(TESTFIXTURE_SRC) $(SQLITE3H) $(LIBRESOBJS) $(HDR)
+!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
+sqlite_tclDecls.h:
+ echo #ifndef SQLITE_TCLAPI > $(SQLITETCLDECLSH)
+ echo # define SQLITE_TCLAPI >> $(SQLITETCLDECLSH)
+ echo #endif >> $(SQLITETCLDECLSH)
+ type "$(TCLINCDIR)\tclDecls.h" \
+ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "^(EXTERN(?: CONST\d+?)?\s+?[^\(]*?\s+?)Tcl_" "\1 SQLITE_TCLAPI Tcl_" \
+ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "^(EXTERN\s+?(?:void|VOID)\s+?)TclFreeObj" "\1 SQLITE_TCLAPI TclFreeObj" \
+ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*tcl_" "(SQLITE_TCLAPI *tcl_" \
+ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*tclFreeObj" "(SQLITE_TCLAPI *tclFreeObj" \
+ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*" "(SQLITE_TCLAPI *" >> $(SQLITETCLDECLSH)
+
+sqlite_tcl.h:
+ type "$(TCLINCDIR)\tcl.h" | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact tclDecls.h sqlite_tclDecls.h \
+ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "typedef (.*?)\(Tcl_" "typedef \1 (SQLITE_TCLAPI Tcl_" \
+ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "void (*freeProc)" "void (SQLITE_TCLAPI *freeProc)" \
+ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "Tcl_HashEntry *(*findProc)" "Tcl_HashEntry *(SQLITE_TCLAPI *findProc)" \
+ | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "Tcl_HashEntry *(*createProc)" "Tcl_HashEntry *(SQLITE_TCLAPI *createProc)" >> $(SQLITETCLH)
+!ENDIF
+
+testfixture.exe: $(TESTFIXTURE_SRC) $(SQLITE3H) $(LIBRESOBJS) $(HDR) $(SQLITE_TCL_DEP)
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \
-DBUILD_sqlite -I$(TCLINCDIR) \
$(TESTFIXTURE_SRC) \
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
@@ -2027,11 +2134,11 @@
smoketest: $(TESTPROGS)
@set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
-sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
+sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(SQLITE_TCL_DEP)
echo #define TCLSH 2 > $@
echo #define SQLITE_ENABLE_DBSTAT_VTAB 1 >> $@
copy $@ + $(SQLITE3C) + $(TOP)\src\tclsqlite.c $@
echo static const char *tclsh_main_loop(void){ >> $@
echo static const char *zMainloop = >> $@
@@ -2107,11 +2214,11 @@
del /Q notasharedlib.* 2>NUL
-rmdir /Q/S .deps 2>NUL
-rmdir /Q/S .libs 2>NUL
-rmdir /Q/S tsrc 2>NUL
del /Q .target_source 2>NUL
- del /Q tclsqlite3.exe 2>NUL
+ del /Q tclsqlite3.exe $(SQLITETCLH) $(SQLITETCLDECLSH) 2>NUL
del /Q testloadext.dll 2>NUL
del /Q testfixture.exe test.db 2>NUL
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe 2>NUL
del /Q changeset.exe 2>NUL
del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL
Index: VERSION
==================================================================
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
-3.15.0
+3.14.2
Index: autoconf/Makefile.msc
==================================================================
--- autoconf/Makefile.msc
+++ autoconf/Makefile.msc
@@ -28,10 +28,17 @@
# has no effect if (any) optimizations are enabled.
#
!IFNDEF USE_RUNTIME_CHECKS
USE_RUNTIME_CHECKS = 0
!ENDIF
+
+# Set this non-0 to create a SQLite amalgamation file that excludes the
+# various built-in extensions.
+#
+!IFNDEF MINIMAL_AMALGAMATION
+MINIMAL_AMALGAMATION = 0
+!ENDIF
# Set this non-0 to use "stdcall" calling convention for the core library
# and shell executable.
#
!IFNDEF USE_STDCALL
@@ -252,17 +259,20 @@
SQLITE3EXEPDB =
!ELSE
SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
!ENDIF
!ENDIF
+
# These are the "standard" SQLite compilation options used when compiling for
# the Windows platform.
#
!IFNDEF OPT_FEATURE_FLAGS
+!IF $(MINIMAL_AMALGAMATION)==0
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
+!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
# Should the session extension be enabled? If so, add compilation options
# to enable it.
@@ -454,16 +464,16 @@
# to how the Tcl library functions are declared and exported (i.e. without
# an explicit calling convention, which results in "cdecl").
#
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
!IF "$(PLATFORM)"=="x86"
-CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
-SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
+CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
+SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
!ELSE
!IFNDEF PLATFORM
-CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
-SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
+CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
+SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
!ELSE
CORE_CCONV_OPTS =
SHELL_CCONV_OPTS =
!ENDIF
!ENDIF
Index: configure
==================================================================
--- configure
+++ configure
@@ -1,8 +1,8 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for sqlite 3.15.0.
+# Generated by GNU Autoconf 2.69 for sqlite 3.14.2.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
#
#
@@ -724,12 +724,12 @@
MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
-PACKAGE_VERSION='3.15.0'
-PACKAGE_STRING='sqlite 3.15.0'
+PACKAGE_VERSION='3.14.2'
+PACKAGE_STRING='sqlite 3.14.2'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
# Factoring default headers for most tests.
ac_includes_default="\
@@ -1461,11 +1461,11 @@
#
if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures sqlite 3.15.0 to adapt to many kinds of systems.
+\`configure' configures sqlite 3.14.2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE. See below for descriptions of some of the useful variables.
@@ -1526,11 +1526,11 @@
_ACEOF
fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of sqlite 3.15.0:";;
+ short | recursive ) echo "Configuration of sqlite 3.14.2:";;
esac
cat <<\_ACEOF
Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
@@ -1650,11 +1650,11 @@
fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-sqlite configure 3.15.0
+sqlite configure 3.14.2
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
@@ -2069,11 +2069,11 @@
} # ac_fn_c_check_header_mongrel
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by sqlite $as_me 3.15.0, which was
+It was created by sqlite $as_me 3.14.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
_ACEOF
@@ -12149,11 +12149,11 @@
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# Save the log message, to keep $0 and so on meaningful, and to
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by sqlite $as_me 3.15.0, which was
+This file was extended by sqlite $as_me 3.14.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
CONFIG_LINKS = $CONFIG_LINKS
@@ -12215,11 +12215,11 @@
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-sqlite config.status 3.15.0
+sqlite config.status 3.14.2
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
Copyright (C) 2012 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
Index: ext/fts5/fts5Int.h
==================================================================
--- ext/fts5/fts5Int.h
+++ ext/fts5/fts5Int.h
@@ -735,11 +735,10 @@
void sqlite3Fts5ParseNearsetFree(Fts5ExprNearset*);
void sqlite3Fts5ParseNodeFree(Fts5ExprNode*);
void sqlite3Fts5ParseSetDistance(Fts5Parse*, Fts5ExprNearset*, Fts5Token*);
void sqlite3Fts5ParseSetColset(Fts5Parse*, Fts5ExprNearset*, Fts5Colset*);
-Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse*, Fts5Colset*);
void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p);
void sqlite3Fts5ParseNear(Fts5Parse *pParse, Fts5Token*);
/*
** End of interface to code in fts5_expr.c.
Index: ext/fts5/fts5_aux.c
==================================================================
--- ext/fts5/fts5_aux.c
+++ ext/fts5/fts5_aux.c
@@ -187,11 +187,11 @@
}
if( p->iRangeEnd>0 && iPos==p->iRangeEnd ){
fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff);
p->iOff = iEndOff;
- if( iPos>=p->iter.iStart && iPositer.iEnd ){
+ if( iPositer.iEnd ){
fts5HighlightAppend(&rc, p, p->zClose, -1);
}
}
return rc;
@@ -244,119 +244,10 @@
}
/*
** End of highlight() implementation.
**************************************************************************/
-/*
-** Context object passed to the fts5SentenceFinderCb() function.
-*/
-typedef struct Fts5SFinder Fts5SFinder;
-struct Fts5SFinder {
- int iPos; /* Current token position */
- int nFirstAlloc; /* Allocated size of aFirst[] */
- int nFirst; /* Number of entries in aFirst[] */
- int *aFirst; /* Array of first token in each sentence */
- const char *zDoc; /* Document being tokenized */
-};
-
-/*
-** Add an entry to the Fts5SFinder.aFirst[] array. Grow the array if
-** necessary. Return SQLITE_OK if successful, or SQLITE_NOMEM if an
-** error occurs.
-*/
-static int fts5SentenceFinderAdd(Fts5SFinder *p, int iAdd){
- if( p->nFirstAlloc==p->nFirst ){
- int nNew = p->nFirstAlloc ? p->nFirstAlloc*2 : 64;
- int *aNew;
-
- aNew = (int*)sqlite3_realloc(p->aFirst, nNew*sizeof(int));
- if( aNew==0 ) return SQLITE_NOMEM;
- p->aFirst = aNew;
- p->nFirstAlloc = nNew;
- }
- p->aFirst[p->nFirst++] = iAdd;
- return SQLITE_OK;
-}
-
-/*
-** This function is an xTokenize() callback used by the auxiliary snippet()
-** function. Its job is to identify tokens that are the first in a sentence.
-** For each such token, an entry is added to the SFinder.aFirst[] array.
-*/
-static int fts5SentenceFinderCb(
- void *pContext, /* Pointer to HighlightContext object */
- int tflags, /* Mask of FTS5_TOKEN_* flags */
- const char *pToken, /* Buffer containing token */
- int nToken, /* Size of token in bytes */
- int iStartOff, /* Start offset of token */
- int iEndOff /* End offset of token */
-){
- int rc = SQLITE_OK;
-
- if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){
- Fts5SFinder *p = (Fts5SFinder*)pContext;
- if( p->iPos>0 ){
- int i;
- char c = 0;
- for(i=iStartOff-1; i>=0; i--){
- c = p->zDoc[i];
- if( c!=' ' && c!='\t' && c!='\n' && c!='\r' ) break;
- }
- if( i!=iStartOff-1 && (c=='.' || c==':') ){
- rc = fts5SentenceFinderAdd(p, p->iPos);
- }
- }else{
- rc = fts5SentenceFinderAdd(p, 0);
- }
- p->iPos++;
- }
- return rc;
-}
-
-static int fts5SnippetScore(
- const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
- Fts5Context *pFts, /* First arg to pass to pApi functions */
- int nDocsize, /* Size of column in tokens */
- unsigned char *aSeen, /* Array with one element per query phrase */
- int iCol, /* Column to score */
- int iPos, /* Starting offset to score */
- int nToken, /* Max tokens per snippet */
- int *pnScore, /* OUT: Score */
- int *piPos /* OUT: Adjusted offset */
-){
- int rc;
- int i;
- int ip = 0;
- int ic = 0;
- int iOff = 0;
- int iFirst = -1;
- int nInst;
- int nScore = 0;
- int iLast = 0;
-
- rc = pApi->xInstCount(pFts, &nInst);
- for(i=0; ixInst(pFts, i, &ip, &ic, &iOff);
- if( rc==SQLITE_OK && ic==iCol && iOff>=iPos && iOff<(iPos+nToken) ){
- nScore += (aSeen[ip] ? 1 : 1000);
- aSeen[ip] = 1;
- if( iFirst<0 ) iFirst = iOff;
- iLast = iOff + pApi->xPhraseSize(pFts, ip);
- }
- }
-
- *pnScore = nScore;
- if( piPos ){
- int iAdj = iFirst - (nToken - (iLast-iFirst)) / 2;
- if( (iAdj+nToken)>nDocsize ) iAdj = nDocsize - nToken;
- if( iAdj<0 ) iAdj = 0;
- *piPos = iAdj;
- }
-
- return rc;
-}
-
/*
** Implementation of snippet() function.
*/
static void fts5SnippetFunction(
const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
@@ -374,141 +265,110 @@
int i; /* Used to iterate through instances */
int nPhrase; /* Number of phrases in query */
unsigned char *aSeen; /* Array of "seen instance" flags */
int iBestCol; /* Column containing best snippet */
int iBestStart = 0; /* First token of best snippet */
+ int iBestLast; /* Last token of best snippet */
int nBestScore = 0; /* Score of best snippet */
int nColSize = 0; /* Total size of iBestCol in tokens */
- Fts5SFinder sFinder; /* Used to find the beginnings of sentences */
- int nCol;
if( nVal!=5 ){
const char *zErr = "wrong number of arguments to function snippet()";
sqlite3_result_error(pCtx, zErr, -1);
return;
}
- nCol = pApi->xColumnCount(pFts);
memset(&ctx, 0, sizeof(HighlightContext));
iCol = sqlite3_value_int(apVal[0]);
ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]);
ctx.zClose = (const char*)sqlite3_value_text(apVal[2]);
zEllips = (const char*)sqlite3_value_text(apVal[3]);
nToken = sqlite3_value_int(apVal[4]);
+ iBestLast = nToken-1;
iBestCol = (iCol>=0 ? iCol : 0);
nPhrase = pApi->xPhraseCount(pFts);
aSeen = sqlite3_malloc(nPhrase);
if( aSeen==0 ){
rc = SQLITE_NOMEM;
}
- if( rc==SQLITE_OK ){
- rc = pApi->xInstCount(pFts, &nInst);
- }
-
- memset(&sFinder, 0, sizeof(Fts5SFinder));
- for(i=0; ixColumnText(pFts, i, &sFinder.zDoc, &nDoc);
- if( rc!=SQLITE_OK ) break;
- rc = pApi->xTokenize(pFts,
- sFinder.zDoc, nDoc, (void*)&sFinder,fts5SentenceFinderCb
- );
- if( rc!=SQLITE_OK ) break;
- rc = pApi->xColumnSize(pFts, i, &nDocsize);
- if( rc!=SQLITE_OK ) break;
-
- for(ii=0; rc==SQLITE_OK && iixInst(pFts, ii, &ip, &ic, &io);
- if( ic!=i || rc!=SQLITE_OK ) continue;
- memset(aSeen, 0, nPhrase);
- rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
- io, nToken, &nScore, &iAdj
- );
- if( rc==SQLITE_OK && nScore>nBestScore ){
- nBestScore = nScore;
- iBestCol = i;
- iBestStart = iAdj;
- nColSize = nDocsize;
- }
-
- if( rc==SQLITE_OK && sFinder.nFirst && nDocsize>nToken ){
- for(jj=0; jj<(sFinder.nFirst-1); jj++){
- if( sFinder.aFirst[jj+1]>io ) break;
- }
-
- if( sFinder.aFirst[jj]nBestScore ){
- nBestScore = nScore;
- iBestCol = i;
- iBestStart = sFinder.aFirst[jj];
- nColSize = nDocsize;
- }
- }
- }
- }
- }
- }
-
- if( rc==SQLITE_OK ){
- rc = pApi->xColumnText(pFts, iBestCol, &ctx.zIn, &ctx.nIn);
- }
- if( rc==SQLITE_OK && nColSize==0 ){
- rc = pApi->xColumnSize(pFts, iBestCol, &nColSize);
- }
- if( ctx.zIn ){
- if( rc==SQLITE_OK ){
- rc = fts5CInstIterInit(pApi, pFts, iBestCol, &ctx.iter);
- }
+
+ if( rc==SQLITE_OK ){
+ rc = pApi->xInstCount(pFts, &nInst);
+ }
+ for(i=0; rc==SQLITE_OK && ixInst(pFts, i, &ip, &iSnippetCol, &iStart);
+ if( rc==SQLITE_OK && (iCol<0 || iSnippetCol==iCol) ){
+ int nScore = 1000;
+ int iLast = iStart - 1 + pApi->xPhraseSize(pFts, ip);
+ int j;
+ aSeen[ip] = 1;
+
+ for(j=i+1; rc==SQLITE_OK && jxInst(pFts, j, &ip, &ic, &io);
+ iFinal = io + pApi->xPhraseSize(pFts, ip) - 1;
+ if( rc==SQLITE_OK && ic==iSnippetCol && iLastiLast ) iLast = iFinal;
+ }
+ }
+
+ if( rc==SQLITE_OK && nScore>nBestScore ){
+ iBestCol = iSnippetCol;
+ iBestStart = iStart;
+ iBestLast = iLast;
+ nBestScore = nScore;
+ }
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ rc = pApi->xColumnSize(pFts, iBestCol, &nColSize);
+ }
+ if( rc==SQLITE_OK ){
+ rc = pApi->xColumnText(pFts, iBestCol, &ctx.zIn, &ctx.nIn);
+ }
+ if( ctx.zIn ){
+ if( rc==SQLITE_OK ){
+ rc = fts5CInstIterInit(pApi, pFts, iBestCol, &ctx.iter);
+ }
+
+ if( (iBestStart+nToken-1)>iBestLast ){
+ iBestStart -= (iBestStart+nToken-1-iBestLast) / 2;
+ }
+ if( iBestStart+nToken>nColSize ){
+ iBestStart = nColSize - nToken;
+ }
+ if( iBestStart<0 ) iBestStart = 0;
ctx.iRangeStart = iBestStart;
ctx.iRangeEnd = iBestStart + nToken - 1;
if( iBestStart>0 ){
fts5HighlightAppend(&rc, &ctx, zEllips, -1);
}
-
- /* Advance iterator ctx.iter so that it points to the first coalesced
- ** phrase instance at or following position iBestStart. */
- while( ctx.iter.iStart>=0 && ctx.iter.iStartxTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb);
}
if( ctx.iRangeEnd>=(nColSize-1) ){
fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff);
}else{
fts5HighlightAppend(&rc, &ctx, zEllips, -1);
}
- }
- if( rc==SQLITE_OK ){
- sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT);
- }else{
- sqlite3_result_error_code(pCtx, rc);
- }
- sqlite3_free(ctx.zOut);
- sqlite3_free(aSeen);
- sqlite3_free(sFinder.aFirst);
+
+ if( rc==SQLITE_OK ){
+ sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT);
+ }else{
+ sqlite3_result_error_code(pCtx, rc);
+ }
+ sqlite3_free(ctx.zOut);
+ }
+ sqlite3_free(aSeen);
}
/************************************************************************/
/*
Index: ext/fts5/fts5_expr.c
==================================================================
--- ext/fts5/fts5_expr.c
+++ ext/fts5/fts5_expr.c
@@ -165,11 +165,10 @@
case '}': tok = FTS5_RCP; break;
case ':': tok = FTS5_COLON; break;
case ',': tok = FTS5_COMMA; break;
case '+': tok = FTS5_PLUS; break;
case '*': tok = FTS5_STAR; break;
- case '-': tok = FTS5_MINUS; break;
case '\0': tok = FTS5_EOF; break;
case '"': {
const char *z2;
tok = FTS5_STRING;
@@ -1657,11 +1656,11 @@
sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*));
}
if( rc==SQLITE_OK ){
Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
if( pColsetOrig ){
- int nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
+ int nByte = sizeof(Fts5Colset) + pColsetOrig->nCol * sizeof(int);
Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
if( pColset ){
memcpy(pColset, pColsetOrig, nByte);
}
pNew->pRoot->pNear->pColset = pColset;
@@ -1792,38 +1791,10 @@
}
return pNew;
}
-/*
-** Allocate and return an Fts5Colset object specifying the inverse of
-** the colset passed as the second argument. Free the colset passed
-** as the second argument before returning.
-*/
-Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse *pParse, Fts5Colset *p){
- Fts5Colset *pRet;
- int nCol = pParse->pConfig->nCol;
-
- pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc,
- sizeof(Fts5Colset) + sizeof(int)*nCol
- );
- if( pRet ){
- int i;
- int iOld = 0;
- for(i=0; i=p->nCol || p->aiCol[iOld]!=i ){
- pRet->aiCol[pRet->nCol++] = i;
- }else{
- iOld++;
- }
- }
- }
-
- sqlite3_free(p);
- return pRet;
-}
-
Fts5Colset *sqlite3Fts5ParseColset(
Fts5Parse *pParse, /* Store SQLITE_NOMEM here if required */
Fts5Colset *pColset, /* Existing colset object */
Fts5Token *p
){
Index: ext/fts5/fts5_index.c
==================================================================
--- ext/fts5/fts5_index.c
+++ ext/fts5/fts5_index.c
@@ -699,31 +699,20 @@
}
assert( (pRet==0)==(p->rc!=SQLITE_OK) );
return pRet;
}
+
/*
** Release a reference to data record returned by an earlier call to
** fts5DataRead().
*/
static void fts5DataRelease(Fts5Data *pData){
sqlite3_free(pData);
}
-static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
- Fts5Data *pRet = fts5DataRead(p, iRowid);
- if( pRet ){
- if( pRet->szLeaf>pRet->nn ){
- p->rc = FTS5_CORRUPT;
- fts5DataRelease(pRet);
- pRet = 0;
- }
- }
- return pRet;
-}
-
static int fts5IndexPrepareStmt(
Fts5Index *p,
sqlite3_stmt **ppStmt,
char *zSql
){
@@ -1528,11 +1517,11 @@
pIter->iLeafPgno++;
if( pIter->pNextLeaf ){
pIter->pLeaf = pIter->pNextLeaf;
pIter->pNextLeaf = 0;
}else if( pIter->iLeafPgno<=pSeg->pgnoLast ){
- pIter->pLeaf = fts5LeafRead(p,
+ pIter->pLeaf = fts5DataRead(p,
FTS5_SEGMENT_ROWID(pSeg->iSegid, pIter->iLeafPgno)
);
}else{
pIter->pLeaf = 0;
}
@@ -2031,12 +2020,13 @@
pIter->iLeafOffset = iOff;
if( pLeaf->nn>pLeaf->szLeaf ){
pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
&pLeaf->p[pLeaf->szLeaf], pIter->iEndofDoclist
- );
+ );
}
+
}
else if( pLeaf->nn>pLeaf->szLeaf ){
pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
&pLeaf->p[pLeaf->szLeaf], iOff
);
@@ -2277,15 +2267,10 @@
iPgidx += fts5GetVarint32(&a[iPgidx], nKeep);
iTermOff += nKeep;
iOff = iTermOff;
- if( iOff>=n ){
- p->rc = FTS5_CORRUPT;
- return;
- }
-
/* Read the nKeep field of the next term. */
fts5FastGetVarint32(a, iOff, nKeep);
}
search_failed:
@@ -3208,19 +3193,10 @@
fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist);
pIter->base.pData = pIter->poslist.p;
}
}
-/*
-** xSetOutputs callback used when the Fts5Colset object has nCol==0 (match
-** against no columns at all).
-*/
-static void fts5IterSetOutputs_ZeroColset(Fts5Iter *pIter, Fts5SegIter *pSeg){
- UNUSED_PARAM(pSeg);
- pIter->base.nData = 0;
-}
-
/*
** xSetOutputs callback used by detail=col when there is a column filter
** and there are 100 or more columns. Also called as a fallback from
** fts5IterSetOutputs_Col100 if the column-list spans more than one page.
*/
@@ -3322,14 +3298,10 @@
else if( pIter->pColset==0 ){
pIter->xSetOutputs = fts5IterSetOutputs_Nocolset;
}
- else if( pIter->pColset->nCol==0 ){
- pIter->xSetOutputs = fts5IterSetOutputs_ZeroColset;
- }
-
else if( pConfig->eDetail==FTS5_DETAIL_FULL ){
pIter->xSetOutputs = fts5IterSetOutputs_Full;
}
else{
Index: ext/fts5/fts5parse.y
==================================================================
--- ext/fts5/fts5parse.y
+++ ext/fts5/fts5parse.y
@@ -118,27 +118,21 @@
%type colset {Fts5Colset*}
%destructor colset { sqlite3_free($$); }
%type colsetlist {Fts5Colset*}
%destructor colsetlist { sqlite3_free($$); }
-colset(A) ::= MINUS LCP colsetlist(X) RCP. {
- A = sqlite3Fts5ParseColsetInvert(pParse, X);
-}
colset(A) ::= LCP colsetlist(X) RCP. { A = X; }
colset(A) ::= STRING(X). {
A = sqlite3Fts5ParseColset(pParse, 0, &X);
}
-colset(A) ::= MINUS STRING(X). {
- A = sqlite3Fts5ParseColset(pParse, 0, &X);
- A = sqlite3Fts5ParseColsetInvert(pParse, A);
-}
colsetlist(A) ::= colsetlist(Y) STRING(X). {
A = sqlite3Fts5ParseColset(pParse, Y, &X); }
colsetlist(A) ::= STRING(X). {
A = sqlite3Fts5ParseColset(pParse, 0, &X);
}
+
%type nearset {Fts5ExprNearset*}
%type nearphrases {Fts5ExprNearset*}
%destructor nearset { sqlite3Fts5ParseNearsetFree($$); }
%destructor nearphrases { sqlite3Fts5ParseNearsetFree($$); }
Index: ext/fts5/test/fts5af.test
==================================================================
--- ext/fts5/test/fts5af.test
+++ ext/fts5/test/fts5af.test
@@ -70,60 +70,46 @@
2.1 {X o o o o o o o} {[X] o o o o o o...}
2.2 {o X o o o o o o} {o [X] o o o o o...}
2.3 {o o X o o o o o} {o o [X] o o o o...}
2.4 {o o o X o o o o} {o o o [X] o o o...}
- 2.5 {o o o o X o o o} {o o o o [X] o o...}
- 2.6 {o o o o o X o o} {o o o o o [X] o...}
- 2.7 {o o o o o o X o} {o o o o o o [X]...}
+ 2.5 {o o o o X o o o} {...o o o [X] o o o}
+ 2.6 {o o o o o X o o} {...o o o o [X] o o}
+ 2.7 {o o o o o o X o} {...o o o o o [X] o}
2.8 {o o o o o o o X} {...o o o o o o [X]}
-
- 2.9 {o o o o o o o X o} {...o o o o o [X] o}
- 2.10 {o o o o o o o X o o} {...o o o o [X] o o}
- 2.11 {o o o o o o o X o o o} {...o o o [X] o o o}
- 2.12 {o o o o o o o X o o o o} {...o o o [X] o o o...}
-
3.1 {X o o o o o o o o} {[X] o o o o o o...}
3.2 {o X o o o o o o o} {o [X] o o o o o...}
3.3 {o o X o o o o o o} {o o [X] o o o o...}
3.4 {o o o X o o o o o} {o o o [X] o o o...}
-
- 3.5 {o o o o o o o X o o o o} {...o o o [X] o o o...}
- 3.6 {o o o o o o o o X o o o} {...o o o [X] o o o}
- 3.7 {o o o o o o o o o X o o} {...o o o o [X] o o}
- 3.8 {o o o o o o o o o o X o} {...o o o o o [X] o}
- 3.9 {o o o o o o o o o o o X} {...o o o o o o [X]}
+ 3.5 {o o o o X o o o o} {...o o o [X] o o o...}
+ 3.6 {o o o o o X o o o} {...o o o [X] o o o}
+ 3.7 {o o o o o o X o o} {...o o o o [X] o o}
+ 3.8 {o o o o o o o X o} {...o o o o o [X] o}
+ 3.9 {o o o o o o o o X} {...o o o o o o [X]}
4.1 {X o o o o o X o o} {[X] o o o o o [X]...}
- 4.2 {o o o o o o o X o o o o o X o} {...[X] o o o o o [X]...}
- 4.3 {o o o o o o o o X o o o o o X} {...[X] o o o o o [X]}
+ 4.2 {o X o o o o o X o} {...[X] o o o o o [X]...}
+ 4.3 {o o X o o o o o X} {...[X] o o o o o [X]}
5.1 {X o o o o X o o o} {[X] o o o o [X] o...}
- 5.2 {o o o o o o o X o o o o X o o} {...[X] o o o o [X] o...}
- 5.3 {o o o o o o o o X o o o o X o} {...[X] o o o o [X] o}
- 5.4 {o o o o o o o o o X o o o o X} {...o [X] o o o o [X]}
+ 5.2 {o X o o o o X o o} {...[X] o o o o [X] o...}
+ 5.3 {o o X o o o o X o} {...[X] o o o o [X] o}
+ 5.4 {o o o X o o o o X} {...o [X] o o o o [X]}
6.1 {X o o o X o o o} {[X] o o o [X] o o...}
6.2 {o X o o o X o o o} {o [X] o o o [X] o...}
- 6.3 {o o o o o o o X o o o X o o} {...o [X] o o o [X] o...}
- 6.4 {o o o o o o o o X o o o X o} {...o [X] o o o [X] o}
- 6.5 {o o o o o o o o o X o o o X} {...o o [X] o o o [X]}
+ 6.3 {o o X o o o X o o} {...o [X] o o o [X] o...}
+ 6.4 {o o o X o o o X o} {...o [X] o o o [X] o}
+ 6.5 {o o o o X o o o X} {...o o [X] o o o [X]}
7.1 {X o o X o o o o o} {[X] o o [X] o o o...}
7.2 {o X o o X o o o o} {o [X] o o [X] o o...}
- 7.3 {o o o o o o o X o o X o o o} {...o [X] o o [X] o o...}
- 7.4 {o o o o o o o o X o o X o o} {...o [X] o o [X] o o}
- 7.5 {o o o o o o o o o X o o X o} {...o o [X] o o [X] o}
- 7.6 {o o o o o o o o o o X o o X} {...o o o [X] o o [X]}
-
- 8.1 {o o o o o o o o o X o o o o o o o o o o o o o o o o X X X o o o}
- {...o o [X] [X] [X] o o...}
- 8.2 {o o o o o o o. o o X o o o o o o o o o o o o o o o o X X X o o o}
- {...o o [X] o o o o...}
- 8.3 {o o o o X o o o o o o o o o o o o o o o o o o o o o X X X o o o}
- {o o o o [X] o o...}
+ 7.3 {o o X o o X o o o} {...o [X] o o [X] o o...}
+ 7.4 {o o o X o o X o o} {...o [X] o o [X] o o}
+ 7.5 {o o o o X o o X o} {...o o [X] o o [X] o}
+ 7.6 {o o o o o X o o X} {...o o o [X] o o [X]}
} {
do_snippet_test 1.$tn $doc X $res
}
if {[detail_is_full]} {
@@ -136,46 +122,27 @@
1.6 {o o o o o X Y} {o o o o o [X Y]}
2.1 {X Y o o o o o o} {[X Y] o o o o o...}
2.2 {o X Y o o o o o} {o [X Y] o o o o...}
2.3 {o o X Y o o o o} {o o [X Y] o o o...}
- 2.4 {o o o o o o o X Y o o o} {...o o [X Y] o o o}
- 2.5 {o o o o o o o o X Y o o} {...o o o [X Y] o o}
- 2.6 {o o o o o o o o o X Y o} {...o o o o [X Y] o}
- 2.7 {o o o o o o o o o o X Y} {...o o o o o [X Y]}
+ 2.4 {o o o X Y o o o} {...o o [X Y] o o o}
+ 2.5 {o o o o X Y o o} {...o o o [X Y] o o}
+ 2.6 {o o o o o X Y o} {...o o o o [X Y] o}
+ 2.7 {o o o o o o X Y} {...o o o o o [X Y]}
3.1 {X Y o o o o o o o} {[X Y] o o o o o...}
3.2 {o X Y o o o o o o} {o [X Y] o o o o...}
3.3 {o o X Y o o o o o} {o o [X Y] o o o...}
- 3.4 {o o o o o o o X Y o o o o} {...o o [X Y] o o o...}
- 3.5 {o o o o o o o o X Y o o o} {...o o [X Y] o o o}
- 3.6 {o o o o o o o o o X Y o o} {...o o o [X Y] o o}
- 3.7 {o o o o o o o o o o X Y o} {...o o o o [X Y] o}
- 3.8 {o o o o o o o o o o o X Y} {...o o o o o [X Y]}
+ 3.4 {o o o X Y o o o o} {...o o [X Y] o o o...}
+ 3.5 {o o o o X Y o o o} {...o o [X Y] o o o}
+ 3.6 {o o o o o X Y o o} {...o o o [X Y] o o}
+ 3.7 {o o o o o o X Y o} {...o o o o [X Y] o}
+ 3.8 {o o o o o o o X Y} {...o o o o o [X Y]}
} {
do_snippet_test 2.$tn $doc "X + Y" $res
}
}
-do_execsql_test 4.0 {
- CREATE VIRTUAL TABLE x1 USING fts5(a, b);
- INSERT INTO x1 VALUES('xyz', '1 2 3 4 5 6 7 8 9 10 11 12 13');
- SELECT snippet(x1, 1, '[', ']', '...', 5) FROM x1('xyz');
-} {
- {1 2 3 4 5...}
-}
-
-do_execsql_test 5.0 {
- CREATE VIRTUAL TABLE p1 USING fts5(a, b);
- INSERT INTO p1 VALUES(
- 'x a a a a a a a a a a',
- 'a a a a a a a a a a a a a a a a a a a x'
- );
-}
-do_execsql_test 5.1 {
- SELECT snippet(p1, 0, '[', ']', '...', 6) FROM p1('x');
-} {{[x] a a a a a...}}
-
} ;# foreach_detail_mode
finish_test
DELETED ext/fts5/test/fts5colset.test
Index: ext/fts5/test/fts5colset.test
==================================================================
--- ext/fts5/test/fts5colset.test
+++ /dev/null
@@ -1,59 +0,0 @@
-# 2016 August 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 script is testing the FTS5 module.
-#
-
-source [file join [file dirname [info script]] fts5_common.tcl]
-set testprefix fts5colset
-
-# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
-ifcapable !fts5 {
- finish_test
- return
-}
-
-foreach_detail_mode $::testprefix {
- if {[detail_is_none]} continue
-
- do_execsql_test 1.0 {
- CREATE VIRTUAL TABLE t1 USING fts5(a, b, c, d, detail=%DETAIL%);
- INSERT INTO t1 VALUES('a', 'b', 'c', 'd'); -- 1
- INSERT INTO t1 VALUES('d', 'a', 'b', 'c'); -- 2
- INSERT INTO t1 VALUES('c', 'd', 'a', 'b'); -- 3
- INSERT INTO t1 VALUES('b', 'c', 'd', 'a'); -- 4
- }
-
- foreach {tn q res} {
- 1 "a" {1 2 3 4}
- 2 "{a} : a" {1}
- 3 "-{a} : a" {2 3 4}
- 4 "- {a c} : a" {2 4}
- 5 " - {d d c} : a" {1 2}
- 6 "- {d c b a} : a" {}
- 7 "-{\"a\"} : b" {1 2 3}
- 8 "- c : a" {1 2 4}
- 9 "-c : a" {1 2 4}
- 10 "-\"c\" : a" {1 2 4}
- } {
- breakpoint
- do_execsql_test 1.$tn {
- SELECT rowid FROM t1($q)
- } $res
- }
-
-
-}
-
-
-finish_test
-
-
Index: ext/fts5/test/fts5corrupt2.test
==================================================================
--- ext/fts5/test/fts5corrupt2.test
+++ ext/fts5/test/fts5corrupt2.test
@@ -35,11 +35,11 @@
WITH ii(i) AS (SELECT 1 UNION SELECT i+1 FROM ii WHERE i<100)
INSERT INTO t1 SELECT rnddoc(10) FROM ii;
}
set mask [expr 31 << 31]
-if 0 {
+if 1 {
# Test 1:
#
# For each page in the t1_data table, open a transaction and DELETE
# the t1_data entry. Then run:
@@ -80,12 +80,10 @@
do_execsql_test 1.$tno.$tn.3.$rowid {
ROLLBACK;
INSERT INTO t1(t1) VALUES('integrity-check');
} {}
}
-}
-
}
# Using the same database as the 1.* tests.
#
# Run N-1 tests, where N is the number of bytes in the rightmost leaf page
@@ -210,10 +208,12 @@
execsql ROLLBACK
}
# do_test 4.$tn.x { expr $nCorrupt>0 } 1
+}
+
}
set doc [string repeat "A B C " 1000]
do_execsql_test 5.0 {
CREATE VIRTUAL TABLE x5 USING fts5(tt);
Index: ext/fts5/test/fts5unicode2.test
==================================================================
--- ext/fts5/test/fts5unicode2.test
+++ ext/fts5/test/fts5unicode2.test
@@ -158,16 +158,16 @@
3 "ROW" {
...returns the value of y on the same [row] that contains
the maximum x value.
}
4 "rollback" {
- Pending statements no longer block [ROLLBACK]. Instead, the pending
- statement will return SQLITE_ABORT upon...
+ ...[ROLLBACK]. Instead, the pending statement
+ will return SQLITE_ABORT upon next access after the [ROLLBACK].
}
5 "rOllback" {
- Pending statements no longer block [ROLLBACK]. Instead, the pending
- statement will return SQLITE_ABORT upon...
+ ...[ROLLBACK]. Instead, the pending statement
+ will return SQLITE_ABORT upon next access after the [ROLLBACK].
}
6 "lang*" {
Added support for the FTS4 [languageid] option.
}
} {
Index: ext/rbu/rbudiff.test
==================================================================
--- ext/rbu/rbudiff.test
+++ ext/rbu/rbudiff.test
@@ -138,19 +138,10 @@
INSERT INTO t2 VALUES(1,
X'0000000000000000111111111111111122222222222222223333333FFF333333'
);
}
- 4 {
- CREATE TABLE x1(a, b, c, PRIMARY KEY(a, b, c));
- INSERT INTO x1 VALUES('u', 'v', NULL);
- INSERT INTO x1 VALUES('x', 'y', 'z');
- INSERT INTO x1 VALUES('a', NULL, 'b');
- } {
- INSERT INTO x1 VALUES('a', 'b', 'c');
- }
-
} {
catch { db close }
forcedelete test.db test.db2
sqlite3 db test.db
@@ -286,9 +277,8 @@
db close
db2 close
}
}
-
finish_test
ADDED ext/rbu/rbuempty.test
Index: ext/rbu/rbuempty.test
==================================================================
--- /dev/null
+++ ext/rbu/rbuempty.test
@@ -0,0 +1,77 @@
+# 2022 September 27
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+
+source [file join [file dirname [info script]] rbu_common.tcl]
+set ::testprefix rbuempty
+
+db close
+sqlite3_shutdown
+sqlite3_config_uri 1
+
+forcedelete rbu.db
+sqlite3 db test.db
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT);
+ INSERT INTO t1 VALUES(1, 'one');
+ INSERT INTO t1 VALUES(2, 'two');
+ INSERT INTO t1 VALUES(3, 'three');
+
+ ATTACH 'rbu.db' AS aux;
+ CREATE TABLE aux.data_t1(a, b, rbu_control);
+ DETACH aux;
+}
+
+do_test 1.1 {
+ sqlite3rbu rbu test.db rbu.db
+ lappend ::v [rbu state]
+ lappend ::v [rbu bp_progress]
+ while {[rbu step]=="SQLITE_OK"} {
+ lappend ::v [rbu state]
+ lappend ::v [rbu bp_progress]
+ }
+ lappend ::v [rbu state]
+ lappend ::v [rbu bp_progress]
+ rbu close
+} {SQLITE_DONE}
+
+do_execsql_test 1.2 {
+ SELECT * FROM t1
+} {1 one 2 two 3 three}
+
+forcedelete rbu.db
+do_execsql_test 1.3 {
+ ATTACH 'rbu.db' AS aux;
+ CREATE TABLE aux.data_t1(a, b, rbu_control);
+ INSERT INTO aux.data_t1 VALUES(4, 'FOUR', 0);
+ DETACH aux;
+}
+
+do_test 1.4 {
+ while {1} {
+ sqlite3rbu rbu test.db rbu.db
+ lappend ::v [rbu state]
+ lappend ::v [rbu bp_progress]
+ set rc [rbu step]
+ lappend ::v [rbu state]
+ lappend ::v [rbu bp_progress]
+ rbu close
+ if {$rc!="SQLITE_OK"} break
+ db eval { SELECT * FROM t1 }
+ db eval { PRAGMA wal_checkpoint = restart }
+ }
+} {}
+
+
+
+finish_test
+
+
Index: ext/rbu/rbuprogress.test
==================================================================
--- ext/rbu/rbuprogress.test
+++ ext/rbu/rbuprogress.test
@@ -359,12 +359,10 @@
vtab {
CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
}
} {
- if {$tn=="vtab"} { ifcapable !fts5 break }
-
foreach {tn2 rbusql r1 r2} {
1 {
CREATE TABLE data0_t1(a, b, c, rbu_rowid, rbu_control);
INSERT INTO data0_t1 VALUES(15, 15, 15, 4, 0);
INSERT INTO data0_t1 VALUES(20, 20, 20, 5, 0);
Index: ext/rbu/rbuvacuum2.test
==================================================================
--- ext/rbu/rbuvacuum2.test
+++ ext/rbu/rbuvacuum2.test
@@ -154,51 +154,9 @@
table t1 t1 2 {CREATE TABLE t1(a, b, c)}
view v1 v1 0 {CREATE VIEW v1 AS SELECT * FROM t1}
trigger tr1 t1 0 {CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END}
}
}
-}
-
-#-------------------------------------------------------------------------
-# Test that passing a NULL value as the second argument to
-# sqlite3rbu_vacuum() causes it to:
-#
-# * Use -vacuum as the state db, and
-# * Set the state db permissions to the same as those on the db file.
-#
-db close
-if {$::tcl_platform(platform)=="unix"} {
- forcedelete test.db
-
- sqlite3 db test.db
- do_execsql_test 5.0 {
- CREATE TABLE t1(a, b);
- INSERT INTO t1 VALUES(1, 2);
- INSERT INTO t1 VALUES(3, 4);
- INSERT INTO t1 VALUES(5, 6);
- INSERT INTO t1 VALUES(7, 8);
- }
- db close
-
- foreach {tn perm} {
- 1 00755
- 2 00666
- 3 00644
- 4 00444
- } {
- forcedelete test.db-vacuum
-
- do_test 5.$tn.1 {
- file attributes test.db -permissions $perm
- sqlite3rbu_vacuum rbu test.db
- rbu step
- } {SQLITE_OK}
-
- do_test 5.$tn.2 { file exists test.db-vacuum } 1
- do_test 5.$tn.3 { file attributes test.db-vacuum -permissions} $perm
- rbu close
- }
-}
-
-
-finish_test
-
+
+}
+
+finish_test
Index: ext/rbu/sqlite3rbu.c
==================================================================
--- ext/rbu/sqlite3rbu.c
+++ ext/rbu/sqlite3rbu.c
@@ -2332,22 +2332,19 @@
/*
** Open the database handle and attach the RBU database as "rbu". If an
** error occurs, leave an error code and message in the RBU handle.
*/
static void rbuOpenDatabase(sqlite3rbu *p){
- assert( p->rc || (p->dbMain==0 && p->dbRbu==0) );
- assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 );
+ assert( p->rc==SQLITE_OK );
+ assert( p->dbMain==0 && p->dbRbu==0 );
+ assert( rbuIsVacuum(p) || p->zTarget!=0 );
/* Open the RBU database */
p->dbRbu = rbuOpenDbhandle(p, p->zRbu, 1);
if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){
sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p);
- if( p->zState==0 ){
- const char *zFile = sqlite3_db_filename(p->dbRbu, "main");
- p->zState = rbuMPrintf(p, "file://%s-vacuum?modeof=%s", zFile, zFile);
- }
}
/* If using separate RBU and state databases, attach the state database to
** the RBU db handle now. */
if( p->zState ){
@@ -2598,18 +2595,20 @@
p->eStage = RBU_STAGE_CAPTURE;
rc2 = sqlite3_exec(p->dbMain, "PRAGMA main.wal_checkpoint=restart", 0, 0,0);
if( rc2!=SQLITE_INTERNAL ) p->rc = rc2;
}
- if( p->rc==SQLITE_OK ){
+ if( p->rc==SQLITE_OK && p->nFrame>0 ){
p->eStage = RBU_STAGE_CKPT;
p->nStep = (pState ? pState->nRow : 0);
p->aBuf = rbuMalloc(p, p->pgsz);
p->iWalCksum = rbuShmChecksum(p);
}
- if( p->rc==SQLITE_OK && pState && pState->iWalCksum!=p->iWalCksum ){
+ if( p->rc==SQLITE_OK
+ && (p->nFrame==0 || (pState && pState->iWalCksum!=p->iWalCksum))
+ ){
p->rc = SQLITE_DONE;
p->eStage = RBU_STAGE_DONE;
}
}
@@ -3478,11 +3477,12 @@
const char *zState
){
sqlite3rbu *p;
size_t nTarget = zTarget ? strlen(zTarget) : 0;
size_t nRbu = strlen(zRbu);
- size_t nByte = sizeof(sqlite3rbu) + nTarget+1 + nRbu+1;
+ size_t nState = zState ? strlen(zState) : 0;
+ size_t nByte = sizeof(sqlite3rbu) + nTarget+1 + nRbu+1+ nState+1;
p = (sqlite3rbu*)sqlite3_malloc64(nByte);
if( p ){
RbuState *pState = 0;
@@ -3500,11 +3500,12 @@
}
p->zRbu = pCsr;
memcpy(p->zRbu, zRbu, nRbu+1);
pCsr += nRbu+1;
if( zState ){
- p->zState = rbuMPrintf(p, "%s", zState);
+ p->zState = pCsr;
+ memcpy(p->zState, zState, nState+1);
}
rbuOpenDatabase(p);
}
if( p->rc==SQLITE_OK ){
@@ -3610,33 +3611,18 @@
}
return p;
}
-/*
-** Allocate and return an RBU handle with all fields zeroed except for the
-** error code, which is set to SQLITE_MISUSE.
-*/
-static sqlite3rbu *rbuMisuseError(void){
- sqlite3rbu *pRet;
- pRet = sqlite3_malloc64(sizeof(sqlite3rbu));
- if( pRet ){
- memset(pRet, 0, sizeof(sqlite3rbu));
- pRet->rc = SQLITE_MISUSE;
- }
- return pRet;
-}
-
/*
** Open and return a new RBU handle.
*/
sqlite3rbu *sqlite3rbu_open(
const char *zTarget,
const char *zRbu,
const char *zState
){
- if( zTarget==0 || zRbu==0 ){ return rbuMisuseError(); }
/* TODO: Check that zTarget and zRbu are non-NULL */
return openRbuHandle(zTarget, zRbu, zState);
}
/*
@@ -3644,11 +3630,10 @@
*/
sqlite3rbu *sqlite3rbu_vacuum(
const char *zTarget,
const char *zState
){
- if( zTarget==0 ){ return rbuMisuseError(); }
/* TODO: Check that both arguments are non-NULL */
return openRbuHandle(0, zTarget, zState);
}
/*
@@ -3722,11 +3707,10 @@
sqlite3_free(p->aFrame);
rbuEditErrmsg(p);
rc = p->rc;
*pzErrmsg = p->zErrmsg;
- sqlite3_free(p->zState);
sqlite3_free(p);
}else{
rc = SQLITE_NOMEM;
*pzErrmsg = 0;
}
Index: ext/rbu/sqlite3rbu.h
==================================================================
--- ext/rbu/sqlite3rbu.h
+++ ext/rbu/sqlite3rbu.h
@@ -102,11 +102,11 @@
**
** Instead of the plain data_ naming scheme, RBU database tables
** may also be named data_, where is any sequence
** of zero or more numeric characters (0-9). This can be significant because
** tables within the RBU database are always processed in order sorted by
-** name. By judicious selection of the portion of the names
+** name. By judicious selection of the the portion of the names
** of the RBU tables the user can therefore control the order in which they
** are processed. This can be useful, for example, to ensure that "external
** content" FTS4 tables are updated before their underlying content tables.
**
** If the target database table is a virtual table or a table that has no
@@ -317,26 +317,20 @@
/*
** Open an RBU handle to perform an RBU vacuum on database file zTarget.
** An RBU vacuum is similar to SQLite's built-in VACUUM command, except
** that it can be suspended and resumed like an RBU update.
**
-** The second argument to this function identifies a database in which
-** to store the state of the RBU vacuum operation if it is suspended. The
-** first time sqlite3rbu_vacuum() is called, to start an RBU vacuum
-** operation, the state database should either not exist or be empty
-** (contain no tables). If an RBU vacuum is suspended by calling
+** The second argument to this function, which may not be NULL, identifies
+** a database in which to store the state of the RBU vacuum operation if
+** it is suspended. The first time sqlite3rbu_vacuum() is called, to start
+** an RBU vacuum operation, the state database should either not exist or
+** be empty (contain no tables). If an RBU vacuum is suspended by calling
** sqlite3rbu_close() on the RBU handle before sqlite3rbu_step() has
** returned SQLITE_DONE, the vacuum state is stored in the state database.
** The vacuum can be resumed by calling this function to open a new RBU
** handle specifying the same target and state databases.
**
-** If the second argument passed to this function is NULL, then the
-** name of the state database is "-vacuum", where
-** is the name of the target database file. In this case, on UNIX, if the
-** state database is not already present in the file-system, it is created
-** with the same permissions as the target db is made.
-**
** This function does not delete the state database after an RBU vacuum
** is completed, even if it created it. However, if the call to
** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents
** of the state tables within the state database are zeroed. This way,
** the next call to sqlite3rbu_vacuum() opens a handle that starts a
Index: ext/rbu/test_rbu.c
==================================================================
--- ext/rbu/test_rbu.c
+++ ext/rbu/test_rbu.c
@@ -238,17 +238,17 @@
sqlite3rbu *pRbu = 0;
const char *zCmd;
const char *zTarget;
const char *zStateDb = 0;
- if( objc!=3 && objc!=4 ){
- Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB ?STATE-DB?");
+ if( objc!=4 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB STATE-DB");
return TCL_ERROR;
}
zCmd = Tcl_GetString(objv[1]);
zTarget = Tcl_GetString(objv[2]);
- if( objc==4 ) zStateDb = Tcl_GetString(objv[3]);
+ zStateDb = Tcl_GetString(objv[3]);
pRbu = sqlite3rbu_vacuum(zTarget, zStateDb);
Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0);
Tcl_SetObjResult(interp, objv[1]);
return TCL_OK;
Index: ext/rtree/rtree.c
==================================================================
--- ext/rtree/rtree.c
+++ ext/rtree/rtree.c
@@ -1540,11 +1540,11 @@
pCsr->iStrategy = idxNum;
if( idxNum==1 ){
/* Special case - lookup by rowid. */
RtreeNode *pLeaf; /* Leaf on which the required cell resides */
- RtreeSearchPoint *p; /* Search point for the leaf */
+ RtreeSearchPoint *p; /* Search point for the the leaf */
i64 iRowid = sqlite3_value_int64(argv[0]);
i64 iNode = 0;
rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode);
if( rc==SQLITE_OK && pLeaf!=0 ){
p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0);
Index: ext/session/session_common.tcl
==================================================================
--- ext/session/session_common.tcl
+++ ext/session/session_common.tcl
@@ -73,13 +73,10 @@
execsql $sql db
execsql $sql db2
}
proc changeset_from_sql {sql {dbname main}} {
- if {$dbname == "main"} {
- return [sql_exec_changeset db $sql]
- }
set rc [catch {
sqlite3session S db $dbname
db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" {
S attach $name
}
Index: ext/session/sqlite3session.h
==================================================================
--- ext/session/sqlite3session.h
+++ ext/session/sqlite3session.h
@@ -725,16 +725,16 @@
void **ppOut /* OUT: Buffer containing output changeset */
);
/*
-** CAPI3REF: Changegroup Handle
+** Changegroup handle.
*/
typedef struct sqlite3_changegroup sqlite3_changegroup;
/*
-** CAPI3REF: Create A New Changegroup Object
+** CAPI3REF: Combine two or more changesets into a single changeset.
**
** An sqlite3_changegroup object is used to combine two or more changesets
** (or patchsets) into a single changeset (or patchset). A single changegroup
** object may combine changesets or patchsets, but not both. The output is
** always in the same format as the input.
@@ -767,12 +767,10 @@
** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm().
*/
int sqlite3changegroup_new(sqlite3_changegroup **pp);
/*
-** CAPI3REF: Add A Changeset To A Changegroup
-**
** Add all changes within the changeset (or patchset) in buffer pData (size
** nData bytes) to the changegroup.
**
** If the buffer contains a patchset, then all prior calls to this function
** on the same changegroup object must also have specified patchsets. Or, if
@@ -844,12 +842,10 @@
** If no error occurs, SQLITE_OK is returned.
*/
int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
/*
-** CAPI3REF: Obtain A Composite Changeset From A Changegroup
-**
** Obtain a buffer containing a changeset (or patchset) representing the
** current contents of the changegroup. If the inputs to the changegroup
** were themselves changesets, the output is a changeset. Or, if the
** inputs were patchsets, the output is also a patchset.
**
@@ -874,11 +870,11 @@
int *pnData, /* OUT: Size of output buffer in bytes */
void **ppData /* OUT: Pointer to output buffer */
);
/*
-** CAPI3REF: Delete A Changegroup Object
+** Delete a changegroup object.
*/
void sqlite3changegroup_delete(sqlite3_changegroup*);
/*
** CAPI3REF: Apply A Changeset To A Database
Index: ext/session/test_session.c
==================================================================
--- ext/session/test_session.c
+++ ext/session/test_session.c
@@ -26,111 +26,10 @@
int nStream; /* Maximum chunk size */
unsigned char *aData; /* Pointer to buffer containing data */
int nData; /* Size of buffer aData in bytes */
int iData; /* Bytes of data already read by sessions */
};
-
-/*
-** Extract an sqlite3* db handle from the object passed as the second
-** argument. If successful, set *pDb to point to the db handle and return
-** TCL_OK. Otherwise, return TCL_ERROR.
-*/
-static int dbHandleFromObj(Tcl_Interp *interp, Tcl_Obj *pObj, sqlite3 **pDb){
- Tcl_CmdInfo info;
- if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(pObj), &info) ){
- Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(pObj), 0);
- return TCL_ERROR;
- }
-
- *pDb = *(sqlite3 **)info.objClientData;
- return TCL_OK;
-}
-
-/*************************************************************************
-** The following code is copied byte-for-byte from the sessions module
-** documentation. It is used by some of the sessions modules tests to
-** ensure that the example in the documentation does actually work.
-*/
-/*
-** Argument zSql points to a buffer containing an SQL script to execute
-** against the database handle passed as the first argument. As well as
-** executing the SQL script, this function collects a changeset recording
-** all changes made to the "main" database file. Assuming no error occurs,
-** output variables (*ppChangeset) and (*pnChangeset) are set to point
-** to a buffer containing the changeset and the size of the changeset in
-** bytes before returning SQLITE_OK. In this case it is the responsibility
-** of the caller to eventually free the changeset blob by passing it to
-** the sqlite3_free function.
-**
-** Or, if an error does occur, return an SQLite error code. The final
-** value of (*pChangeset) and (*pnChangeset) are undefined in this case.
-*/
-int sql_exec_changeset(
- sqlite3 *db, /* Database handle */
- const char *zSql, /* SQL script to execute */
- int *pnChangeset, /* OUT: Size of changeset blob in bytes */
- void **ppChangeset /* OUT: Pointer to changeset blob */
-){
- sqlite3_session *pSession = 0;
- int rc;
-
- /* Create a new session object */
- rc = sqlite3session_create(db, "main", &pSession);
-
- /* Configure the session object to record changes to all tables */
- if( rc==SQLITE_OK ) rc = sqlite3session_attach(pSession, NULL);
-
- /* Execute the SQL script */
- if( rc==SQLITE_OK ) rc = sqlite3_exec(db, zSql, 0, 0, 0);
-
- /* Collect the changeset */
- if( rc==SQLITE_OK ){
- rc = sqlite3session_changeset(pSession, pnChangeset, ppChangeset);
- }
-
- /* Delete the session object */
- sqlite3session_delete(pSession);
-
- return rc;
-}
-/************************************************************************/
-
-/*
-** Tclcmd: sql_exec_changeset DB SQL
-*/
-static int SQLITE_TCLAPI test_sql_exec_changeset(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- const char *zSql;
- sqlite3 *db;
- void *pChangeset;
- int nChangeset;
- int rc;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB SQL");
- return TCL_ERROR;
- }
- if( dbHandleFromObj(interp, objv[1], &db) ) return TCL_ERROR;
- zSql = (const char*)Tcl_GetString(objv[2]);
-
- rc = sql_exec_changeset(db, zSql, &nChangeset, &pChangeset);
- if( rc!=SQLITE_OK ){
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "error in sql_exec_changeset()", 0);
- return TCL_ERROR;
- }
-
- Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pChangeset, nChangeset));
- sqlite3_free(pChangeset);
- return TCL_OK;
-}
-
-
#define SESSION_STREAM_TCL_VAR "sqlite3session_streams"
/*
** Attempt to find the global variable zVar within interpreter interp
@@ -1018,29 +917,26 @@
return TCL_OK;
}
int TestSession_Init(Tcl_Interp *interp){
- struct Cmd {
- const char *zCmd;
- Tcl_ObjCmdProc *xProc;
- } aCmd[] = {
- { "sqlite3session", test_sqlite3session },
- { "sqlite3session_foreach", test_sqlite3session_foreach },
- { "sqlite3changeset_invert", test_sqlite3changeset_invert },
- { "sqlite3changeset_concat", test_sqlite3changeset_concat },
- { "sqlite3changeset_apply", test_sqlite3changeset_apply },
- { "sqlite3changeset_apply_replace_all",
- test_sqlite3changeset_apply_replace_all },
- { "sql_exec_changeset", test_sql_exec_changeset },
- };
- int i;
-
- for(i=0; izCmd, p->xProc, 0, 0);
- }
-
+ Tcl_CreateObjCommand(interp, "sqlite3session", test_sqlite3session, 0, 0);
+ Tcl_CreateObjCommand(
+ interp, "sqlite3session_foreach", test_sqlite3session_foreach, 0, 0
+ );
+ Tcl_CreateObjCommand(
+ interp, "sqlite3changeset_invert", test_sqlite3changeset_invert, 0, 0
+ );
+ Tcl_CreateObjCommand(
+ interp, "sqlite3changeset_concat", test_sqlite3changeset_concat, 0, 0
+ );
+ Tcl_CreateObjCommand(
+ interp, "sqlite3changeset_apply", test_sqlite3changeset_apply, 0, 0
+ );
+ Tcl_CreateObjCommand(
+ interp, "sqlite3changeset_apply_replace_all",
+ test_sqlite3changeset_apply_replace_all, 0, 0
+ );
return TCL_OK;
}
#endif /* SQLITE_TEST && SQLITE_SESSION && SQLITE_PREUPDATE_HOOK */
Index: src/alter.c
==================================================================
--- src/alter.c
+++ src/alter.c
@@ -411,11 +411,11 @@
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
if( !pTab ) goto exit_rename_table;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- zDb = db->aDb[iDb].zDbSName;
+ zDb = db->aDb[iDb].zName;
db->flags |= SQLITE_PreferBuiltin;
/* Get a NULL terminated version of the new table name. */
zName = sqlite3NameFromToken(db, pName);
if( !zName ) goto exit_rename_table;
@@ -609,11 +609,11 @@
pNew = pParse->pNewTable;
assert( pNew );
assert( sqlite3BtreeHoldsAllMutexes(db) );
iDb = sqlite3SchemaToIndex(db, pNew->pSchema);
- zDb = db->aDb[iDb].zDbSName;
+ zDb = db->aDb[iDb].zName;
zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */
pCol = &pNew->aCol[pNew->nCol-1];
pDflt = pCol->pDflt;
pTab = sqlite3FindTable(db, zTab, zDb);
assert( pTab );
Index: src/analyze.c
==================================================================
--- src/analyze.c
+++ src/analyze.c
@@ -208,18 +208,18 @@
** if they do already exist.
*/
for(i=0; izDbSName))==0 ){
+ if( (pStat = sqlite3FindTable(db, zTab, pDb->zName))==0 ){
if( aTable[i].zCols ){
/* The sqlite_statN table does not exist. Create it. Note that a
** side-effect of the CREATE TABLE statement is to leave the rootpage
** of the new table in register pParse->regRoot. This is important
** because the OpenWrite opcode below will be needing it. */
sqlite3NestedParse(pParse,
- "CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols
+ "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
);
aRoot[i] = pParse->regRoot;
aCreateTbl[i] = OPFLAG_P2ISREG;
}
}else{
@@ -230,11 +230,11 @@
aCreateTbl[i] = 0;
sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
if( zWhere ){
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE %s=%Q",
- pDb->zDbSName, zTab, zWhereType, zWhere
+ pDb->zName, zTab, zWhereType, zWhere
);
}else{
/* The sqlite_stat[134] table already exists. Delete all rows. */
sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb);
}
@@ -992,11 +992,11 @@
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb>=0 );
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
#ifndef SQLITE_OMIT_AUTHORIZATION
if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0,
- db->aDb[iDb].zDbSName ) ){
+ db->aDb[iDb].zName ) ){
return;
}
#endif
/* Establish a read-lock on the table at the shared-cache level.
@@ -1382,11 +1382,11 @@
}
}else{
/* Form 3: Analyze the fully qualified table name */
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName);
if( iDb>=0 ){
- zDb = db->aDb[iDb].zDbSName;
+ zDb = db->aDb[iDb].zName;
z = sqlite3NameFromToken(db, pTableName);
if( z ){
if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){
analyzeTable(pParse, pIdx->pTable, pIdx);
}else if( (pTab = sqlite3LocateTable(pParse, 0, z, zDb))!=0 ){
@@ -1842,11 +1842,11 @@
#endif
}
/* Load new statistics out of the sqlite_stat1 table */
sInfo.db = db;
- sInfo.zDatabase = db->aDb[iDb].zDbSName;
+ sInfo.zDatabase = db->aDb[iDb].zName;
if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)!=0 ){
zSql = sqlite3MPrintf(db,
"SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
if( zSql==0 ){
rc = SQLITE_NOMEM_BKPT;
Index: src/attach.c
==================================================================
--- src/attach.c
+++ src/attach.c
@@ -95,11 +95,11 @@
if( !db->autoCommit ){
zErrDyn = sqlite3MPrintf(db, "cannot ATTACH database within transaction");
goto attach_error;
}
for(i=0; inDb; i++){
- char *z = db->aDb[i].zDbSName;
+ char *z = db->aDb[i].zName;
assert( z && zName );
if( sqlite3StrICmp(z, zName)==0 ){
zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
goto attach_error;
}
@@ -160,12 +160,12 @@
PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK));
#endif
sqlite3BtreeLeave(aNew->pBt);
}
aNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
- aNew->zDbSName = sqlite3DbStrDup(db, zName);
- if( rc==SQLITE_OK && aNew->zDbSName==0 ){
+ aNew->zName = sqlite3DbStrDup(db, zName);
+ if( rc==SQLITE_OK && aNew->zName==0 ){
rc = SQLITE_NOMEM_BKPT;
}
#ifdef SQLITE_HAS_CODEC
@@ -273,11 +273,11 @@
if( zName==0 ) zName = "";
for(i=0; inDb; i++){
pDb = &db->aDb[i];
if( pDb->pBt==0 ) continue;
- if( sqlite3StrICmp(pDb->zDbSName, zName)==0 ) break;
+ if( sqlite3StrICmp(pDb->zName, zName)==0 ) break;
}
if( i>=db->nDb ){
sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName);
goto detach_error;
@@ -431,11 +431,11 @@
sqlite3 *db;
db = pParse->db;
assert( db->nDb>iDb );
pFix->pParse = pParse;
- pFix->zDb = db->aDb[iDb].zDbSName;
+ pFix->zDb = db->aDb[iDb].zName;
pFix->pSchema = db->aDb[iDb].pSchema;
pFix->zType = zType;
pFix->pName = pName;
pFix->bVarOnly = (iDb==1);
}
Index: src/auth.c
==================================================================
--- src/auth.c
+++ src/auth.c
@@ -105,13 +105,13 @@
Parse *pParse, /* The parser context */
const char *zTab, /* Table name */
const char *zCol, /* Column name */
int iDb /* Index of containing database. */
){
- sqlite3 *db = pParse->db; /* Database handle */
- char *zDb = db->aDb[iDb].zDbSName; /* Schema name of attached database */
- int rc; /* Auth callback return code */
+ sqlite3 *db = pParse->db; /* Database handle */
+ char *zDb = db->aDb[iDb].zName; /* Name of attached database */
+ int rc; /* Auth callback return code */
if( db->init.busy ) return SQLITE_OK;
rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext
#ifdef SQLITE_USER_AUTHENTICATION
,db->auth.zAuthUser
Index: src/backup.c
==================================================================
--- src/backup.c
+++ src/backup.c
@@ -194,10 +194,11 @@
p->pSrcDb = pSrcDb;
p->iNext = 1;
p->isAttached = 0;
if( 0==p->pSrc || 0==p->pDest
+ || setDestPgsz(p)==SQLITE_NOMEM
|| checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK
){
/* One (or both) of the named databases did not exist or an OOM
** error was hit. Or there is a transaction open on the destination
** database. The error has already been written into the pDestDb
@@ -380,10 +381,18 @@
if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){
rc = SQLITE_BUSY;
}else{
rc = SQLITE_OK;
}
+
+ /* Lock the destination database, if it is not locked already. */
+ if( SQLITE_OK==rc && p->bDestLocked==0
+ && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2))
+ ){
+ p->bDestLocked = 1;
+ sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema);
+ }
/* If there is no open read-transaction on the source database, open
** one now. If a transaction is opened here, then it will be closed
** before this function exits.
*/
@@ -390,28 +399,10 @@
if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){
rc = sqlite3BtreeBeginTrans(p->pSrc, 0);
bCloseTrans = 1;
}
- /* If the destination database has not yet been locked (i.e. if this
- ** is the first call to backup_step() for the current backup operation),
- ** try to set its page size to the same as the source database. This
- ** is especially important on ZipVFS systems, as in that case it is
- ** not possible to create a database file that uses one page size by
- ** writing to it with another. */
- if( p->bDestLocked==0 && rc==SQLITE_OK && setDestPgsz(p)==SQLITE_NOMEM ){
- rc = SQLITE_NOMEM;
- }
-
- /* Lock the destination database, if it is not locked already. */
- if( SQLITE_OK==rc && p->bDestLocked==0
- && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2))
- ){
- p->bDestLocked = 1;
- sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema);
- }
-
/* Do not allow backup if the destination database is in WAL mode
** and the page sizes are different between source and destination */
pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
pgszDest = sqlite3BtreeGetPageSize(p->pDest);
destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest));
Index: src/build.c
==================================================================
--- src/build.c
+++ src/build.c
@@ -151,12 +151,12 @@
#if SQLITE_USER_AUTHENTICATION
if( pParse->nTableLock>0 && db->init.busy==0 ){
sqlite3UserAuthInit(db);
if( db->auth.authLevelrc = SQLITE_AUTH_USER;
+ sqlite3ErrorMsg(pParse, "user not authenticated");
return;
}
}
#endif
@@ -316,15 +316,14 @@
return 0;
}
#endif
for(i=OMIT_TEMPDB; inDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
- if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){
- assert( sqlite3SchemaMutexHeld(db, j, 0) );
- p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
- if( p ) break;
- }
+ if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue;
+ assert( sqlite3SchemaMutexHeld(db, j, 0) );
+ p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
+ if( p ) break;
}
return p;
}
/*
@@ -394,11 +393,11 @@
){
const char *zDb;
assert( p->pSchema==0 || p->zDatabase==0 );
if( p->pSchema ){
int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
- zDb = pParse->db->aDb[iDb].zDbSName;
+ zDb = pParse->db->aDb[iDb].zName;
}else{
zDb = p->zDatabase;
}
return sqlite3LocateTable(pParse, flags, p->zName, zDb);
}
@@ -422,11 +421,11 @@
assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
for(i=OMIT_TEMPDB; inDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
Schema *pSchema = db->aDb[j].pSchema;
assert( pSchema );
- if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zDbSName) ) continue;
+ if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue;
assert( sqlite3SchemaMutexHeld(db, j, 0) );
p = sqlite3HashFind(&pSchema->idxHash, zName);
if( p ) break;
}
return p;
@@ -491,12 +490,12 @@
void sqlite3CollapseDatabaseArray(sqlite3 *db){
int i, j;
for(i=j=2; inDb; i++){
struct Db *pDb = &db->aDb[i];
if( pDb->pBt==0 ){
- sqlite3DbFree(db, pDb->zDbSName);
- pDb->zDbSName = 0;
+ sqlite3DbFree(db, pDb->zName);
+ pDb->zName = 0;
continue;
}
if( jaDb[j] = db->aDb[i];
}
@@ -712,11 +711,11 @@
int sqlite3FindDbName(sqlite3 *db, const char *zName){
int i = -1; /* Database number */
if( zName ){
Db *pDb;
for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){
- if( 0==sqlite3StrICmp(pDb->zDbSName, zName) ) break;
+ if( 0==sqlite3StrICmp(pDb->zName, zName) ) break;
}
}
return i;
}
@@ -771,11 +770,11 @@
if( iDb<0 ){
sqlite3ErrorMsg(pParse, "unknown database %T", pName1);
return -1;
}
}else{
- assert( db->init.iDb==0 || db->init.busy || (db->flags & SQLITE_Vacuum)!=0);
+ assert( db->init.iDb==0 || db->init.busy );
iDb = db->init.iDb;
*pUnqual = pName1;
}
return iDb;
}
@@ -882,11 +881,11 @@
SQLITE_CREATE_TABLE,
SQLITE_CREATE_TEMP_TABLE,
SQLITE_CREATE_VIEW,
SQLITE_CREATE_TEMP_VIEW
};
- char *zDb = db->aDb[iDb].zDbSName;
+ char *zDb = db->aDb[iDb].zName;
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
goto begin_table_error;
}
if( !isVirtual && sqlite3AuthCheck(pParse, (int)aCode[isTemp+2*isView],
zName, 0, zDb) ){
@@ -901,11 +900,11 @@
** to an sqlite3_declare_vtab() call. In that case only the column names
** and types will be used, so there is no need to test for namespace
** collisions.
*/
if( !IN_DECLARE_VTAB ){
- char *zDb = db->aDb[iDb].zDbSName;
+ char *zDb = db->aDb[iDb].zName;
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto begin_table_error;
}
pTable = sqlite3FindTable(db, zName, zDb);
if( pTable ){
@@ -1994,11 +1993,11 @@
*/
sqlite3NestedParse(pParse,
"UPDATE %Q.%s "
"SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q "
"WHERE rowid=#%d",
- db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb),
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
zType,
p->zName,
p->zName,
pParse->regRoot,
zStmt,
@@ -2009,17 +2008,17 @@
#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Check to see if we need to create an sqlite_sequence table for
** keeping track of autoincrement keys.
*/
- if( (p->tabFlags & TF_Autoincrement)!=0 ){
+ if( p->tabFlags & TF_Autoincrement ){
Db *pDb = &db->aDb[iDb];
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( pDb->pSchema->pSeqTab==0 ){
sqlite3NestedParse(pParse,
"CREATE TABLE %Q.sqlite_sequence(name,seq)",
- pDb->zDbSName
+ pDb->zName
);
}
}
#endif
@@ -2329,11 +2328,11 @@
** is in register NNN. See grammar rules associated with the TK_REGISTER
** token for additional information.
*/
sqlite3NestedParse(pParse,
"UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
- pParse->db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), iTable, r1, r1);
+ pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable, r1, r1);
#endif
sqlite3ReleaseTempReg(pParse, r1);
}
/*
@@ -2405,11 +2404,11 @@
int iDb, /* The database number */
const char *zType, /* "idx" or "tbl" */
const char *zName /* Name of index or table */
){
int i;
- const char *zDbName = pParse->db->aDb[iDb].zDbSName;
+ const char *zDbName = pParse->db->aDb[iDb].zName;
for(i=1; i<=4; i++){
char zTab[24];
sqlite3_snprintf(sizeof(zTab),zTab,"sqlite_stat%d",i);
if( sqlite3FindTable(pParse->db, zTab, zDbName) ){
sqlite3NestedParse(pParse,
@@ -2458,11 +2457,11 @@
** move as a result of the drop (can happen in auto-vacuum mode).
*/
if( pTab->tabFlags & TF_Autoincrement ){
sqlite3NestedParse(pParse,
"DELETE FROM %Q.sqlite_sequence WHERE name=%Q",
- pDb->zDbSName, pTab->zName
+ pDb->zName, pTab->zName
);
}
#endif
/* Drop all SQLITE_MASTER table and index entries that refer to the
@@ -2472,11 +2471,11 @@
** created in the temp database that refers to a table in another
** database.
*/
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
- pDb->zDbSName, SCHEMA_TABLE(iDb), pTab->zName);
+ pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
if( !isView && !IsVirtual(pTab) ){
destroyTable(pParse, pTab);
}
/* Remove the table entry from SQLite's internal schema and modify
@@ -2526,11 +2525,11 @@
}
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code;
const char *zTab = SCHEMA_TABLE(iDb);
- const char *zDb = db->aDb[iDb].zDbSName;
+ const char *zDb = db->aDb[iDb].zName;
const char *zArg2 = 0;
if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){
goto exit_drop_table;
}
if( isView ){
@@ -2767,11 +2766,11 @@
sqlite3 *db = pParse->db; /* The database connection */
int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
#ifndef SQLITE_OMIT_AUTHORIZATION
if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
- db->aDb[iDb].zDbSName ) ){
+ db->aDb[iDb].zName ) ){
return;
}
#endif
/* Require a write-lock on the table to perform this operation */
@@ -3019,11 +3018,11 @@
if( sqlite3FindTable(db, zName, 0)!=0 ){
sqlite3ErrorMsg(pParse, "there is already a table named %s", zName);
goto exit_create_index;
}
}
- if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){
+ if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){
if( !ifNotExist ){
sqlite3ErrorMsg(pParse, "index %s already exists", zName);
}else{
assert( !db->init.busy );
sqlite3CodeVerifySchema(pParse, iDb);
@@ -3049,11 +3048,11 @@
/* Check for authorization to create an index.
*/
#ifndef SQLITE_OMIT_AUTHORIZATION
{
- const char *zDb = pDb->zDbSName;
+ const char *zDb = pDb->zName;
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){
goto exit_create_index;
}
i = SQLITE_CREATE_INDEX;
if( !OMIT_TEMPDB && iDb==1 ) i = SQLITE_CREATE_TEMP_INDEX;
@@ -3364,11 +3363,11 @@
/* Add an entry in sqlite_master for this index
*/
sqlite3NestedParse(pParse,
"INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
- db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb),
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
pIndex->zName,
pTab->zName,
iMem,
zStmt
);
@@ -3498,11 +3497,11 @@
iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_DROP_INDEX;
Table *pTab = pIndex->pTable;
- const char *zDb = db->aDb[iDb].zDbSName;
+ const char *zDb = db->aDb[iDb].zName;
const char *zTab = SCHEMA_TABLE(iDb);
if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
goto exit_drop_index;
}
if( !OMIT_TEMPDB && iDb ) code = SQLITE_DROP_TEMP_INDEX;
@@ -3516,11 +3515,11 @@
v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3BeginWriteOperation(pParse, 1, iDb);
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
- db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pIndex->zName
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pIndex->zName
);
sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
sqlite3ChangeCookie(pParse, iDb);
destroyRootPage(pParse, pIndex->tnum, iDb);
sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
@@ -4061,11 +4060,11 @@
void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb){
sqlite3 *db = pParse->db;
int i;
for(i=0; inDb; i++){
Db *pDb = &db->aDb[i];
- if( pDb->pBt && (!zDb || 0==sqlite3StrICmp(zDb, pDb->zDbSName)) ){
+ if( pDb->pBt && (!zDb || 0==sqlite3StrICmp(zDb, pDb->zName)) ){
sqlite3CodeVerifySchema(pParse, i);
}
}
}
@@ -4308,11 +4307,11 @@
}
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName);
if( iDb<0 ) return;
z = sqlite3NameFromToken(db, pObjName);
if( z==0 ) return;
- zDb = db->aDb[iDb].zDbSName;
+ zDb = db->aDb[iDb].zName;
pTab = sqlite3FindTable(db, z, zDb);
if( pTab ){
reindexTable(pParse, pTab, 0);
sqlite3DbFree(db, z);
return;
Index: src/dbstat.c
==================================================================
--- src/dbstat.c
+++ src/dbstat.c
@@ -600,11 +600,11 @@
zSql = sqlite3_mprintf(
"SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
" UNION ALL "
"SELECT name, rootpage, type"
" FROM \"%w\".%s WHERE rootpage!=0"
- " ORDER BY name", pTab->db->aDb[pCsr->iDb].zDbSName, zMaster);
+ " ORDER BY name", pTab->db->aDb[pCsr->iDb].zName, zMaster);
if( zSql==0 ){
return SQLITE_NOMEM_BKPT;
}else{
rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
@@ -654,11 +654,11 @@
sqlite3_result_int(ctx, pCsr->szPage);
break;
default: { /* schema */
sqlite3 *db = sqlite3_context_db_handle(ctx);
int iDb = pCsr->iDb;
- sqlite3_result_text(ctx, db->aDb[iDb].zDbSName, -1, SQLITE_STATIC);
+ sqlite3_result_text(ctx, db->aDb[iDb].zName, -1, SQLITE_STATIC);
break;
}
}
return SQLITE_OK;
}
Index: src/delete.c
==================================================================
--- src/delete.c
+++ src/delete.c
@@ -100,11 +100,11 @@
pWhere = sqlite3ExprDup(db, pWhere, 0);
pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
if( pFrom ){
assert( pFrom->nSrc==1 );
pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
- pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
+ pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName);
assert( pFrom->a[0].pOn==0 );
assert( pFrom->a[0].pUsing==0 );
}
pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0,
SF_IncludeHidden, 0, 0);
@@ -287,11 +287,11 @@
if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){
goto delete_from_cleanup;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDbnDb );
- zDb = db->aDb[iDb].zDbSName;
+ zDb = db->aDb[iDb].zName;
rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb);
assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE );
if( rcauth==SQLITE_DENY ){
goto delete_from_cleanup;
}
Index: src/fkey.c
==================================================================
--- src/fkey.c
+++ src/fkey.c
@@ -869,11 +869,11 @@
/* If foreign-keys are disabled, this function is a no-op. */
if( (db->flags&SQLITE_ForeignKeys)==0 ) return;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- zDb = db->aDb[iDb].zDbSName;
+ zDb = db->aDb[iDb].zName;
/* Loop through all the foreign key constraints for which pTab is the
** child table (the table that the foreign key definition is part of). */
for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
Table *pTo; /* Parent table of foreign key pFKey */
Index: src/insert.c
==================================================================
--- src/insert.c
+++ src/insert.c
@@ -198,13 +198,11 @@
#ifndef SQLITE_OMIT_AUTOINCREMENT
/*
** Locate or create an AutoincInfo structure associated with table pTab
** which is in database iDb. Return the register number for the register
-** that holds the maximum rowid. Return zero if pTab is not an AUTOINCREMENT
-** table. (Also return zero when doing a VACUUM since we do not want to
-** update the AUTOINCREMENT counters during a VACUUM.)
+** that holds the maximum rowid.
**
** There is at most one AutoincInfo structure per table even if the
** same table is autoincremented multiple times due to inserts within
** triggers. A new AutoincInfo structure is created if this is the
** first use of table pTab. On 2nd and subsequent uses, the original
@@ -223,13 +221,11 @@
Parse *pParse, /* Parsing context */
int iDb, /* Index of the database holding pTab */
Table *pTab /* The table we are writing to */
){
int memId = 0; /* Register holding maximum rowid */
- if( (pTab->tabFlags & TF_Autoincrement)!=0
- && (pParse->db->flags & SQLITE_Vacuum)==0
- ){
+ if( pTab->tabFlags & TF_Autoincrement ){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
AutoincInfo *pInfo;
pInfo = pToplevel->pAinc;
while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
@@ -549,11 +545,11 @@
goto insert_cleanup;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDbnDb );
pDb = &db->aDb[iDb];
- zDb = pDb->zDbSName;
+ zDb = pDb->zName;
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
goto insert_cleanup;
}
withoutRowid = !HasRowid(pTab);
Index: src/main.c
==================================================================
--- src/main.c
+++ src/main.c
@@ -787,15 +787,10 @@
int sqlite3_db_config(sqlite3 *db, int op, ...){
va_list ap;
int rc;
va_start(ap, op);
switch( op ){
- case SQLITE_DBCONFIG_MAINDBNAME: {
- db->aDb[0].zDbSName = va_arg(ap,char*);
- rc = SQLITE_OK;
- break;
- }
case SQLITE_DBCONFIG_LOOKASIDE: {
void *pBuf = va_arg(ap, void*); /* IMP: R-26835-10964 */
int sz = va_arg(ap, int); /* IMP: R-47871-25994 */
int cnt = va_arg(ap, int); /* IMP: R-04460-53386 */
rc = setupLookaside(db, pBuf, sz, cnt);
@@ -2937,13 +2932,13 @@
db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
/* The default safety_level for the main database is FULL; for the temp
** database it is OFF. This matches the pager layer defaults.
*/
- db->aDb[0].zDbSName = "main";
+ db->aDb[0].zName = "main";
db->aDb[0].safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
- db->aDb[1].zDbSName = "temp";
+ db->aDb[1].zName = "temp";
db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF;
db->magic = SQLITE_MAGIC_OPEN;
if( db->mallocFailed ){
goto opendb_out;
@@ -2953,24 +2948,15 @@
** database schema yet. This is delayed until the first time the database
** is accessed.
*/
sqlite3Error(db, SQLITE_OK);
sqlite3RegisterPerConnectionBuiltinFunctions(db);
- rc = sqlite3_errcode(db);
-
-#ifdef SQLITE_ENABLE_FTS5
- /* Register any built-in FTS5 module before loading the automatic
- ** extensions. This allows automatic extensions to register FTS5
- ** tokenizers and auxiliary functions. */
- if( !db->mallocFailed && rc==SQLITE_OK ){
- rc = sqlite3Fts5Init(db);
- }
-#endif
/* Load automatic extensions - extensions that have been registered
** using the sqlite3_automatic_extension() API.
*/
+ rc = sqlite3_errcode(db);
if( rc==SQLITE_OK ){
sqlite3AutoLoadExtensions(db);
rc = sqlite3_errcode(db);
if( rc!=SQLITE_OK ){
goto opendb_out;
@@ -2994,10 +2980,16 @@
#ifdef SQLITE_ENABLE_FTS3 /* automatically defined by SQLITE_ENABLE_FTS4 */
if( !db->mallocFailed && rc==SQLITE_OK ){
rc = sqlite3Fts3Init(db);
}
#endif
+
+#ifdef SQLITE_ENABLE_FTS5
+ if( !db->mallocFailed && rc==SQLITE_OK ){
+ rc = sqlite3Fts5Init(db);
+ }
+#endif
#ifdef SQLITE_ENABLE_ICU
if( !db->mallocFailed && rc==SQLITE_OK ){
rc = sqlite3IcuInit(db);
}
@@ -3903,11 +3895,11 @@
*/
Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
int i;
for(i=0; inDb; i++){
if( db->aDb[i].pBt
- && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zDbSName)==0)
+ && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zName)==0)
){
return db->aDb[i].pBt;
}
}
return 0;
Index: src/os_unix.c
==================================================================
--- src/os_unix.c
+++ src/os_unix.c
@@ -5527,31 +5527,10 @@
}
#endif /* if !OS_VXWORKS */
return pUnused;
}
-/*
-** Find the mode, uid and gid of file zFile.
-*/
-static int getFileMode(
- const char *zFile, /* File name */
- mode_t *pMode, /* OUT: Permissions of zFile */
- uid_t *pUid, /* OUT: uid of zFile. */
- gid_t *pGid /* OUT: gid of zFile. */
-){
- struct stat sStat; /* Output of stat() on database file */
- int rc = SQLITE_OK;
- if( 0==osStat(zFile, &sStat) ){
- *pMode = sStat.st_mode & 0777;
- *pUid = sStat.st_uid;
- *pGid = sStat.st_gid;
- }else{
- rc = SQLITE_IOERR_FSTAT;
- }
- return rc;
-}
-
/*
** This function is called by unixOpen() to determine the unix permissions
** to create new files with. If no error occurs, then SQLITE_OK is returned
** and a value suitable for passing as the third argument to open(2) is
** written to *pMode. If an IO error occurs, an SQLite error code is
@@ -5583,10 +5562,11 @@
*pUid = 0;
*pGid = 0;
if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
char zDb[MAX_PATHNAME+1]; /* Database file path */
int nDb; /* Number of valid bytes in zDb */
+ struct stat sStat; /* Output of stat() on database file */
/* zPath is a path to a WAL or journal file. The following block derives
** the path to the associated database file from zPath. This block handles
** the following naming conventions:
**
@@ -5613,22 +5593,19 @@
nDb--;
}
memcpy(zDb, zPath, nDb);
zDb[nDb] = '\0';
- rc = getFileMode(zDb, pMode, pUid, pGid);
+ if( 0==osStat(zDb, &sStat) ){
+ *pMode = sStat.st_mode & 0777;
+ *pUid = sStat.st_uid;
+ *pGid = sStat.st_gid;
+ }else{
+ rc = SQLITE_IOERR_FSTAT;
+ }
}else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
*pMode = 0600;
- }else if( flags & SQLITE_OPEN_URI ){
- /* If this is a main database file and the file was opened using a URI
- ** filename, check for the "modeof" parameter. If present, interpret
- ** its value as a filename and try to copy the mode, uid and gid from
- ** that file. */
- const char *z = sqlite3_uri_parameter(zPath, "modeof");
- if( z ){
- rc = getFileMode(z, pMode, pUid, pGid);
- }
}
return rc;
}
/*
Index: src/pager.c
==================================================================
--- src/pager.c
+++ src/pager.c
@@ -6654,15 +6654,11 @@
** This function may return SQLITE_NOMEM if a memory allocation fails,
** or an IO error code if an IO error occurs while rolling back a
** savepoint. If no errors occur, SQLITE_OK is returned.
*/
int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
- int rc = pPager->errCode;
-
-#ifdef SQLITE_ENABLE_ZIPVFS
- if( op==SAVEPOINT_RELEASE ) rc = SQLITE_OK;
-#endif
+ int rc = pPager->errCode; /* Return code */
assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK );
if( rc==SQLITE_OK && iSavepointnSavepoint ){
@@ -6699,24 +6695,10 @@
else if( pagerUseWal(pPager) || isOpen(pPager->jfd) ){
PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1];
rc = pagerPlaybackSavepoint(pPager, pSavepoint);
assert(rc!=SQLITE_DONE);
}
-
-#ifdef SQLITE_ENABLE_ZIPVFS
- /* If the cache has been modified but the savepoint cannot be rolled
- ** back journal_mode=off, put the pager in the error state. This way,
- ** if the VFS used by this pager includes ZipVFS, the entire transaction
- ** can be rolled back at the ZipVFS level. */
- else if(
- pPager->journalMode==PAGER_JOURNALMODE_OFF
- && pPager->eState>=PAGER_WRITER_CACHEMOD
- ){
- pPager->errCode = SQLITE_ABORT;
- pPager->eState = PAGER_ERROR;
- }
-#endif
}
return rc;
}
Index: src/parse.y
==================================================================
--- src/parse.y
+++ src/parse.y
@@ -1283,12 +1283,12 @@
///////////////////////////// The VACUUM command /////////////////////////////
//
%ifndef SQLITE_OMIT_VACUUM
%ifndef SQLITE_OMIT_ATTACH
-cmd ::= VACUUM. {sqlite3Vacuum(pParse,0);}
-cmd ::= VACUUM nm(X). {sqlite3Vacuum(pParse,&X);}
+cmd ::= VACUUM. {sqlite3Vacuum(pParse);}
+cmd ::= VACUUM nm. {sqlite3Vacuum(pParse);}
%endif SQLITE_OMIT_ATTACH
%endif SQLITE_OMIT_VACUUM
///////////////////////////// The PRAGMA command /////////////////////////////
//
Index: src/pragma.c
==================================================================
--- src/pragma.c
+++ src/pragma.c
@@ -336,11 +336,11 @@
}else{
zRight = sqlite3NameFromToken(db, pValue);
}
assert( pId2 );
- zDb = pId2->n>0 ? pDb->zDbSName : 0;
+ zDb = pId2->n>0 ? pDb->zName : 0;
if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){
goto pragma_out;
}
/* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS
@@ -1189,14 +1189,14 @@
int i;
pParse->nMem = 3;
setAllColumnNames(v, 3, azCol); assert( 3==ArraySize(azCol) );
for(i=0; inDb; i++){
if( db->aDb[i].pBt==0 ) continue;
- assert( db->aDb[i].zDbSName!=0 );
+ assert( db->aDb[i].zName!=0 );
sqlite3VdbeMultiLoad(v, 1, "iss",
i,
- db->aDb[i].zDbSName,
+ db->aDb[i].zName,
sqlite3BtreeGetFilename(db->aDb[i].pBt));
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
}
}
break;
@@ -1481,11 +1481,11 @@
/* Do the b-tree integrity checks */
sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY);
sqlite3VdbeChangeP5(v, (u8)i);
addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
- sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName),
+ sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
P4_DYNAMIC);
sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1);
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
sqlite3VdbeJumpHere(v, addr);
@@ -1920,19 +1920,19 @@
pParse->nMem = 2;
for(i=0; inDb; i++){
Btree *pBt;
const char *zState = "unknown";
int j;
- if( db->aDb[i].zDbSName==0 ) continue;
+ if( db->aDb[i].zName==0 ) continue;
pBt = db->aDb[i].pBt;
if( pBt==0 || sqlite3BtreePager(pBt)==0 ){
zState = "closed";
- }else if( sqlite3_file_control(db, i ? db->aDb[i].zDbSName : 0,
+ }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0,
SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){
zState = azLockName[j];
}
- sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zDbSName, zState);
+ sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zName, zState);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
break;
}
#endif
Index: src/prepare.c
==================================================================
--- src/prepare.c
+++ src/prepare.c
@@ -71,11 +71,10 @@
** But because db->init.busy is set to 1, no VDBE code is generated
** or executed. All the parser does is build the internal data
** structures that describe the table, index, or view.
*/
int rc;
- u8 saved_iDb = db->init.iDb;
sqlite3_stmt *pStmt;
TESTONLY(int rcp); /* Return code from sqlite3_prepare() */
assert( db->init.busy );
db->init.iDb = iDb;
@@ -82,12 +81,11 @@
db->init.newTnum = sqlite3Atoi(argv[1]);
db->init.orphanTrigger = 0;
TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0);
rc = db->errCode;
assert( (rc&0xFF)==(rcp&0xFF) );
- db->init.iDb = saved_iDb;
- assert( saved_iDb==0 || (db->flags & SQLITE_Vacuum)!=0 );
+ db->init.iDb = 0;
if( SQLITE_OK!=rc ){
if( db->init.orphanTrigger ){
assert( iDb==1 );
}else{
pData->rc = rc;
@@ -107,11 +105,11 @@
** constraint for a CREATE TABLE. The index should have already
** been created when we processed the CREATE TABLE. All we have
** to do here is record the root page number for that index.
*/
Index *pIndex;
- pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName);
+ pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName);
if( pIndex==0 ){
/* This can occur if there exists an index on a TEMP table which
** has the same name as another index on a permanent index. Since
** the permanent table is hidden by the TEMP table, we can also
** safely ignore the index on the permanent table.
@@ -286,11 +284,11 @@
assert( db->init.busy );
{
char *zSql;
zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM \"%w\".%s ORDER BY rowid",
- db->aDb[iDb].zDbSName, zMasterName);
+ db->aDb[iDb].zName, zMasterName);
#ifndef SQLITE_OMIT_AUTHORIZATION
{
sqlite3_xauth xAuth;
xAuth = db->xAuth;
db->xAuth = 0;
@@ -561,11 +559,11 @@
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
assert( sqlite3BtreeHoldsMutex(pBt) );
rc = sqlite3BtreeSchemaLocked(pBt);
if( rc ){
- const char *zDb = db->aDb[i].zDbSName;
+ const char *zDb = db->aDb[i].zName;
sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb);
testcase( db->flags & SQLITE_ReadUncommitted );
goto end_prepare;
}
}
Index: src/resolve.c
==================================================================
--- src/resolve.c
+++ src/resolve.c
@@ -219,12 +219,12 @@
** legacy and because it does not hurt anything to just ignore the
** database name. */
zDb = 0;
}else{
for(i=0; inDb; i++){
- assert( db->aDb[i].zDbSName );
- if( sqlite3StrICmp(db->aDb[i].zDbSName,zDb)==0 ){
+ assert( db->aDb[i].zName );
+ if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
pSchema = db->aDb[i].pSchema;
break;
}
}
}
Index: src/select.c
==================================================================
--- src/select.c
+++ src/select.c
@@ -1456,11 +1456,11 @@
estWidth = pTab->aCol[iCol].szEst;
}
zOrigTab = pTab->zName;
if( pNC->pParse ){
int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
- zOrigDb = pNC->pParse->db->aDb[iDb].zDbSName;
+ zOrigDb = pNC->pParse->db->aDb[iDb].zName;
}
#else
if( iCol<0 ){
zType = "INTEGER";
}else{
@@ -4412,11 +4412,11 @@
pSub = 0;
if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
continue;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*";
+ zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*";
}
for(j=0; jnCol; j++){
char *zName = pTab->aCol[j].zName;
char *zColname; /* The computed column name */
char *zToFree; /* Malloced string that needs to be freed */
Index: src/shell.c
==================================================================
--- src/shell.c
+++ src/shell.c
@@ -522,11 +522,11 @@
}
}
#if defined(_WIN32) || defined(WIN32)
/* For interactive input on Windows systems, translate the
** multi-byte characterset characters into UTF-8. */
- if( stdin_is_interactive ){
+ if( stdin_is_interactive && in==stdin ){
char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
if( zTrans ){
int nTrans = strlen30(zTrans)+1;
if( nTrans>nLine ){
zLine = realloc(zLine, nTrans);
@@ -4903,11 +4903,11 @@
while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
fflush(p->out);
zLine = one_input_line(in, zLine, nSql>0);
if( zLine==0 ){
/* End of input */
- if( stdin_is_interactive ) printf("\n");
+ if( in==0 && stdin_is_interactive ) printf("\n");
break;
}
if( seenInterrupt ){
if( in!=0 ) break;
seenInterrupt = 0;
Index: src/sqlite.h.in
==================================================================
--- src/sqlite.h.in
+++ src/sqlite.h.in
@@ -1967,22 +1967,12 @@
** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface
** is disabled or enabled following this call. The second parameter may
** be a NULL pointer, in which case the new setting is not reported back.
**
**
-** SQLITE_DBCONFIG_MAINDBNAME
-** ^This option is used to change the name of the "main" database
-** schema. ^The sole argument is a pointer to a constant UTF8 string
-** which will become the new schema name in place of "main". ^SQLite
-** does not make a copy of the new main schema name string, so the application
-** must ensure that the argument passed into this DBCONFIG option is unchanged
-** until after the database connection closes.
-**
-**
**
*/
-#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
Index: src/sqliteInt.h
==================================================================
--- src/sqliteInt.h
+++ src/sqliteInt.h
@@ -1095,11 +1095,11 @@
** in the sqlite.aDb[] array. aDb[0] is the main database file and
** aDb[1] is the database file used to hold temporary tables. Additional
** databases may be attached.
*/
struct Db {
- char *zDbSName; /* Name of this database. (schema name, not filename) */
+ char *zName; /* Name of this database */
Btree *pBt; /* The B*Tree structure for this database file */
u8 safety_level; /* How aggressive at syncing data to disk */
u8 bSyncSet; /* True if "PRAGMA synchronous=N" has been run */
Schema *pSchema; /* Pointer to database schema (possibly shared) */
};
@@ -3699,12 +3699,12 @@
Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*);
Table *sqlite3LocateTableItem(Parse*,u32 flags,struct SrcList_item *);
Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
-void sqlite3Vacuum(Parse*,Token*);
-int sqlite3RunVacuum(char**, sqlite3*, int);
+void sqlite3Vacuum(Parse*);
+int sqlite3RunVacuum(char**, sqlite3*);
char *sqlite3NameFromToken(sqlite3*, Token*);
int sqlite3ExprCompare(Expr*, Expr*, int);
int sqlite3ExprListCompare(ExprList*, ExprList*, int);
int sqlite3ExprImpliesExpr(Expr*, Expr*, int);
void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
Index: src/test1.c
==================================================================
--- src/test1.c
+++ src/test1.c
@@ -7193,33 +7193,10 @@
sqlite3_db_config(db, aSetting[i].eVal, v, &v);
Tcl_SetObjResult(interp, Tcl_NewIntObj(v));
return TCL_OK;
}
-/*
-** Change the name of the main database schema from "main" to "icecube".
-*/
-static int SQLITE_TCLAPI test_dbconfig_maindbname_icecube(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int rc;
- sqlite3 *db;
- extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }else{
- if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
- rc = sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, "icecube");
- Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
- return TCL_OK;
- }
-}
-
/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest1_Init(Tcl_Interp *interp){
extern int sqlite3_search_count;
@@ -7349,11 +7326,10 @@
{ "sqlite3_load_extension", test_load_extension, 0},
{ "sqlite3_enable_load_extension", test_enable_load, 0},
{ "sqlite3_extended_result_codes", test_extended_result_codes, 0},
{ "sqlite3_limit", test_limit, 0},
- { "dbconfig_maindbname_icecube", test_dbconfig_maindbname_icecube },
{ "save_prng_state", save_prng_state, 0 },
{ "restore_prng_state", restore_prng_state, 0 },
{ "reset_prng_state", reset_prng_state, 0 },
{ "database_never_corrupt", database_never_corrupt, 0},
Index: src/tokenize.c
==================================================================
--- src/tokenize.c
+++ src/tokenize.c
@@ -500,30 +500,18 @@
assert( pParse->pNewTable==0 );
assert( pParse->pNewTrigger==0 );
assert( pParse->nVar==0 );
assert( pParse->nzVar==0 );
assert( pParse->azVar==0 );
- while( 1 ){
+ while( zSql[i]!=0 ){
assert( i>=0 );
- if( zSql[i]!=0 ){
- pParse->sLastToken.z = &zSql[i];
- pParse->sLastToken.n = sqlite3GetToken((u8*)&zSql[i],&tokenType);
- i += pParse->sLastToken.n;
- if( i>mxSqlLen ){
- pParse->rc = SQLITE_TOOBIG;
- break;
- }
- }else{
- /* Upon reaching the end of input, call the parser two more times
- ** with tokens TK_SEMI and 0, in that order. */
- if( lastTokenParsed==TK_SEMI ){
- tokenType = 0;
- }else if( lastTokenParsed==0 ){
- break;
- }else{
- tokenType = TK_SEMI;
- }
+ pParse->sLastToken.z = &zSql[i];
+ pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType);
+ i += pParse->sLastToken.n;
+ if( i>mxSqlLen ){
+ pParse->rc = SQLITE_TOOBIG;
+ break;
}
if( tokenType>=TK_SPACE ){
assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL );
if( db->u1.isInterrupted ){
pParse->rc = SQLITE_INTERRUPT;
@@ -540,10 +528,19 @@
if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break;
}
}
assert( nErr==0 );
pParse->zTail = &zSql[i];
+ if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){
+ assert( zSql[i]==0 );
+ if( lastTokenParsed!=TK_SEMI ){
+ sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
+ }
+ if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){
+ sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
+ }
+ }
#ifdef YYTRACKMAXSTACKDEPTH
sqlite3_mutex_enter(sqlite3MallocMutex());
sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK,
sqlite3ParserStackPeak(pEngine)
);
Index: src/treeview.c
==================================================================
--- src/treeview.c
+++ src/treeview.c
@@ -118,11 +118,11 @@
}
}
/*
-** Generate a human-readable description of a Select object.
+** Generate a human-readable description of a the Select object.
*/
void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
int n = 0;
int cnt = 0;
pView = sqlite3TreeViewPush(pView, moreToFollow);
Index: src/trigger.c
==================================================================
--- src/trigger.c
+++ src/trigger.c
@@ -212,12 +212,12 @@
iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_CREATE_TRIGGER;
- const char *zDb = db->aDb[iTabDb].zDbSName;
- const char *zDbTrig = isTemp ? db->aDb[1].zDbSName : zDb;
+ const char *zDb = db->aDb[iTabDb].zName;
+ const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){
goto trigger_cleanup;
}
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){
@@ -307,11 +307,11 @@
if( v==0 ) goto triggerfinish_cleanup;
sqlite3BeginWriteOperation(pParse, 0, iDb);
z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
sqlite3NestedParse(pParse,
"INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
- db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), zName,
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zName,
pTrig->table, z);
sqlite3DbFree(db, z);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddParseSchemaOp(v, iDb,
sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName));
@@ -496,11 +496,11 @@
zDb = pName->a[0].zDatabase;
zName = pName->a[0].zName;
assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
for(i=OMIT_TEMPDB; inDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
- if( zDb && sqlite3StrICmp(db->aDb[j].zDbSName, zDb) ) continue;
+ if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue;
assert( sqlite3SchemaMutexHeld(db, j, 0) );
pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName);
if( pTrigger ) break;
}
if( !pTrigger ){
@@ -542,11 +542,11 @@
assert( pTable );
assert( pTable->pSchema==pTrigger->pSchema || iDb==1 );
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_DROP_TRIGGER;
- const char *zDb = db->aDb[iDb].zDbSName;
+ const char *zDb = db->aDb[iDb].zName;
const char *zTab = SCHEMA_TABLE(iDb);
if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER;
if( sqlite3AuthCheck(pParse, code, pTrigger->zName, pTable->zName, zDb) ||
sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
return;
@@ -558,11 +558,11 @@
*/
assert( pTable!=0 );
if( (v = sqlite3GetVdbe(pParse))!=0 ){
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'",
- db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pTrigger->zName
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrigger->zName
);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0);
}
}
@@ -661,14 +661,12 @@
if( pSrc ){
assert( pSrc->nSrc>0 );
pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget);
iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema);
if( iDb==0 || iDb>=2 ){
- const char *zDb;
assert( iDbnDb );
- zDb = db->aDb[iDb].zDbSName;
- pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, zDb);
+ pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName);
}
}
return pSrc;
}
Index: src/update.c
==================================================================
--- src/update.c
+++ src/update.c
@@ -247,11 +247,11 @@
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int rc;
rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
j<0 ? "ROWID" : pTab->aCol[j].zName,
- db->aDb[iDb].zDbSName);
+ db->aDb[iDb].zName);
if( rc==SQLITE_DENY ){
goto update_cleanup;
}else if( rc==SQLITE_IGNORE ){
aXRef[j] = -1;
}
Index: src/vacuum.c
==================================================================
--- src/vacuum.c
+++ src/vacuum.c
@@ -16,56 +16,61 @@
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
+/*
+** Finalize a prepared statement. If there was an error, store the
+** text of the error message in *pzErrMsg. Return the result code.
+*/
+static int vacuumFinalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){
+ int rc;
+ rc = sqlite3VdbeFinalize((Vdbe*)pStmt);
+ if( rc ){
+ sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
+ }
+ return rc;
+}
/*
-** Execute zSql on database db.
-**
-** If zSql returns rows, then each row will have exactly one
-** column. (This will only happen if zSql begins with "SELECT".)
-** Take each row of result and call execSql() again recursively.
-**
-** The execSqlF() routine does the same thing, except it accepts
-** a format string as its third argument
+** Execute zSql on database db. Return an error code.
*/
static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
sqlite3_stmt *pStmt;
- int rc;
-
- /* printf("SQL: [%s]\n", zSql); fflush(stdout); */
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ) return rc;
- while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
- const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0);
- assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 );
- if( zSubSql ){
- assert( zSubSql[0]!='S' );
- rc = execSql(db, pzErrMsg, zSubSql);
- if( rc!=SQLITE_OK ) break;
- }
- }
- assert( rc!=SQLITE_ROW );
- if( rc==SQLITE_DONE ) rc = SQLITE_OK;
- if( rc ){
- sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
- }
- (void)sqlite3_finalize(pStmt);
- return rc;
-}
-static int execSqlF(sqlite3 *db, char **pzErrMsg, const char *zSql, ...){
- char *z;
- va_list ap;
- int rc;
- va_start(ap, zSql);
- z = sqlite3VMPrintf(db, zSql, ap);
- va_end(ap);
- if( z==0 ) return SQLITE_NOMEM;
- rc = execSql(db, pzErrMsg, z);
- sqlite3DbFree(db, z);
- return rc;
+ VVA_ONLY( int rc; )
+ if( !zSql ){
+ return SQLITE_NOMEM_BKPT;
+ }
+ if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
+ sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
+ return sqlite3_errcode(db);
+ }
+ VVA_ONLY( rc = ) sqlite3_step(pStmt);
+ assert( rc!=SQLITE_ROW || (db->flags&SQLITE_CountRows) );
+ return vacuumFinalize(db, pStmt, pzErrMsg);
+}
+
+/*
+** Execute zSql on database db. The statement returns exactly
+** one column. Execute this as SQL on the same database.
+*/
+static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
+ sqlite3_stmt *pStmt;
+ int rc;
+
+ rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
+ if( rc!=SQLITE_OK ) return rc;
+
+ while( SQLITE_ROW==sqlite3_step(pStmt) ){
+ rc = execSql(db, pzErrMsg, (char*)sqlite3_column_text(pStmt, 0));
+ if( rc!=SQLITE_OK ){
+ vacuumFinalize(db, pStmt, pzErrMsg);
+ return rc;
+ }
+ }
+
+ return vacuumFinalize(db, pStmt, pzErrMsg);
}
/*
** The VACUUM command is used to clean up the database,
** collapse free space, etc. It is modelled after the VACUUM command
@@ -94,36 +99,35 @@
** not work if other processes are attached to the original database.
** And a power loss in between deleting the original and renaming the
** transient would cause the database file to appear to be deleted
** following reboot.
*/
-void sqlite3Vacuum(Parse *pParse, Token *pNm){
+void sqlite3Vacuum(Parse *pParse){
Vdbe *v = sqlite3GetVdbe(pParse);
- int iDb = pNm ? sqlite3TwoPartName(pParse, pNm, pNm, &pNm) : 0;
- if( v && (iDb>=2 || iDb==0) ){
- sqlite3VdbeAddOp1(v, OP_Vacuum, iDb);
- sqlite3VdbeUsesBtree(v, iDb);
+ if( v ){
+ sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0);
+ sqlite3VdbeUsesBtree(v, 0);
}
return;
}
/*
** This routine implements the OP_Vacuum opcode of the VDBE.
*/
-int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
+int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
int rc = SQLITE_OK; /* Return code from service routines */
Btree *pMain; /* The database being vacuumed */
Btree *pTemp; /* The temporary database we vacuum into */
+ char *zSql = 0; /* SQL statements */
int saved_flags; /* Saved value of the db->flags */
int saved_nChange; /* Saved value of db->nChange */
int saved_nTotalChange; /* Saved value of db->nTotalChange */
u8 saved_mTrace; /* Saved trace settings */
Db *pDb = 0; /* Database to detach at end of vacuum */
int isMemDb; /* True if vacuuming a :memory: database */
int nRes; /* Bytes of reserved space at the end of each page */
int nDb; /* Number of attached databases */
- const char *zDbMain; /* Schema name of database to vacuum */
if( !db->autoCommit ){
sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
return SQLITE_ERROR;
}
@@ -137,17 +141,15 @@
** disable CHECK and foreign key constraints. */
saved_flags = db->flags;
saved_nChange = db->nChange;
saved_nTotalChange = db->nTotalChange;
saved_mTrace = db->mTrace;
- db->flags |= (SQLITE_WriteSchema | SQLITE_IgnoreChecks
- | SQLITE_PreferBuiltin | SQLITE_Vacuum);
- db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_CountRows);
+ db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_PreferBuiltin;
+ db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder);
db->mTrace = 0;
- zDbMain = db->aDb[iDb].zDbSName;
- pMain = db->aDb[iDb].pBt;
+ pMain = db->aDb[0].pBt;
isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain));
/* Attach the temporary database as 'vacuum_db'. The synchronous pragma
** can be set to 'off' for this file, as it is not recovered if a crash
** occurs anyway. The integrity of the database is maintained by a
@@ -161,16 +163,22 @@
** empty. Only the journal header is written. Apparently it takes more
** time to parse and run the PRAGMA to turn journalling off than it does
** to write the journal header file.
*/
nDb = db->nDb;
- rc = execSql(db, pzErrMsg, "ATTACH''AS vacuum_db");
+ if( sqlite3TempInMemory(db) ){
+ zSql = "ATTACH ':memory:' AS vacuum_db;";
+ }else{
+ zSql = "ATTACH '' AS vacuum_db;";
+ }
+ rc = execSql(db, pzErrMsg, zSql);
+ if( db->nDb>nDb ){
+ pDb = &db->aDb[db->nDb-1];
+ assert( strcmp(pDb->zName,"vacuum_db")==0 );
+ }
if( rc!=SQLITE_OK ) goto end_of_vacuum;
- assert( (db->nDb-1)==nDb );
- pDb = &db->aDb[nDb];
- assert( strcmp(pDb->zDbSName,"vacuum_db")==0 );
- pTemp = pDb->pBt;
+ pTemp = db->aDb[db->nDb-1].pBt;
/* The call to execSql() to attach the temp database has left the file
** locked (as there was more than one active statement when the transaction
** to read the schema was concluded. Unlock it here so that this doesn't
** cause problems for the call to BtreeSetPageSize() below. */
@@ -187,19 +195,20 @@
sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
if( nKey ) db->nextPagesize = 0;
}
#endif
- sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
+ sqlite3BtreeSetCacheSize(pTemp, db->aDb[0].pSchema->cache_size);
sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
- sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF);
+ rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF");
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Begin a transaction and take an exclusive lock on the main database
** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below,
** to ensure that we do not try to change the page-size on a WAL database.
*/
- rc = execSql(db, pzErrMsg, "BEGIN");
+ rc = execSql(db, pzErrMsg, "BEGIN;");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeBeginTrans(pMain, 2);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Do not attempt to change the page size for a WAL database */
@@ -222,52 +231,68 @@
#endif
/* Query the schema of the main database. Create a mirror schema
** in the temporary database.
*/
- db->init.iDb = nDb; /* force new CREATE statements into vacuum_db */
- rc = execSqlF(db, pzErrMsg,
- "SELECT sql FROM \"%w\".sqlite_master"
- " WHERE type='table'AND name<>'sqlite_sequence'"
- " AND coalesce(rootpage,1)>0",
- zDbMain
- );
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
- rc = execSqlF(db, pzErrMsg,
- "SELECT sql FROM \"%w\".sqlite_master"
- " WHERE type='index' AND length(sql)>10",
- zDbMain
- );
- if( rc!=SQLITE_OK ) goto end_of_vacuum;
- db->init.iDb = 0;
+ rc = execExecSql(db, pzErrMsg,
+ "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) "
+ " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
+ " AND coalesce(rootpage,1)>0"
+ );
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ rc = execExecSql(db, pzErrMsg,
+ "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)"
+ " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' ");
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ rc = execExecSql(db, pzErrMsg,
+ "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) "
+ " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'");
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Loop through the tables in the main database. For each, do
** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy
** the contents to the temporary database.
*/
- rc = execSqlF(db, pzErrMsg,
- "SELECT'INSERT INTO vacuum_db.'||quote(name)"
- "||' SELECT*FROM\"%w\".'||quote(name)"
- "FROM vacuum_db.sqlite_master "
- "WHERE type='table'AND coalesce(rootpage,1)>0",
- zDbMain
+ assert( (db->flags & SQLITE_Vacuum)==0 );
+ db->flags |= SQLITE_Vacuum;
+ rc = execExecSql(db, pzErrMsg,
+ "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
+ "|| ' SELECT * FROM main.' || quote(name) || ';'"
+ "FROM main.sqlite_master "
+ "WHERE type = 'table' AND name!='sqlite_sequence' "
+ " AND coalesce(rootpage,1)>0"
);
assert( (db->flags & SQLITE_Vacuum)!=0 );
db->flags &= ~SQLITE_Vacuum;
if( rc!=SQLITE_OK ) goto end_of_vacuum;
+
+ /* Copy over the sequence table
+ */
+ rc = execExecSql(db, pzErrMsg,
+ "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' "
+ "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' "
+ );
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+ rc = execExecSql(db, pzErrMsg,
+ "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
+ "|| ' SELECT * FROM main.' || quote(name) || ';' "
+ "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';"
+ );
+ if( rc!=SQLITE_OK ) goto end_of_vacuum;
+
/* Copy the triggers, views, and virtual tables from the main database
** over to the temporary database. None of these objects has any
** associated storage, so all we have to do is copy their entries
** from the SQLITE_MASTER table.
*/
- rc = execSqlF(db, pzErrMsg,
- "INSERT INTO vacuum_db.sqlite_master"
- " SELECT*FROM \"%w\".sqlite_master"
- " WHERE type IN('view','trigger')"
- " OR(type='table'AND rootpage=0)",
- zDbMain
+ rc = execSql(db, pzErrMsg,
+ "INSERT INTO vacuum_db.sqlite_master "
+ " SELECT type, name, tbl_name, rootpage, sql"
+ " FROM main.sqlite_master"
+ " WHERE type='view' OR type='trigger'"
+ " OR (type='table' AND rootpage=0)"
);
if( rc ) goto end_of_vacuum;
/* At this point, there is a write transaction open on both the
** vacuum database and the main database. Assuming no error occurs,
@@ -317,11 +342,10 @@
assert( rc==SQLITE_OK );
rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1);
end_of_vacuum:
/* Restore the original value of db->flags */
- db->init.iDb = 0;
db->flags = saved_flags;
db->nChange = saved_nChange;
db->nTotalChange = saved_nTotalChange;
db->mTrace = saved_mTrace;
sqlite3BtreeSetPageSize(pMain, -1, -1, 1);
Index: src/vdbe.c
==================================================================
--- src/vdbe.c
+++ src/vdbe.c
@@ -4344,11 +4344,11 @@
}
if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
assert( pC->isTable );
assert( pC->iDb>=0 );
- zDb = db->aDb[pC->iDb].zDbSName;
+ zDb = db->aDb[pC->iDb].zName;
pTab = pOp->p4.pTab;
assert( HasRowid(pTab) );
op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
}else{
pTab = 0; /* Not needed. Silence a comiler warning. */
@@ -4461,11 +4461,11 @@
** last moved with OP_Next or OP_Prev, not Seek or NotFound, set
** VdbeCursor.movetoTarget to the current rowid. */
if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
assert( pC->iDb>=0 );
assert( pOp->p4.pTab!=0 );
- zDb = db->aDb[pC->iDb].zDbSName;
+ zDb = db->aDb[pC->iDb].zName;
pTab = pOp->p4.pTab;
if( (pOp->p5 & OPFLAG_SAVEPOSITION)!=0 && pC->isTable ){
pC->movetoTarget = sqlite3BtreeIntegerKey(pC->uc.pCursor);
}
}else{
@@ -5431,11 +5431,11 @@
initData.db = db;
initData.iDb = pOp->p1;
initData.pzErrMsg = &p->zErrMsg;
zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
- db->aDb[iDb].zDbSName, zMaster, pOp->p4.z);
+ db->aDb[iDb].zName, zMaster, pOp->p4.z);
if( zSql==0 ){
rc = SQLITE_NOMEM_BKPT;
}else{
assert( db->init.busy==0 );
db->init.busy = 1;
@@ -6260,18 +6260,19 @@
break;
};
#endif /* SQLITE_OMIT_PRAGMA */
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
-/* Opcode: Vacuum P1 * * * *
+/* Opcode: Vacuum * * * * *
**
-** Vacuum the entire database P1. P1 is 0 for "main", and 2 or more
-** for an attached database. The "temp" database may not be vacuumed.
+** Vacuum the entire database. This opcode will cause other virtual
+** machines to be created and run. It may not be called from within
+** a transaction.
*/
case OP_Vacuum: {
assert( p->readOnly==0 );
- rc = sqlite3RunVacuum(&p->zErrMsg, db, pOp->p1);
+ rc = sqlite3RunVacuum(&p->zErrMsg, db);
if( rc ) goto abort_due_to_error;
break;
}
#endif
@@ -6814,11 +6815,11 @@
zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
if( zTrace ){
int i;
for(i=0; inDb; i++){
if( DbMaskTest(p->btreeMask, i)==0 ) continue;
- sqlite3_file_control(db, db->aDb[i].zDbSName, SQLITE_FCNTL_TRACE, zTrace);
+ sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
}
}
#endif /* SQLITE_USE_FCNTL_TRACE */
#ifdef SQLITE_DEBUG
if( (db->flags & SQLITE_SqlTrace)!=0
Index: src/vdbeapi.c
==================================================================
--- src/vdbeapi.c
+++ src/vdbeapi.c
@@ -497,11 +497,11 @@
int nEntry;
sqlite3BtreeEnter(pBt);
nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
sqlite3BtreeLeave(pBt);
if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){
- rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zDbSName, nEntry);
+ rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry);
}
}
}
#endif
return rc;
Index: src/vdbeblob.c
==================================================================
--- src/vdbeblob.c
+++ src/vdbeblob.c
@@ -174,11 +174,11 @@
rc = SQLITE_ERROR;
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
}
pBlob->pTab = pTab;
- pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
+ pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zName;
/* Now search pTab for the exact column. */
for(iCol=0; iColnCol; iCol++) {
if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){
break;
Index: src/vtab.c
==================================================================
--- src/vtab.c
+++ src/vtab.c
@@ -342,11 +342,11 @@
** sqlite_master table, has already been made by sqlite3StartTable().
** The second call, to obtain permission to create the table, is made now.
*/
if( pTable->azModuleArg ){
sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
- pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName);
+ pTable->azModuleArg[0], pParse->db->aDb[iDb].zName);
}
#endif
}
/*
@@ -406,11 +406,11 @@
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3NestedParse(pParse,
"UPDATE %Q.%s "
"SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
"WHERE rowid=#%d",
- db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb),
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
pTab->zName,
pTab->zName,
zStmt,
pParse->regRowid
);
@@ -516,11 +516,11 @@
}
pVTable->db = db;
pVTable->pMod = pMod;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- pTab->azModuleArg[1] = db->aDb[iDb].zDbSName;
+ pTab->azModuleArg[1] = db->aDb[iDb].zName;
/* Invoke the virtual table constructor */
assert( &db->pVtabCtx );
assert( xConstruct );
sCtx.pTab = pTab;
@@ -670,21 +670,21 @@
/*
** This function is invoked by the vdbe to call the xCreate method
** of the virtual table named zTab in database iDb.
**
-** If an error occurs, *pzErr is set to point to an English language
+** If an error occurs, *pzErr is set to point an an English language
** description of the error and an SQLITE_XXX error code is returned.
** In this case the caller must call sqlite3DbFree(db, ) on *pzErr.
*/
int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
int rc = SQLITE_OK;
Table *pTab;
Module *pMod;
const char *zMod;
- pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
+ pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
assert( pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVTable );
/* Locate the required virtual table module */
zMod = pTab->azModuleArg[0];
pMod = (Module*)sqlite3HashFind(&db->aModule, zMod);
@@ -804,11 +804,11 @@
*/
int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){
int rc = SQLITE_OK;
Table *pTab;
- pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
+ pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
if( pTab!=0 && ALWAYS(pTab->pVTable!=0) ){
VTable *p;
int (*xDestroy)(sqlite3_vtab *);
for(p=pTab->pVTable; p; p=p->pNext){
assert( p->pVtab );
Index: src/walker.c
==================================================================
--- src/walker.c
+++ src/walker.c
@@ -39,19 +39,21 @@
static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
int rc;
testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
testcase( ExprHasProperty(pExpr, EP_Reduced) );
rc = pWalker->xExprCallback(pWalker, pExpr);
- if( rc || ExprHasProperty(pExpr,EP_TokenOnly) ) return rc & WRC_Abort;
- if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
- if( pExpr->pRight && walkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
- }else{
- if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
- }
- return WRC_Continue;
+ if( rc==WRC_Continue
+ && !ExprHasProperty(pExpr,EP_TokenOnly) ){
+ if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
+ }else{
+ if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
+ }
+ }
+ return rc & WRC_Abort;
}
int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
return pExpr ? walkExpr(pWalker,pExpr) : WRC_Continue;
}
Index: src/where.c
==================================================================
--- src/where.c
+++ src/where.c
@@ -3399,10 +3399,18 @@
if( pOBExpr->op!=TK_COLUMN ) continue;
if( pOBExpr->iTable!=iCur ) continue;
pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
~ready, eqOpMask, 0);
if( pTerm==0 ) continue;
+ if( pTerm->eOperator==WO_IN ){
+ /* IN terms are only valid for sorting in the ORDER BY LIMIT
+ ** optimization, and then only if they are actually used
+ ** by the query plan */
+ assert( wctrlFlags & WHERE_ORDERBY_LIMIT );
+ for(j=0; jnLTerm && pTerm!=pLoop->aLTerm[j]; j++){}
+ if( j>=pLoop->nLTerm ) continue;
+ }
if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){
const char *z1, *z2;
pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
if( !pColl ) pColl = db->pDfltColl;
z1 = pColl->zName;
Index: src/wherecode.c
==================================================================
--- src/wherecode.c
+++ src/wherecode.c
@@ -534,13 +534,19 @@
regBase = r1;
}else{
sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j);
}
}
- testcase( pTerm->eOperator & WO_ISNULL );
- testcase( pTerm->eOperator & WO_IN );
- if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
+ if( (pTerm->eOperator & WO_IN)!=0 ){
+ if( pTerm->pExpr->flags & EP_xIsSelect ){
+ /* No affinity ever needs to be (or should be) applied to a value
+ ** from the RHS of an "? IN (SELECT ...)" expression. The
+ ** sqlite3FindInIndex() routine has already ensured that the
+ ** affinity of the comparison has been applied to the value. */
+ if( zAff ) zAff[j] = SQLITE_AFF_BLOB;
+ }
+ }else if( (pTerm->eOperator & WO_ISNULL)==0 ){
Expr *pRight = pTerm->pExpr->pRight;
if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
VdbeCoverage(v);
}
Index: src/whereexpr.c
==================================================================
--- src/whereexpr.c
+++ src/whereexpr.c
@@ -288,11 +288,11 @@
*/
static int isMatchOfColumn(
Expr *pExpr, /* Test this expression */
unsigned char *peOp2 /* OUT: 0 for MATCH, or else an op2 value */
){
- static const struct Op2 {
+ struct Op2 {
const char *zOp;
unsigned char eOp2;
} aOp[] = {
{ "match", SQLITE_INDEX_CONSTRAINT_MATCH },
{ "glob", SQLITE_INDEX_CONSTRAINT_GLOB },
@@ -1273,18 +1273,17 @@
** These routines walk (recursively) an expression tree and generate
** a bitmask indicating which tables are used in that expression
** tree.
*/
Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
- Bitmask mask;
+ Bitmask mask = 0;
if( p==0 ) return 0;
if( p->op==TK_COLUMN ){
mask = sqlite3WhereGetMask(pMaskSet, p->iTable);
return mask;
}
- assert( !ExprHasProperty(p, EP_TokenOnly) );
- mask = p->pRight ? sqlite3WhereExprUsage(pMaskSet, p->pRight) : 0;
+ mask = sqlite3WhereExprUsage(pMaskSet, p->pRight);
if( p->pLeft ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft);
if( ExprHasProperty(p, EP_xIsSelect) ){
mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
}else if( p->x.pList ){
mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
Index: test/backup_malloc.test
==================================================================
--- test/backup_malloc.test
+++ test/backup_malloc.test
@@ -82,37 +82,6 @@
} -cleanup {
catch { B finish }
db2 close
}
-reset_db
-do_execsql_test 3.0 {
- PRAGMA page_size = 16384;
- BEGIN;
- CREATE TABLE t1(a, b);
- INSERT INTO t1 VALUES(1, 2);
- COMMIT;
-}
-
-do_faultsim_test 3 -faults oom* -prep {
- catch { db close }
-
- forcedelete test2.db
- sqlite3 db2 test2.db
- sqlite3 db test.db
- sqlite3_backup B db2 main db main
-} -body {
-
- set rc [B step 50]
- if {$rc == "SQLITE_NOMEM" || $rc == "SQLITE_IOERR_NOMEM"} {
- error "out of memory"
- }
-
-} -test {
- faultsim_test_result {0 {}}
- faultsim_integrity_check
-
- # Finalize the backup.
- catch { B finish }
-}
-
finish_test
Index: test/e_vacuum.test
==================================================================
--- test/e_vacuum.test
+++ test/e_vacuum.test
@@ -200,12 +200,16 @@
CREATE TABLE aux.t3 AS SELECT * FROM t1;
DELETE FROM t3;
} {}
set original_size [file size test.db2]
-# Vacuuming the main database does not affect aux
+# Try everything we can think of to get the aux database vacuumed:
do_execsql_test e_vacuum-2.1.3 { VACUUM } {}
+do_execsql_test e_vacuum-2.1.4 { VACUUM aux } {}
+do_execsql_test e_vacuum-2.1.5 { VACUUM 'test.db2' } {}
+
+# Despite our efforts, space in the aux database has not been reclaimed:
do_test e_vacuum-2.1.6 { expr {[file size test.db2]==$::original_size} } 1
# EVIDENCE-OF: R-17495-17419 The VACUUM command may change the ROWIDs of
# entries in any tables that do not have an explicit INTEGER PRIMARY
# KEY.
Index: test/limit2.test
==================================================================
--- test/limit2.test
+++ test/limit2.test
@@ -94,11 +94,22 @@
} {2 2 2 12345 |}
do_execsql_test limit2-210 {
SELECT *, '|' FROM t200 LEFT JOIN t201 ON x=b ORDER BY y LIMIT 3;
} {1 1 {} {} | 3 3 {} {} | 4 4 {} {} |}
-
+# Bug in the ORDER BY LIMIT optimization reported on 2016-09-06.
+# Ticket https://www.sqlite.org/src/info/559733b09e96
+#
+do_execsql_test limit2-300 {
+ CREATE TABLE t300(a,b,c);
+ CREATE INDEX t300x ON t300(a,b,c);
+ INSERT INTO t300 VALUES(0,1,99),(0,1,0),(0,0,0);
+ SELECT *,'.' FROM t300 WHERE a=0 AND (c=0 OR c=99) ORDER BY c DESC;
+} {0 1 99 . 0 0 0 . 0 1 0 .}
+do_execsql_test limit2-310 {
+ SELECT *,'.' FROM t300 WHERE a=0 AND (c=0 OR c=99) ORDER BY c DESC LIMIT 1;
+} {0 1 99 .}
finish_test
Index: test/misc8.test
==================================================================
--- test/misc8.test
+++ test/misc8.test
@@ -105,33 +105,7 @@
) AS x3,
(SELECT 6 AS j UNION ALL SELECT 7) AS x4
WHERE ibase;
- return SQLITE_OK;
-}
-
-/*
-** Destructor for a series_cursor.
-*/
-static int seriesClose(sqlite3_vtab_cursor *cur){
- sqlite3_free(cur);
- return SQLITE_OK;
-}
-
-
-/*
-** Advance a series_cursor to its next row of output.
-*/
-static int seriesNext(sqlite3_vtab_cursor *cur){
- series_cursor *pCur = (series_cursor*)cur;
- if( pCur->isDesc ){
- pCur->iValue -= pCur->iStep;
- }else{
- pCur->iValue += pCur->iStep;
- }
- pCur->iRowid++;
- return SQLITE_OK;
-}
-
-/*
-** Return values of columns for the row at which the series_cursor
-** is currently pointing.
-*/
-static int seriesColumn(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- series_cursor *pCur = (series_cursor*)cur;
- sqlite3_int64 x = 0;
- switch( i ){
- case SERIES_COLUMN_START: x = pCur->mnValue; break;
- case SERIES_COLUMN_STOP: x = pCur->mxValue; break;
- case SERIES_COLUMN_STEP: x = pCur->iStep; break;
- default: x = pCur->iValue; break;
- }
- sqlite3_result_int64(ctx, x);
- return SQLITE_OK;
-}
-
-/*
-** Return the rowid for the current row. In this implementation, the
-** rowid is the same as the output value.
-*/
-static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- series_cursor *pCur = (series_cursor*)cur;
- *pRowid = pCur->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
-*/
-static int seriesEof(sqlite3_vtab_cursor *cur){
- series_cursor *pCur = (series_cursor*)cur;
- if( pCur->isDesc ){
- return pCur->iValue < pCur->mnValue;
- }else{
- return pCur->iValue > pCur->mxValue;
- }
-}
-
-/* True to cause run-time checking of the start=, stop=, and/or step=
-** parameters. The only reason to do this is for testing the
-** constraint checking logic for virtual tables in the SQLite core.
-*/
-#ifndef SQLITE_SERIES_CONSTRAINT_VERIFY
-# define SQLITE_SERIES_CONSTRAINT_VERIFY 0
-#endif
-
-/*
-** This method is called to "rewind" the series_cursor object back
-** to the first row of output. This method is always called at least
-** once prior to any call to seriesColumn() or seriesRowid() or
-** seriesEof().
-**
-** The query plan selected by seriesBestIndex is passed in the idxNum
-** parameter. (idxStr is not used in this implementation.) idxNum
-** is a bitmask showing which constraints are available:
-**
-** 1: start=VALUE
-** 2: stop=VALUE
-** 4: step=VALUE
-**
-** Also, if bit 8 is set, that means that the series should be output
-** in descending order rather than in ascending order.
-**
-** This routine should initialize the cursor and position it so that it
-** is pointing at the first row, or pointing off the end of the table
-** (so that seriesEof() will return true) if the table is empty.
-*/
-static int seriesFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- series_cursor *pCur = (series_cursor *)pVtabCursor;
- int i = 0;
- if( idxNum & 1 ){
- pCur->mnValue = sqlite3_value_int64(argv[i++]);
- }else{
- pCur->mnValue = 0;
- }
- if( idxNum & 2 ){
- pCur->mxValue = sqlite3_value_int64(argv[i++]);
- }else{
- pCur->mxValue = 0xffffffff;
- }
- if( idxNum & 4 ){
- pCur->iStep = sqlite3_value_int64(argv[i++]);
- if( pCur->iStep<1 ) pCur->iStep = 1;
- }else{
- pCur->iStep = 1;
- }
- if( idxNum & 8 ){
- pCur->isDesc = 1;
- pCur->iValue = pCur->mxValue;
- if( pCur->iStep>0 ){
- pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep;
- }
- }else{
- pCur->isDesc = 0;
- pCur->iValue = pCur->mnValue;
- }
- pCur->iRowid = 1;
- return SQLITE_OK;
-}
-
-/*
-** SQLite will invoke this method one or more times while planning a query
-** that uses the generate_series virtual table. This routine needs to create
-** a query plan for each invocation and compute an estimated cost for that
-** plan.
-**
-** In this implementation idxNum is used to represent the
-** query plan. idxStr is unused.
-**
-** The query plan is represented by bits in idxNum:
-**
-** (1) start = $value -- constraint exists
-** (2) stop = $value -- constraint exists
-** (4) step = $value -- constraint exists
-** (8) output in descending order
-*/
-static int seriesBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- int i; /* Loop over constraints */
- int idxNum = 0; /* The query plan bitmask */
- int startIdx = -1; /* Index of the start= constraint, or -1 if none */
- int stopIdx = -1; /* Index of the stop= constraint, or -1 if none */
- int stepIdx = -1; /* Index of the step= constraint, or -1 if none */
- int nArg = 0; /* Number of arguments that seriesFilter() expects */
-
- const struct sqlite3_index_constraint *pConstraint;
- pConstraint = pIdxInfo->aConstraint;
- for(i=0; inConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- switch( pConstraint->iColumn ){
- case SERIES_COLUMN_START:
- startIdx = i;
- idxNum |= 1;
- break;
- case SERIES_COLUMN_STOP:
- stopIdx = i;
- idxNum |= 2;
- break;
- case SERIES_COLUMN_STEP:
- stepIdx = i;
- idxNum |= 4;
- break;
- }
- }
- if( startIdx>=0 ){
- pIdxInfo->aConstraintUsage[startIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[startIdx].omit= !SQLITE_SERIES_CONSTRAINT_VERIFY;
- }
- if( stopIdx>=0 ){
- pIdxInfo->aConstraintUsage[stopIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[stopIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
- }
- if( stepIdx>=0 ){
- pIdxInfo->aConstraintUsage[stepIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[stepIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
- }
- if( (idxNum & 3)==3 ){
- /* Both start= and stop= boundaries are available. This is the
- ** the preferred case */
- pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
- pIdxInfo->estimatedRows = 1000;
- if( pIdxInfo->nOrderBy==1 ){
- if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8;
- pIdxInfo->orderByConsumed = 1;
- }
- }else{
- /* If either boundary is missing, we have to generate a huge span
- ** of numbers. Make this case very expensive so that the query
- ** planner will work hard to avoid it. */
- pIdxInfo->estimatedCost = (double)2147483647;
- pIdxInfo->estimatedRows = 2147483647;
- }
- pIdxInfo->idxNum = idxNum;
- return SQLITE_OK;
-}
-
-/*
-** This following structure defines all the methods for the
-** generate_series virtual table.
-*/
-static sqlite3_module seriesModule = {
- 0, /* iVersion */
- 0, /* xCreate */
- seriesConnect, /* xConnect */
- seriesBestIndex, /* xBestIndex */
- seriesDisconnect, /* xDisconnect */
- 0, /* xDestroy */
- seriesOpen, /* xOpen - open a cursor */
- seriesClose, /* xClose - close a cursor */
- seriesFilter, /* xFilter - configure scan constraints */
- seriesNext, /* xNext - advance a cursor */
- seriesEof, /* xEof - check for end of scan */
- seriesColumn, /* xColumn - read data */
- seriesRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
-};
-/* END the generate_series(START,END,STEP) implementation
-*********************************************************************************/
-
/*
** Print sketchy documentation for this utility program
*/
static void showHelp(void){
printf("Usage: %s [options] ?FILE...?\n", g.zArgv0);
@@ -1047,11 +727,10 @@
#ifndef SQLITE_OMIT_TRACE
sqlite3_trace(db, verboseFlag ? traceCallback : traceNoop, 0);
#endif
sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
- sqlite3_create_module(db, "generate_series", &seriesModule, 0);
sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000);
if( zEncoding ) sqlexec(db, "PRAGMA encoding=%s", zEncoding);
if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize);
if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL");
iStart = timeOfDay();
Index: tool/lemon.c
==================================================================
--- tool/lemon.c
+++ tool/lemon.c
@@ -261,12 +261,11 @@
char *firstset; /* First-set for all rules of this symbol */
Boolean lambda; /* True if NT and can generate an empty string */
int useCnt; /* Number of times used */
char *destructor; /* Code which executes whenever this symbol is
** popped from the stack during error processing */
- int destLineno; /* Line number for start of destructor. Set to
- ** -1 for duplicate destructors. */
+ int destLineno; /* Line number for start of destructor */
char *datatype; /* The data type of information held by this
** object. Only used if type==NONTERMINAL */
int dtnum; /* The data type number. In the parser, the value
** stack is a union. The .yy%d element of this
** union is the correct data type for this object */
@@ -4230,25 +4229,24 @@
}
}
fprintf(out, "};\n"); lineno++;
/* Output the yy_shift_ofst[] table */
+ fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
n = lemp->nxstate;
while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--;
- fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", lemp->nactiontab); lineno++;
- fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++;
- fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++;
- fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++;
+ fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++;
+ fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++;
+ fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++;
fprintf(out, "static const %s yy_shift_ofst[] = {\n",
- minimum_size_type(mnTknOfst, lemp->nterminal+lemp->nactiontab, &sz));
- lineno++;
+ minimum_size_type(mnTknOfst-1, mxTknOfst, &sz)); lineno++;
lemp->tablesize += n*sz;
for(i=j=0; isorted[i];
ofst = stp->iTknOfst;
- if( ofst==NO_OFFSET ) ofst = lemp->nactiontab;
+ if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1;
if( j==0 ) fprintf(out," /* %5d */ ", i);
fprintf(out, " %4d,", ofst);
if( j==9 || i==n-1 ){
fprintf(out, "\n"); lineno++;
j = 0;
@@ -4384,11 +4382,10 @@
fprintf(out," break;\n"); lineno++;
}
for(i=0; insymbol; i++){
struct symbol *sp = lemp->symbols[i];
if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
- if( sp->destLineno<0 ) continue; /* Already emitted */
fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++;
/* Combine duplicate destructors into a single case */
for(j=i+1; jnsymbol; j++){
struct symbol *sp2 = lemp->symbols[j];
@@ -4395,11 +4392,11 @@
if( sp2 && sp2->type!=TERMINAL && sp2->destructor
&& sp2->dtnum==sp->dtnum
&& strcmp(sp->destructor,sp2->destructor)==0 ){
fprintf(out," case %d: /* %s */\n",
sp2->index, sp2->name); lineno++;
- sp2->destLineno = -1; /* Avoid emitting this destructor again */
+ sp2->destructor = 0;
}
}
emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
fprintf(out," break;\n"); lineno++;
Index: tool/lempar.c
==================================================================
--- tool/lempar.c
+++ tool/lempar.c
@@ -114,33 +114,29 @@
** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then
** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE.
**
** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE
** and YY_MAX_REDUCE
-**
+
** N == YY_ERROR_ACTION A syntax error has occurred.
**
** N == YY_ACCEPT_ACTION The parser accepts its input.
**
** N == YY_NO_ACTION No such action. Denotes unused
** slots in the yy_action[] table.
**
** The action table is constructed as a single large table named yy_action[].
-** Given state S and lookahead X, the action is computed as either:
-**
-** (A) N = yy_action[ yy_shift_ofst[S] + X ]
-** (B) N = yy_default[S]
-**
-** The (A) formula is preferred. The B formula is used instead if:
-** (1) The yy_shift_ofst[S]+X value is out of range, or
-** (2) yy_lookahead[yy_shift_ofst[S]+X] is not equal to X, or
-** (3) yy_shift_ofst[S] equal YY_SHIFT_USE_DFLT.
-** (Implementation note: YY_SHIFT_USE_DFLT is chosen so that
-** YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X.
-** Hence only tests (1) and (2) need to be evaluated.)
-**
-** The formulas above are for computing the action when the lookahead is
+** Given state S and lookahead X, the action is computed as
+**
+** yy_action[ yy_shift_ofst[S] + X ]
+**
+** If the index value yy_shift_ofst[S]+X is out of range or if the value
+** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
+** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
+** and that yy_default[S] should be used instead.
+**
+** The formula above is for computing the action when the lookahead is
** a terminal symbol. If the lookahead is a non-terminal (as occurs after
** a reduce action) then the yy_reduce_ofst[] array is used in place of
** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
** YY_SHIFT_USE_DFLT.
**
@@ -452,51 +448,54 @@
if( stateno>=YY_MIN_REDUCE ) return stateno;
assert( stateno <= YY_SHIFT_COUNT );
do{
i = yy_shift_ofst[stateno];
+ if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno];
assert( iLookAhead!=YYNOCODE );
i += iLookAhead;
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
+ if( iLookAhead>0 ){
#ifdef YYFALLBACK
- YYCODETYPE iFallback; /* Fallback token */
- if( iLookAhead %s\n",
- yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
- }
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
+ yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
+ }
#endif
- assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */
- iLookAhead = iFallback;
- continue;
- }
+ assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */
+ iLookAhead = iFallback;
+ continue;
+ }
#endif
#ifdef YYWILDCARD
- {
- int j = i - iLookAhead + YYWILDCARD;
- if(
+ {
+ int j = i - iLookAhead + YYWILDCARD;
+ if(
#if YY_SHIFT_MIN+YYWILDCARD<0
- j>=0 &&
+ j>=0 &&
#endif
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
- j0
- ){
+ yy_lookahead[j]==YYWILDCARD
+ ){
#ifndef NDEBUG
- if( yyTraceFILE ){
- fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
- yyTracePrompt, yyTokenName[iLookAhead],
- yyTokenName[YYWILDCARD]);
- }
+ if( yyTraceFILE ){
+ fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
+ yyTracePrompt, yyTokenName[iLookAhead],
+ yyTokenName[YYWILDCARD]);
+ }
#endif /* NDEBUG */
- return yy_action[j];
+ return yy_action[j];
+ }
}
- }
#endif /* YYWILDCARD */
+ }
return yy_default[stateno];
}else{
return yy_action[i];
}
}while(1);
Index: tool/mksqlite3c-noext.tcl
==================================================================
--- tool/mksqlite3c-noext.tcl
+++ tool/mksqlite3c-noext.tcl
@@ -1,19 +1,19 @@
#!/usr/bin/tclsh
#
# To build a single huge source file holding all of SQLite (or at
-# least the core components - the test harness, shell, and TCL
+# least the core components - the test harness, shell, and TCL
# interface are omitted.) first do
#
# make target_source
#
# The make target above moves all of the source code files into
# a subdirectory named "tsrc". (This script expects to find the files
# there and will not work if they are not found.) There are a few
# generated C code files that are also added to the tsrc directory.
# For example, the "parse.c" and "parse.h" files to implement the
-# the parser are derived from "parse.y" using lemon. And the
+# the parser are derived from "parse.y" using lemon. And the
# "keywordhash.h" files is generated by a program named "mkkeywordhash".
#
# After the "tsrc" directory has been created and populated, run
# this script:
#
@@ -24,19 +24,24 @@
# Begin by reading the "sqlite3.h" header file. Extract the version number
# from in this file. The version number is needed to generate the header
# comment of the amalgamation.
#
-if {[lsearch $argv --nostatic]>=0} {
- set addstatic 0
-} else {
- set addstatic 1
-}
-if {[lsearch $argv --linemacros]>=0} {
- set linemacros 1
-} else {
- set linemacros 0
+set addstatic 1
+set linemacros 0
+set useapicall 0
+for {set i 0} {$i<[llength $argv]} {incr i} {
+ set x [lindex $argv $i]
+ if {[regexp {^-+nostatic$} $x]} {
+ set addstatic 0
+ } elseif {[regexp {^-+linemacros} $x]} {
+ set linemacros 1
+ } elseif {[regexp {^-+useapicall} $x]} {
+ set useapicall 1
+ } else {
+ error "unknown command-line option: $x"
+ }
}
set in [open tsrc/sqlite3.h]
set cnt 0
set VERSION ?????
while {![eof $in]} {
@@ -55,20 +60,20 @@
fconfigure $out -translation lf
set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
puts $out [subst \
{/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version $VERSION. By combining all the individual C code files into this
+** version $VERSION. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
** of 5% or more are commonly seen when SQLite is compiled as a single
** translation unit.
**
** This file is all you need to compile SQLite. To use SQLite in other
** programs, you need this file and the "sqlite3.h" header file that defines
-** the programming interface to the SQLite library. (If you do not have
+** the programming interface to the SQLite library. (If you do not have
** the "sqlite3.h" header file at hand, you will find a copy embedded within
** the text of this file. Search for "Begin file sqlite3.h" to find the start
** of the embedded sqlite3.h header file.) Additional code files may be needed
** if you want a wrapper to interface SQLite with your choice of programming
** language. The code for the "sqlite3" command-line shell is also in a
@@ -81,11 +86,11 @@
{#ifndef SQLITE_PRIVATE
# define SQLITE_PRIVATE static
#endif}
}
-# These are the header files used by SQLite. The first time any of these
+# These are the header files used by SQLite. The first time any of these
# files are seen in a #include statement in the C code, include the complete
# text of the file in-line. The file only needs to be included once.
#
foreach hdr {
btree.h
@@ -102,12 +107,12 @@
os.h
pager.h
parse.h
pcache.h
pragma.h
- sqlite3ext.h
sqlite3.h
+ sqlite3ext.h
sqliteicu.h
sqliteInt.h
sqliteLimit.h
vdbe.h
vdbeInt.h
@@ -153,11 +158,12 @@
# Read the source file named $filename and write it into the
# sqlite3.c output file. If any #include statements are seen,
# process them appropriately.
#
proc copy_file {filename} {
- global seen_hdr available_hdr varonly_hdr cdecllist out addstatic linemacros
+ global seen_hdr available_hdr varonly_hdr cdecllist out
+ global addstatic linemacros useapicall
set ln 0
set tail [file tail $filename]
section_comment "Begin file $tail"
if {$linemacros} {puts $out "#line 1 \"$filename\""}
set in [open $filename r]
@@ -201,30 +207,33 @@
}
} elseif {[regexp {^#ifdef __cplusplus} $line]} {
puts $out "#if 0"
} elseif {!$linemacros && [regexp {^#line} $line]} {
# Skip #line directives.
- } elseif {$addstatic && ![regexp {^(static|typedef)} $line]} {
+ } elseif {$addstatic
+ && ![regexp {^(static|typedef|SQLITE_PRIVATE)} $line]} {
# Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
# functions if this header file does not need it.
if {![info exists varonly_hdr($tail)]
&& [regexp $declpattern $line all rettype funcname rest]} {
regsub {^SQLITE_API } $line {} line
# Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
# so that linkage can be modified at compile-time.
- if {[regexp {^sqlite3_} $funcname]} {
+ if {[regexp {^sqlite3[a-z]*_} $funcname]} {
set line SQLITE_API
append line " " [string trim $rettype]
if {[string index $rettype end] ne "*"} {
append line " "
}
- if {[lsearch -exact $cdecllist $funcname] >= 0} {
- append line SQLITE_CDECL
- } else {
- append line SQLITE_APICALL
+ if {$useapicall} {
+ if {[lsearch -exact $cdecllist $funcname] >= 0} {
+ append line SQLITE_CDECL " "
+ } else {
+ append line SQLITE_APICALL " "
+ }
}
- append line " " $funcname $rest
+ append line $funcname $rest
puts $out $line
} else {
puts $out "SQLITE_PRIVATE $line"
}
} elseif {[regexp $varpattern $line all varname]} {
@@ -283,10 +292,11 @@
mutex_noop.c
mutex_unix.c
mutex_w32.c
malloc.c
printf.c
+ treeview.c
random.c
threads.c
utf.c
util.c
hash.c
@@ -311,11 +321,10 @@
vdbeapi.c
vdbetrace.c
vdbe.c
vdbeblob.c
vdbesort.c
- journal.c
memjournal.c
walker.c
resolve.c
expr.c
@@ -337,10 +346,12 @@
table.c
trigger.c
update.c
vacuum.c
vtab.c
+ wherecode.c
+ whereexpr.c
where.c
parse.c
tokenize.c
Index: tool/mksqlite3c.tcl
==================================================================
--- tool/mksqlite3c.tcl
+++ tool/mksqlite3c.tcl
@@ -1,19 +1,19 @@
#!/usr/bin/tclsh
#
# To build a single huge source file holding all of SQLite (or at
-# least the core components - the test harness, shell, and TCL
+# least the core components - the test harness, shell, and TCL
# interface are omitted.) first do
#
# make target_source
#
# The make target above moves all of the source code files into
# a subdirectory named "tsrc". (This script expects to find the files
# there and will not work if they are not found.) There are a few
# generated C code files that are also added to the tsrc directory.
# For example, the "parse.c" and "parse.h" files to implement the
-# the parser are derived from "parse.y" using lemon. And the
+# the parser are derived from "parse.y" using lemon. And the
# "keywordhash.h" files is generated by a program named "mkkeywordhash".
#
# After the "tsrc" directory has been created and populated, run
# this script:
#
@@ -26,16 +26,19 @@
# from in this file. The version number is needed to generate the header
# comment of the amalgamation.
#
set addstatic 1
set linemacros 0
+set useapicall 0
for {set i 0} {$i<[llength $argv]} {incr i} {
set x [lindex $argv $i]
if {[regexp {^-+nostatic$} $x]} {
set addstatic 0
} elseif {[regexp {^-+linemacros} $x]} {
set linemacros 1
+ } elseif {[regexp {^-+useapicall} $x]} {
+ set useapicall 1
} else {
error "unknown command-line option: $x"
}
}
set in [open tsrc/sqlite3.h]
@@ -57,20 +60,20 @@
fconfigure $out -translation lf
set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
puts $out [subst \
{/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version $VERSION. By combining all the individual C code files into this
+** version $VERSION. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
** of 5% or more are commonly seen when SQLite is compiled as a single
** translation unit.
**
** This file is all you need to compile SQLite. To use SQLite in other
** programs, you need this file and the "sqlite3.h" header file that defines
-** the programming interface to the SQLite library. (If you do not have
+** the programming interface to the SQLite library. (If you do not have
** the "sqlite3.h" header file at hand, you will find a copy embedded within
** the text of this file. Search for "Begin file sqlite3.h" to find the start
** of the embedded sqlite3.h header file.) Additional code files may be needed
** if you want a wrapper to interface SQLite with your choice of programming
** language. The code for the "sqlite3" command-line shell is also in a
@@ -83,11 +86,11 @@
{#ifndef SQLITE_PRIVATE
# define SQLITE_PRIVATE static
#endif}
}
-# These are the header files used by SQLite. The first time any of these
+# These are the header files used by SQLite. The first time any of these
# files are seen in a #include statement in the C code, include the complete
# text of the file in-line. The file only needs to be included once.
#
foreach hdr {
btree.h
@@ -110,11 +113,10 @@
parse.h
pcache.h
pragma.h
rtree.h
sqlite3session.h
- sqlite3ext.h
sqlite3.h
sqlite3ext.h
sqlite3rbu.h
sqliteicu.h
sqliteInt.h
@@ -164,11 +166,12 @@
# Read the source file named $filename and write it into the
# sqlite3.c output file. If any #include statements are seen,
# process them appropriately.
#
proc copy_file {filename} {
- global seen_hdr available_hdr varonly_hdr cdecllist out addstatic linemacros
+ global seen_hdr available_hdr varonly_hdr cdecllist out
+ global addstatic linemacros useapicall
set ln 0
set tail [file tail $filename]
section_comment "Begin file $tail"
if {$linemacros} {puts $out "#line 1 \"$filename\""}
set in [open $filename r]
@@ -227,16 +230,18 @@
set line SQLITE_API
append line " " [string trim $rettype]
if {[string index $rettype end] ne "*"} {
append line " "
}
- if {[lsearch -exact $cdecllist $funcname] >= 0} {
- append line SQLITE_CDECL
- } else {
- append line SQLITE_STDCALL
+ if {$useapicall} {
+ if {[lsearch -exact $cdecllist $funcname] >= 0} {
+ append line SQLITE_CDECL " "
+ } else {
+ append line SQLITE_APICALL " "
+ }
}
- append line " " $funcname $rest
+ append line $funcname $rest
puts $out $line
} else {
puts $out "SQLITE_PRIVATE $line"
}
} elseif {[regexp $varpattern $line all varname]} {
Index: tool/mksqlite3h.tcl
==================================================================
--- tool/mksqlite3h.tcl
+++ tool/mksqlite3h.tcl
@@ -8,21 +8,23 @@
# 3) The manifest file from the fossil SCM. This gives use the date.
# 4) The manifest.uuid file from the fossil SCM. This gives the SHA1 hash.
#
# Run this script by specifying the root directory of the source tree
# on the command-line.
-#
+#
# This script performs processing on src/sqlite.h.in. It:
#
# 1) Adds SQLITE_EXTERN in front of the declaration of global variables,
# 2) Adds SQLITE_API in front of the declaration of API functions,
-# 3) Replaces the string --VERS-- with the current library version,
+# 3) Replaces the string --VERS-- with the current library version,
# formatted as a string (e.g. "3.6.17"), and
# 4) Replaces the string --VERSION-NUMBER-- with current library version,
# formatted as an integer (e.g. "3006017").
-# 5) Replaces the string --SOURCE-ID-- with the date and time and sha1
+# 5) Replaces the string --SOURCE-ID-- with the date and time and sha1
# hash of the fossil-scm manifest for the source tree.
+# 6) Adds the SQLITE_CALLBACK calling convention macro in front of all
+# callback declarations.
#
# This script outputs to stdout.
#
# Example usage:
#
@@ -31,10 +33,18 @@
# Get the source tree root directory from the command-line
#
set TOP [lindex $argv 0]
+
+# Enable use of SQLITE_APICALL macros at the right points?
+#
+set useapicall 0
+
+if {[lsearch -regexp [lrange $argv 1 end] {^-+useapicall}] != -1} {
+ set useapicall 1
+}
# Get the SQLite version number (ex: 3.6.18) from the $TOP/VERSION file.
#
set in [open $TOP/VERSION]
set zVersion [string trim [read $in]]
@@ -94,18 +104,18 @@
set in [open $file]
if {![regexp {sqlite\.h\.in} $file]} {
puts "/******** Begin file [file tail $file] *********/"
}
while {![eof $in]} {
-
+
set line [gets $in]
# File sqlite3rtree.h contains a line "#include ". Omit this
# line when copying sqlite3rtree.h into sqlite3.h.
#
if {[string match {*#include*[<"]sqlite3.h[>"]*} $line]} continue
-
+
regsub -- --VERS-- $line $zVersion line
regsub -- --VERSION-NUMBER-- $line $nVersion line
regsub -- --SOURCE-ID-- $line "$zDate $zUuid" line
if {[regexp $varpattern $line] && ![regexp {^ *typedef} $line]} {
@@ -115,20 +125,27 @@
set line SQLITE_API
append line " " [string trim $rettype]
if {[string index $rettype end] ne "*"} {
append line " "
}
- if {[lsearch -exact $cdecllist $funcname] >= 0} {
- append line SQLITE_CDECL
- } else {
- append line SQLITE_STDCALL
+ if {$useapicall} {
+ if {[lsearch -exact $cdecllist $funcname] >= 0} {
+ append line SQLITE_CDECL " "
+ } else {
+ append line SQLITE_APICALL " "
+ }
}
- append line " " $funcname $rest
+ append line $funcname $rest
}
}
+ if {$useapicall} {
+ set line [string map [list (*sqlite3_syscall_ptr) \
+ "(SQLITE_SYSAPI *sqlite3_syscall_ptr)"] $line]
+ regsub {\(\*} $line {(SQLITE_CALLBACK *} line
+ }
puts $line
}
close $in
if {![regexp {sqlite\.h\.in} $file]} {
puts "/******** End of [file tail $file] *********/"
}
}
Index: tool/sqldiff.c
==================================================================
--- tool/sqldiff.c
+++ tool/sqldiff.c
@@ -1177,13 +1177,12 @@
strPrintf(pSql, ", 0, "); /* Set ota_control to 0 for an insert */
strPrintfArray(pSql, ", ", "NULL", azCol, -1);
strPrintf(pSql, " FROM aux.%Q AS n WHERE NOT EXISTS (\n", zTab);
strPrintf(pSql, " SELECT 1 FROM ", zTab);
strPrintf(pSql, " main.%Q AS o WHERE ", zTab);
- strPrintfArray(pSql, " AND ", "(n.%Q = o.%Q)", azCol, nPK);
- strPrintf(pSql, "\n) AND ");
- strPrintfArray(pSql, " AND ", "(n.%Q IS NOT NULL)", azCol, nPK);
+ strPrintfArray(pSql, " AND ", "(n.%Q IS o.%Q)", azCol, nPK);
+ strPrintf(pSql, "\n)");
/* Deleted rows: */
strPrintf(pSql, "\nUNION ALL\nSELECT ");
strPrintfArray(pSql, ", ", "%s", azCol, nPK);
if( azCol[nPK] ){
@@ -1193,13 +1192,12 @@
strPrintf(pSql, ", 1, "); /* Set ota_control to 1 for a delete */
strPrintfArray(pSql, ", ", "NULL", azCol, -1);
strPrintf(pSql, " FROM main.%Q AS n WHERE NOT EXISTS (\n", zTab);
strPrintf(pSql, " SELECT 1 FROM ", zTab);
strPrintf(pSql, " aux.%Q AS o WHERE ", zTab);
- strPrintfArray(pSql, " AND ", "(n.%Q = o.%Q)", azCol, nPK);
- strPrintf(pSql, "\n) AND ");
- strPrintfArray(pSql, " AND ", "(n.%Q IS NOT NULL)", azCol, nPK);
+ strPrintfArray(pSql, " AND ", "(n.%Q IS o.%Q)", azCol, nPK);
+ strPrintf(pSql, "\n) ");
/* Updated rows. If all table columns are part of the primary key, there
** can be no updates. In this case this part of the compound SELECT can
** be omitted altogether. */
if( azCol[nPK] ){
@@ -1226,11 +1224,11 @@
strPrintfArray(pSql, " ,\n",
" CASE WHEN n.%s IS o.%s THEN NULL ELSE o.%s END", &azCol[nPK], -1
);
strPrintf(pSql, "\nFROM main.%Q AS o, aux.%Q AS n\nWHERE ", zTab, zTab);
- strPrintfArray(pSql, " AND ", "(n.%Q = o.%Q)", azCol, nPK);
+ strPrintfArray(pSql, " AND ", "(n.%Q IS o.%Q)", azCol, nPK);
strPrintf(pSql, " AND ota_control LIKE '%%x%%'");
}
/* Now add an ORDER BY clause to sort everything by PK. */
strPrintf(pSql, "\nORDER BY ");