Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e8f850e7bd |
@@ -1 +0,0 @@
|
||||
*.db
|
||||
+14
-20
@@ -79,7 +79,7 @@ libdir = @libdir@
|
||||
|
||||
INSTALL = @BIN_INSTALL@
|
||||
AR = @AR@
|
||||
AR.flags = cr
|
||||
AR.flags = cr # TODO? Add a configure test to determine this?
|
||||
CC = @CC@
|
||||
B.cc = @CC_FOR_BUILD@ @BUILD_CFLAGS@
|
||||
T.cc = $(CC)
|
||||
@@ -118,7 +118,6 @@ LDFLAGS.dlopen = @LDFLAGS_DLOPEN@
|
||||
LDFLAGS.readline = @LDFLAGS_READLINE@
|
||||
CFLAGS.readline = @CFLAGS_READLINE@
|
||||
LDFLAGS.icu = @LDFLAGS_ICU@
|
||||
LDFLAGS.rt = @LDFLAGS_RT@
|
||||
CFLAGS.icu = @CFLAGS_ICU@
|
||||
LDFLAGS.libsqlite3.soname = @LDFLAGS_LIBSQLITE3_SONAME@
|
||||
# soname: see https://sqlite.org/src/forumpost/5a3b44f510df8ded
|
||||
@@ -126,17 +125,11 @@ LDFLAGS.libsqlite3.os-specific = @LDFLAGS_MAC_CVERSION@ @LDFLAGS_OUT_IMPLIB@
|
||||
# os-specific: see
|
||||
# - https://sqlite.org/forum/forumpost/9dfd5b8fd525a5d7
|
||||
# - https://sqlite.org/forum/forumpost/0c7fc097b2
|
||||
libsqlite3.DLL.basename = @SQLITE_DLL_BASENAME@
|
||||
# DLL.basename: see https://sqlite.org/forum/forumpost/828fdfe904
|
||||
libsqlite3.out.implib = @SQLITE_OUT_IMPLIB@
|
||||
# libsqlite3.out.implib => the output filename part of LDFLAGS_OUT_IMPLIB.
|
||||
ENABLE_LIB_SHARED = @ENABLE_LIB_SHARED@
|
||||
ENABLE_LIB_STATIC = @ENABLE_LIB_STATIC@
|
||||
ENABLE_SHARED = @ENABLE_SHARED@
|
||||
ENABLE_STATIC = @ENABLE_STATIC@
|
||||
HAVE_WASI_SDK = @HAVE_WASI_SDK@
|
||||
libsqlite3.DLL.install-rules = @SQLITE_DLL_INSTALL_RULES@
|
||||
|
||||
# -fsanitize flags for the fuzzcheck-asap app
|
||||
CFLAGS.fuzzcheck-asan.fsanitize = @CFLAGS_ASAN_FSANITIZE@
|
||||
T.cc.sqlite = $(T.cc) @TARGET_DEBUG@
|
||||
|
||||
#
|
||||
# Define -D_HAVE_SQLITE_CONFIG_H so that the code knows it
|
||||
@@ -145,12 +138,7 @@ CFLAGS.fuzzcheck-asan.fsanitize = @CFLAGS_ASAN_FSANITIZE@
|
||||
# main.mk will fill out T.cc.sqlite with additional flags common to
|
||||
# all builds.
|
||||
#
|
||||
T.cc.sqlite.extras = -D_HAVE_SQLITE_CONFIG_H -DBUILD_sqlite
|
||||
|
||||
#
|
||||
# Intended to either be empty or be set to -g -DSQLITE_DEBUG=1.
|
||||
#
|
||||
T.cc.TARGET_DEBUG = @TARGET_DEBUG@
|
||||
T.cc.sqlite += -D_HAVE_SQLITE_CONFIG_H -DBUILD_sqlite
|
||||
|
||||
#
|
||||
# $(JIMSH) and $(CFLAGS.jimsh) are documented in main.mk. $(JIMSH)
|
||||
@@ -158,7 +146,7 @@ T.cc.TARGET_DEBUG = @TARGET_DEBUG@
|
||||
# shell command.
|
||||
#
|
||||
CFLAGS.jimsh = @CFLAGS_JIMSH@
|
||||
JIMSH = ./jimsh$(T.exe)
|
||||
JIMSH = ./jimsh$(TEXE)
|
||||
|
||||
#
|
||||
# $(B.tclsh) is documented in main.mk.
|
||||
@@ -267,7 +255,6 @@ AS_AUTORECONFIG = @SQLITE_AUTORECONFIG@
|
||||
USE_AMALGAMATION ?= @USE_AMALGAMATION@
|
||||
LINK_TOOLS_DYNAMICALLY ?= @LINK_TOOLS_DYNAMICALLY@
|
||||
AMALGAMATION_GEN_FLAGS ?= --linemacros=@AMALGAMATION_LINE_MACROS@
|
||||
EXTRA_SRC ?= @AMALGAMATION_EXTRA_SRC@
|
||||
|
||||
#
|
||||
# CFLAGS for sqlite3$(T.exe)
|
||||
@@ -329,7 +316,13 @@ misspell: ./custom.rws has_tclsh84
|
||||
# perform cleanup known to be relevant to (only) the autosetup-driven
|
||||
# build.
|
||||
#
|
||||
distclean-autosetup:
|
||||
#clean-autosetup:
|
||||
# -if [ -f ext/wasm/GNUmakefile ]; then \
|
||||
# gmake --no-print-directory --ignore-errors -C ext/wasm clean; \
|
||||
# fi >/dev/null 2>&1; true
|
||||
#clean: clean-autosetup
|
||||
|
||||
distclean-autosetup: clean
|
||||
rm -f sqlite_cfg.h config.log config.status config.defines.* Makefile sqlite3.pc
|
||||
rm -f $(TOP)/tool/emcc.sh
|
||||
rm -f libsqlite3*$(T.dll)
|
||||
@@ -343,4 +336,5 @@ distclean: distclean-autosetup
|
||||
version-info$(T.exe): $(TOP)/tool/version-info.c Makefile sqlite3.h
|
||||
$(T.link) $(ST_OPT) -o $@ $(TOP)/tool/version-info.c
|
||||
|
||||
IS_CROSS_COMPILING = @IS_CROSS_COMPILING@
|
||||
include $(TOP)/main.mk
|
||||
|
||||
+7
-30
@@ -294,12 +294,6 @@ SESSION = 0
|
||||
RBU = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this to non-0 to enable support for blocking locks.
|
||||
#
|
||||
!IFNDEF SETLK_TIMEOUT
|
||||
SETLK_TIMEOUT = 0
|
||||
!ENDIF
|
||||
|
||||
# Set the source code file to be used by executables and libraries when
|
||||
# they need the amalgamation.
|
||||
#
|
||||
@@ -456,10 +450,6 @@ EXT_FEATURE_FLAGS =
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
!IF $(SETLK_TIMEOUT)!=0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SETLK_TIMEOUT
|
||||
!ENDIF
|
||||
|
||||
###############################################################################
|
||||
############################### END OF OPTIONS ################################
|
||||
###############################################################################
|
||||
@@ -1406,7 +1396,7 @@ SRC00 = \
|
||||
$(TOP)\src\build.c \
|
||||
$(TOP)\src\callback.c \
|
||||
$(TOP)\src\complete.c \
|
||||
ctime.c \
|
||||
$(TOP)\src\ctime.c \
|
||||
$(TOP)\src\date.c \
|
||||
$(TOP)\src\dbpage.c \
|
||||
$(TOP)\src\dbstat.c \
|
||||
@@ -1505,7 +1495,7 @@ SRC04 = \
|
||||
SRC05 = \
|
||||
$(TOP)\src\pager.h \
|
||||
$(TOP)\src\pcache.h \
|
||||
pragma.h \
|
||||
$(TOP)\src\pragma.h \
|
||||
$(TOP)\src\sqlite.h.in \
|
||||
$(TOP)\src\sqlite3ext.h \
|
||||
$(TOP)\src\sqliteInt.h \
|
||||
@@ -1708,7 +1698,7 @@ HDR = \
|
||||
$(TOP)\src\pager.h \
|
||||
$(TOP)\src\pcache.h \
|
||||
parse.h \
|
||||
pragma.h \
|
||||
$(TOP)\src\pragma.h \
|
||||
$(SQLITE3H) \
|
||||
sqlite3ext.h \
|
||||
$(TOP)\src\sqliteInt.h \
|
||||
@@ -2109,11 +2099,8 @@ callback.lo: $(TOP)\src\callback.c $(HDR)
|
||||
complete.lo: $(TOP)\src\complete.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\complete.c
|
||||
|
||||
ctime.c: $(TOP)\tool\mkctimec.tcl $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\tool\mkctimec.tcl
|
||||
|
||||
ctime.lo: ctime.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c ctime.c
|
||||
ctime.lo: $(TOP)\src\ctime.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\ctime.c
|
||||
|
||||
date.lo: $(TOP)\src\date.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\date.c
|
||||
@@ -2346,9 +2333,6 @@ parse.c: $(TOP)\src\parse.y lemon.exe
|
||||
copy /B parse.y +,,
|
||||
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) -S parse.y
|
||||
|
||||
pragma.h: $(TOP)\tool\mkpragmatab.tcl $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\tool\mkpragmatab.tcl
|
||||
|
||||
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest mksourceid.exe $(TOP)\VERSION $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\tool\mksqlite3h.tcl "$(TOP:\=/)" -o $(SQLITE3H) $(MKSQLITE3H_ARGS)
|
||||
|
||||
@@ -2593,11 +2577,6 @@ testfixture.exe: $(TESTFIXTURE_SRC) $(TESTFIXTURE_DEP) $(SQLITE3H) $(LIBRESOBJS)
|
||||
$(TESTFIXTURE_SRC) \
|
||||
/link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
|
||||
|
||||
# A small helper for manually running individual tests
|
||||
tf.bat: testfixture.exe Makefile.msc
|
||||
echo @set PATH=$(LIBTCLPATH);%PATH% > $@
|
||||
echo .\testfixture.exe %* >> $@
|
||||
|
||||
extensiontest: testfixture.exe testloadext.dll
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS)
|
||||
@@ -2833,7 +2812,7 @@ moreclean: clean
|
||||
clean:
|
||||
del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
|
||||
del /Q *.bsc *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
|
||||
del /Q sqlite3.def tclsqlite3.def ctime.c pragma.h 2>NUL
|
||||
del /Q sqlite3.def tclsqlite3.def 2>NUL
|
||||
del /Q $(SQLITE3EXE) $(SQLITE3DLL) Replace.exe 2>NUL
|
||||
# <<mark>>
|
||||
del /Q $(SQLITE3TCLDLL) pkgIndex.tcl 2>NUL
|
||||
@@ -2849,9 +2828,7 @@ clean:
|
||||
del /Q lsm.dll lsmtest.exe 2>NUL
|
||||
del /Q atrc.exe changesetfuzz.exe dbtotxt.exe index_usage.exe 2>NUL
|
||||
del /Q testloadext.dll 2>NUL
|
||||
del /Q testfixture.exe test.db tf.bat 2>NUL
|
||||
del /Q /S testdir 2>/NUL
|
||||
-rmdir /Q /S testdir 2>NUL
|
||||
del /Q testfixture.exe test.db 2>NUL
|
||||
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe dbdump.exe 2>NUL
|
||||
del /Q changeset.exe 2>NUL
|
||||
del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL
|
||||
|
||||
@@ -134,7 +134,7 @@ later. The "tclextension-install" target and the test targets that follow
|
||||
all require TCL development libraries too. ("apt install tcl-dev"). It is
|
||||
helpful, but is not required, to install the SQLite TCL extension (the
|
||||
"tclextension-install" target) prior to running tests. The "releasetest"
|
||||
target has additional requirements, such as "valgrind".
|
||||
target has additional requiremenst, such as "valgrind".
|
||||
|
||||
On "make" command-lines, one can add "OPTIONS=..." to specify additional
|
||||
compile-time options over and above those set by ./configure. For example,
|
||||
|
||||
@@ -1,57 +1,279 @@
|
||||
#!/do/not/tclsh
|
||||
#/do/not/tclsh
|
||||
# ^^^ help out editors which guess this file's content type.
|
||||
#
|
||||
# This is the main autosetup-compatible configure script for the
|
||||
# SQLite project.
|
||||
#
|
||||
# This script and all of its dependencies must be kept compatible with
|
||||
# JimTCL, a copy of which is included in this source tree as
|
||||
# ./autosetup/jimsh0.c. The number of incompatibilities between
|
||||
# canonical TCL and JimTCL is very low and alternative formulations of
|
||||
# incompatible constructs have, so far, been easy to find.
|
||||
# This script should be kept compatible with JimTCL, a copy of which
|
||||
# is included in this source tree as ./autosetup/jimsh0.c. The number
|
||||
# of incompatibilities between canonical TCL and JimTCL is very low
|
||||
# and alternative formulations of incompatible constructs have, so
|
||||
# far, been easy to find.
|
||||
#
|
||||
# JimTCL: https://jim.tcl.tk
|
||||
#
|
||||
use sqlite-config
|
||||
sqlite-configure canonical {
|
||||
proj-if-opt-truthy dev {
|
||||
# --enable-dev needs to come early so that the downstream tests
|
||||
# which check for the following flags use their updated state.
|
||||
proj-opt-set all 1
|
||||
proj-opt-set debug 1
|
||||
proj-opt-set amalgamation 0
|
||||
define CFLAGS [get-env CFLAGS {-O0 -g}]
|
||||
# -------------^^^^^^^ intentionally using [get-env] instead of
|
||||
# [proj-get-env] here because [sqlite-setup-default-cflags] uses
|
||||
# [proj-get-env] and we want this to supercede that.
|
||||
sqlite-munge-cflags; # straighten out -DSQLITE_ENABLE/OMIT flags
|
||||
}
|
||||
sqlite-handle-debug
|
||||
sqlite-check-common-bins ;# must come before [sqlite-handle-wasi-sdk]
|
||||
sqlite-handle-wasi-sdk ;# must run relatively early, as it changes the environment
|
||||
sqlite-check-common-system-deps
|
||||
|
||||
proj-define-for-opt amalgamation USE_AMALGAMATION "Use amalgamation for builds?"
|
||||
|
||||
proj-define-for-opt gcov USE_GCOV "Use gcov?"
|
||||
|
||||
proj-define-for-opt test-status TSTRNNR_OPTS \
|
||||
"test-runner flags:" {--status} {}
|
||||
|
||||
proj-define-for-opt linemacros AMALGAMATION_LINE_MACROS \
|
||||
"Use #line macros in the amalgamation:"
|
||||
|
||||
define AMALGAMATION_EXTRA_SRC \
|
||||
[join [opt-val amalgamation-extra-src ""] " "]
|
||||
|
||||
define LINK_TOOLS_DYNAMICALLY [proj-opt-was-provided dynlink-tools]
|
||||
|
||||
if {[set fsan [join [opt-val asan-fsanitize] ","]] in {auto ""}} {
|
||||
set fsan address,bounds-strict
|
||||
}
|
||||
define CFLAGS_ASAN_FSANITIZE [proj-check-fsanitize [split $fsan ", "]]
|
||||
|
||||
sqlite-handle-tcl
|
||||
sqlite-handle-emsdk
|
||||
|
||||
if {[string first " " $autosetup(srcdir)] != -1} {
|
||||
user-error "The pathname of the source tree\
|
||||
may not contain space characters"
|
||||
}
|
||||
if {[string first " " $autosetup(builddir)] != -1} {
|
||||
user-error "The pathname of the build directory\
|
||||
may not contain space characters"
|
||||
}
|
||||
|
||||
|
||||
########################################################################
|
||||
# Regarding flag compatibility with the historical autotool configure
|
||||
# script:
|
||||
#
|
||||
# A very long story made short, autosetup's --flag handling has
|
||||
# some behaviors which make it impossible to implement 100% identical
|
||||
# flags compared to the historical autotools build. The differences
|
||||
# are documented here:
|
||||
#
|
||||
# 1) --debug is used by autosetup itself, but we patch it because
|
||||
# decades of muscle memory expect --debug to apply to this code,
|
||||
# not the configure script (details are in autosetup/README.md).
|
||||
#
|
||||
# 2) In autosetup, all flags starting with (--enable, --disable) are
|
||||
# forced to be booleans and receive special handling in how they're
|
||||
# resolved. Because of that we have to rename:
|
||||
#
|
||||
# 2.1) --enable-tempstore[=no] to --with-tempstore[=no], noting that
|
||||
# it has four legal values, not two.
|
||||
#
|
||||
########################################################################
|
||||
# A gentle introduction to flags handling in autosetup
|
||||
#
|
||||
# Reference: https://msteveb.github.io/autosetup/developer/
|
||||
#
|
||||
# All configure flags must be described in an 'options' call, which
|
||||
# must appear very early on in this script. The general syntax is:
|
||||
#
|
||||
# FLAG => {Help text}
|
||||
#
|
||||
# Where FLAG can have any of the following formats:
|
||||
#
|
||||
# boolopt => "a boolean option which defaults to disabled"
|
||||
# boolopt2=1 => "a boolean option which defaults to enabled"
|
||||
# stringopt: => "an option which takes an argument, e.g. --stringopt=value"
|
||||
# stringopt2:=value => "an option where the argument is optional and defaults to 'value'"
|
||||
# optalias booltopt3 => "a boolean with a hidden alias. --optalias is not shown in --help"
|
||||
#
|
||||
# Autosetup does no small amount of specialized handling for flags,
|
||||
# especially booleans. Each bool-type --FLAG implicitly gets
|
||||
# --enable-FLAG and --disable-FLAG forms. e.g. we define a flag
|
||||
# "readline", which will be interpreted in one of two ways, depending
|
||||
# on how it's invoked and how its default is defined:
|
||||
#
|
||||
# --enable-readline ==> boolean true
|
||||
# --disable-readline ==> boolean false
|
||||
#
|
||||
# Passing --readline or --readline=1 is equivalent to passing
|
||||
# --enable-readline, and --readline=0 is equivalent to
|
||||
# --disable-readline.
|
||||
#
|
||||
# The behavior described above can lead lead to some confusion when
|
||||
# writing help text. For example:
|
||||
#
|
||||
# options { json=1 {Disable JSON functions} }
|
||||
#
|
||||
# The reason the help text says "disable" is because a boolean option
|
||||
# which defaults to true is, in the --help text, rendered as:
|
||||
#
|
||||
# --disable-json Disable JSON functions
|
||||
#
|
||||
# Whereas a bool flag which defaults to false will instead render as:
|
||||
#
|
||||
# --enable-FLAG
|
||||
#
|
||||
# Non-boolean flags, in contrast, use the names specifically given to
|
||||
# them in the [options] invocation. e.g. "with-tcl" is the --with-tcl
|
||||
# flag.
|
||||
#
|
||||
# Fetching values for flags:
|
||||
#
|
||||
# booleans: use one of:
|
||||
# - [opt-bool FLAG] is autosetup's built-in command for this, but we
|
||||
# have some convenience variants:
|
||||
# - [proj-opt-truthy FLAG]
|
||||
# - [proj-opt-if-truthy FLAG {THEN} {ELSE}]
|
||||
#
|
||||
# Non-boolean (i.e. string) flags:
|
||||
# - [opt-val FLAG ?default?]
|
||||
# - [opt-str ...] - see the docs in ./autosetup/autosetup
|
||||
#
|
||||
########################################################################
|
||||
set flags {
|
||||
# When writing {help text blocks}, be aware that autosetup formats
|
||||
# them differently (left-aligned, directly under the --flag) if the
|
||||
# block starts with a newline. It does NOT expand vars and commands,
|
||||
# but we use a [subst] call below which will replace (only) var
|
||||
# refs.
|
||||
|
||||
# <build-modes>
|
||||
shared=1 => {Disable build of shared libary}
|
||||
static=1 => {Disable build of static library (mostly)}
|
||||
amalgamation=1 => {Disable the amalgamation and instead build all files separately.}
|
||||
# </build-modes>
|
||||
# <lib-feature>
|
||||
threadsafe=1 => {Disable mutexing}
|
||||
with-tempstore:=no => {Use an in-RAM database for temporary tables: never,no,yes,always}
|
||||
largefile=1 => {Disable large file support}
|
||||
load-extension=1 => {Disable loading of external extensions}
|
||||
math=1 => {Disable math functions}
|
||||
json=1 => {Disable JSON functions}
|
||||
memsys5 => {Enable MEMSYS5}
|
||||
memsys3 => {Enable MEMSYS3}
|
||||
fts3 => {Enable the FTS3 extension}
|
||||
fts4 => {Enable the FTS4 extension}
|
||||
fts5 => {Enable the FTS5 extension}
|
||||
update-limit => {Enable the UPDATE/DELETE LIMIT clause}
|
||||
geopoly => {Enable the GEOPOLY extension}
|
||||
rtree => {Enable the RTREE extension}
|
||||
session => {Enable the SESSION extension}
|
||||
all => {Enable FTS4, FTS5, Geopoly, RTree, Sessions}
|
||||
# </lib-feature>
|
||||
# <tcl>
|
||||
with-tcl:DIR =>
|
||||
{Directory containing tclConfig.sh or a directory one level up from
|
||||
that, from which we can derive a directory containing tclConfig.sh.
|
||||
A dir name of "prefix" is equivalent to the directory specified by
|
||||
the --prefix flag.}
|
||||
with-tclsh:PATH =>
|
||||
{Full pathname of tclsh to use. It is used for (A) trying to find
|
||||
tclConfig.sh and (B) all TCL-based code generation. Warning: if
|
||||
its containing dir has multiple tclsh versions, it may select the
|
||||
wrong tclConfig.sh!}
|
||||
tcl=1 =>
|
||||
{Disable components which require TCL, including all tests.
|
||||
This tree requires TCL for code generation but can use the in-tree
|
||||
copy of autosetup/jimsh0.c for that. The SQLite TCL extension and the
|
||||
test code require a canonical tclsh.}
|
||||
# <tcl>
|
||||
# <line-editing>
|
||||
readline=1 => {Disable readline support}
|
||||
# --with-readline-lib is a backwards-compatible alias for
|
||||
# --with-readline-ldflags
|
||||
with-readline-lib:
|
||||
with-readline-ldflags:=auto
|
||||
=> {Readline LDFLAGS, e.g. -lreadline -lncurses}
|
||||
# --with-readline-inc is a backwards-compatible alias for
|
||||
# --with-readline-cflags.
|
||||
with-readline-inc:
|
||||
with-readline-cflags:=auto
|
||||
=> {Readline CFLAGS, e.g. -I/path/to/includes}
|
||||
with-readline-header:PATH
|
||||
=> {Full path to readline.h, from which --with-readline-cflags will be derived}
|
||||
with-linenoise:DIR => {Source directory for linenoise.c and linenoise.h}
|
||||
editline=0 => {Enable BSD editline support}
|
||||
# </line-editing>
|
||||
# <icu>
|
||||
with-icu-ldflags:LDFLAGS
|
||||
=> {Enable SQLITE_ENABLE_ICU and add the given linker flags for the ICU libraries}
|
||||
with-icu-cflags:CFLAGS
|
||||
=> {Apply extra CFLAGS/CPPFLAGS necessary for building with ICU. e.g. -I/usr/local/include}
|
||||
with-icu-config:=auto => {Enable SQLITE_ENABLE_ICU. Value must be one of: auto, pkg-config, /path/to/icu-config}
|
||||
icu-collations=0 => {Enable SQLITE_ENABLE_ICU_COLLATIONS. Requires --with-icu-ldflags=... or --with-icu-config}
|
||||
# </icu>
|
||||
# <alternative-builds>
|
||||
with-wasi-sdk:=/opt/wasi-sdk
|
||||
=> {Top-most dir of the wasi-sdk for a WASI build}
|
||||
with-emsdk:=auto => {Top-most dir of the Emscripten SDK installation. Default = EMSDK env var.}
|
||||
# </alternative-builds>
|
||||
# <developer>
|
||||
# Note that using the --debug/--enable-debug flag here requires patching
|
||||
# autosetup/autosetup to rename the --debug to --autosetup-debug.
|
||||
with-debug=0
|
||||
debug=0 =>
|
||||
{Enable debug build flags. This option will impact performance by
|
||||
as much as 4x, as it includes large numbers of assert()s in
|
||||
performance-critical loops. Never use --debug for production
|
||||
builds.}
|
||||
scanstatus => {Enable the SQLITE_ENABLE_STMT_SCANSTATUS feature flag}
|
||||
dev => {Enable dev-mode build: automatically enables certain other flags}
|
||||
test-status => {Enable status of tests}
|
||||
gcov=0 => {Enable coverage testing using gcov}
|
||||
linemacros => {Enable #line macros in the amalgamation}
|
||||
dynlink-tools => {Dynamically link libsqlite3 to certain tools which normally statically embed it.}
|
||||
soname:=legacy =>
|
||||
# --soname has a long story behind it: https://sqlite.org/src/forumpost/5a3b44f510df8ded
|
||||
{SONAME for libsqlite3.so. "none", or not using this flag, sets no
|
||||
soname. "legacy" sets it to its historical value of
|
||||
libsqlite3.so.0. A value matching the glob "libsqlite3.*" sets
|
||||
it to that literal value. Any other value is assumed to be a
|
||||
suffix which gets applied to "libsqlite3.so.",
|
||||
e.g. --soname=9.10 equates to "libsqlite3.so.9.10".
|
||||
}
|
||||
dump-defines=0 => {Dump autosetup defines to $::sqliteConfig(dump-defines-txt) (for build debugging)}
|
||||
# </developer>
|
||||
}
|
||||
if {"" ne $::sqliteConfig(dump-defines-json)} {
|
||||
lappend flags \
|
||||
defines-json-include-lowercase=0 \
|
||||
=> {Include lower-case defines (primarily system paths) in $::sqliteConfig(dump-defines-json)}
|
||||
}
|
||||
|
||||
options [subst -nobackslashes -nocommands $flags]
|
||||
unset flags
|
||||
sqlite-post-options-init
|
||||
|
||||
sqlite-setup-default-cflags
|
||||
proj-if-opt-truthy dev {
|
||||
# --enable-dev needs to come early so that the downstream tests
|
||||
# which check for the following flags use their updated state.
|
||||
proj-opt-set all 1
|
||||
proj-opt-set debug 1
|
||||
proj-opt-set amalgamation 0
|
||||
define CFLAGS [get-env CFLAGS {-O0 -g}]
|
||||
# -------------^^^^^^^ intentionally using [get-env] instead of
|
||||
# [proj-get-env] here because [sqlite-setup-default-cflags] uses
|
||||
# [proj-get-env] and we want this to supercede that.
|
||||
}
|
||||
|
||||
sqlite-check-common-bins ;# must come before [sqlite-handle-wasi-sdk]
|
||||
sqlite-handle-wasi-sdk ;# must run relatively early, as it changes the environment
|
||||
sqlite-check-common-system-deps
|
||||
|
||||
#
|
||||
# Enable large file support (if special flags are necessary)
|
||||
#
|
||||
define HAVE_LFS 0
|
||||
if {[opt-bool largefile]} {
|
||||
cc-check-lfs
|
||||
}
|
||||
|
||||
proj-define-for-opt shared ENABLE_SHARED "Build shared library?"
|
||||
|
||||
if {![proj-define-for-opt static ENABLE_STATIC \
|
||||
"Build static library?"]} {
|
||||
proj-warn "Static lib build may be implicitly re-activated by other components, e.g. some test apps."
|
||||
}
|
||||
|
||||
proj-define-for-opt amalgamation USE_AMALGAMATION "Use amalgamation for builds?"
|
||||
|
||||
proj-define-for-opt gcov USE_GCOV "Use gcov?"
|
||||
|
||||
proj-define-for-opt test-status TSTRNNR_OPTS \
|
||||
"test-runner flags:" {--status} {}
|
||||
|
||||
proj-define-for-opt linemacros AMALGAMATION_LINE_MACROS \
|
||||
"Use #line macros in the amalgamation:"
|
||||
|
||||
define LINK_TOOLS_DYNAMICALLY [proj-opt-was-provided dynlink-tools]
|
||||
|
||||
proj-check-rpath
|
||||
sqlite-handle-soname
|
||||
sqlite-handle-debug
|
||||
sqlite-handle-tcl
|
||||
sqlite-handle-threadsafe
|
||||
sqlite-handle-tempstore
|
||||
sqlite-handle-line-editing
|
||||
sqlite-handle-load-extension
|
||||
sqlite-handle-math
|
||||
sqlite-handle-icu
|
||||
sqlite-handle-emsdk
|
||||
sqlite-common-late-stage-config
|
||||
sqlite-dump-defines
|
||||
|
||||
+52
-93
@@ -50,7 +50,6 @@ CC = @CC@
|
||||
|
||||
ENABLE_LIB_SHARED = @ENABLE_LIB_SHARED@
|
||||
ENABLE_LIB_STATIC = @ENABLE_LIB_STATIC@
|
||||
HAVE_WASI_SDK = @HAVE_WASI_SDK@
|
||||
|
||||
CFLAGS = @CFLAGS@ @CPPFLAGS@
|
||||
#
|
||||
@@ -68,12 +67,14 @@ LDFLAGS.pthread = @LDFLAGS_PTHREAD@
|
||||
LDFLAGS.dlopen = @LDFLAGS_DLOPEN@
|
||||
LDFLAGS.readline = @LDFLAGS_READLINE@
|
||||
CFLAGS.readline = @CFLAGS_READLINE@
|
||||
LDFLAGS.rt = @LDFLAGS_RT@
|
||||
LDFLAGS.icu = @LDFLAGS_ICU@
|
||||
CFLAGS.icu = @CFLAGS_ICU@
|
||||
|
||||
# INSTALL reminder: we specifically do not strip binaries,
|
||||
# as discussed in https://sqlite.org/forum/forumpost/9a67df63eda9925c.
|
||||
# When cross-compiling, we need to avoid the -s flag because it only
|
||||
# works on the build host's platform.
|
||||
INSTALL.strip.1 = $(INSTALL)
|
||||
INSTALL.strip.0 = $(INSTALL) -s
|
||||
INSTALL.strip = $(INSTALL.strip.@IS_CROSS_COMPILING@)
|
||||
INSTALL.noexec = $(INSTALL) -m 0644
|
||||
|
||||
install-dir.bin = $(DESTDIR)$(bindir)
|
||||
@@ -85,7 +86,7 @@ install-dir.all = $(install-dir.bin) $(install-dir.include) \
|
||||
$(install-dir.lib) $(install-dir.man1) \
|
||||
$(install-dir.pkgconfig)
|
||||
$(install-dir.all):
|
||||
@if [ ! -d "$@" ]; then set -x; $(INSTALL) -d "$@"; fi
|
||||
if [ ! -d "$@" ]; then $(INSTALL) -d "$@"; fi
|
||||
# ^^^^ on some platforms, install -d fails if the target already exists.
|
||||
|
||||
|
||||
@@ -134,85 +135,58 @@ LDFLAGS.libsqlite3 = \
|
||||
$(LDFLAGS.rpath) $(LDFLAGS.pthread) \
|
||||
$(LDFLAGS.math) $(LDFLAGS.dlopen) \
|
||||
$(LDFLAGS.zlib) $(LDFLAGS.icu) \
|
||||
$(LDFLAGS.rt) $(LDFLAGS.configure)
|
||||
$(LDFLAGS.configure)
|
||||
CFLAGS.libsqlite3 = -I. $(CFLAGS.core) $(CFLAGS.icu) $(OPT_FEATURE_FLAGS)
|
||||
|
||||
sqlite3.o: $(TOP)/sqlite3.h $(TOP)/sqlite3.c
|
||||
$(CC) -c $(TOP)/sqlite3.c -o $@ $(CFLAGS) $(CFLAGS.libsqlite3)
|
||||
|
||||
libsqlite3.LIB = libsqlite3$(T.lib)
|
||||
libsqlite3.DLL.basename = @SQLITE_DLL_BASENAME@
|
||||
libsqlite3.out.implib = @SQLITE_OUT_IMPLIB@
|
||||
libsqlite3.DLL = $(libsqlite3.DLL.basename)$(T.dll)
|
||||
libsqlite3.DLL.install-rules = @SQLITE_DLL_INSTALL_RULES@
|
||||
libsqlite3.SO = libsqlite3$(T.dll)
|
||||
|
||||
$(libsqlite3.DLL): sqlite3.o
|
||||
$(libsqlite3.SO): sqlite3.o
|
||||
$(CC) -o $@ sqlite3.o $(LDFLAGS.shlib) \
|
||||
$(LDFLAGS) $(LDFLAGS.libsqlite3) \
|
||||
$(LDFLAGS.libsqlite3.os-specific) $(LDFLAGS.libsqlite3.soname)
|
||||
$(libsqlite3.DLL)-1: $(libsqlite3.DLL)
|
||||
$(libsqlite3.DLL)-0:
|
||||
all: $(libsqlite3.DLL)-$(ENABLE_LIB_SHARED)
|
||||
all: $(libsqlite3.SO)
|
||||
|
||||
$(libsqlite3.LIB): sqlite3.o
|
||||
$(AR) $(AR.flags) $@ sqlite3.o
|
||||
$(libsqlite3.LIB)-1: $(libsqlite3.LIB)
|
||||
$(libsqlite3.LIB)-0:
|
||||
all: $(libsqlite3.LIB)-$(ENABLE_LIB_STATIC)
|
||||
all: $(libsqlite3.LIB)
|
||||
|
||||
#
|
||||
# Maintenance reminder: the install-dll-... rules must be kept in sync
|
||||
# with the main copies rom /main.mk.
|
||||
#
|
||||
install-dll-out-implib: $(install-dir.lib) $(libsqlite3.DLL)
|
||||
if [ x != "x$(libsqlite3.out.implib)" ] && [ -f "$(libsqlite3.out.implib)" ]; then \
|
||||
$(INSTALL) $(libsqlite3.out.implib) "$(install-dir.lib)"; \
|
||||
install-so-1: $(install-dir.lib) $(libsqlite3.SO)
|
||||
$(INSTALL) $(libsqlite3.SO) "$(install-dir.lib)"
|
||||
@echo "Setting up $(libsqlite3.SO) version symlinks..."; \
|
||||
cd "$(install-dir.lib)" || exit $$?; \
|
||||
if [ x.dylib = x$(T.dll) ]; then \
|
||||
rm -f libsqlite3.0$(T.dll) libsqlite3.$(PACKAGE_VERSION)$(T.dll) || exit $$?; \
|
||||
dllname=libsqlite3.$(PACKAGE_VERSION)$(T.dll); \
|
||||
mv $(libsqlite3.SO) $$dllname || exit $$?; \
|
||||
ln -s $$dllname $(libsqlite3.SO) || exit $$?; \
|
||||
ln -s $$dllname libsqlite3.0$(T.dll) || exit $$?; \
|
||||
ls -la $$dllname $(libsqlite3.SO) libsqlite3.0$(T.dll); \
|
||||
else \
|
||||
rm -f $(libsqlite3.SO).0 $(libsqlite3.SO).$(PACKAGE_VERSION) || exit $$?; \
|
||||
mv $(libsqlite3.SO) $(libsqlite3.SO).$(PACKAGE_VERSION) || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO) || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0 || exit $$?; \
|
||||
ls -la $(libsqlite3.SO) $(libsqlite3.SO).[03]*; \
|
||||
if [ -e $(libsqlite3.SO).0.8.6 ]; then \
|
||||
echo "ACHTUNG: legacy libtool-compatible install found. Re-linking it..."; \
|
||||
rm -f libsqlite3.la $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ls -la $(libsqlite3.SO).0.8.6; \
|
||||
elif [ x1 = "x$(INSTALL_SO_086_LINK)" ]; then \
|
||||
echo "ACHTUNG: installing legacy libtool-style links because INSTALL_SO_086_LINK=1"; \
|
||||
rm -f libsqlite3.la $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ls -la $(libsqlite3.SO).0.8.6; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
install-dll-unix-generic: install-dll-out-implib
|
||||
$(INSTALL) $(libsqlite3.DLL) "$(install-dir.lib)"
|
||||
@echo "Setting up $(libsqlite3.DLL) version symlinks..."; \
|
||||
cd "$(install-dir.lib)" || exit $$?; \
|
||||
rm -f $(libsqlite3.DLL).0 $(libsqlite3.DLL).$(PACKAGE_VERSION) || exit $$?; \
|
||||
mv $(libsqlite3.DLL) $(libsqlite3.DLL).$(PACKAGE_VERSION) || exit $$?; \
|
||||
ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL) || exit $$?; \
|
||||
ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL).0 || exit $$?; \
|
||||
ls -la $(libsqlite3.DLL) $(libsqlite3.DLL).[a03]*; \
|
||||
if [ -e $(libsqlite3.DLL).0.8.6 ]; then \
|
||||
echo "ACHTUNG: legacy libtool-compatible install found. Re-linking it..."; \
|
||||
rm -f libsqlite3.la $(libsqlite3.DLL).0.8.6 || exit $$?; \
|
||||
ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL).0.8.6 || exit $$?; \
|
||||
ls -la $(libsqlite3.DLL).0.8.6; \
|
||||
elif [ x1 = "x$(INSTALL_SO_086_LINK)" ]; then \
|
||||
echo "ACHTUNG: installing legacy libtool-style links because INSTALL_SO_086_LINK=1"; \
|
||||
rm -f libsqlite3.la $(libsqlite3.DLL).0.8.6 || exit $$?; \
|
||||
ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL).0.8.6 || exit $$?; \
|
||||
ls -la $(libsqlite3.DLL).0.8.6; \
|
||||
fi
|
||||
|
||||
install-dll-msys: install-dll-out-implib $(install-dir.bin)
|
||||
$(INSTALL) $(libsqlite3.DLL) "$(install-dir.bin)"
|
||||
# ----------------------------------------------^^^ yes, bin
|
||||
# Each of {msys,mingw,cygwin} uses a different name for the DLL, but
|
||||
# that is already accounted for via $(libsqlite3.DLL).
|
||||
install-dll-mingw: install-dll-msys
|
||||
install-dll-cygwin: install-dll-msys
|
||||
|
||||
install-dll-darwin: $(install-dir.lib) $(libsqlite3.DLL)
|
||||
$(INSTALL) $(libsqlite3.DLL) "$(install-dir.lib)"
|
||||
@echo "Setting up $(libsqlite3.DLL) version symlinks..."; \
|
||||
cd "$(install-dir.lib)" || exit $$?; \
|
||||
rm -f libsqlite3.0$(T.dll) libsqlite3.$(PACKAGE_VERSION)$(T.dll) || exit $$?; \
|
||||
dllname=libsqlite3.$(PACKAGE_VERSION)$(T.dll); \
|
||||
mv $(libsqlite3.DLL) $$dllname || exit $$?; \
|
||||
ln -s $$dllname $(libsqlite3.DLL) || exit $$?; \
|
||||
ln -s $$dllname libsqlite3.0$(T.dll) || exit $$?; \
|
||||
ls -la $$dllname $(libsqlite3.DLL) libsqlite3.0$(T.dll)
|
||||
|
||||
install-dll-1: install-dll-$(libsqlite3.DLL.install-rules)
|
||||
install-dll-0 install-dll-:
|
||||
install-dll: install-dll-$(ENABLE_LIB_SHARED)
|
||||
install: install-dll
|
||||
install-so-0 install-so-:
|
||||
install-so: install-so-$(ENABLE_LIB_SHARED)
|
||||
install: install-so
|
||||
|
||||
install-lib-1: $(install-dir.lib) $(libsqlite3.LIB)
|
||||
$(INSTALL.noexec) $(libsqlite3.LIB) "$(install-dir.lib)"
|
||||
@@ -220,30 +194,18 @@ install-lib-0 install-lib-:
|
||||
install-lib: install-lib-$(ENABLE_LIB_STATIC)
|
||||
install: install-lib
|
||||
|
||||
#
|
||||
# Flags to link the shell app either directly against sqlite3.c
|
||||
# (ENABLE_STATIC_SHELL==1) or libsqlite3.so (ENABLE_STATIC_SHELL==0).
|
||||
#
|
||||
ENABLE_STATIC_SHELL = @ENABLE_STATIC_SHELL@
|
||||
sqlite3-shell-link-flags.1 = $(TOP)/sqlite3.c $(LDFLAGS.libsqlite3)
|
||||
sqlite3-shell-link-flags.0 = -L. -lsqlite3 $(LDFLAGS.zlib)
|
||||
sqlite3-shell-deps.1 = $(TOP)/sqlite3.c
|
||||
sqlite3-shell-deps.0 = $(libsqlite3.DLL)
|
||||
sqlite3$(T.exe): $(TOP)/shell.c $(sqlite3-shell-deps.$(ENABLE_STATIC_SHELL))
|
||||
|
||||
sqlite3$(T.exe): $(TOP)/shell.c $(TOP)/sqlite3.c
|
||||
$(CC) -o $@ \
|
||||
$(TOP)/shell.c $(sqlite3-shell-link-flags.$(ENABLE_STATIC_SHELL)) \
|
||||
$(TOP)/shell.c $(TOP)/sqlite3.c \
|
||||
-I. $(OPT_FEATURE_FLAGS) $(SHELL_OPT) \
|
||||
$(CFLAGS) $(CFLAGS.readline) $(CFLAGS.icu) \
|
||||
$(LDFLAGS) $(LDFLAGS.readline)
|
||||
$(LDFLAGS) $(LDFLAGS.libsqlite3) $(LDFLAGS.readline)
|
||||
all: sqlite3$(T.exe)
|
||||
|
||||
sqlite3$(T.exe)-1:
|
||||
sqlite3$(T.exe)-0: sqlite3$(T.exe)
|
||||
all: sqlite3$(T.exe)-$(HAVE_WASI_SDK)
|
||||
|
||||
install-shell-0: sqlite3$(T.exe) $(install-dir.bin)
|
||||
$(INSTALL) sqlite3$(T.exe) "$(install-dir.bin)"
|
||||
install-shell-1:
|
||||
install: install-shell-$(HAVE_WASI_SDK)
|
||||
install-shell: sqlite3$(T.exe) $(install-dir.bin)
|
||||
$(INSTALL.strip) sqlite3$(T.exe) "$(install-dir.bin)"
|
||||
install: install-shell
|
||||
|
||||
install-headers: $(TOP)/sqlite3.h $(install-dir.include)
|
||||
$(INSTALL.noexec) $(TOP)/sqlite3.h $(TOP)/sqlite3ext.h "$(install-dir.include)"
|
||||
@@ -259,10 +221,10 @@ install: install-man1
|
||||
|
||||
clean:
|
||||
rm -f *.o sqlite3$(T.exe)
|
||||
rm -f $(libsqlite3.LIB) $(libsqlite3.DLL) libsqlite3$(T.dll).a
|
||||
rm -f $(libsqlite3.LIB) $(libsqlite3.SO) $(libsqlite3.SO).a
|
||||
|
||||
distclean: clean
|
||||
rm -f jimsh0$(T.exe) config.* sqlite3.pc sqlite_cfg.h Makefile
|
||||
rm -f jimsh0$(T.exe) config.* sqlite3.pc
|
||||
|
||||
DIST_FILES := \
|
||||
README.txt VERSION \
|
||||
@@ -272,17 +234,14 @@ DIST_FILES := \
|
||||
sqlite3.rc sqlite3rc.h Replace.cs \
|
||||
sqlite3.pc.in sqlite3.1
|
||||
|
||||
#
|
||||
# Maintenance note: dist_name must be sqlite-$(PACKAGE_VERSION) so
|
||||
# that tool/mkautoconfamal.sh knows how to find it.
|
||||
#
|
||||
dist_name = sqlite-$(PACKAGE_VERSION)
|
||||
dist_tarball = $(dist_name).tar.gz
|
||||
dist:
|
||||
rm -fr $(dist_name)
|
||||
mkdir -p $(dist_name)
|
||||
cp -rp $(DIST_FILES) $(dist_name)/.
|
||||
rm -f $(dist_name)/tea/configure.ac.in
|
||||
tar czf $(dist_tarball) $(dist_name)
|
||||
rm -fr $(dist_name)
|
||||
ls -l $(dist_tarball)
|
||||
|
||||
+1
-11
@@ -247,12 +247,6 @@ SESSION = 0
|
||||
RBU = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this to non-0 to enable support for blocking locks.
|
||||
#
|
||||
!IFNDEF SETLK_TIMEOUT
|
||||
SETLK_TIMEOUT = 0
|
||||
!ENDIF
|
||||
|
||||
# Set the source code file to be used by executables and libraries when
|
||||
# they need the amalgamation.
|
||||
#
|
||||
@@ -378,10 +372,6 @@ EXT_FEATURE_FLAGS =
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
!IF $(SETLK_TIMEOUT)!=0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SETLK_TIMEOUT
|
||||
!ENDIF
|
||||
|
||||
###############################################################################
|
||||
############################### END OF OPTIONS ################################
|
||||
###############################################################################
|
||||
@@ -1098,5 +1088,5 @@ $(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H)
|
||||
clean:
|
||||
del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
|
||||
del /Q *.bsc *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
|
||||
del /Q sqlite3.def tclsqlite3.def ctime.c pragma.h 2>NUL
|
||||
del /Q sqlite3.def tclsqlite3.def 2>NUL
|
||||
del /Q $(SQLITE3EXE) $(SQLITE3DLL) Replace.exe 2>NUL
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ the embedded copy of JimTCL).
|
||||
REASONS TO USE THE CANONICAL BUILD SYSTEM RATHER THAN THIS PACKAGE
|
||||
==================================================================
|
||||
|
||||
* the canonical build system allows you to run tests to verify that
|
||||
* the cononical build system allows you to run tests to verify that
|
||||
the build worked
|
||||
* the canonical build system supports more compile-time options
|
||||
* the canonical build system works for any arbitrary check-in to
|
||||
|
||||
+90
-14
@@ -1,21 +1,97 @@
|
||||
#!/do/not/tclsh
|
||||
#/do/not/tclsh
|
||||
# ^^^ help out editors which guess this file's content type.
|
||||
#
|
||||
# This is the main autosetup-compatible configure script for the
|
||||
# "autoconf" bundle of the SQLite project.
|
||||
#
|
||||
# This script must be kept compatible with JimTCL, a copy of which is
|
||||
# included in this source tree as ./autosetup/jimsh0.c.
|
||||
#
|
||||
use sqlite-config
|
||||
sqlite-configure autoconf {
|
||||
sqlite-handle-debug
|
||||
sqlite-check-common-bins ;# must come before [sqlite-handle-wasi-sdk]
|
||||
sqlite-handle-wasi-sdk ;# must run relatively early, as it changes the environment
|
||||
sqlite-check-common-system-deps
|
||||
proj-define-for-opt static-shell ENABLE_STATIC_SHELL \
|
||||
"Link library statically into the CLI shell?"
|
||||
if {![opt-bool shared] && ![opt-bool static-shell]} {
|
||||
proj-opt-set shared 1
|
||||
proj-indented-notice {
|
||||
NOTICE: ignoring --disable-shared because --disable-static-shell
|
||||
was specified.
|
||||
|
||||
options {
|
||||
# <build-modes>
|
||||
static=1 => {Disable build of static library}
|
||||
shared=1 => {Disable build of shared library}
|
||||
# </build-modes>
|
||||
# <lib-feature>
|
||||
threadsafe=1 => {Disable mutexing}
|
||||
with-tempstore:=no => {Use an in-RAM database for temporary tables: never,no,yes,always}
|
||||
load-extension=1 => {Disable loading of external extensions}
|
||||
math=1 => {Disable math functions}
|
||||
json=1 => {Disable JSON functions}
|
||||
memsys5 => {Enable MEMSYS5}
|
||||
memsys3 => {Enable MEMSYS3}
|
||||
fts3 => {Enable the FTS3 extension}
|
||||
fts4 => {Enable the FTS4 extension}
|
||||
fts5 => {Enable the FTS5 extension}
|
||||
update-limit => {Enable the UPDATE/DELETE LIMIT clause}
|
||||
geopoly => {Enable the GEOPOLY extension}
|
||||
rtree => {Enable the RTREE extension}
|
||||
session => {Enable the SESSION extension}
|
||||
all => {Enable FTS4, FTS5, Geopoly, RTree, Sessions}
|
||||
# </lib-feature>
|
||||
# <line-editing>
|
||||
readline=1 => {Disable readline support}
|
||||
# --with-readline-lib is a backwards-compatible alias for
|
||||
# --with-readline-ldflags
|
||||
with-readline-lib:
|
||||
with-readline-ldflags:=auto
|
||||
=> {Readline LDFLAGS, e.g. -lreadline -lncurses}
|
||||
# --with-readline-inc is a backwards-compatible alias for
|
||||
# --with-readline-cflags.
|
||||
with-readline-inc:
|
||||
with-readline-cflags:=auto
|
||||
=> {Readline CFLAGS, e.g. -I/path/to/includes}
|
||||
with-readline-header:PATH
|
||||
=> {Full path to readline.h, from which --with-readline-cflags will be derived}
|
||||
with-linenoise:DIR => {Source directory for linenoise.c and linenoise.h}
|
||||
editline=0 => {Enable BSD editline support}
|
||||
# </line-editing>
|
||||
# <icu>
|
||||
with-icu-ldflags:LDFLAGS
|
||||
=> {Enable SQLITE_ENABLE_ICU and add the given linker flags for the ICU libraries}
|
||||
with-icu-cflags:CFLAGS
|
||||
=> {Apply extra CFLAGS/CPPFLAGS necessary for building with ICU. e.g. -I/usr/local/include}
|
||||
with-icu-config:=auto => {Enable SQLITE_ENABLE_ICU. Value must be one of: auto, pkg-config, /path/to/icu-config}
|
||||
icu-collations=0 => {Enable SQLITE_ENABLE_ICU_COLLATIONS. Requires --with-icu-ldflags=... or --with-icu-config}
|
||||
# </icu>
|
||||
# <developer>
|
||||
# Note that using the --debug/--enable-debug flag here requires patching
|
||||
# autosetup/autosetup to rename the --debug to --autosetup-debug.
|
||||
with-debug=0
|
||||
debug=0 =>
|
||||
{Enable debug build flags. This option will impact performance by
|
||||
as much as 4x, as it includes large numbers of assert()s in
|
||||
performance-critical loops. Never use --debug for production
|
||||
builds.}
|
||||
# </developer>
|
||||
soname:=legacy =>
|
||||
# --soname has a long story behind it: https://sqlite.org/src/forumpost/5a3b44f510df8ded
|
||||
{SONAME for libsqlite3.so. "none", or not using this flag, sets no
|
||||
soname. "legacy" sets it to its historical value of
|
||||
libsqlite3.so.0. A value matching the glob "libsqlite3.*" sets
|
||||
it to that literal value. Any other value is assumed to be a
|
||||
suffix which gets applied to "libsqlite3.so.",
|
||||
e.g. --soname=9.10 equates to "libsqlite3.so.9.10".
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqlite-post-options-init
|
||||
sqlite-check-common-bins
|
||||
sqlite-check-common-system-deps
|
||||
proj-check-rpath
|
||||
sqlite-handle-soname
|
||||
sqlite-setup-default-cflags
|
||||
sqlite-handle-debug
|
||||
sqlite-handle-threadsafe
|
||||
sqlite-handle-tempstore
|
||||
sqlite-handle-line-editing
|
||||
sqlite-handle-load-extension
|
||||
sqlite-handle-math
|
||||
sqlite-handle-icu
|
||||
|
||||
define ENABLE_LIB_SHARED [opt-bool shared]
|
||||
define ENABLE_LIB_STATIC [opt-bool static]
|
||||
|
||||
sqlite-common-late-stage-config
|
||||
|
||||
@@ -26,7 +26,7 @@ SQLite that does not require first installing TCL and/or "tclsh".
|
||||
The canonical Makefile in the SQLite source tree provides more
|
||||
capabilities (such as the the ability to run test cases to ensure
|
||||
that the build worked) and is better maintained. The only
|
||||
downside of the canonical Makefile is that it requires a TCL
|
||||
downside of the canonical Makfile is that it requires a TCL
|
||||
installation. But if you are wanting to build the TCL extension for
|
||||
SQLite, then presumably you already have a TCL installation. So why
|
||||
not just use the more-capable and better-maintained canoncal Makefile?
|
||||
|
||||
@@ -19,7 +19,7 @@ dnl to configure the system for the local environment.
|
||||
# so that we create the export library with the dll.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_INIT([sqlite],[@VERSION@])
|
||||
AC_INIT([sqlite],[3.50.0])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
|
||||
@@ -93,7 +93,7 @@ TEA_ADD_TCL_SOURCES([])
|
||||
# The --with-system-sqlite causes the TCL bindings to SQLite to use
|
||||
# the system shared library for SQLite rather than statically linking
|
||||
# against its own private copy. This is dangerous and leads to
|
||||
# undesirable dependences and is not recommended.
|
||||
# undersirable dependences and is not recommended.
|
||||
# Patchs from rmax.
|
||||
#--------------------------------------------------------------------
|
||||
AC_ARG_WITH([system-sqlite],
|
||||
+44
-117
@@ -14,9 +14,7 @@ build infrastructure. It is not an [Autosetup][] reference.
|
||||
- Symbolic Names of Feature Flags
|
||||
- Do Not Update Global Shared State
|
||||
- [Updating Autosetup](#updating)
|
||||
- ***[Patching Autosetup for Project-local changes](#patching)***
|
||||
- [Branch-specific Customization](#branch-customization)
|
||||
|
||||
- [Patching Autosetup for Project-local changes](#patching)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
@@ -44,13 +42,12 @@ following files:
|
||||
(e.g. Fossil), and personal projects of SQLite's developers. It is
|
||||
essentially an amalgamation of a decade's worth of autosetup-related
|
||||
utility code.
|
||||
- [auto.def][]: the primary driver for the `./configure` process.
|
||||
When we talk about "the configure script," we're referring to
|
||||
this file.
|
||||
- [sqlite-config.tcl][]: utility code which is too project-specific
|
||||
for `proj.tcl`. We split this out of `auto.def` so that it can be
|
||||
used by both `auto.def` and...
|
||||
- [auto.def][]: the primary driver for the `./configure` process.
|
||||
When we talk about "the configure script," we're technically
|
||||
referring to this file, though it actually contains very little
|
||||
of the TCL code.
|
||||
- [autoconf/auto.def][]: the main driver script for the "autoconf"
|
||||
bundle's configure script. It is essentially a slightly trimmed-down
|
||||
version of the main `auto.def` file. The `autoconf` dir was ported
|
||||
@@ -64,11 +61,11 @@ Autosetup API Tips
|
||||
|
||||
This section briefly covers only APIs which are frequently useful in
|
||||
day-to-day maintenance and might not be immediately recognized as such
|
||||
from a casual perusal of the relevant TCL files. The complete docs of
|
||||
those with `proj-` prefix can be found in [proj.tcl][] and those with
|
||||
an `sqlite-` prefix are in [sqlite-config.tcl][]. The others are part
|
||||
of Autosetup's core packages and are scattered around [the TCL files
|
||||
in ./autosetup](/dir/autosetup).
|
||||
obvious from a casual perusal of the relevant TCL files. The complete
|
||||
docs of those with `proj-` prefix can be found in [proj.tcl][] and
|
||||
those with an `sqlite-` prefix are in [sqlite-config.tcl][]. The
|
||||
others are scattered around [the TCL files in
|
||||
./autosetup](/dir/autosetup).
|
||||
|
||||
In (mostly) alphabetical order:
|
||||
|
||||
@@ -86,14 +83,19 @@ In (mostly) alphabetical order:
|
||||
Works like `get-env` but will, if that function finds no match,
|
||||
look for a file named `./.env-$VAR` and, if found, return its
|
||||
trimmed contents. This can be used, e.g., to set a developer's
|
||||
local preferences for the default `CFLAGS`.\
|
||||
Tip: adding `-O0` to `.env-CFLAGS` reduces rebuild times
|
||||
considerably at the cost of performance in `make devtest` and the
|
||||
like.
|
||||
local preferences for the default `CFLAGS`.
|
||||
|
||||
- **`define-for-opt flag defineName ?checkingMsg? ?yesVal=1? ?noVal=0?`**\
|
||||
`[define $defineName]` to either `$yesVal` or `$noVal`, depending on
|
||||
whether `--$flag` is truthy or not. `$checkingMsg` is a
|
||||
human-readable description of the check being made, e.g. "enable foo?"
|
||||
If no `checkingMsg` is provided, the operation is silent.\
|
||||
Potential TODO: change the final two args to `-yes` and `-no`
|
||||
flags. They're rarely needed, though: search [auto.def][] for
|
||||
`TSTRNNR_OPTS` for an example of where they are used.
|
||||
|
||||
- **`proj-fatal msg`**\
|
||||
Emits `$msg` to stderr and exits with non-zero. Its differences from
|
||||
autosetup's `user-error` are purely cosmetic.
|
||||
Emits `$msg` to stderr and exits with non-zero.
|
||||
|
||||
- **`proj-if-opt-truthy flag thenScript ?elseScript?`**\
|
||||
Evals `thenScript` if the given `--flag` is truthy, else it
|
||||
@@ -115,10 +117,7 @@ In (mostly) alphabetical order:
|
||||
else 0. This distinction can be used to determine, e.g., whether
|
||||
`--with-readline` was provided or whether we're searching for
|
||||
readline by default. In the former case, failure to find it should
|
||||
be treated as fatal, where in the latter case it's not.\
|
||||
Unlike most functions which deal with `--flags`, this one does not
|
||||
validate that `$FLAG` is a registered flag so will not fail fatally
|
||||
if `$FLAG` is not registered as an Autosetup option.
|
||||
be treated as fatal, where in the latter case it's not.
|
||||
|
||||
- **`proj-val-truthy value`**\
|
||||
Returns 1 if `$value` is "truthy," See `proj-opt-truthy` for the definition
|
||||
@@ -140,15 +139,6 @@ In (mostly) alphabetical order:
|
||||
The shell-specific counterpart of `sqlite-add-feature-flag` which
|
||||
only adds the given flag(s) to the CLI-shell-specific CFLAGS.
|
||||
|
||||
- **`sqlite-configure BUILD-NAME {script}`**\
|
||||
This is where all configure `--flags` are defined for all known
|
||||
build modes ("canonical" or "autoconf"). After processing all flags,
|
||||
this function runs `$script`, which contains the build-mode-specific
|
||||
configuration bits, and then runs any finalization bits which are
|
||||
common to all build modes. The `auto.def` files are intended to contain
|
||||
exactly two commands:
|
||||
`use sqlite-config; sqlite-configure BUILD-NAME {script}`
|
||||
|
||||
- **`user-notice msg`**\
|
||||
Queues `$msg` to be sent to stderr, but does not emit it until
|
||||
either `show-notices` is called or the next time autosetup would
|
||||
@@ -162,18 +152,13 @@ In (mostly) alphabetical order:
|
||||
Ensuring TCL Compatibility
|
||||
========================================================================
|
||||
|
||||
One of the significant benefits of using Autosetup is that (A) this
|
||||
project uses many TCL scripts in the build process and (B) Autosetup
|
||||
comes with a TCL interpreter named [JimTCL][].
|
||||
|
||||
It is important that any TCL files used by the configure process and
|
||||
makefiles remain compatible with both [JimTCL][] and the canonical
|
||||
TCL. Though JimTCL has outstanding compatibility with canonical TCL,
|
||||
it does have a few corners with incompatibilities, e.g. regular
|
||||
expressions. If a script runs in JimTCL without using any
|
||||
JimTCL-specific features, then it's a certainty that it will run in
|
||||
canonical TCL as well. The opposite, however, is not _always_ the
|
||||
case.
|
||||
It is important that any TCL files used by the configure process
|
||||
remain compatible with both [JimTCL][] and the canonical TCL. Though
|
||||
JimTCL has outstanding compatibility with canonical TCL, it does have
|
||||
a few corners with incompatibilities, e.g. regular expressions. If a
|
||||
script runs in JimTCL without using any JimTCL-specific features, then
|
||||
it's a certainty that it will run in canonical TCL as well. The
|
||||
opposite, however, is not _always_ the case.
|
||||
|
||||
When [`./configure`](/file/configure) is run, it goes through a
|
||||
bootstrapping process to find a suitable TCL with which to run the
|
||||
@@ -202,17 +187,14 @@ compatibility across TCL implementations:
|
||||
before looking for a system-level `tclsh`. Be aware, though, that
|
||||
`make distclean` will remove that file.
|
||||
|
||||
**Note that `./jimsh0` is distinctly different from the `./jimsh`**
|
||||
which gets built for code-generation purposes. The latter requires
|
||||
**Note that `jimsh0` is distinctly different from the `jimsh`** which
|
||||
gets built for code-generation purposes. The latter requires
|
||||
non-default build flags to enable features which are
|
||||
platform-dependent, most notably to make its `[file normalize]` work.
|
||||
This means, for example, that the configure script and its utility
|
||||
APIs must not use `[file normalize]`, but autosetup provides a
|
||||
TCL-only implementation of `[file-normalize]` (note the dash) for
|
||||
portable use in the configure script. Contrariwise, code-generation
|
||||
scripts invoked via `make` may use `[file normalize]`, as they'll use
|
||||
`./jimsh` or `tclsh` instead of `./jimsh0`.
|
||||
|
||||
portable use in the configure script.
|
||||
|
||||
Known TCL Incompatibilities
|
||||
------------------------------------------------------------------------
|
||||
@@ -239,7 +221,6 @@ A summary of known incompatibilities in JimTCL
|
||||
- `regsub` does not support the `\y` flag. A workaround is demonstrated
|
||||
in [](/info/c2e5dd791cce3ec4).
|
||||
|
||||
|
||||
<a name="conventions"></a>
|
||||
Design Conventions
|
||||
========================================================================
|
||||
@@ -266,9 +247,8 @@ dots are not permitted.
|
||||
The `X.y` convention is used in the makefiles primarily because the
|
||||
person who did the initial port finds that considerably easier on the
|
||||
eyes and fingers. In practice, the `X_Y` form of such exports is used
|
||||
exactly once in [Makefile.in][], where it's translated from `@X_Y@`
|
||||
into into `X.y` form for consumption by [Makefile.in][] and
|
||||
[main.mk][]. For example:
|
||||
exactly once in [Makefile.in][], where it's translated into into `X.y`
|
||||
form for consumption by [Makefile.in][] and [main.mk][]. For example:
|
||||
|
||||
>
|
||||
```
|
||||
@@ -285,9 +265,9 @@ of taste, for which there is no accounting.)
|
||||
Do Not Update Global Shared State
|
||||
------------------------------------------------------------------------
|
||||
|
||||
In both the legacy Autotools-driven build and common Autosetup usage,
|
||||
feature tests performed by the configure script may amend global flags
|
||||
such as `LIBS`, `LDFLAGS`, and `CFLAGS`[^as-cflags]. That's
|
||||
In both the legacy Autotools-driven build and in common Autosetup
|
||||
usage, feature tests performed by the configure script may amend
|
||||
global flags such as `LIBS`, `LDFLAGS`, and `CFLAGS`[^as-cflags]. That's
|
||||
appropriate for a makefile which builds a single deliverable, but less
|
||||
so for makefiles which produce multiple deliverables. Drawbacks of
|
||||
that approach include:
|
||||
@@ -295,8 +275,8 @@ that approach include:
|
||||
- It's unlikely that every single deliverable will require the same
|
||||
core set of those flags.
|
||||
- It can be difficult to determine the origin of any given change to
|
||||
that global state because those changes are hidden behind voodoo
|
||||
performed outside the immediate visibility of the configure script's
|
||||
that global state because those changes are hidden behind voodoo performed
|
||||
outside the immediate visibility of the configure script's
|
||||
maintainer.
|
||||
- It can force the maintainers of the configure script to place tests
|
||||
in a specific order so that the resulting flags get applied at
|
||||
@@ -377,70 +357,17 @@ Patching Autosetup for Project-local Changes
|
||||
|
||||
Autosetup reserves the flag name **`--debug`** for its own purposes,
|
||||
and its own special handling of `--enable-...` flags makes `--debug`
|
||||
an alias for `--enable-debug`. As this project has a long history of
|
||||
using `--enable-debug`, we patch autosetup to use the name
|
||||
`--autosetup-debug` in place of `--debug`. That requires (as of this
|
||||
writing) four small edits in [](/file/autosetup/autosetup), as
|
||||
demonstrated in [check-in 3296c8d3](/info/3296c8d3).
|
||||
an alias for `--enable-debug`. As we have a long history of using
|
||||
`--enable-debug` for this project's own purposes, we patch autosetup
|
||||
to use the name `--autosetup-debug` in place of `--debug`. That
|
||||
requires (as of this writing) four small edits in
|
||||
[](/file/autosetup/autosetup), as demonstrated in [check-in
|
||||
3296c8d3](/info/3296c8d3).
|
||||
|
||||
If autosetup is upgraded and this patch is _not_ applied the invoking
|
||||
`./configure` will fail loudly because of the declaration of the
|
||||
`debug` flag in `auto.def` - duplicated flags are not permitted.
|
||||
|
||||
<a name="branch-customization"></a>
|
||||
Branch-specific Customization
|
||||
========================================================================
|
||||
|
||||
Certain vendor-specific branches require slight configure script
|
||||
customization. Rather than editing `sqlite-config.tcl` for this,
|
||||
which frequently leads to merge conflicts, the following approach
|
||||
is recommended:
|
||||
|
||||
In the vendor-specific branch, create a file named
|
||||
`autosetup/sqlite-custom.tcl`.
|
||||
|
||||
That file should contain the following content...
|
||||
|
||||
If flag customization is required, add:
|
||||
|
||||
>
|
||||
```
|
||||
proc sqlite-custom-flags {} {
|
||||
# If any existing --flags require different default values
|
||||
# then call:
|
||||
options-defaults {
|
||||
flag-name new-default-value
|
||||
...
|
||||
}
|
||||
# ^^^ That will replace the default value but will not update
|
||||
# the --help text, which may lead to some confusion:
|
||||
# https://github.com/msteveb/autosetup/issues/77
|
||||
|
||||
return {
|
||||
{*} {
|
||||
new-flag-name => {Help text}
|
||||
...
|
||||
}
|
||||
}; #see below
|
||||
}
|
||||
```
|
||||
|
||||
That function must return either an empty string or a list in the form
|
||||
used internally by `sqlite-config.tcl:sqlite-configure`.
|
||||
|
||||
Next, define:
|
||||
|
||||
>
|
||||
```
|
||||
proc sqlite-custom-handle-flags {} {
|
||||
... do any custom flag handling here ...
|
||||
}
|
||||
```
|
||||
|
||||
That function, if defined, will be called relatively late in the
|
||||
configure process, before any filtered files are generated but after
|
||||
all other significant processing.
|
||||
|
||||
|
||||
[Autosetup]: https://msteveb.github.io/autosetup/
|
||||
[auto.def]: /file/auto.def
|
||||
|
||||
+4
-8
@@ -1634,8 +1634,8 @@ proc automf_command_reference {} {
|
||||
|
||||
if {[regexp {^#.*@section (.*)$} $line -> section]} {
|
||||
lappend doc($current) [list section $section]
|
||||
continue
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
# Find embedded module names
|
||||
if {[regexp {^#.*@module ([^ ]*)} $line -> modulename]} {
|
||||
@@ -1651,7 +1651,7 @@ proc automf_command_reference {} {
|
||||
if {$cmd eq "synopsis:"} {
|
||||
set current $modulename
|
||||
lappend doc($current) [list section "Module: $modulename"]
|
||||
} else {
|
||||
} else {
|
||||
lappend doc($current) [list subsection $cmd]
|
||||
}
|
||||
|
||||
@@ -2088,12 +2088,8 @@ if {$autosetup(iswin)} {
|
||||
proc split-path {} {
|
||||
split [getenv PATH .] :
|
||||
}
|
||||
# Check for an executable file
|
||||
proc file-isexec {exec} {
|
||||
if {[file executable $exec] && [file isfile $exec]} {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
file executable $exec
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ for tclsh in ./jimsh0 $autosetup_tclsh jimsh tclsh tclsh8.5 tclsh8.6 tclsh8.7; d
|
||||
done
|
||||
echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
|
||||
for cc in ${CC_FOR_BUILD:-cc} gcc; do
|
||||
{ $cc -o jimsh0 "$d/jimsh0.c"; } 2>/dev/null >/dev/null || continue
|
||||
{ $cc -o jimsh0 "$d/jimsh0.c"; } >/dev/null 2>&1 || continue
|
||||
./jimsh0 "$d/${1-autosetup-test-tclsh}" && exit 0
|
||||
done
|
||||
echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc."
|
||||
|
||||
+12
-8
@@ -1252,14 +1252,6 @@ int Jim_OpenForRead(const char *filename);
|
||||
|
||||
#endif
|
||||
|
||||
# ifndef MAXPATHLEN
|
||||
# ifdef PATH_MAX
|
||||
# define MAXPATHLEN PATH_MAX
|
||||
# else
|
||||
# define MAXPATHLEN JIM_PATH_LEN
|
||||
# endif
|
||||
# endif
|
||||
|
||||
|
||||
int Jim_FileStoreStatData(Jim_Interp *interp, Jim_Obj *varName, const jim_stat_t *sb);
|
||||
|
||||
@@ -2096,6 +2088,10 @@ enum wbuftype {
|
||||
#define UNIX_SOCKETS 0
|
||||
#endif
|
||||
|
||||
#ifndef MAXPATHLEN
|
||||
#define MAXPATHLEN JIM_PATH_LEN
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4177,6 +4173,14 @@ int Jim_regexpInit(Jim_Interp *interp)
|
||||
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
# ifndef MAXPATHLEN
|
||||
# ifdef PATH_MAX
|
||||
# define MAXPATHLEN PATH_MAX
|
||||
# else
|
||||
# define MAXPATHLEN JIM_PATH_LEN
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#if defined(__MINGW32__) || defined(__MSYS__) || defined(_MSC_VER)
|
||||
#define ISWINDOWS 1
|
||||
|
||||
|
||||
+65
-228
@@ -64,7 +64,6 @@ proc proj-warn {msg} {
|
||||
show-notices
|
||||
puts stderr "WARNING: $msg"
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# @proj-error msg
|
||||
#
|
||||
@@ -76,22 +75,22 @@ proc proj-fatal {msg} {
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# @proj-assert script ?message?
|
||||
# @proj-assert script
|
||||
#
|
||||
# Kind of like a C assert: if uplevel (eval) of [expr {$script}] is
|
||||
# false, a fatal error is triggered. The error message, by default,
|
||||
# includes the body of the failed assertion, but if $msg is set then
|
||||
# includes the body of the failed assertion, but if $descr is set then
|
||||
# that is used instead.
|
||||
proc proj-assert {script {msg ""}} {
|
||||
proc proj-assert {script {descr ""}} {
|
||||
if {1 == [get-env proj-assert 0]} {
|
||||
msg-result [proj-bold "asserting: $script"]
|
||||
}
|
||||
set x "expr \{ $script \}"
|
||||
if {![uplevel 1 $x]} {
|
||||
if {"" eq $msg} {
|
||||
set msg $script
|
||||
if {"" eq $descr} {
|
||||
set descr $script
|
||||
}
|
||||
proj-fatal "Assertion failed: $msg"
|
||||
proj-fatal "Assertion failed: $descr"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +111,6 @@ proc proj-bold {str} {
|
||||
# @proj-indented-notice ?-error? ?-notice? msg
|
||||
#
|
||||
# Takes a multi-line message and emits it with consistent indentation.
|
||||
# It does not perform any line-wrapping of its own.
|
||||
#
|
||||
# If the -notice flag it used then it emits using [user-notice], which
|
||||
# means its rendering will (A) go to stderr and (B) be delayed until
|
||||
@@ -165,13 +163,30 @@ proc proj-is-cross-compiling {} {
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# @proj-strip-hash-comments value
|
||||
# proj-lshift_ shifts $count elements from the list named $listVar
|
||||
# and returns them as a new list. On empty input, returns "".
|
||||
#
|
||||
# Modified slightly from: https://wiki.tcl-lang.org/page/lshift
|
||||
proc proj-lshift_ {listVar {count 1}} {
|
||||
upvar 1 $listVar l
|
||||
if {![info exists l]} {
|
||||
# make the error message show the real variable name
|
||||
error "can't read \"$listVar\": no such variable"
|
||||
}
|
||||
if {![llength $l]} {
|
||||
# error Empty
|
||||
return ""
|
||||
}
|
||||
set r [lrange $l 0 [incr count -1]]
|
||||
set l [lreplace $l [set l 0] $count]
|
||||
return $r
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Expects to receive string input, which it splits on newlines, strips
|
||||
# out any lines which begin with any number of whitespace followed by
|
||||
# a '#', and returns a value containing the [append]ed results of each
|
||||
# remaining line with a \n between each. It does not strip out
|
||||
# comments which appear after the first non-whitespace character.
|
||||
# remaining line with a \n between each.
|
||||
proc proj-strip-hash-comments {val} {
|
||||
set x {}
|
||||
foreach line [split $val \n] {
|
||||
@@ -182,42 +197,16 @@ proc proj-strip-hash-comments {val} {
|
||||
return $x
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# @proj-cflags-without-werror
|
||||
#
|
||||
# Fetches [define $var], strips out any -Werror entries, and returns
|
||||
# the new value. This is intended for temporarily stripping -Werror
|
||||
# from CFLAGS or CPPFLAGS within the scope of a [define-push] block.
|
||||
proc proj-cflags-without-werror {{var CFLAGS}} {
|
||||
set rv {}
|
||||
foreach f [get-define $var ""] {
|
||||
switch -exact -- $f {
|
||||
-Werror {}
|
||||
default { lappend rv $f }
|
||||
}
|
||||
}
|
||||
return [join $rv " "]
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# @proj-check-function-in-lib
|
||||
#
|
||||
# A proxy for cc-check-function-in-lib with the following differences:
|
||||
#
|
||||
# - Does not make any global changes to the LIBS define.
|
||||
#
|
||||
# - Strips out the -Werror flag from CFLAGS before running the test,
|
||||
# as these feature tests will often fail if -Werror is used.
|
||||
#
|
||||
# Returns the result of cc-check-function-in-lib (i.e. true or false).
|
||||
# The resulting linker flags are stored in the [define] named
|
||||
# lib_${function}.
|
||||
# A proxy for cc-check-function-in-lib which does not make any global
|
||||
# changes to the LIBS define. Returns the result of
|
||||
# cc-check-function-in-lib (i.e. true or false). The resulting linker
|
||||
# flags are stored in the [define] named lib_${function}.
|
||||
proc proj-check-function-in-lib {function libs {otherlibs {}}} {
|
||||
set found 0
|
||||
define-push {LIBS CFLAGS} {
|
||||
#puts "CFLAGS before=[get-define CFLAGS]"
|
||||
define CFLAGS [proj-cflags-without-werror]
|
||||
#puts "CFLAGS after =[get-define CFLAGS]"
|
||||
define-push {LIBS} {
|
||||
set found [cc-check-function-in-lib $function $libs $otherlibs]
|
||||
}
|
||||
return $found
|
||||
@@ -364,6 +353,7 @@ proc proj-opt-was-provided {key} {
|
||||
#
|
||||
# Returns $val.
|
||||
proc proj-opt-set {flag {val 1}} {
|
||||
global autosetup
|
||||
if {$flag ni $::autosetup(options)} {
|
||||
# We have to add this to autosetup(options) or else future calls
|
||||
# to [opt-bool $flag] will fail validation of $flag.
|
||||
@@ -373,15 +363,6 @@ proc proj-opt-set {flag {val 1}} {
|
||||
return $val
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# @proj-opt-exists flag
|
||||
#
|
||||
# Returns 1 if the given flag has been defined as a legal configure
|
||||
# option, else returns 0.
|
||||
proc proj-opt-exists {flag} {
|
||||
expr {$flag in $::autosetup(options)};
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# @proj-val-truthy val
|
||||
#
|
||||
@@ -461,16 +442,16 @@ proc proj-opt-define-bool {args} {
|
||||
set invert 0
|
||||
if {[lindex $args 0] eq "-v"} {
|
||||
set invert 1
|
||||
lassign $args - optName defName descr
|
||||
} else {
|
||||
lassign $args optName defName descr
|
||||
set args [lrange $args 1 end]
|
||||
}
|
||||
set optName [proj-lshift_ args]
|
||||
set defName [proj-lshift_ args]
|
||||
set descr [proj-lshift_ args]
|
||||
if {"" eq $descr} {
|
||||
set descr $defName
|
||||
}
|
||||
puts "optName=$optName defName=$defName descr=$descr"
|
||||
set rc 0
|
||||
msg-checking "[join $descr] ... "
|
||||
msg-checking "$descr ... "
|
||||
if {[proj-opt-truthy $optName]} {
|
||||
if {0 eq $invert} {
|
||||
set rc 1
|
||||
@@ -576,7 +557,7 @@ proc proj-file-content {args} {
|
||||
set trim 1
|
||||
lassign $args - fname
|
||||
}
|
||||
set fp [open $fname rb]
|
||||
set fp [open $fname r]
|
||||
set rc [read $fp]
|
||||
close $fp
|
||||
if {$trim} { return [string trim $rc] }
|
||||
@@ -589,7 +570,7 @@ proc proj-file-content {args} {
|
||||
# Returns the contents of the given file as an array of lines, with
|
||||
# the EOL stripped from each input line.
|
||||
proc proj-file-content-list {fname} {
|
||||
set fp [open $fname rb]
|
||||
set fp [open $fname r]
|
||||
set rc {}
|
||||
while { [gets $fp line] >= 0 } {
|
||||
lappend rc $line
|
||||
@@ -598,31 +579,6 @@ proc proj-file-content-list {fname} {
|
||||
return $rc
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# @proj-file-write ?-ro? fname content
|
||||
#
|
||||
# Works like autosetup's [writefile] but explicitly uses binary mode
|
||||
# to avoid EOL translation on Windows. If $fname already exists, it is
|
||||
# overwritten, even if it's flagged as read-only.
|
||||
proc proj-file-write {args} {
|
||||
if {"-ro" eq [lindex $args 0]} {
|
||||
lassign $args ro fname content
|
||||
} else {
|
||||
set ro ""
|
||||
lassign $args fname content
|
||||
}
|
||||
file delete -force -- $fname; # in case it's read-only
|
||||
set f [open $fname wb]
|
||||
puts -nonewline $f $content
|
||||
close $f
|
||||
if {"" ne $ro} {
|
||||
catch {
|
||||
exec chmod -w $fname
|
||||
#file attributes -w $fname; #jimtcl has no 'attributes'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# @proj-check-compile-commands ?configFlag?
|
||||
#
|
||||
@@ -689,17 +645,12 @@ proc proj-make-from-dot-in {args} {
|
||||
}
|
||||
foreach f $filename {
|
||||
set f [string trim $f]
|
||||
if {[file exists $f]} {
|
||||
catch { exec chmod u+w $f }
|
||||
}
|
||||
catch { exec chmod u+w $f }
|
||||
make-template $f.in $f
|
||||
if {$touch} {
|
||||
proj-touch $f
|
||||
}
|
||||
catch {
|
||||
exec chmod -w $f
|
||||
#file attributes -w $f; #jimtcl has no 'attributes'
|
||||
}
|
||||
catch { exec chmod -w $f }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -757,7 +708,7 @@ proc proj-looks-like-windows {{key host}} {
|
||||
# These apply only to the local OS, not a cross-compilation target,
|
||||
# as the above check potentially can.
|
||||
if {$::autosetup(iswin)} { return 1 }
|
||||
if {[find-an-executable cygpath] ne "" || $::tcl_platform(os) eq "Windows NT"} {
|
||||
if {[find-an-executable cygpath] ne "" || $::tcl_platform(os)=="Windows NT"} {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
@@ -956,35 +907,6 @@ proc proj-check-emsdk {} {
|
||||
return $rc
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# @proj-cc-check-Wl-flag ?flag ?args??
|
||||
#
|
||||
# Checks whether the given linker flag (and optional arguments) can be
|
||||
# passed from the compiler to the linker using one of these formats:
|
||||
#
|
||||
# - -Wl,flag[,arg1[,...argN]]
|
||||
# - -Wl,flag -Wl,arg1 ...-Wl,argN
|
||||
#
|
||||
# If so, that flag string is returned, else an empty string is
|
||||
# returned.
|
||||
proc proj-cc-check-Wl-flag {args} {
|
||||
cc-with {-link 1} {
|
||||
# Try -Wl,flag,...args
|
||||
set fli "-Wl"
|
||||
foreach f $args { append fli ",$f" }
|
||||
if {[cc-check-flags $fli]} {
|
||||
return $fli
|
||||
}
|
||||
# Try -Wl,flag -Wl,arg1 ...-Wl,argN
|
||||
set fli ""
|
||||
foreach f $args { append fli "-Wl,$f " }
|
||||
if {[cc-check-flags $fli]} {
|
||||
return [string trim $fli]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# @proj-check-rpath
|
||||
#
|
||||
@@ -996,7 +918,12 @@ proc proj-cc-check-Wl-flag {args} {
|
||||
# --exec-prefix=... or --libdir=... are explicitly passed to
|
||||
# configure then [get-define libdir] is used (noting that it derives
|
||||
# from exec-prefix by default).
|
||||
#
|
||||
# Achtung: we have seen platforms which report that a given option
|
||||
# checked here will work but then fails at build-time, and the current
|
||||
# order of checks reflects that.
|
||||
proc proj-check-rpath {} {
|
||||
set rc 1
|
||||
if {[proj-opt-was-provided libdir]
|
||||
|| [proj-opt-was-provided exec-prefix]} {
|
||||
set lp "[get-define libdir]"
|
||||
@@ -1007,18 +934,21 @@ proc proj-check-rpath {} {
|
||||
# CFLAGS or LIBS or whatever it is that cc-check-flags updates) then
|
||||
# downstream tests may fail because the resulting rpath gets
|
||||
# implicitly injected into them.
|
||||
cc-with {-link 1} {
|
||||
cc-with {} {
|
||||
if {[cc-check-flags "-rpath $lp"]} {
|
||||
define LDFLAGS_RPATH "-rpath $lp"
|
||||
} elseif {[cc-check-flags "-Wl,-rpath,$lp"]} {
|
||||
define LDFLAGS_RPATH "-Wl,-rpath,$lp"
|
||||
} elseif {[cc-check-flags "-Wl,-rpath -Wl,$lp"]} {
|
||||
define LDFLAGS_RPATH "-Wl,-rpath -Wl,$lp"
|
||||
} elseif {[cc-check-flags -Wl,-R$lp]} {
|
||||
define LDFLAGS_RPATH "-Wl,-R$lp"
|
||||
} else {
|
||||
set wl [proj-cc-check-Wl-flag -rpath $lp]
|
||||
if {"" eq $wl} {
|
||||
set wl [proj-cc-check-Wl-flag -R$lp]
|
||||
}
|
||||
define LDFLAGS_RPATH $wl
|
||||
define LDFLAGS_RPATH ""
|
||||
set rc 0
|
||||
}
|
||||
}
|
||||
expr {"" ne [get-define LDFLAGS_RPATH]}
|
||||
return $rc
|
||||
}
|
||||
|
||||
########################################################################
|
||||
@@ -1035,7 +965,7 @@ proc proj-check-rpath {} {
|
||||
# potentially avoid some end-user confusion by using their own lib's
|
||||
# name here (which shows up in the "checking..." output).
|
||||
proc proj-check-soname {{libname "libfoo.so.0"}} {
|
||||
cc-with {-link 1} {
|
||||
cc-with {} {
|
||||
if {[cc-check-flags "-Wl,-soname,${libname}"]} {
|
||||
define LDFLAGS_SONAME_PREFIX "-Wl,-soname,"
|
||||
return 1
|
||||
@@ -1046,39 +976,6 @@ proc proj-check-soname {{libname "libfoo.so.0"}} {
|
||||
}
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# @proj-check-fsanitize ?list-of-opts?
|
||||
#
|
||||
# Checks whether CC supports -fsanitize=X, where X is each entry of
|
||||
# the given list of flags. If any of those flags are supported, it
|
||||
# returns the string "-fsanitize=X..." where X... is a comma-separated
|
||||
# list of all flags from the original set which are supported. If none
|
||||
# of the given options are supported then it returns an empty string.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# set f [proj-check-fsanitize {address bounds-check just-testing}]
|
||||
#
|
||||
# Will, on many systems, resolve to "-fsanitize=address,bounds-check",
|
||||
# but may also resolve to "-fsanitize=address".
|
||||
proc proj-check-fsanitize {{opts {address bounds-strict}}} {
|
||||
set sup {}
|
||||
foreach opt $opts {
|
||||
# -nooutput is used because -fsanitize=hwaddress will otherwise
|
||||
# pass this test on x86_64, but then warn at build time that
|
||||
# "hwaddress is not supported for this target".
|
||||
cc-with {-nooutput 1} {
|
||||
if {[cc-check-flags "-fsanitize=$opt"]} {
|
||||
lappend sup $opt
|
||||
}
|
||||
}
|
||||
}
|
||||
if {[llength $sup] > 0} {
|
||||
return "-fsanitize=[join $sup ,]"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Internal helper for proj-dump-defs-json. Expects to be passed a
|
||||
# [define] name and the variadic $args which are passed to
|
||||
@@ -1241,7 +1138,7 @@ proc proj-xfer-options-aliases {mapping} {
|
||||
########################################################################
|
||||
# Arguable/debatable...
|
||||
#
|
||||
# When _not_ cross-compiling and CC_FOR_BUILD is _not_ explicitly
|
||||
# When _not_ cross-compiling and CC_FOR_BUILD is _not_ explcitely
|
||||
# specified, force CC_FOR_BUILD to be the same as CC, so that:
|
||||
#
|
||||
# ./configure CC=clang
|
||||
@@ -1249,7 +1146,7 @@ proc proj-xfer-options-aliases {mapping} {
|
||||
# will use CC_FOR_BUILD=clang, instead of cc, for building in-tree
|
||||
# tools. This is based off of an email discussion and is thought to
|
||||
# be likely to cause less confusion than seeing 'cc' invocations
|
||||
# when when the user passes CC=clang.
|
||||
# will when the user passes CC=clang.
|
||||
#
|
||||
# Sidebar: if we do this before the cc package is installed, it gets
|
||||
# reverted by that package. Ergo, the cc package init will tell the
|
||||
@@ -1294,11 +1191,11 @@ proc proj-which-linenoise {dotH} {
|
||||
#
|
||||
# In that make invocation, $(libdir) would, at make-time, normally be
|
||||
# hard-coded to /foo/lib, rather than /blah/lib. That happens because
|
||||
# autosetup exports conventional $prefix-based values for the numerous
|
||||
# autoconfig-compatible XYZdir vars at configure-time. What we would
|
||||
# normally want, however, is that --libdir derives from the make-time
|
||||
# $(prefix). The distinction between configure-time and make-time is
|
||||
# the significant factor there.
|
||||
# the autosetup exports conventional $prefix-based values for the
|
||||
# numerous autoconfig-compatible XYZdir vars at configure-time. What
|
||||
# we would normally want, however, is that --libdir derives from the
|
||||
# make-time $(prefix). The distinction between configure-time and
|
||||
# make-time is the significant factor there.
|
||||
#
|
||||
# This function attempts to reconcile those vars in such a way that
|
||||
# they will derive, at make-time, from $(prefix) in a conventional
|
||||
@@ -1378,63 +1275,3 @@ proc proj-env-file {flag {dflt ""}} {
|
||||
proc proj-get-env {var {dflt ""}} {
|
||||
return [get-env $var [proj-env-file $var $dflt]]
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# @proj-current-proc-name
|
||||
#
|
||||
# Returns the name of the _calling_ proc from ($lvl + 1) levels up the
|
||||
# call stack (where the caller's level will be 1 up from _this_
|
||||
# call). It is not legal to call this from the top scope.
|
||||
proc proj-current-proc-name {{lvl 0}} {
|
||||
#uplevel [expr {$lvl + 1}] {lindex [info level 0] 0}
|
||||
lindex [info level [expr {-$lvl - 1}]] 0
|
||||
}
|
||||
|
||||
|
||||
########################################################################
|
||||
# Converts parts of tclConfig.sh to autosetup [define]s.
|
||||
#
|
||||
# Expects to be passed the name of a value tclConfig.sh or an empty
|
||||
# string. It converts certain parts of that file's contents to
|
||||
# [define]s (see the code for the whole list). If $tclConfigSh is an
|
||||
# empty string then it [define]s the various vars as empty strings.
|
||||
proc proj-tclConfig-sh-to-autosetup {tclConfigSh} {
|
||||
set shBody {}
|
||||
set tclVars {
|
||||
TCL_INCLUDE_SPEC
|
||||
TCL_LIB_SPEC
|
||||
TCL_STUB_LIB_SPEC
|
||||
TCL_EXEC_PREFIX
|
||||
TCL_PREFIX
|
||||
TCL_VERSION
|
||||
}
|
||||
# Build a small shell script which proxies the $tclVars from
|
||||
# $tclConfigSh into autosetup code...
|
||||
lappend shBody "if test x = \"x${tclConfigSh}\"; then"
|
||||
foreach v $tclVars {
|
||||
lappend shBody "$v= ;"
|
||||
}
|
||||
lappend shBody "else . \"${tclConfigSh}\"; fi"
|
||||
foreach v $tclVars {
|
||||
lappend shBody "echo define $v {\$$v} ;"
|
||||
}
|
||||
lappend shBody "exit"
|
||||
set shBody [join $shBody "\n"]
|
||||
#puts "shBody=$shBody\n"; exit
|
||||
if {0} {
|
||||
# This doesn't work but would be preferable to using a temp file...
|
||||
set fd [open "| sh" "rw"]
|
||||
#puts "fd = $fd"; exit
|
||||
puts $fd $shBody
|
||||
flush $fd
|
||||
set rd [read $fd]
|
||||
close $fd
|
||||
puts "rd=$rd"; exit 1
|
||||
eval $rd
|
||||
} else {
|
||||
set shName ".tclConfigSh.tcl"
|
||||
proj-file-write $shName $shBody
|
||||
eval [exec sh $shName $tclConfigSh]
|
||||
file delete -force $shName
|
||||
}
|
||||
}
|
||||
|
||||
+189
-843
File diff suppressed because it is too large
Load Diff
@@ -567,7 +567,7 @@ proc sqlitecon::Cut w {
|
||||
}
|
||||
}
|
||||
|
||||
# Do a paste operation.
|
||||
# Do a paste opeation.
|
||||
#
|
||||
proc sqlitecon::Paste w {
|
||||
if {[sqlitecon::canCut $w]==1} {
|
||||
|
||||
+1
-1
@@ -281,7 +281,7 @@ happen if and when they are actually needed.
|
||||
A valid JSONB BLOB consists of a single JSON element. The element must
|
||||
exactly fill the BLOB. This one element is often a JSON object or array
|
||||
and those usually contain additional elements as its payload, but the
|
||||
element can be a primitive value such a string, number, boolean, or null.
|
||||
element can be a primite value such a string, number, boolean, or null.
|
||||
|
||||
When the built-in JSON functions are attempting to determine if a BLOB
|
||||
argument is a JSONB or just a random BLOB, they look at the header of
|
||||
|
||||
+1
-1
@@ -881,7 +881,7 @@ is allowed between the "%" and the directive name.</p>
|
||||
<p>Grammar text in between "<tt>%ifdef MACRO</tt>" and the next nested
|
||||
"<tt>%endif</tt>" is
|
||||
ignored unless the "-DMACRO" command-line option is used. Grammar text
|
||||
between "<tt>%ifndef MACRO</tt>" and the next nested "<tt>%endif</tt>" is
|
||||
betwen "<tt>%ifndef MACRO</tt>" and the next nested "<tt>%endif</tt>" is
|
||||
included except when the "-DMACRO" command-line option is used.<p>
|
||||
|
||||
<p>The text in between "<tt>%if</tt> <i>CONDITIONAL</i>" and its
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
*** Definition: Two databases (or the same database at two points it time)
|
||||
are said to be "logically equivalent" if they give the same answer to
|
||||
all queries. Note in particular the content of freelist leaf
|
||||
pages can be changed arbitrarily without effecting the logical equivalence
|
||||
pages can be changed arbitarily without effecting the logical equivalence
|
||||
of the database.
|
||||
|
||||
(7) At any time, if any subset, including the empty set and the total set,
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
The 5 states of an historical rollback lock as implemented by the
|
||||
xLock, xUnlock, and xCheckReservedLock methods of the sqlite3_io_methods
|
||||
object are:
|
||||
objec are:
|
||||
|
||||
UNLOCKED
|
||||
SHARED
|
||||
@@ -58,7 +58,7 @@ The meanings of the various wal-index locking states is as follows:
|
||||
|
||||
A particular lock manager implementation may coalesce one or more of
|
||||
the wal-index locking states, though with a reduction in concurrency.
|
||||
For example, an implementation might implement only exclusive locking,
|
||||
For example, an implemention might implement only exclusive locking,
|
||||
in which case all states would be equivalent to CHECKPOINT, meaning that
|
||||
only one reader or one writer or one checkpointer could be active at a
|
||||
time. Or, an implementation might combine READ and READ_FULL into
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ facilitates transfer of OS priority between processes when a high priority
|
||||
process is blocked by a lower priority one.
|
||||
|
||||
Only read/write clients use blocking locks. Clients that have read-only access
|
||||
to the \*-shm file never use blocking locks.
|
||||
to the \*-shm file nevery use blocking locks.
|
||||
|
||||
Threads or processes that access a single database at a time never deadlock as
|
||||
a result of blocking database locks. But it is of course possible for threads
|
||||
|
||||
@@ -2052,7 +2052,7 @@ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
|
||||
sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew);
|
||||
}
|
||||
|
||||
/* If an error has occurred, free the new object and return NULL. Otherwise,
|
||||
/* If an error has occurred, free the new object and reutrn NULL. Otherwise,
|
||||
** return the new sqlite3expert handle. */
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_expert_destroy(pNew);
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
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), NULL);
|
||||
Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(pObj), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,20 +62,20 @@
|
||||
matches rows that contain both the "engineering" and "consultancy" tokens
|
||||
in the same column with not more than 10 other words between them. It does
|
||||
not matter which of the two terms occurs first in the document, only that
|
||||
they be separated by only 10 tokens or less. The user may also specify
|
||||
they be seperated by only 10 tokens or less. The user may also specify
|
||||
a different required proximity by adding "/N" immediately after the NEAR
|
||||
operator, where N is an integer. For example:
|
||||
|
||||
<col> MATCH 'engineering NEAR/5 consultancy'
|
||||
|
||||
searches for a row containing an instance of each specified token separated
|
||||
searches for a row containing an instance of each specified token seperated
|
||||
by not more than 5 other tokens. More than one NEAR operator can be used
|
||||
in as sequence. For example this query:
|
||||
|
||||
<col> MATCH 'reliable NEAR/2 engineering NEAR/5 consultancy'
|
||||
|
||||
searches for a row that contains an instance of the token "reliable"
|
||||
separated by not more than two tokens from an instance of "engineering",
|
||||
seperated by not more than two tokens from an instance of "engineering",
|
||||
which is in turn separated by not more than 5 other tokens from an
|
||||
instance of the term "consultancy". Phrases enclosed in quotes may
|
||||
also be used as arguments to the NEAR operator.
|
||||
@@ -146,7 +146,7 @@
|
||||
<col> MATCH '(hello world) OR (simple example)'
|
||||
|
||||
matches documents that contain both "hello" and "world", and documents
|
||||
that contain both "simple" and "example". It is not possible to formulate
|
||||
that contain both "simple" and "example". It is not possible to forumlate
|
||||
such a query using the standard syntax.
|
||||
|
||||
2) Instead of separating tokens and phrases by whitespace, an AND operator
|
||||
@@ -174,7 +174,7 @@
|
||||
|
||||
4) Unlike in the standard syntax, where the OR operator has a higher
|
||||
precedence than the implicit AND operator, when using the enhanced
|
||||
syntax implicit and explicit AND operators have a higher precedence
|
||||
syntax implicit and explict AND operators have a higher precedence
|
||||
than OR operators. Using the enhanced syntax, the following two
|
||||
queries are equivalent:
|
||||
|
||||
|
||||
+11
-5
@@ -87,7 +87,7 @@
|
||||
** Here, array { X } means zero or more occurrences of X, adjacent in
|
||||
** memory. A "position" is an index of a token in the token stream
|
||||
** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
|
||||
** in the same logical place as the position element, and act as sentinels
|
||||
** in the same logical place as the position element, and act as sentinals
|
||||
** ending a position list array. POS_END is 0. POS_COLUMN is 1.
|
||||
** The positions numbers are not stored literally but rather as two more
|
||||
** than the difference from the prior position, or the just the position plus
|
||||
@@ -295,6 +295,12 @@
|
||||
# define SQLITE_CORE 1
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "fts3.h"
|
||||
#ifndef SQLITE_CORE
|
||||
@@ -2633,7 +2639,7 @@ static int fts3DoclistOrMerge(
|
||||
** sizes of the two inputs, plus enough space for exactly one of the input
|
||||
** docids to grow.
|
||||
**
|
||||
** A symmetric argument may be made if the doclists are in descending
|
||||
** A symetric argument may be made if the doclists are in descending
|
||||
** order.
|
||||
*/
|
||||
aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING);
|
||||
@@ -4432,7 +4438,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
|
||||
nDistance = iPrev - nMaxUndeferred;
|
||||
}
|
||||
|
||||
aOut = (char *)sqlite3Fts3MallocZero(((i64)nPoslist)+FTS3_BUFFER_PADDING);
|
||||
aOut = (char *)sqlite3Fts3MallocZero(nPoslist+FTS3_BUFFER_PADDING);
|
||||
if( !aOut ){
|
||||
sqlite3_free(aPoslist);
|
||||
return SQLITE_NOMEM;
|
||||
@@ -4731,7 +4737,7 @@ static int incrPhraseTokenNext(
|
||||
**
|
||||
** * does not contain any deferred tokens.
|
||||
**
|
||||
** Advance it to the next matching document in the database and populate
|
||||
** Advance it to the next matching documnent in the database and populate
|
||||
** the Fts3Doclist.pList and nList fields.
|
||||
**
|
||||
** If there is no "next" entry and no error occurs, then *pbEof is set to
|
||||
@@ -5738,7 +5744,7 @@ static int fts3EvalNext(Fts3Cursor *pCsr){
|
||||
}
|
||||
|
||||
/*
|
||||
** Restart iteration for expression pExpr so that the next call to
|
||||
** Restart interation for expression pExpr so that the next call to
|
||||
** fts3EvalNext() visits the first row. Do not allow incremental
|
||||
** loading or merging of phrase doclists for this iteration.
|
||||
**
|
||||
|
||||
+3
-27
@@ -14,13 +14,6 @@
|
||||
#ifndef _FTSINT_H
|
||||
#define _FTSINT_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
|
||||
# define NDEBUG 1
|
||||
#endif
|
||||
@@ -209,19 +202,6 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */
|
||||
|
||||
#define deliberate_fall_through
|
||||
|
||||
/*
|
||||
** Macros needed to provide flexible arrays in a portable way
|
||||
*/
|
||||
#ifndef offsetof
|
||||
# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
|
||||
#endif
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
# define FLEXARRAY
|
||||
#else
|
||||
# define FLEXARRAY 1
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* SQLITE_AMALGAMATION */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
@@ -326,7 +306,7 @@ struct Fts3Table {
|
||||
#endif
|
||||
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
/* True to disable the incremental doclist optimization. This is controlled
|
||||
/* True to disable the incremental doclist optimization. This is controled
|
||||
** by special insert command 'test-no-incr-doclist'. */
|
||||
int bNoIncrDoclist;
|
||||
|
||||
@@ -378,7 +358,7 @@ struct Fts3Cursor {
|
||||
|
||||
/*
|
||||
** The Fts3Cursor.eSearch member is always set to one of the following.
|
||||
** Actually, Fts3Cursor.eSearch can be greater than or equal to
|
||||
** Actualy, Fts3Cursor.eSearch can be greater than or equal to
|
||||
** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index
|
||||
** of the column to be searched. For example, in
|
||||
**
|
||||
@@ -451,13 +431,9 @@ struct Fts3Phrase {
|
||||
*/
|
||||
int nToken; /* Number of tokens in the phrase */
|
||||
int iColumn; /* Index of column this phrase must match */
|
||||
Fts3PhraseToken aToken[FLEXARRAY]; /* One for each token in the phrase */
|
||||
Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts3Phrase object large enough to hold N tokens */
|
||||
#define SZ_FTS3PHRASE(N) \
|
||||
(offsetof(Fts3Phrase,aToken)+(N)*sizeof(Fts3PhraseToken))
|
||||
|
||||
/*
|
||||
** A tree of these objects forms the RHS of a MATCH operator.
|
||||
**
|
||||
|
||||
+16
-40
@@ -161,23 +161,6 @@ int sqlite3Fts3OpenTokenizer(
|
||||
*/
|
||||
static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
|
||||
|
||||
/*
|
||||
** Search buffer z[], size n, for a '"' character. Or, if enable_parenthesis
|
||||
** is defined, search for '(' and ')' as well. Return the index of the first
|
||||
** such character in the buffer. If there is no such character, return -1.
|
||||
*/
|
||||
static int findBarredChar(const char *z, int n){
|
||||
int ii;
|
||||
for(ii=0; ii<n; ii++){
|
||||
if( (z[ii]=='"')
|
||||
|| (sqlite3_fts3_enable_parentheses && (z[ii]=='(' || z[ii]==')'))
|
||||
){
|
||||
return ii;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Extract the next token from buffer z (length n) using the tokenizer
|
||||
** and other information (column names etc.) in pParse. Create an Fts3Expr
|
||||
@@ -202,9 +185,16 @@ static int getNextToken(
|
||||
int rc;
|
||||
sqlite3_tokenizer_cursor *pCursor;
|
||||
Fts3Expr *pRet = 0;
|
||||
int i = 0;
|
||||
|
||||
*pnConsumed = n;
|
||||
rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
|
||||
/* Set variable i to the maximum number of bytes of input to tokenize. */
|
||||
for(i=0; i<n; i++){
|
||||
if( sqlite3_fts3_enable_parentheses && (z[i]=='(' || z[i]==')') ) break;
|
||||
if( z[i]=='"' ) break;
|
||||
}
|
||||
|
||||
*pnConsumed = i;
|
||||
rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, i, &pCursor);
|
||||
if( rc==SQLITE_OK ){
|
||||
const char *zToken;
|
||||
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
|
||||
@@ -212,18 +202,7 @@ static int getNextToken(
|
||||
|
||||
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* Check that this tokenization did not gobble up any " characters. Or,
|
||||
** if enable_parenthesis is true, that it did not gobble up any
|
||||
** open or close parenthesis characters either. If it did, call
|
||||
** getNextToken() again, but pass only that part of the input buffer
|
||||
** up to the first such character. */
|
||||
int iBarred = findBarredChar(z, iEnd);
|
||||
if( iBarred>=0 ){
|
||||
pModule->xClose(pCursor);
|
||||
return getNextToken(pParse, iCol, z, iBarred, ppExpr, pnConsumed);
|
||||
}
|
||||
|
||||
nByte = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1) + nToken;
|
||||
nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
|
||||
pRet = (Fts3Expr *)sqlite3Fts3MallocZero(nByte);
|
||||
if( !pRet ){
|
||||
rc = SQLITE_NOMEM;
|
||||
@@ -233,7 +212,7 @@ static int getNextToken(
|
||||
pRet->pPhrase->nToken = 1;
|
||||
pRet->pPhrase->iColumn = iCol;
|
||||
pRet->pPhrase->aToken[0].n = nToken;
|
||||
pRet->pPhrase->aToken[0].z = (char*)&pRet->pPhrase->aToken[1];
|
||||
pRet->pPhrase->aToken[0].z = (char *)&pRet->pPhrase[1];
|
||||
memcpy(pRet->pPhrase->aToken[0].z, zToken, nToken);
|
||||
|
||||
if( iEnd<n && z[iEnd]=='*' ){
|
||||
@@ -257,11 +236,7 @@ static int getNextToken(
|
||||
|
||||
}
|
||||
*pnConsumed = iEnd;
|
||||
}else if( n && rc==SQLITE_DONE ){
|
||||
int iBarred = findBarredChar(z, n);
|
||||
if( iBarred>=0 ){
|
||||
*pnConsumed = iBarred;
|
||||
}
|
||||
}else if( i && rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -308,9 +283,9 @@ static int getNextString(
|
||||
Fts3Expr *p = 0;
|
||||
sqlite3_tokenizer_cursor *pCursor = 0;
|
||||
char *zTemp = 0;
|
||||
i64 nTemp = 0;
|
||||
int nTemp = 0;
|
||||
|
||||
const int nSpace = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1);
|
||||
const int nSpace = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
|
||||
int nToken = 0;
|
||||
|
||||
/* The final Fts3Expr data structure, including the Fts3Phrase,
|
||||
@@ -682,7 +657,7 @@ static int fts3ExprParse(
|
||||
|
||||
/* The isRequirePhrase variable is set to true if a phrase or
|
||||
** an expression contained in parenthesis is required. If a
|
||||
** binary operator (AND, OR, NOT or NEAR) is encountered when
|
||||
** binary operator (AND, OR, NOT or NEAR) is encounted when
|
||||
** isRequirePhrase is set, this is a syntax error.
|
||||
*/
|
||||
if( !isPhrase && isRequirePhrase ){
|
||||
@@ -1264,6 +1239,7 @@ static void fts3ExprTestCommon(
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
|
||||
sqlite3Fts3ExprFree(pExpr);
|
||||
sqlite3_result_error(context, "Error parsing expression", -1);
|
||||
}else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
|
||||
@@ -187,7 +187,7 @@ static void fts3HashInsertElement(
|
||||
}
|
||||
|
||||
|
||||
/* Resize the hash table so that it contains "new_size" buckets.
|
||||
/* Resize the hash table so that it cantains "new_size" buckets.
|
||||
** "new_size" must be a power of 2. The hash table might fail
|
||||
** to resize if sqliteMalloc() fails.
|
||||
**
|
||||
|
||||
@@ -256,7 +256,7 @@ static int star_oh(const char *z){
|
||||
|
||||
/*
|
||||
** If the word ends with zFrom and xCond() is true for the stem
|
||||
** of the word that precedes the zFrom ending, then change the
|
||||
** of the word that preceeds the zFrom ending, then change the
|
||||
** ending to zTo.
|
||||
**
|
||||
** The input word *pz and zFrom are both in reverse order. zTo
|
||||
|
||||
+12
-16
@@ -108,13 +108,9 @@ struct MatchinfoBuffer {
|
||||
int nElem;
|
||||
int bGlobal; /* Set if global data is loaded */
|
||||
char *zMatchinfo;
|
||||
u32 aMI[FLEXARRAY];
|
||||
u32 aMatchinfo[1];
|
||||
};
|
||||
|
||||
/* Size (in bytes) of a MatchinfoBuffer sufficient for N elements */
|
||||
#define SZ_MATCHINFOBUFFER(N) \
|
||||
(offsetof(MatchinfoBuffer,aMI)+(((N)+1)/2)*sizeof(u64))
|
||||
|
||||
|
||||
/*
|
||||
** The snippet() and offsets() functions both return text values. An instance
|
||||
@@ -139,13 +135,13 @@ struct StrBuffer {
|
||||
static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
|
||||
MatchinfoBuffer *pRet;
|
||||
sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1)
|
||||
+ SZ_MATCHINFOBUFFER(1);
|
||||
+ sizeof(MatchinfoBuffer);
|
||||
sqlite3_int64 nStr = strlen(zMatchinfo);
|
||||
|
||||
pRet = sqlite3Fts3MallocZero(nByte + nStr+1);
|
||||
if( pRet ){
|
||||
pRet->aMI[0] = (u8*)(&pRet->aMI[1]) - (u8*)pRet;
|
||||
pRet->aMI[1+nElem] = pRet->aMI[0]
|
||||
pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet;
|
||||
pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0]
|
||||
+ sizeof(u32)*((int)nElem+1);
|
||||
pRet->nElem = (int)nElem;
|
||||
pRet->zMatchinfo = ((char*)pRet) + nByte;
|
||||
@@ -159,10 +155,10 @@ static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
|
||||
static void fts3MIBufferFree(void *p){
|
||||
MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]);
|
||||
|
||||
assert( (u32*)p==&pBuf->aMI[1]
|
||||
|| (u32*)p==&pBuf->aMI[pBuf->nElem+2]
|
||||
assert( (u32*)p==&pBuf->aMatchinfo[1]
|
||||
|| (u32*)p==&pBuf->aMatchinfo[pBuf->nElem+2]
|
||||
);
|
||||
if( (u32*)p==&pBuf->aMI[1] ){
|
||||
if( (u32*)p==&pBuf->aMatchinfo[1] ){
|
||||
pBuf->aRef[1] = 0;
|
||||
}else{
|
||||
pBuf->aRef[2] = 0;
|
||||
@@ -179,18 +175,18 @@ static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){
|
||||
|
||||
if( p->aRef[1]==0 ){
|
||||
p->aRef[1] = 1;
|
||||
aOut = &p->aMI[1];
|
||||
aOut = &p->aMatchinfo[1];
|
||||
xRet = fts3MIBufferFree;
|
||||
}
|
||||
else if( p->aRef[2]==0 ){
|
||||
p->aRef[2] = 1;
|
||||
aOut = &p->aMI[p->nElem+2];
|
||||
aOut = &p->aMatchinfo[p->nElem+2];
|
||||
xRet = fts3MIBufferFree;
|
||||
}else{
|
||||
aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32));
|
||||
if( aOut ){
|
||||
xRet = sqlite3_free;
|
||||
if( p->bGlobal ) memcpy(aOut, &p->aMI[1], p->nElem*sizeof(u32));
|
||||
if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +196,7 @@ static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){
|
||||
|
||||
static void fts3MIBufferSetGlobal(MatchinfoBuffer *p){
|
||||
p->bGlobal = 1;
|
||||
memcpy(&p->aMI[2+p->nElem], &p->aMI[1], p->nElem*sizeof(u32));
|
||||
memcpy(&p->aMatchinfo[2+p->nElem], &p->aMatchinfo[1], p->nElem*sizeof(u32));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -615,7 +611,7 @@ static int fts3StringAppend(
|
||||
}
|
||||
|
||||
/* If there is insufficient space allocated at StrBuffer.z, use realloc()
|
||||
** to grow the buffer until so that it is big enough to accommodate the
|
||||
** to grow the buffer until so that it is big enough to accomadate the
|
||||
** appended data.
|
||||
*/
|
||||
if( pStr->n+nAppend+1>=pStr->nAlloc ){
|
||||
|
||||
@@ -219,7 +219,7 @@ static int SQLITE_TCLAPI fts3_near_match_cmd(
|
||||
rc = Tcl_ListObjGetElements(interp, pPhrase, &nToken, &apToken);
|
||||
if( rc!=TCL_OK ) goto near_match_out;
|
||||
if( nToken>NM_MAX_TOKEN ){
|
||||
Tcl_AppendResult(interp, "Too many tokens in phrase", NULL);
|
||||
Tcl_AppendResult(interp, "Too many tokens in phrase", 0);
|
||||
rc = TCL_ERROR;
|
||||
goto near_match_out;
|
||||
}
|
||||
@@ -547,7 +547,7 @@ static int SQLITE_TCLAPI fts3_test_varint_cmd(
|
||||
if( w!=w2 || nByte!=nByte2 ){
|
||||
char *zErr = sqlite3_mprintf("error testing %lld", w);
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_AppendResult(interp, zErr, NULL);
|
||||
Tcl_AppendResult(interp, zErr, 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -557,7 +557,7 @@ static int SQLITE_TCLAPI fts3_test_varint_cmd(
|
||||
if( (int)w!=i || nByte!=nByte2 ){
|
||||
char *zErr = sqlite3_mprintf("error testing %lld (32-bit)", w);
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_AppendResult(interp, zErr, NULL);
|
||||
Tcl_AppendResult(interp, zErr, 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3956,7 +3956,7 @@ static int fts3IncrmergePush(
|
||||
**
|
||||
** It is assumed that the buffer associated with pNode is already large
|
||||
** enough to accommodate the new entry. The buffer associated with pPrev
|
||||
** is extended by this function if required.
|
||||
** is extended by this function if requrired.
|
||||
**
|
||||
** If an error (i.e. OOM condition) occurs, an SQLite error code is
|
||||
** returned. Otherwise, SQLITE_OK.
|
||||
@@ -5619,7 +5619,7 @@ int sqlite3Fts3DeferToken(
|
||||
/*
|
||||
** SQLite value pRowid contains the rowid of a row that may or may not be
|
||||
** present in the FTS3 table. If it is, delete it and adjust the contents
|
||||
** of subsidiary data structures accordingly.
|
||||
** of subsiduary data structures accordingly.
|
||||
*/
|
||||
static int fts3DeleteByRowid(
|
||||
Fts3Table *p,
|
||||
|
||||
@@ -893,7 +893,7 @@ proc print_test_main {} {
|
||||
puts "\}"
|
||||
}
|
||||
|
||||
# Process the command line arguments. Exit early if they are not to
|
||||
# Proces the command line arguments. Exit early if they are not to
|
||||
# our liking.
|
||||
#
|
||||
proc usage {} {
|
||||
|
||||
+2
-15
@@ -75,18 +75,6 @@ typedef sqlite3_uint64 u64;
|
||||
# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Macros needed to provide flexible arrays in a portable way
|
||||
*/
|
||||
#ifndef offsetof
|
||||
# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
|
||||
#endif
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
# define FLEXARRAY
|
||||
#else
|
||||
# define FLEXARRAY 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Truncate very long tokens to this many bytes. Hard limit is
|
||||
@@ -159,11 +147,10 @@ typedef struct Fts5Colset Fts5Colset;
|
||||
*/
|
||||
struct Fts5Colset {
|
||||
int nCol;
|
||||
int aiCol[FLEXARRAY];
|
||||
int aiCol[1];
|
||||
};
|
||||
|
||||
/* Size (int bytes) of a complete Fts5Colset object with N columns. */
|
||||
#define SZ_FTS5COLSET(N) (sizeof(i64)*((N+2)/2))
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
** Interface to code in fts5_config.c. fts5_config.c contains contains code
|
||||
|
||||
+1
-1
@@ -667,7 +667,7 @@ static int fts5Bm25GetData(
|
||||
** under consideration.
|
||||
**
|
||||
** The problem with this is that if (N < 2*nHit), the IDF is
|
||||
** negative. Which is undesirable. So the minimum allowable IDF is
|
||||
** negative. Which is undesirable. So the mimimum allowable IDF is
|
||||
** (1e-6) - roughly the same as a term that appears in just over
|
||||
** half of set of 5,000,000 documents. */
|
||||
double idf = log( (nRow - nHit + 0.5) / (nHit + 0.5) );
|
||||
|
||||
@@ -308,7 +308,7 @@ char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){
|
||||
** * The 52 upper and lower case ASCII characters, and
|
||||
** * The 10 integer ASCII characters.
|
||||
** * The underscore character "_" (0x5F).
|
||||
** * The unicode "substitute" character (0x1A).
|
||||
** * The unicode "subsitute" character (0x1A).
|
||||
*/
|
||||
int sqlite3Fts5IsBareword(char t){
|
||||
u8 aBareword[128] = {
|
||||
|
||||
+23
-34
@@ -86,13 +86,9 @@ struct Fts5ExprNode {
|
||||
/* Child nodes. For a NOT node, this array always contains 2 entries. For
|
||||
** AND or OR nodes, it contains 2 or more entries. */
|
||||
int nChild; /* Number of child nodes */
|
||||
Fts5ExprNode *apChild[FLEXARRAY]; /* Array of child nodes */
|
||||
Fts5ExprNode *apChild[1]; /* Array of child nodes */
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts5ExprNode object that holds up to N children */
|
||||
#define SZ_FTS5EXPRNODE(N) \
|
||||
(offsetof(Fts5ExprNode,apChild) + (N)*sizeof(Fts5ExprNode*))
|
||||
|
||||
#define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING)
|
||||
|
||||
/*
|
||||
@@ -123,13 +119,9 @@ struct Fts5ExprPhrase {
|
||||
Fts5ExprNode *pNode; /* FTS5_STRING node this phrase is part of */
|
||||
Fts5Buffer poslist; /* Current position list */
|
||||
int nTerm; /* Number of entries in aTerm[] */
|
||||
Fts5ExprTerm aTerm[FLEXARRAY]; /* Terms that make up this phrase */
|
||||
Fts5ExprTerm aTerm[1]; /* Terms that make up this phrase */
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts5ExprPhrase object that holds up to N terms */
|
||||
#define SZ_FTS5EXPRPHRASE(N) \
|
||||
(offsetof(Fts5ExprPhrase,aTerm) + (N)*sizeof(Fts5ExprTerm))
|
||||
|
||||
/*
|
||||
** One or more phrases that must appear within a certain token distance of
|
||||
** each other within each matching document.
|
||||
@@ -138,12 +130,9 @@ struct Fts5ExprNearset {
|
||||
int nNear; /* NEAR parameter */
|
||||
Fts5Colset *pColset; /* Columns to search (NULL -> all columns) */
|
||||
int nPhrase; /* Number of entries in aPhrase[] array */
|
||||
Fts5ExprPhrase *apPhrase[FLEXARRAY]; /* Array of phrase pointers */
|
||||
Fts5ExprPhrase *apPhrase[1]; /* Array of phrase pointers */
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts5ExprNearset object covering up to N phrases */
|
||||
#define SZ_FTS5EXPRNEARSET(N) \
|
||||
(offsetof(Fts5ExprNearset,apPhrase)+(N)*sizeof(Fts5ExprPhrase*))
|
||||
|
||||
/*
|
||||
** Parse context.
|
||||
@@ -303,7 +292,7 @@ int sqlite3Fts5ExprNew(
|
||||
/* If the LHS of the MATCH expression was a user column, apply the
|
||||
** implicit column-filter. */
|
||||
if( sParse.rc==SQLITE_OK && iCol<pConfig->nCol ){
|
||||
int n = SZ_FTS5COLSET(1);
|
||||
int n = sizeof(Fts5Colset);
|
||||
Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&sParse.rc, n);
|
||||
if( pColset ){
|
||||
pColset->nCol = 1;
|
||||
@@ -1661,7 +1650,7 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
|
||||
if( pParse->rc==SQLITE_OK ){
|
||||
if( pNear==0 ){
|
||||
sqlite3_int64 nByte;
|
||||
nByte = SZ_FTS5EXPRNEARSET(SZALLOC+1);
|
||||
nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
|
||||
pRet = sqlite3_malloc64(nByte);
|
||||
if( pRet==0 ){
|
||||
pParse->rc = SQLITE_NOMEM;
|
||||
@@ -1672,7 +1661,7 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
|
||||
int nNew = pNear->nPhrase + SZALLOC;
|
||||
sqlite3_int64 nByte;
|
||||
|
||||
nByte = SZ_FTS5EXPRNEARSET(nNew+1);
|
||||
nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
|
||||
pRet = (Fts5ExprNearset*)sqlite3_realloc64(pNear, nByte);
|
||||
if( pRet==0 ){
|
||||
pParse->rc = SQLITE_NOMEM;
|
||||
@@ -1763,12 +1752,12 @@ static int fts5ParseTokenize(
|
||||
int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0);
|
||||
|
||||
pNew = (Fts5ExprPhrase*)sqlite3_realloc64(pPhrase,
|
||||
SZ_FTS5EXPRPHRASE(nNew+1)
|
||||
sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * nNew
|
||||
);
|
||||
if( pNew==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
if( pPhrase==0 ) memset(pNew, 0, SZ_FTS5EXPRPHRASE(1));
|
||||
if( pPhrase==0 ) memset(pNew, 0, sizeof(Fts5ExprPhrase));
|
||||
pCtx->pPhrase = pPhrase = pNew;
|
||||
pNew->nTerm = nNew - SZALLOC;
|
||||
}
|
||||
@@ -1876,7 +1865,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
|
||||
if( sCtx.pPhrase==0 ){
|
||||
/* This happens when parsing a token or quoted phrase that contains
|
||||
** no token characters at all. (e.g ... MATCH '""'). */
|
||||
sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, SZ_FTS5EXPRPHRASE(1));
|
||||
sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase));
|
||||
}else if( sCtx.pPhrase->nTerm ){
|
||||
sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
|
||||
}
|
||||
@@ -1911,18 +1900,19 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
sizeof(Fts5ExprPhrase*));
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc, SZ_FTS5EXPRNODE(1));
|
||||
pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc,
|
||||
sizeof(Fts5ExprNode));
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
|
||||
SZ_FTS5EXPRNEARSET(2));
|
||||
pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
|
||||
sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*));
|
||||
}
|
||||
if( rc==SQLITE_OK && ALWAYS(pOrig!=0) ){
|
||||
Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
|
||||
if( pColsetOrig ){
|
||||
sqlite3_int64 nByte;
|
||||
Fts5Colset *pColset;
|
||||
nByte = SZ_FTS5COLSET(pColsetOrig->nCol);
|
||||
nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
|
||||
pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
|
||||
if( pColset ){
|
||||
memcpy(pColset, pColsetOrig, (size_t)nByte);
|
||||
@@ -1950,7 +1940,7 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
}else{
|
||||
/* This happens when parsing a token or quoted phrase that contains
|
||||
** no token characters at all. (e.g ... MATCH '""'). */
|
||||
sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, SZ_FTS5EXPRPHRASE(1));
|
||||
sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2015,8 +2005,7 @@ void sqlite3Fts5ParseSetDistance(
|
||||
);
|
||||
return;
|
||||
}
|
||||
if( nNear<214748363 ) nNear = nNear * 10 + (p->p[i] - '0');
|
||||
/* ^^^^^^^^^^^^^^^--- Prevent integer overflow */
|
||||
nNear = nNear * 10 + (p->p[i] - '0');
|
||||
}
|
||||
}else{
|
||||
nNear = FTS5_DEFAULT_NEARDIST;
|
||||
@@ -2045,7 +2034,7 @@ static Fts5Colset *fts5ParseColset(
|
||||
assert( pParse->rc==SQLITE_OK );
|
||||
assert( iCol>=0 && iCol<pParse->pConfig->nCol );
|
||||
|
||||
pNew = sqlite3_realloc64(p, SZ_FTS5COLSET(nCol+1));
|
||||
pNew = sqlite3_realloc64(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
|
||||
if( pNew==0 ){
|
||||
pParse->rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -2080,7 +2069,7 @@ Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse *pParse, Fts5Colset *p){
|
||||
int nCol = pParse->pConfig->nCol;
|
||||
|
||||
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc,
|
||||
SZ_FTS5COLSET(nCol+1)
|
||||
sizeof(Fts5Colset) + sizeof(int)*nCol
|
||||
);
|
||||
if( pRet ){
|
||||
int i;
|
||||
@@ -2141,7 +2130,7 @@ Fts5Colset *sqlite3Fts5ParseColset(
|
||||
static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){
|
||||
Fts5Colset *pRet;
|
||||
if( pOrig ){
|
||||
sqlite3_int64 nByte = SZ_FTS5COLSET(pOrig->nCol);
|
||||
sqlite3_int64 nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
|
||||
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte);
|
||||
if( pRet ){
|
||||
memcpy(pRet, pOrig, (size_t)nByte);
|
||||
@@ -2309,7 +2298,7 @@ static Fts5ExprNode *fts5ParsePhraseToAnd(
|
||||
assert( pNear->nPhrase==1 );
|
||||
assert( pParse->bPhraseToAnd );
|
||||
|
||||
nByte = SZ_FTS5EXPRNODE(nTerm+1);
|
||||
nByte = sizeof(Fts5ExprNode) + nTerm*sizeof(Fts5ExprNode*);
|
||||
pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
|
||||
if( pRet ){
|
||||
pRet->eType = FTS5_AND;
|
||||
@@ -2319,7 +2308,7 @@ static Fts5ExprNode *fts5ParsePhraseToAnd(
|
||||
pParse->nPhrase--;
|
||||
for(ii=0; ii<nTerm; ii++){
|
||||
Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(
|
||||
&pParse->rc, SZ_FTS5EXPRPHRASE(1)
|
||||
&pParse->rc, sizeof(Fts5ExprPhrase)
|
||||
);
|
||||
if( pPhrase ){
|
||||
if( parseGrowPhraseArray(pParse) ){
|
||||
@@ -2388,7 +2377,7 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
|
||||
if( pRight->eType==eType ) nChild += pRight->nChild-1;
|
||||
}
|
||||
|
||||
nByte = SZ_FTS5EXPRNODE(nChild);
|
||||
nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
|
||||
pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
|
||||
|
||||
if( pRet ){
|
||||
@@ -3263,7 +3252,7 @@ int sqlite3Fts5ExprInstToken(
|
||||
}
|
||||
|
||||
/*
|
||||
** Clear the token mappings for all Fts5IndexIter objects managed by
|
||||
** Clear the token mappings for all Fts5IndexIter objects mannaged by
|
||||
** the expression passed as the only argument.
|
||||
*/
|
||||
void sqlite3Fts5ExprClearTokens(Fts5Expr *pExpr){
|
||||
|
||||
@@ -20,7 +20,7 @@ typedef struct Fts5HashEntry Fts5HashEntry;
|
||||
|
||||
/*
|
||||
** This file contains the implementation of an in-memory hash table used
|
||||
** to accumulate "term -> doclist" content before it is flushed to a level-0
|
||||
** to accumuluate "term -> doclist" content before it is flused to a level-0
|
||||
** segment.
|
||||
*/
|
||||
|
||||
@@ -77,7 +77,7 @@ struct Fts5HashEntry {
|
||||
};
|
||||
|
||||
/*
|
||||
** Equivalent to:
|
||||
** Eqivalent to:
|
||||
**
|
||||
** char *fts5EntryKey(Fts5HashEntry *pEntry){ return zKey; }
|
||||
*/
|
||||
|
||||
+34
-52
@@ -422,13 +422,9 @@ struct Fts5Structure {
|
||||
u64 nOriginCntr; /* Origin value for next top-level segment */
|
||||
int nSegment; /* Total segments in this structure */
|
||||
int nLevel; /* Number of levels in this index */
|
||||
Fts5StructureLevel aLevel[FLEXARRAY]; /* Array of nLevel level objects */
|
||||
Fts5StructureLevel aLevel[1]; /* Array of nLevel level objects */
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts5Structure object holding up to N levels */
|
||||
#define SZ_FTS5STRUCTURE(N) \
|
||||
(offsetof(Fts5Structure,aLevel) + (N)*sizeof(Fts5StructureLevel))
|
||||
|
||||
/*
|
||||
** An object of type Fts5SegWriter is used to write to segments.
|
||||
*/
|
||||
@@ -558,15 +554,11 @@ struct Fts5SegIter {
|
||||
** Array of tombstone pages. Reference counted.
|
||||
*/
|
||||
struct Fts5TombstoneArray {
|
||||
int nRef; /* Number of pointers to this object */
|
||||
int nRef; /* Number of pointers to this object */
|
||||
int nTombstone;
|
||||
Fts5Data *apTombstone[FLEXARRAY]; /* Array of tombstone pages */
|
||||
Fts5Data *apTombstone[1]; /* Array of tombstone pages */
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts5TombstoneArray holding up to N tombstones */
|
||||
#define SZ_FTS5TOMBSTONEARRAY(N) \
|
||||
(offsetof(Fts5TombstoneArray,apTombstone)+(N)*sizeof(Fts5Data*))
|
||||
|
||||
/*
|
||||
** Argument is a pointer to an Fts5Data structure that contains a
|
||||
** leaf page.
|
||||
@@ -635,12 +627,9 @@ struct Fts5Iter {
|
||||
|
||||
i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */
|
||||
Fts5CResult *aFirst; /* Current merge state (see above) */
|
||||
Fts5SegIter aSeg[FLEXARRAY]; /* Array of segment iterators */
|
||||
Fts5SegIter aSeg[1]; /* Array of segment iterators */
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts5Iter object holding up to N segment iterators */
|
||||
#define SZ_FTS5ITER(N) (offsetof(Fts5Iter,aSeg)+(N)*sizeof(Fts5SegIter))
|
||||
|
||||
/*
|
||||
** An instance of the following type is used to iterate through the contents
|
||||
** of a doclist-index record.
|
||||
@@ -667,13 +656,9 @@ struct Fts5DlidxLvl {
|
||||
struct Fts5DlidxIter {
|
||||
int nLvl;
|
||||
int iSegid;
|
||||
Fts5DlidxLvl aLvl[FLEXARRAY];
|
||||
Fts5DlidxLvl aLvl[1];
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts5DlidxIter object with up to N levels */
|
||||
#define SZ_FTS5DLIDXITER(N) \
|
||||
(offsetof(Fts5DlidxIter,aLvl)+(N)*sizeof(Fts5DlidxLvl))
|
||||
|
||||
static void fts5PutU16(u8 *aOut, u16 iVal){
|
||||
aOut[0] = (iVal>>8);
|
||||
aOut[1] = (iVal&0xFF);
|
||||
@@ -1041,7 +1026,7 @@ int sqlite3Fts5StructureTest(Fts5Index *p, void *pStruct){
|
||||
static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){
|
||||
Fts5Structure *p = *pp;
|
||||
if( *pRc==SQLITE_OK && p->nRef>1 ){
|
||||
i64 nByte = SZ_FTS5STRUCTURE(p->nLevel);
|
||||
i64 nByte = sizeof(Fts5Structure)+(p->nLevel-1)*sizeof(Fts5StructureLevel);
|
||||
Fts5Structure *pNew;
|
||||
pNew = (Fts5Structure*)sqlite3Fts5MallocZero(pRc, nByte);
|
||||
if( pNew ){
|
||||
@@ -1115,7 +1100,10 @@ static int fts5StructureDecode(
|
||||
){
|
||||
return FTS5_CORRUPT;
|
||||
}
|
||||
nByte = SZ_FTS5STRUCTURE(nLevel);
|
||||
nByte = (
|
||||
sizeof(Fts5Structure) + /* Main structure */
|
||||
sizeof(Fts5StructureLevel) * (nLevel-1) /* aLevel[] array */
|
||||
);
|
||||
pRet = (Fts5Structure*)sqlite3Fts5MallocZero(&rc, nByte);
|
||||
|
||||
if( pRet ){
|
||||
@@ -1195,7 +1183,10 @@ static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){
|
||||
if( *pRc==SQLITE_OK ){
|
||||
Fts5Structure *pStruct = *ppStruct;
|
||||
int nLevel = pStruct->nLevel;
|
||||
sqlite3_int64 nByte = SZ_FTS5STRUCTURE(nLevel+2);
|
||||
sqlite3_int64 nByte = (
|
||||
sizeof(Fts5Structure) + /* Main structure */
|
||||
sizeof(Fts5StructureLevel) * (nLevel+1) /* aLevel[] array */
|
||||
);
|
||||
|
||||
pStruct = sqlite3_realloc64(pStruct, nByte);
|
||||
if( pStruct ){
|
||||
@@ -1734,7 +1725,7 @@ static Fts5DlidxIter *fts5DlidxIterInit(
|
||||
int bDone = 0;
|
||||
|
||||
for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
|
||||
sqlite3_int64 nByte = SZ_FTS5DLIDXITER(i+1);
|
||||
sqlite3_int64 nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
|
||||
Fts5DlidxIter *pNew;
|
||||
|
||||
pNew = (Fts5DlidxIter*)sqlite3_realloc64(pIter, nByte);
|
||||
@@ -1952,7 +1943,7 @@ static void fts5SegIterSetNext(Fts5Index *p, Fts5SegIter *pIter){
|
||||
static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){
|
||||
const int nTomb = pIter->pSeg->nPgTombstone;
|
||||
if( nTomb>0 ){
|
||||
int nByte = SZ_FTS5TOMBSTONEARRAY(nTomb+1);
|
||||
int nByte = nTomb * sizeof(Fts5Data*) + sizeof(Fts5TombstoneArray);
|
||||
Fts5TombstoneArray *pNew;
|
||||
pNew = (Fts5TombstoneArray*)sqlite3Fts5MallocZero(&p->rc, nByte);
|
||||
if( pNew ){
|
||||
@@ -3413,7 +3404,8 @@ static Fts5Iter *fts5MultiIterAlloc(
|
||||
|
||||
for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2);
|
||||
pNew = fts5IdxMalloc(p,
|
||||
SZ_FTS5ITER(nSlot) + /* pNew + pNew->aSeg[] */
|
||||
sizeof(Fts5Iter) + /* pNew */
|
||||
sizeof(Fts5SegIter) * (nSlot-1) + /* pNew->aSeg[] */
|
||||
sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */
|
||||
);
|
||||
if( pNew ){
|
||||
@@ -5214,7 +5206,7 @@ static void fts5DoSecureDelete(
|
||||
int iDelKeyOff = 0; /* Offset of deleted key, if any */
|
||||
|
||||
nIdx = nPg-iPgIdx;
|
||||
aIdx = sqlite3Fts5MallocZero(&p->rc, ((i64)nIdx)+16);
|
||||
aIdx = sqlite3Fts5MallocZero(&p->rc, nIdx+16);
|
||||
if( p->rc ) return;
|
||||
memcpy(aIdx, &aPg[iPgIdx], nIdx);
|
||||
|
||||
@@ -5779,7 +5771,7 @@ static Fts5Structure *fts5IndexOptimizeStruct(
|
||||
Fts5Structure *pStruct
|
||||
){
|
||||
Fts5Structure *pNew = 0;
|
||||
sqlite3_int64 nByte = SZ_FTS5STRUCTURE(1);
|
||||
sqlite3_int64 nByte = sizeof(Fts5Structure);
|
||||
int nSeg = pStruct->nSegment;
|
||||
int i;
|
||||
|
||||
@@ -5808,8 +5800,7 @@ static Fts5Structure *fts5IndexOptimizeStruct(
|
||||
assert( pStruct->aLevel[i].nMerge<=nThis );
|
||||
}
|
||||
|
||||
nByte += (((i64)pStruct->nLevel)+1) * sizeof(Fts5StructureLevel);
|
||||
assert( nByte==SZ_FTS5STRUCTURE(pStruct->nLevel+2) );
|
||||
nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel);
|
||||
pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
|
||||
|
||||
if( pNew ){
|
||||
@@ -6386,13 +6377,9 @@ struct Fts5TokenDataIter {
|
||||
int nIterAlloc;
|
||||
Fts5PoslistReader *aPoslistReader;
|
||||
int *aPoslistToIter;
|
||||
Fts5Iter *apIter[FLEXARRAY];
|
||||
Fts5Iter *apIter[1];
|
||||
};
|
||||
|
||||
/* Size in bytes of an Fts5TokenDataIter object holding up to N iterators */
|
||||
#define SZ_FTS5TOKENDATAITER(N) \
|
||||
(offsetof(Fts5TokenDataIter,apIter) + (N)*sizeof(Fts5Iter))
|
||||
|
||||
/*
|
||||
** The two input arrays - a1[] and a2[] - are in sorted order. This function
|
||||
** merges the two arrays together and writes the result to output array
|
||||
@@ -6464,7 +6451,7 @@ static void fts5TokendataIterAppendMap(
|
||||
/*
|
||||
** Sort the contents of the pT->aMap[] array.
|
||||
**
|
||||
** The sorting algorithm requires a malloc(). If this fails, an error code
|
||||
** The sorting algorithm requries a malloc(). If this fails, an error code
|
||||
** is left in Fts5Index.rc before returning.
|
||||
*/
|
||||
static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){
|
||||
@@ -6655,7 +6642,7 @@ static void fts5SetupPrefixIter(
|
||||
&& p->pConfig->bPrefixInsttoken
|
||||
){
|
||||
s.pTokendata = &s2;
|
||||
s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, SZ_FTS5TOKENDATAITER(1));
|
||||
s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, sizeof(*s2.pT));
|
||||
}
|
||||
|
||||
if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
|
||||
@@ -6701,8 +6688,7 @@ static void fts5SetupPrefixIter(
|
||||
}
|
||||
}
|
||||
|
||||
pData = fts5IdxMalloc(p, sizeof(*pData)
|
||||
+ ((i64)s.doclist.n)+FTS5_DATA_ZERO_PADDING);
|
||||
pData = fts5IdxMalloc(p, sizeof(*pData)+s.doclist.n+FTS5_DATA_ZERO_PADDING);
|
||||
assert( pData!=0 || p->rc!=SQLITE_OK );
|
||||
if( pData ){
|
||||
pData->p = (u8*)&pData[1];
|
||||
@@ -6783,17 +6769,15 @@ int sqlite3Fts5IndexRollback(Fts5Index *p){
|
||||
** and the initial version of the "averages" record (a zero-byte blob).
|
||||
*/
|
||||
int sqlite3Fts5IndexReinit(Fts5Index *p){
|
||||
Fts5Structure *pTmp;
|
||||
u8 tmpSpace[SZ_FTS5STRUCTURE(1)];
|
||||
Fts5Structure s;
|
||||
fts5StructureInvalidate(p);
|
||||
fts5IndexDiscardData(p);
|
||||
pTmp = (Fts5Structure*)tmpSpace;
|
||||
memset(pTmp, 0, SZ_FTS5STRUCTURE(1));
|
||||
memset(&s, 0, sizeof(Fts5Structure));
|
||||
if( p->pConfig->bContentlessDelete ){
|
||||
pTmp->nOriginCntr = 1;
|
||||
s.nOriginCntr = 1;
|
||||
}
|
||||
fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
|
||||
fts5StructureWrite(p, pTmp);
|
||||
fts5StructureWrite(p, &s);
|
||||
return fts5IndexReturn(p);
|
||||
}
|
||||
|
||||
@@ -7001,7 +6985,7 @@ static Fts5TokenDataIter *fts5AppendTokendataIter(
|
||||
if( p->rc==SQLITE_OK ){
|
||||
if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){
|
||||
int nAlloc = pIn ? pIn->nIterAlloc*2 : 16;
|
||||
int nByte = SZ_FTS5TOKENDATAITER(nAlloc+1);
|
||||
int nByte = nAlloc * sizeof(Fts5Iter*) + sizeof(Fts5TokenDataIter);
|
||||
Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte);
|
||||
|
||||
if( pNew==0 ){
|
||||
@@ -7517,8 +7501,7 @@ static int fts5SetupPrefixIterTokendata(
|
||||
|
||||
fts5BufferGrow(&p->rc, &token, nToken+1);
|
||||
assert( token.p!=0 || p->rc!=SQLITE_OK );
|
||||
ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc,
|
||||
SZ_FTS5TOKENDATAITER(1));
|
||||
ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*ctx.pT));
|
||||
|
||||
if( p->rc==SQLITE_OK ){
|
||||
|
||||
@@ -7649,8 +7632,7 @@ int sqlite3Fts5IndexIterWriteTokendata(
|
||||
if( pIter->nSeg>0 ){
|
||||
/* This is a prefix term iterator. */
|
||||
if( pT==0 ){
|
||||
pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc,
|
||||
SZ_FTS5TOKENDATAITER(1));
|
||||
pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*pT));
|
||||
pIter->pTokenDataIter = pT;
|
||||
}
|
||||
if( pT ){
|
||||
@@ -8684,7 +8666,7 @@ static void fts5DecodeRowid(
|
||||
|
||||
#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
|
||||
static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
|
||||
int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid components */
|
||||
int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid compenents */
|
||||
fts5DecodeRowid(iKey, &bTomb, &iSegid, &bDlidx, &iHeight, &iPgno);
|
||||
|
||||
if( iSegid==0 ){
|
||||
@@ -8930,7 +8912,7 @@ static void fts5DecodeFunction(
|
||||
** buffer overreads even if the record is corrupt. */
|
||||
n = sqlite3_value_bytes(apVal[1]);
|
||||
aBlob = sqlite3_value_blob(apVal[1]);
|
||||
nSpace = ((i64)n) + FTS5_DATA_ZERO_PADDING;
|
||||
nSpace = n + FTS5_DATA_ZERO_PADDING;
|
||||
a = (u8*)sqlite3Fts5MallocZero(&rc, nSpace);
|
||||
if( a==0 ) goto decode_out;
|
||||
if( n>0 ) memcpy(a, aBlob, n);
|
||||
|
||||
@@ -170,11 +170,9 @@ struct Fts5Sorter {
|
||||
i64 iRowid; /* Current rowid */
|
||||
const u8 *aPoslist; /* Position lists for current row */
|
||||
int nIdx; /* Number of entries in aIdx[] */
|
||||
int aIdx[FLEXARRAY]; /* Offsets into aPoslist for current row */
|
||||
int aIdx[1]; /* Offsets into aPoslist for current row */
|
||||
};
|
||||
|
||||
/* Size (int bytes) of an Fts5Sorter object with N indexes */
|
||||
#define SZ_FTS5SORTER(N) (offsetof(Fts5Sorter,nIdx)+((N+2)/2)*sizeof(i64))
|
||||
|
||||
/*
|
||||
** Virtual-table cursor object.
|
||||
@@ -1052,7 +1050,7 @@ static int fts5CursorFirstSorted(
|
||||
const char *zRankArgs = pCsr->zRankArgs;
|
||||
|
||||
nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
|
||||
nByte = SZ_FTS5SORTER(nPhrase);
|
||||
nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
|
||||
pSorter = (Fts5Sorter*)sqlite3_malloc64(nByte);
|
||||
if( pSorter==0 ) return SQLITE_NOMEM;
|
||||
memset(pSorter, 0, (size_t)nByte);
|
||||
@@ -3803,8 +3801,8 @@ static int fts5Init(sqlite3 *db){
|
||||
** its entry point to enable the matchinfo() demo. */
|
||||
#ifdef SQLITE_FTS5_ENABLE_TEST_MI
|
||||
if( rc==SQLITE_OK ){
|
||||
extern int sqlite3Fts5TestRegisterMatchinfoAPI(fts5_api*);
|
||||
rc = sqlite3Fts5TestRegisterMatchinfoAPI(&pGlobal->api);
|
||||
extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*);
|
||||
rc = sqlite3Fts5TestRegisterMatchinfo(db);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+10
-22
@@ -393,13 +393,17 @@ static void fts5MatchinfoFunc(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Register "matchinfo" with global API object pApi.
|
||||
*/
|
||||
int sqlite3Fts5TestRegisterMatchinfoAPI(fts5_api *pApi){
|
||||
int rc;
|
||||
int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
|
||||
int rc; /* Return code */
|
||||
fts5_api *pApi; /* FTS5 API functions */
|
||||
|
||||
/* If fts5_api_from_db() returned NULL, then either FTS5 is not registered
|
||||
/* Extract the FTS5 API pointer from the database handle. The
|
||||
** fts5_api_from_db() function above is copied verbatim from the
|
||||
** FTS5 documentation. Refer there for details. */
|
||||
rc = fts5_api_from_db(db, &pApi);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
/* If fts5_api_from_db() returns NULL, then either FTS5 is not registered
|
||||
** with this database handle, or an error (OOM perhaps?) has occurred.
|
||||
**
|
||||
** Also check that the fts5_api object is version 2 or newer.
|
||||
@@ -414,20 +418,4 @@ int sqlite3Fts5TestRegisterMatchinfoAPI(fts5_api *pApi){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Register "matchinfo" with database handle db.
|
||||
*/
|
||||
int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
|
||||
int rc; /* Return code */
|
||||
fts5_api *pApi; /* FTS5 API functions */
|
||||
|
||||
/* Extract the FTS5 API pointer from the database handle. The
|
||||
** fts5_api_from_db() function above is copied verbatim from the
|
||||
** FTS5 documentation. Refer there for details. */
|
||||
rc = fts5_api_from_db(db, &pApi);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
return sqlite3Fts5TestRegisterMatchinfoAPI(pApi);
|
||||
}
|
||||
|
||||
#endif /* SQLITE_ENABLE_FTS5 */
|
||||
|
||||
@@ -193,12 +193,12 @@ static int fts5VocabInitVtab(
|
||||
*pzErr = sqlite3_mprintf("wrong number of vtable arguments");
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
i64 nByte; /* Bytes of space to allocate */
|
||||
int nByte; /* Bytes of space to allocate */
|
||||
const char *zDb = bDb ? argv[3] : argv[1];
|
||||
const char *zTab = bDb ? argv[4] : argv[3];
|
||||
const char *zType = bDb ? argv[5] : argv[4];
|
||||
i64 nDb = strlen(zDb)+1;
|
||||
i64 nTab = strlen(zTab)+1;
|
||||
int nDb = (int)strlen(zDb)+1;
|
||||
int nTab = (int)strlen(zTab)+1;
|
||||
int eType = 0;
|
||||
|
||||
rc = fts5VocabTableType(zType, pzErr, &eType);
|
||||
|
||||
@@ -520,26 +520,4 @@ do_execsql_test 15.3 {
|
||||
{columnsize {1 1} columntext {c d} columntotalsize {2 2} poslist {} tokenize {c d} rowcount 2}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 16.0 {
|
||||
CREATE TABLE t1(x);
|
||||
BEGIN EXCLUSIVE;
|
||||
}
|
||||
|
||||
sqlite3 db2 test.db
|
||||
do_test 16.1 {
|
||||
catchsql { SELECT * FROM t1 } db2
|
||||
} {1 {database is locked}}
|
||||
|
||||
do_execsql_test 16.2 {
|
||||
ROLLBACK;
|
||||
}
|
||||
|
||||
do_test 16.3 {
|
||||
catchsql { SELECT * FROM t1 } db2
|
||||
} {0 {}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ do_execsql_test 3.0 {
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that a crash occurring when the second or subsequent tokens in a
|
||||
# Test that a crash occuring when the second or subsequent tokens in a
|
||||
# phrase matched zero rows has been fixed.
|
||||
#
|
||||
do_execsql_test 4.0 {
|
||||
|
||||
+2
-2
@@ -79,7 +79,7 @@ $(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
|
||||
$(MAKE) -C $(dir.top) version-info
|
||||
|
||||
# Be explicit about which Java files to compile so that we can work on
|
||||
# in-progress files without requiring them to be in a compilable state.
|
||||
# in-progress files without requiring them to be in a compilable statae.
|
||||
JAVA_FILES.main := $(patsubst %,$(dir.src.jni)/annotation/%,\
|
||||
Experimental.java \
|
||||
NotNull.java \
|
||||
@@ -451,7 +451,7 @@ distclean: clean
|
||||
-rm -fr $(dir.bld.c) $(dir.doc)
|
||||
|
||||
########################################################################
|
||||
# distribution bundle rules...
|
||||
# disttribution bundle rules...
|
||||
|
||||
ifeq (,$(filter snapshot,$(MAKECMDGOALS)))
|
||||
dist-name-prefix := sqlite-jni
|
||||
|
||||
+1
-1
@@ -169,7 +169,7 @@ deliberately return an error code, instead of segfaulting, when passed
|
||||
a `null`.
|
||||
|
||||
Client-defined callbacks _must never throw exceptions_ unless _very
|
||||
explicitly documented_ as being throw-safe. Exceptions are generally
|
||||
explitly documented_ as being throw-safe. Exceptions are generally
|
||||
reserved for higher-level bindings which are constructed to
|
||||
specifically deal with them and ensure that they do not leak C-level
|
||||
resources. In some cases, callback handlers are permitted to throw, in
|
||||
|
||||
@@ -948,7 +948,7 @@ static JNIEnv * s3jni_env(void){
|
||||
}
|
||||
|
||||
/*
|
||||
** Fetches the S3JniGlobal.envCache row for the given env, allocating a
|
||||
** Fetches the S3JniGlobal.envCache row for the given env, allocing a
|
||||
** row if needed. When a row is allocated, its state is initialized
|
||||
** insofar as possible. Calls (*env)->FatalError() if allocation of an
|
||||
** entry fails. That's hypothetically possible but "shouldn't happen."
|
||||
@@ -1603,7 +1603,7 @@ static void * NativePointerHolder__get(JNIEnv * env, jobject jNph,
|
||||
** 2023-11-09: testing has not revealed any measurable performance
|
||||
** difference between the approach of passing type T to C compared to
|
||||
** passing pointer-to-T to C, and adding support for the latter
|
||||
** everywhere requires significantly more code. As of this writing, the
|
||||
** everywhere requires sigificantly more code. As of this writing, the
|
||||
** older/simpler approach is being applied except for (A) where the
|
||||
** newer approach has already been applied and (B) hot-spot APIs where
|
||||
** a difference of microseconds (i.e. below our testing measurement
|
||||
@@ -3290,7 +3290,7 @@ static void s3jni_rollback_hook_impl(void *pP){
|
||||
static jobject s3jni_commit_rollback_hook(int isCommit, JNIEnv * const env,
|
||||
jlong jpDb, jobject jHook){
|
||||
S3JniDb * ps;
|
||||
jobject pOld = 0; /* previous hook */
|
||||
jobject pOld = 0; /* previous hoook */
|
||||
S3JniHook * pHook; /* ps->hooks.commit|rollback */
|
||||
|
||||
S3JniDb_mutex_enter;
|
||||
@@ -5696,7 +5696,7 @@ JniDeclFtsApi(jint,xCreateFunction)(JniArgsEnvObj, jstring jName,
|
||||
|
||||
typedef struct S3JniFts5AuxData S3JniFts5AuxData;
|
||||
/*
|
||||
** TODO: this middle-man struct is no longer necessary. Consider
|
||||
** TODO: this middle-man struct is no longer necessary. Conider
|
||||
** removing it and passing around jObj itself instead.
|
||||
*/
|
||||
struct S3JniFts5AuxData {
|
||||
|
||||
@@ -199,16 +199,16 @@ public final class CApi {
|
||||
}
|
||||
|
||||
private static native sqlite3_backup sqlite3_backup_init(
|
||||
@NotNull long ptrToDbDest, @NotNull String destSchemaName,
|
||||
@NotNull long ptrToDbSrc, @NotNull String srcSchemaName
|
||||
@NotNull long ptrToDbDest, @NotNull String destTableName,
|
||||
@NotNull long ptrToDbSrc, @NotNull String srcTableName
|
||||
);
|
||||
|
||||
public static sqlite3_backup sqlite3_backup_init(
|
||||
@NotNull sqlite3 dbDest, @NotNull String destSchemaName,
|
||||
@NotNull sqlite3 dbSrc, @NotNull String srcSchemaName
|
||||
@NotNull sqlite3 dbDest, @NotNull String destTableName,
|
||||
@NotNull sqlite3 dbSrc, @NotNull String srcTableName
|
||||
){
|
||||
return sqlite3_backup_init( dbDest.getNativePointer(), destSchemaName,
|
||||
dbSrc.getNativePointer(), srcSchemaName );
|
||||
return sqlite3_backup_init( dbDest.getNativePointer(), destTableName,
|
||||
dbSrc.getNativePointer(), srcTableName );
|
||||
}
|
||||
|
||||
private static native int sqlite3_backup_pagecount(@NotNull long ptrToBackup);
|
||||
@@ -264,7 +264,7 @@ public final class CApi {
|
||||
}
|
||||
|
||||
/**
|
||||
Convenience overload which is equivalent to passing its arguments
|
||||
Convenience overload which is equivalant to passing its arguments
|
||||
to sqlite3_bind_nio_buffer() with the values 0 and -1 for the
|
||||
final two arguments.
|
||||
*/
|
||||
@@ -312,7 +312,7 @@ public final class CApi {
|
||||
|
||||
The byte range of the buffer may be restricted by providing a
|
||||
start index and a number of bytes. beginPos may not be negative.
|
||||
Negative howMany is interpreted as the remainder of the buffer
|
||||
Negative howMany is interpretated as the remainder of the buffer
|
||||
past the given start position, up to the buffer's limit() (as
|
||||
opposed its capacity()).
|
||||
|
||||
@@ -1076,7 +1076,7 @@ public final class CApi {
|
||||
|
||||
/**
|
||||
<p>Works like in the C API with the exception that it only supports
|
||||
the following subset of configuration flags:
|
||||
the following subset of configution flags:
|
||||
|
||||
<p>SQLITE_CONFIG_SINGLETHREAD
|
||||
SQLITE_CONFIG_MULTITHREAD
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.sqlite.jni.capi;
|
||||
classes which have a call() method implementing some specific
|
||||
callback interface on behalf of the C library.
|
||||
|
||||
<p>Unless very explicitly documented otherwise, callbacks must
|
||||
<p>Unless very explicitely documented otherwise, callbacks must
|
||||
never throw. Any which do throw but should not might trigger debug
|
||||
output regarding the error, but the exception will not be
|
||||
propagated. For callback interfaces which support returning error
|
||||
|
||||
@@ -20,7 +20,7 @@ public interface PrepareMultiCallback extends CallbackProxy {
|
||||
|
||||
/**
|
||||
Gets passed a sqlite3_stmt which it may handle in arbitrary ways,
|
||||
transferring ownership of it to this function.
|
||||
transfering ownership of it to this function.
|
||||
|
||||
sqlite3_prepare_multi() will _not_ finalize st - it is up
|
||||
to the call() implementation how st is handled.
|
||||
|
||||
@@ -264,7 +264,7 @@ public class SQLTester {
|
||||
threw = true;
|
||||
outln("🔥EXCEPTION: ",e.getClass().getSimpleName(),": ",e.getMessage());
|
||||
++nAbortedScript;
|
||||
if( keepGoing ) outln("Continuing anyway because of the keep-going option.");
|
||||
if( keepGoing ) outln("Continuing anyway becaure of the keep-going option.");
|
||||
else if( e.isFatal() ) throw e;
|
||||
}finally{
|
||||
final long timeEnd = System.currentTimeMillis();
|
||||
|
||||
@@ -101,7 +101,7 @@ interpreter is in a "verbose" mode, the interpreter might choose to emit
|
||||
an informational message along the lines of "test script NAME abandoned
|
||||
due to unsupported command: --whatever".
|
||||
|
||||
The initial implementation will only recognize a few commands. Other
|
||||
The initial implemention will only recognize a few commands. Other
|
||||
commands may be added later. The following is the initial set of
|
||||
commands:
|
||||
|
||||
|
||||
@@ -661,7 +661,7 @@ public final class Sqlite implements AutoCloseable {
|
||||
}
|
||||
|
||||
/**
|
||||
Equivalent to prepareMulti(X,prepFlags,visitor), where X is
|
||||
Equivallent to prepareMulti(X,prepFlags,visitor), where X is
|
||||
sql.getBytes(StandardCharsets.UTF_8).
|
||||
*/
|
||||
public void prepareMulti(String sql, int prepFlags, PrepareMulti visitor){
|
||||
|
||||
+1
-1
@@ -570,7 +570,7 @@ struct FreelistEntry {
|
||||
/*
|
||||
** A snapshot of a database. A snapshot contains all the information required
|
||||
** to read or write a database file on disk. See the description of struct
|
||||
** Database below for further details.
|
||||
** Database below for futher details.
|
||||
*/
|
||||
struct Snapshot {
|
||||
Database *pDatabase; /* Database this snapshot belongs to */
|
||||
|
||||
+1
-1
@@ -169,7 +169,7 @@
|
||||
** The argument to this macro must be of type u32. On a little-endian
|
||||
** architecture, it returns the u32 value that results from interpreting
|
||||
** the 4 bytes as a big-endian value. On a big-endian architecture, it
|
||||
** returns the value that would be produced by interpreting the 4 bytes
|
||||
** returns the value that would be produced by intepreting the 4 bytes
|
||||
** of the input value as a little-endian integer.
|
||||
*/
|
||||
#define BYTESWAP32(x) ( \
|
||||
|
||||
+2
-2
@@ -793,7 +793,7 @@ void lsmFsClose(FileSystem *pFS){
|
||||
**
|
||||
** This function returns a pointer to an object that can be linked into
|
||||
** the list described above. The returned object now 'owns' the database
|
||||
** file descriptor, so that when the FileSystem object is destroyed, it
|
||||
** file descriptr, so that when the FileSystem object is destroyed, it
|
||||
** will not be closed.
|
||||
**
|
||||
** This function may be called at most once in the life-time of a
|
||||
@@ -2293,7 +2293,7 @@ int lsmFsMetaPageGet(
|
||||
);
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
/* pPg->aData causes an uninitialized access via a downstream write().
|
||||
/* pPg->aData causes an uninitialized access via a downstreadm write().
|
||||
After discussion on this list, this memory should not, for performance
|
||||
reasons, be memset. However, tracking down "real" misuse is more
|
||||
difficult with this "false" positive, so it is set when NDEBUG.
|
||||
|
||||
+1
-1
@@ -758,7 +758,7 @@ void lsmLogTell(
|
||||
}
|
||||
|
||||
/*
|
||||
** Seek (rewind) back to the log file offset stored by an earlier call to
|
||||
** Seek (rewind) back to the log file offset stored by an ealier call to
|
||||
** lsmLogTell() in *pMark.
|
||||
*/
|
||||
void lsmLogSeek(
|
||||
|
||||
@@ -2652,7 +2652,7 @@ int lsmSortedLoadFreelist(
|
||||
void **ppVal, /* OUT: Blob containing LSM free-list */
|
||||
int *pnVal /* OUT: Size of *ppVal blob in bytes */
|
||||
){
|
||||
MultiCursor *pCsr; /* Cursor used to retrieve free-list */
|
||||
MultiCursor *pCsr; /* Cursor used to retreive free-list */
|
||||
int rc = LSM_OK; /* Return Code */
|
||||
|
||||
assert( pDb->pWorker );
|
||||
@@ -2764,7 +2764,7 @@ static int mcursorLocationOk(MultiCursor *pCsr, int bDeleteOk){
|
||||
}
|
||||
|
||||
/* If the cursor points to a system key (free-list entry), and the
|
||||
** CURSOR_IGNORE_SYSTEM flag is set, skip this entry. */
|
||||
** CURSOR_IGNORE_SYSTEM flag is set, skip thie entry. */
|
||||
if( (pCsr->flags & CURSOR_IGNORE_SYSTEM) && rtTopic(eType)!=0 ){
|
||||
return 0;
|
||||
}
|
||||
@@ -3586,7 +3586,7 @@ static int mergeWorkerBtreeWrite(
|
||||
Hierarchy *p = &pMW->hier;
|
||||
lsm_db *pDb = pMW->pDb; /* Database handle */
|
||||
int rc = LSM_OK; /* Return Code */
|
||||
int iLevel; /* Level of b-tree hierarchy to write to */
|
||||
int iLevel; /* Level of b-tree hierachy to write to */
|
||||
int nData; /* Size of aData[] in bytes */
|
||||
u8 *aData; /* Page data for level iLevel */
|
||||
int iOff; /* Offset on b-tree page to write record to */
|
||||
|
||||
+2
-2
@@ -482,9 +482,9 @@ struct amatch_rule {
|
||||
amatch_rule *pNext; /* Next rule in order of increasing rCost */
|
||||
char *zFrom; /* Transform from (a string from user input) */
|
||||
amatch_cost rCost; /* Cost of this transformation */
|
||||
amatch_langid iLang; /* The language to which this rule belongs */
|
||||
amatch_langid iLang; /* The langauge to which this rule belongs */
|
||||
amatch_len nFrom, nTo; /* Length of the zFrom and zTo strings */
|
||||
char zTo[4]; /* Transform to V.W value (extra space appended) */
|
||||
char zTo[4]; /* Tranform to V.W value (extra space appended) */
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
** USAGE EXAMPLES:
|
||||
**
|
||||
** Show the table btrees in a schema order with the tables with the most
|
||||
** rows occurring first:
|
||||
** rows occuring first:
|
||||
**
|
||||
** SELECT name, nEntry
|
||||
** FROM sqlite_btreeinfo
|
||||
|
||||
@@ -41,11 +41,6 @@ SQLITE_EXTENSION_INIT1
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
#ifndef IsAlnum
|
||||
#define IsAlnum(X) isalnum((unsigned char)X)
|
||||
#endif
|
||||
|
||||
|
||||
/* completion_vtab is a subclass of sqlite3_vtab which will
|
||||
** serve as the underlying representation of a completion virtual table
|
||||
*/
|
||||
@@ -382,7 +377,7 @@ static int completionFilter(
|
||||
}
|
||||
if( pCur->zLine!=0 && pCur->zPrefix==0 ){
|
||||
int i = pCur->nLine;
|
||||
while( i>0 && (IsAlnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
|
||||
while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
|
||||
i--;
|
||||
}
|
||||
pCur->nPrefix = pCur->nLine - i;
|
||||
|
||||
+1
-1
@@ -315,7 +315,7 @@ typedef struct CsvTable {
|
||||
} CsvTable;
|
||||
|
||||
/* Allowed values for tstFlags */
|
||||
#define CSVTEST_FIDX 0x0001 /* Pretend that constrained search cost less*/
|
||||
#define CSVTEST_FIDX 0x0001 /* Pretend that constrained searchs cost less*/
|
||||
|
||||
/* A cursor for the CSV virtual table */
|
||||
typedef struct CsvCursor {
|
||||
|
||||
+2
-5
@@ -27,9 +27,6 @@ SQLITE_EXTENSION_INIT1
|
||||
# define UNUSED_PARAMETER(X) (void)(X)
|
||||
#endif
|
||||
|
||||
#ifndef IsSpace
|
||||
#define IsSpace(X) isspace((unsigned char)X)
|
||||
#endif
|
||||
|
||||
/* A decimal object */
|
||||
typedef struct Decimal Decimal;
|
||||
@@ -79,7 +76,7 @@ static Decimal *decimalNewFromText(const char *zIn, int n){
|
||||
p->nFrac = 0;
|
||||
p->a = sqlite3_malloc64( n+1 );
|
||||
if( p->a==0 ) goto new_from_text_failed;
|
||||
for(i=0; IsSpace(zIn[i]); i++){}
|
||||
for(i=0; isspace(zIn[i]); i++){}
|
||||
if( zIn[i]=='-' ){
|
||||
p->sign = 1;
|
||||
i++;
|
||||
@@ -734,7 +731,7 @@ static void decimalSubFunc(
|
||||
decimal_free(pB);
|
||||
}
|
||||
|
||||
/* Aggregate function: decimal_sum(X)
|
||||
/* Aggregate funcion: decimal_sum(X)
|
||||
**
|
||||
** Works like sum() except that it uses decimal arithmetic for unlimited
|
||||
** precision.
|
||||
|
||||
+3
-3
@@ -68,7 +68,7 @@
|
||||
** AND distance<200;
|
||||
**
|
||||
** This first query outputs the string "abcdefg" and all strings that
|
||||
** can be derived from that string by applying the specified transformations.
|
||||
** can be derived from that string by appling the specified transformations.
|
||||
** The strings are output together with their total transformation cost
|
||||
** (called "distance") and appear in order of increasing cost. No string
|
||||
** is output more than once. If there are multiple ways to transform the
|
||||
@@ -97,7 +97,7 @@
|
||||
** LIMIT 20
|
||||
**
|
||||
** The query above gives the 20 closest words to the $word being tested.
|
||||
** (Note that for good performance, the vocabulary.w column should be
|
||||
** (Note that for good performance, the vocubulary.w column should be
|
||||
** indexed.)
|
||||
**
|
||||
** A similar query can be used to find all words in the dictionary that
|
||||
@@ -207,7 +207,7 @@ struct fuzzer_rule {
|
||||
** Every stem is added to a hash table as it is output. Generation of
|
||||
** duplicate stems is suppressed.
|
||||
**
|
||||
** Active stems (those that might generate new outputs) are kept on a linked
|
||||
** Active stems (those that might generate new outputs) are kepts on a linked
|
||||
** list sorted by increasing cost. The cost is the sum of rBaseCost and
|
||||
** pRule->rCost.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@
|
||||
** WITH c(name,bin) AS (VALUES
|
||||
** ('minimum positive value', x'0000000000000001'),
|
||||
** ('maximum subnormal value', x'000fffffffffffff'),
|
||||
** ('minimum positive normal value', x'0010000000000000'),
|
||||
** ('mininum positive nornal value', x'0010000000000000'),
|
||||
** ('maximum value', x'7fefffffffffffff'))
|
||||
** SELECT c.name, decimal_mul(ieee754_mantissa(c.bin),pow2.v)
|
||||
** FROM pow2, c WHERE pow2.x=ieee754_exponent(c.bin);
|
||||
|
||||
@@ -286,7 +286,7 @@ static const unsigned char sqlite3CtypeMap[256] = {
|
||||
#define TK_VARIABLE TK_LITERAL
|
||||
#define TK_BLOB TK_LITERAL
|
||||
|
||||
/* Disable nuisance warnings about case fall-through */
|
||||
/* Disable nuisence warnings about case fall-through */
|
||||
#if !defined(deliberate_fall_through) && defined(__GCC__) && __GCC__>=7
|
||||
# define deliberate_fall_through __attribute__((fallthrough));
|
||||
#else
|
||||
|
||||
@@ -205,7 +205,7 @@ static int percentBinarySearch(Percentile *p, double y, int bExact){
|
||||
/*
|
||||
** Generate an error for a percentile function.
|
||||
**
|
||||
** The error format string must have exactly one occurrence of "%%s()"
|
||||
** The error format string must have exactly one occurrance of "%%s()"
|
||||
** (with two '%' characters). That substring will be replaced by the name
|
||||
** of the function.
|
||||
*/
|
||||
|
||||
+23
-50
@@ -60,7 +60,8 @@
|
||||
** step HIDDEN
|
||||
** );
|
||||
**
|
||||
** The virtual table also has a rowid which is an alias for the value.
|
||||
** The virtual table also has a rowid, logically equivalent to n+1 where
|
||||
** "n" is the ascending integer in the aforesaid production definition.
|
||||
**
|
||||
** Function arguments in queries against this virtual table are translated
|
||||
** into equality constraints against successive hidden columns. In other
|
||||
@@ -115,7 +116,6 @@ SQLITE_EXTENSION_INIT1
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/*
|
||||
@@ -139,7 +139,7 @@ static sqlite3_int64 genSeqMember(
|
||||
smBase += (mxI64 - mxI64/2) * smStep;
|
||||
}
|
||||
/* Under UBSAN (or on 1's complement machines), must do this last term
|
||||
* in steps to avoid the dreaded (and harmless) signed multiply overflow. */
|
||||
* in steps to avoid the dreaded (and harmless) signed multiply overlow. */
|
||||
if( ix>=2 ){
|
||||
sqlite3_int64 ix2 = (sqlite3_int64)ix/2;
|
||||
smBase += ix2*smStep;
|
||||
@@ -276,7 +276,6 @@ static int seriesConnect(
|
||||
int rc;
|
||||
|
||||
/* Column numbers */
|
||||
#define SERIES_COLUMN_ROWID (-1)
|
||||
#define SERIES_COLUMN_VALUE 0
|
||||
#define SERIES_COLUMN_START 1
|
||||
#define SERIES_COLUMN_STOP 2
|
||||
@@ -364,11 +363,13 @@ static int seriesColumn(
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The rowid is the same as the value.
|
||||
** Return the rowid for the current row, logically equivalent to n+1 where
|
||||
** "n" is the ascending integer in the aforesaid production definition.
|
||||
*/
|
||||
static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
series_cursor *pCur = (series_cursor*)cur;
|
||||
*pRowid = pCur->ss.iValueNow;
|
||||
sqlite3_uint64 n = pCur->ss.uSeqIndexNow;
|
||||
*pRowid = (sqlite3_int64)((n<LARGEST_UINT64)? n+1 : 0);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -481,52 +482,25 @@ static int seriesFilter(
|
||||
** constraints on the "value" column.
|
||||
*/
|
||||
if( idxNum & 0x0080 ){
|
||||
if( sqlite3_value_numeric_type(argv[i])==SQLITE_FLOAT ){
|
||||
double r = sqlite3_value_double(argv[i++]);
|
||||
if( r==ceil(r) ){
|
||||
iMin = iMax = (sqlite3_int64)r;
|
||||
}else{
|
||||
returnNoRows = 1;
|
||||
}
|
||||
}else{
|
||||
iMin = iMax = sqlite3_value_int64(argv[i++]);
|
||||
}
|
||||
iMin = iMax = sqlite3_value_int64(argv[i++]);
|
||||
}else{
|
||||
if( idxNum & 0x0300 ){
|
||||
if( sqlite3_value_numeric_type(argv[i])==SQLITE_FLOAT ){
|
||||
double r = sqlite3_value_double(argv[i++]);
|
||||
if( idxNum & 0x0200 && r==ceil(r) ){
|
||||
iMin = (sqlite3_int64)ceil(r+1.0);
|
||||
iMin = sqlite3_value_int64(argv[i++]);
|
||||
if( idxNum & 0x0200 ){
|
||||
if( iMin==LARGEST_INT64 ){
|
||||
returnNoRows = 1;
|
||||
}else{
|
||||
iMin = (sqlite3_int64)ceil(r);
|
||||
}
|
||||
}else{
|
||||
iMin = sqlite3_value_int64(argv[i++]);
|
||||
if( idxNum & 0x0200 ){
|
||||
if( iMin==LARGEST_INT64 ){
|
||||
returnNoRows = 1;
|
||||
}else{
|
||||
iMin++;
|
||||
}
|
||||
iMin++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( idxNum & 0x3000 ){
|
||||
if( sqlite3_value_numeric_type(argv[i])==SQLITE_FLOAT ){
|
||||
double r = sqlite3_value_double(argv[i++]);
|
||||
if( (idxNum & 0x2000)!=0 && r==floor(r) ){
|
||||
iMax = (sqlite3_int64)(r-1.0);
|
||||
iMax = sqlite3_value_int64(argv[i++]);
|
||||
if( idxNum & 0x2000 ){
|
||||
if( iMax==SMALLEST_INT64 ){
|
||||
returnNoRows = 1;
|
||||
}else{
|
||||
iMax = (sqlite3_int64)floor(r);
|
||||
}
|
||||
}else{
|
||||
iMax = sqlite3_value_int64(argv[i++]);
|
||||
if( idxNum & 0x2000 ){
|
||||
if( iMax==SMALLEST_INT64 ){
|
||||
returnNoRows = 1;
|
||||
}else{
|
||||
iMax--;
|
||||
}
|
||||
iMax--;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -545,7 +519,8 @@ static int seriesFilter(
|
||||
pCur->ss.iBase += ((d+szStep-1)/szStep)*szStep;
|
||||
}
|
||||
if( pCur->ss.iTerm>iMax ){
|
||||
pCur->ss.iTerm = iMax;
|
||||
sqlite3_uint64 d = pCur->ss.iTerm - iMax;
|
||||
pCur->ss.iTerm -= ((d+szStep-1)/szStep)*szStep;
|
||||
}
|
||||
}else{
|
||||
sqlite3_int64 szStep = -pCur->ss.iStep;
|
||||
@@ -555,7 +530,8 @@ static int seriesFilter(
|
||||
pCur->ss.iBase -= ((d+szStep-1)/szStep)*szStep;
|
||||
}
|
||||
if( pCur->ss.iTerm<iMin ){
|
||||
pCur->ss.iTerm = iMin;
|
||||
sqlite3_uint64 d = iMin - pCur->ss.iTerm;
|
||||
pCur->ss.iTerm += ((d+szStep-1)/szStep)*szStep;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -683,10 +659,7 @@ static int seriesBestIndex(
|
||||
continue;
|
||||
}
|
||||
if( pConstraint->iColumn<SERIES_COLUMN_START ){
|
||||
if( (pConstraint->iColumn==SERIES_COLUMN_VALUE ||
|
||||
pConstraint->iColumn==SERIES_COLUMN_ROWID)
|
||||
&& pConstraint->usable
|
||||
){
|
||||
if( pConstraint->iColumn==SERIES_COLUMN_VALUE && pConstraint->usable ){
|
||||
switch( op ){
|
||||
case SQLITE_INDEX_CONSTRAINT_EQ:
|
||||
case SQLITE_INDEX_CONSTRAINT_IS: {
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@
|
||||
**
|
||||
** typeof(Y)='blob' The hash is taken over prefix "Bnnn:" followed
|
||||
** by the binary content of the blob. The "nnn"
|
||||
** in the prefix is the minimum-length decimal
|
||||
** in the prefix is the mimimum-length decimal
|
||||
** representation of the byte-length of the blob.
|
||||
**
|
||||
** According to the rules above, all of the following SELECT statements
|
||||
|
||||
+1
-1
@@ -346,7 +346,7 @@ totype_atof_calc:
|
||||
/* store the result */
|
||||
*pResult = result;
|
||||
|
||||
/* return true if number and no extra non-whitespace characters after */
|
||||
/* return true if number and no extra non-whitespace chracters after */
|
||||
return z>=zEnd && nDigits>0 && eValid && nonNum==0;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
** of digits compare in numeric order.
|
||||
**
|
||||
** * Leading zeros are handled properly, in the sense that
|
||||
** they do not mess of the magnitude comparison of embedded
|
||||
** they do not mess of the maginitude comparison of embedded
|
||||
** strings of digits. "x00123y" is equal to "x123y".
|
||||
**
|
||||
** * Only unsigned integers are recognized. Plus and minus
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ SQLITE_EXTENSION_INIT1
|
||||
** To use this module, first compile it as a loadable extension. See
|
||||
** https://www.sqlite.org/loadext.html#build for compilations instructions.
|
||||
**
|
||||
** After compiling, load this extension, then open database connections to be
|
||||
** After compliing, load this extension, then open database connections to be
|
||||
** measured. Query usages status using the vfsstat virtual table:
|
||||
**
|
||||
** SELECT * FROM vfsstat;
|
||||
|
||||
+1
-1
@@ -120,7 +120,7 @@
|
||||
**
|
||||
** Individual APIs can be enabled or disabled by name, with or without
|
||||
** the initial "x" character. For example, to set up for tracing lock
|
||||
** primitives only:
|
||||
** primatives only:
|
||||
**
|
||||
** PRAGMA vfstrace('-all, +Lock,Unlock,ShmLock');
|
||||
**
|
||||
|
||||
+1
-1
@@ -425,7 +425,7 @@ static int vtshimRollbackTo(sqlite3_vtab *pBase, int n){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* The destructor function for a disposable module */
|
||||
/* The destructor function for a disposible module */
|
||||
static void vtshimAuxDestructor(void *pXAux){
|
||||
vtshim_aux *pAux = (vtshim_aux*)pXAux;
|
||||
assert( pAux->pAllVtab==0 );
|
||||
|
||||
@@ -171,7 +171,7 @@ foreach {ttt state} {
|
||||
# * Set the state db permissions to the same as those on the db file.
|
||||
#
|
||||
db close
|
||||
if {$::tcl_platform(platform) eq "unix"} {
|
||||
if {$::tcl_platform(platform)=="unix"} {
|
||||
forcedelete test.db
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
@@ -4822,7 +4822,7 @@ static int rbuVfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
||||
|
||||
/* If this is an RBU vacuum operation and this is the target database,
|
||||
** pretend that it has at least one page. Otherwise, SQLite will not
|
||||
** check for the existence of a *-wal file. rbuVfsRead() contains
|
||||
** check for the existance of a *-wal file. rbuVfsRead() contains
|
||||
** similar logic. */
|
||||
if( rc==SQLITE_OK && *pSize==0
|
||||
&& p->pRbu && rbuIsVacuum(p->pRbu)
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
**
|
||||
** "RBU" stands for "Resumable Bulk Update". As in a large database update
|
||||
** transmitted via a wireless network to a mobile device. A transaction
|
||||
** applied using this extension is hence referred to as an "RBU update".
|
||||
** applied using this extension is hence refered to as an "RBU update".
|
||||
**
|
||||
**
|
||||
** LIMITATIONS
|
||||
@@ -346,7 +346,7 @@ SQLITE_API sqlite3rbu *sqlite3rbu_open(
|
||||
** the next call to sqlite3rbu_vacuum() opens a handle that starts a
|
||||
** new RBU vacuum operation.
|
||||
**
|
||||
** As with sqlite3rbu_open(), Zipvfs users should refer to the comment
|
||||
** As with sqlite3rbu_open(), Zipvfs users should rever to the comment
|
||||
** describing the sqlite3rbu_create_vfs() API function below for
|
||||
** a description of the complications associated with using RBU with
|
||||
** zipvfs databases.
|
||||
@@ -442,7 +442,7 @@ SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *pRbu);
|
||||
**
|
||||
** If the RBU update has been completely applied, mark the RBU database
|
||||
** as fully applied. Otherwise, assuming no error has occurred, save the
|
||||
** current state of the RBU update application to the RBU database.
|
||||
** current state of the RBU update appliation to the RBU database.
|
||||
**
|
||||
** If an error has already occurred as part of an sqlite3rbu_step()
|
||||
** or sqlite3rbu_open() call, or if one occurs within this function, an
|
||||
|
||||
+2
-2
@@ -139,7 +139,7 @@ static int SQLITE_TCLAPI test_sqlite3rbu_cmd(
|
||||
}else{
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
||||
if( zErrmsg ){
|
||||
Tcl_AppendResult(interp, " - ", zErrmsg, NULL);
|
||||
Tcl_AppendResult(interp, " - ", zErrmsg, 0);
|
||||
sqlite3_free(zErrmsg);
|
||||
}
|
||||
ret = TCL_ERROR;
|
||||
@@ -399,7 +399,7 @@ static int SQLITE_TCLAPI test_sqlite3rbu_internal_test(
|
||||
|
||||
db = sqlite3rbu_db(0, 0);
|
||||
if( db!=0 ){
|
||||
Tcl_AppendResult(interp, "sqlite3rbu_db(0, 0)!=0", NULL);
|
||||
Tcl_AppendResult(interp, "sqlite3rbu_db(0, 0)!=0", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ do_test 1.2 {
|
||||
} [list {*}{
|
||||
{BEGIN}
|
||||
{PRAGMA writable_schema = on}
|
||||
{PRAGMA foreign_keys = off}
|
||||
{PRAGMA encoding = 'UTF-8'}
|
||||
{PRAGMA page_size = '1024'}
|
||||
{PRAGMA auto_vacuum = '0'}
|
||||
@@ -68,7 +67,6 @@ do_test 1.4 {
|
||||
} [list {*}{
|
||||
{BEGIN}
|
||||
{PRAGMA writable_schema = on}
|
||||
{PRAGMA foreign_keys = off}
|
||||
{PRAGMA encoding = 'UTF-8'}
|
||||
{PRAGMA page_size = '1024'}
|
||||
{PRAGMA auto_vacuum = '0'}
|
||||
|
||||
@@ -33,16 +33,6 @@ typedef unsigned int u32;
|
||||
typedef unsigned char u8;
|
||||
typedef sqlite3_int64 i64;
|
||||
|
||||
/*
|
||||
** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
|
||||
** to avoid complaints from -fsanitize=strict-bounds.
|
||||
*/
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
# define FLEXARRAY
|
||||
#else
|
||||
# define FLEXARRAY 1
|
||||
#endif
|
||||
|
||||
typedef struct RecoverTable RecoverTable;
|
||||
typedef struct RecoverColumn RecoverColumn;
|
||||
|
||||
@@ -150,12 +140,9 @@ struct RecoverColumn {
|
||||
typedef struct RecoverBitmap RecoverBitmap;
|
||||
struct RecoverBitmap {
|
||||
i64 nPg; /* Size of bitmap */
|
||||
u32 aElem[FLEXARRAY]; /* Array of 32-bit bitmasks */
|
||||
u32 aElem[1]; /* Array of 32-bit bitmasks */
|
||||
};
|
||||
|
||||
/* Size in bytes of a RecoverBitmap object sufficient to cover 32 pages */
|
||||
#define SZ_RECOVERBITMAP_32 (16)
|
||||
|
||||
/*
|
||||
** State variables (part of the sqlite3_recover structure) used while
|
||||
** recovering data for tables identified in the recovered schema (state
|
||||
@@ -395,7 +382,7 @@ static int recoverError(
|
||||
*/
|
||||
static RecoverBitmap *recoverBitmapAlloc(sqlite3_recover *p, i64 nPg){
|
||||
int nElem = (nPg+1+31) / 32;
|
||||
int nByte = SZ_RECOVERBITMAP_32 + nElem*sizeof(u32);
|
||||
int nByte = sizeof(RecoverBitmap) + nElem*sizeof(u32);
|
||||
RecoverBitmap *pRet = (RecoverBitmap*)recoverMalloc(p, nByte);
|
||||
|
||||
if( pRet ){
|
||||
@@ -2587,53 +2574,37 @@ static void recoverUninstallWrapper(sqlite3_recover *p){
|
||||
static void recoverStep(sqlite3_recover *p){
|
||||
assert( p && p->errCode==SQLITE_OK );
|
||||
switch( p->eState ){
|
||||
case RECOVER_STATE_INIT: {
|
||||
int bUseWrapper = 1;
|
||||
case RECOVER_STATE_INIT:
|
||||
/* This is the very first call to sqlite3_recover_step() on this object.
|
||||
*/
|
||||
recoverSqlCallback(p, "BEGIN");
|
||||
recoverSqlCallback(p, "PRAGMA writable_schema = on");
|
||||
recoverSqlCallback(p, "PRAGMA foreign_keys = off");
|
||||
|
||||
recoverEnterMutex();
|
||||
recoverInstallWrapper(p);
|
||||
|
||||
/* Open the output database. And register required virtual tables and
|
||||
** user functions with the new handle. */
|
||||
recoverOpenOutput(p);
|
||||
|
||||
/* Attempt to open a transaction and read page 1 of the input database.
|
||||
** Two attempts may be made - one with a wrapper installed to ensure
|
||||
** that the database header is sane, and then if that attempt returns
|
||||
** SQLITE_NOTADB, then again with no wrapper. The second attempt is
|
||||
** required for encrypted databases. */
|
||||
if( p->errCode==SQLITE_OK ){
|
||||
do{
|
||||
p->errCode = SQLITE_OK;
|
||||
if( bUseWrapper ) recoverInstallWrapper(p);
|
||||
|
||||
/* Open a transaction on the input database. */
|
||||
sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);
|
||||
recoverExec(p, p->dbIn, "PRAGMA writable_schema = on");
|
||||
recoverExec(p, p->dbIn, "BEGIN");
|
||||
if( p->errCode==SQLITE_OK ) p->bCloseTransaction = 1;
|
||||
recoverExec(p, p->dbIn, "SELECT 1 FROM sqlite_schema");
|
||||
recoverTransferSettings(p);
|
||||
recoverOpenRecovery(p);
|
||||
recoverCacheSchema(p);
|
||||
|
||||
if( bUseWrapper ) recoverUninstallWrapper(p);
|
||||
}while( p->errCode==SQLITE_NOTADB
|
||||
&& (bUseWrapper--)
|
||||
&& SQLITE_OK==sqlite3_exec(p->dbIn, "ROLLBACK", 0, 0, 0)
|
||||
);
|
||||
}
|
||||
/* Open transactions on both the input and output databases. */
|
||||
sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);
|
||||
recoverExec(p, p->dbIn, "PRAGMA writable_schema = on");
|
||||
recoverExec(p, p->dbIn, "BEGIN");
|
||||
if( p->errCode==SQLITE_OK ) p->bCloseTransaction = 1;
|
||||
recoverExec(p, p->dbIn, "SELECT 1 FROM sqlite_schema");
|
||||
recoverTransferSettings(p);
|
||||
recoverOpenRecovery(p);
|
||||
recoverCacheSchema(p);
|
||||
|
||||
recoverUninstallWrapper(p);
|
||||
recoverLeaveMutex();
|
||||
|
||||
recoverExec(p, p->dbOut, "BEGIN");
|
||||
|
||||
recoverWriteSchema1(p);
|
||||
p->eState = RECOVER_STATE_WRITING;
|
||||
break;
|
||||
}
|
||||
|
||||
case RECOVER_STATE_WRITING: {
|
||||
if( p->w1.pTbls==0 ){
|
||||
|
||||
@@ -58,7 +58,7 @@ static int xSqlCallback(void *pSqlArg, const char *zSql){
|
||||
static int getDbPointer(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), NULL);
|
||||
Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(pObj), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
*pDb = *(sqlite3 **)info.objClientData;
|
||||
|
||||
@@ -110,7 +110,7 @@ static int cidxConnect(
|
||||
" current_key TEXT," /* SQLite quote() text of key values */
|
||||
" index_name HIDDEN," /* IN: name of the index being scanned */
|
||||
" after_key HIDDEN," /* IN: Start scanning after this key */
|
||||
" scanner_sql HIDDEN" /* debugging info: SQL used for scanner */
|
||||
" scanner_sql HIDDEN" /* debuggingn info: SQL used for scanner */
|
||||
")"
|
||||
);
|
||||
pRet = cidxMalloc(&rc, sizeof(CidxTable));
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ and query r-tree structures using ordinary SQL statements.
|
||||
3 and 11. Unlike regular SQLite tables, r-tree tables are strongly
|
||||
typed.
|
||||
|
||||
The leftmost column is always the primary key and contains 64-bit
|
||||
The leftmost column is always the pimary key and contains 64-bit
|
||||
integer values. Each subsequent column contains a 32-bit real
|
||||
value. For each pair of real values, the first (leftmost) must be
|
||||
less than or equal to the second. R-tree tables may be
|
||||
|
||||
+2
-2
@@ -771,7 +771,7 @@ static void geopolyBBoxFinal(
|
||||
** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2).
|
||||
** Returns:
|
||||
**
|
||||
** +2 x0,y0 is on the line segment
|
||||
** +2 x0,y0 is on the line segement
|
||||
**
|
||||
** +1 x0,y0 is beneath line segment
|
||||
**
|
||||
@@ -877,7 +877,7 @@ static void geopolyWithinFunc(
|
||||
sqlite3_free(p2);
|
||||
}
|
||||
|
||||
/* Objects used by the overlap algorithm. */
|
||||
/* Objects used by the overlap algorihm. */
|
||||
typedef struct GeoEvent GeoEvent;
|
||||
typedef struct GeoSegment GeoSegment;
|
||||
typedef struct GeoOverlap GeoOverlap;
|
||||
|
||||
+5
-16
@@ -94,14 +94,6 @@ typedef unsigned int u32;
|
||||
# define ALWAYS(X) (X)
|
||||
# define NEVER(X) (X)
|
||||
#endif
|
||||
#ifndef offsetof
|
||||
#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
|
||||
#endif
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
# define FLEXARRAY
|
||||
#else
|
||||
# define FLEXARRAY 1
|
||||
#endif
|
||||
#endif /* !defined(SQLITE_AMALGAMATION) */
|
||||
|
||||
/* Macro to check for 4-byte alignment. Only used inside of assert() */
|
||||
@@ -422,13 +414,9 @@ struct RtreeMatchArg {
|
||||
RtreeGeomCallback cb; /* Info about the callback functions */
|
||||
int nParam; /* Number of parameters to the SQL function */
|
||||
sqlite3_value **apSqlParam; /* Original SQL parameter values */
|
||||
RtreeDValue aParam[FLEXARRAY]; /* Values for parameters to the SQL function */
|
||||
RtreeDValue aParam[1]; /* Values for parameters to the SQL function */
|
||||
};
|
||||
|
||||
/* Size of an RtreeMatchArg object with N parameters */
|
||||
#define SZ_RTREEMATCHARG(N) \
|
||||
(offsetof(RtreeMatchArg,aParam)+(N)*sizeof(RtreeDValue))
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(x,y) ((x) < (y) ? (y) : (x))
|
||||
#endif
|
||||
@@ -2117,7 +2105,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the N-dimensional volume of the cell stored in *p.
|
||||
** Return the N-dimensional volumn of the cell stored in *p.
|
||||
*/
|
||||
static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
|
||||
RtreeDValue area = (RtreeDValue)1;
|
||||
@@ -3883,7 +3871,7 @@ static sqlite3_stmt *rtreeCheckPrepare(
|
||||
/*
|
||||
** The second and subsequent arguments to this function are a printf()
|
||||
** style format string and arguments. This function formats the string and
|
||||
** appends it to the report being accumulated in pCheck.
|
||||
** appends it to the report being accumuated in pCheck.
|
||||
*/
|
||||
static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){
|
||||
va_list ap;
|
||||
@@ -4381,7 +4369,8 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
|
||||
sqlite3_int64 nBlob;
|
||||
int memErr = 0;
|
||||
|
||||
nBlob = SZ_RTREEMATCHARG(nArg) + nArg*sizeof(sqlite3_value*);
|
||||
nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue)
|
||||
+ nArg*sizeof(sqlite3_value*);
|
||||
pBlob = (RtreeMatchArg *)sqlite3_malloc64(nBlob);
|
||||
if( !pBlob ){
|
||||
sqlite3_result_error_nomem(ctx);
|
||||
|
||||
@@ -116,7 +116,7 @@ set testprefix rtreedoc2-2
|
||||
# 1-dimensional R*Tree, 4 for a 2-dimensional R*Tree, 6 for a
|
||||
# 3-dimensional R*Tree, and so forth.
|
||||
#
|
||||
# The second argument referred to above is the length of the list passed
|
||||
# The second argument refered to above is the length of the list passed
|
||||
# as the 3rd parameter to the Tcl script.
|
||||
#
|
||||
do_execsql_test 1.0 {
|
||||
|
||||
Executable → Regular
+1
-117
@@ -684,124 +684,8 @@ do_test $tn.14.4 {
|
||||
list [catch {sqlite3session_config invalid 123} msg] $msg
|
||||
} {1 SQLITE_MISUSE}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test $tn.15.0 {
|
||||
CREATE TABLE records(
|
||||
idx INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
tbl TEXT NOT NULL,
|
||||
pk TEXT NOT NULL,
|
||||
value TEXT,
|
||||
UNIQUE(tbl, pk)
|
||||
);
|
||||
|
||||
CREATE TABLE changes(
|
||||
idx INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
tbl TEXT NOT NULL,
|
||||
pk TEXT NOT NULL,
|
||||
op TEXT DEFAULT ('='),
|
||||
path TEXT DEFAULT ('$'),
|
||||
value TEXT,
|
||||
UNIQUE(tbl, pk)
|
||||
);
|
||||
|
||||
CREATE TRIGGER changes_after_insert
|
||||
AFTER INSERT ON changes
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
INSERT INTO records(tbl, pk, value)
|
||||
VALUES (NEW.tbl, NEW.pk, NEW.value)
|
||||
ON CONFLICT(tbl, pk) DO UPDATE SET value = NEW.value;
|
||||
END;
|
||||
|
||||
CREATE VIEW data_view AS
|
||||
SELECT *, '=' AS op, '$' AS path FROM records
|
||||
WHERE tbl = 'data';
|
||||
|
||||
CREATE TRIGGER data_insert
|
||||
INSTEAD OF INSERT ON data_view
|
||||
BEGIN
|
||||
INSERT INTO changes(tbl, pk, op, path, value)
|
||||
VALUES (NEW.tbl, NEW.pk, NEW.op, NEW.path, NEW.value);
|
||||
END;
|
||||
|
||||
CREATE TRIGGER data_update
|
||||
INSTEAD OF UPDATE ON data_view
|
||||
BEGIN
|
||||
INSERT INTO changes(tbl, pk, op, path, value)
|
||||
VALUES (NEW.tbl, NEW.pk, NEW.op, NEW.path, NEW.value);
|
||||
END;
|
||||
|
||||
CREATE TRIGGER data_delete
|
||||
INSTEAD OF DELETE ON data_view
|
||||
BEGIN
|
||||
INSERT INTO changes(tbl, pk, op, path, value)
|
||||
VALUES (NEW.tbl, NEW.pk, NEW.op, NEW.path, NEW.value);
|
||||
END;
|
||||
}
|
||||
|
||||
do_test $tn.15.1 {
|
||||
set C [changeset_from_sql {
|
||||
INSERT INTO data_view (tbl, pk, value) VALUES
|
||||
('data', '1', 'First'),
|
||||
('data', '2', 'Second');
|
||||
}]
|
||||
changeset_to_list $C
|
||||
} [list \
|
||||
{INSERT changes 1 X..... {} {i 1 t data t 1 n {} n {} t First}} \
|
||||
{INSERT changes 1 X..... {} {i 2 t data t 2 n {} n {} t Second}} \
|
||||
{INSERT records 1 X... {} {i 1 t data t 1 t First}} \
|
||||
{INSERT records 1 X... {} {i 2 t data t 2 t Second}} \
|
||||
]
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_test $tn.15.2 {
|
||||
db2 eval {
|
||||
CREATE TABLE records(
|
||||
idx INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
tbl TEXT NOT NULL,
|
||||
pk TEXT NOT NULL,
|
||||
value TEXT,
|
||||
UNIQUE(tbl, pk)
|
||||
);
|
||||
CREATE TABLE changes(
|
||||
idx INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
tbl TEXT NOT NULL,
|
||||
pk TEXT NOT NULL,
|
||||
op TEXT DEFAULT ('='),
|
||||
path TEXT DEFAULT ('$'),
|
||||
value TEXT,
|
||||
UNIQUE(tbl, pk)
|
||||
);
|
||||
|
||||
CREATE TRIGGER changes_after_insert
|
||||
AFTER INSERT ON changes
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
INSERT INTO records(tbl, pk, value)
|
||||
VALUES (NEW.tbl, NEW.pk, NEW.value)
|
||||
ON CONFLICT(tbl, pk) DO UPDATE SET value = NEW.value;
|
||||
END;
|
||||
}
|
||||
|
||||
sqlite3changeset_apply db2 $C ""
|
||||
|
||||
db2 eval {
|
||||
SELECT * FROM records;
|
||||
}
|
||||
} [list 1 data 1 First 2 data 2 Second]
|
||||
|
||||
do_test $tn.15.3 {
|
||||
db2 eval {
|
||||
SELECT * FROM changes;
|
||||
}
|
||||
} {1 data 1 {} {} First 2 data 2 {} {} Second}
|
||||
|
||||
db2 close
|
||||
}]
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
Executable → Regular
+1
-1
@@ -72,5 +72,5 @@ do_execsql_test -db db2 1.3 {
|
||||
}
|
||||
|
||||
|
||||
db2 close
|
||||
|
||||
finish_test
|
||||
|
||||
Executable → Regular
-2
@@ -155,8 +155,6 @@ do_test 3.2 {
|
||||
compare_db db db2
|
||||
} {}
|
||||
|
||||
db2 close
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
|
||||
@@ -1190,7 +1190,7 @@ static int sessionTableInfo(
|
||||
/*
|
||||
** This function is called to initialize the SessionTable.nCol, azCol[]
|
||||
** abPK[] and azDflt[] members of SessionTable object pTab. If these
|
||||
** fields are already initialized, this function is a no-op.
|
||||
** fields are already initilialized, this function is a no-op.
|
||||
**
|
||||
** If an error occurs, an error code is stored in sqlite3_session.rc and
|
||||
** non-zero returned. Or, if no error occurs but the table has no primary
|
||||
@@ -3013,7 +3013,7 @@ static int sessionGenerateChangeset(
|
||||
){
|
||||
sqlite3 *db = pSession->db; /* Source database handle */
|
||||
SessionTable *pTab; /* Used to iterate through attached tables */
|
||||
SessionBuffer buf = {0,0,0}; /* Buffer in which to accumulate changeset */
|
||||
SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */
|
||||
int rc; /* Return code */
|
||||
|
||||
assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0) );
|
||||
|
||||
@@ -883,6 +883,19 @@ int sqlite3changeset_concat(
|
||||
void **ppOut /* OUT: Buffer containing output changeset */
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Upgrade the Schema of a Changeset/Patchset
|
||||
*/
|
||||
int sqlite3changeset_upgrade(
|
||||
sqlite3 *db,
|
||||
const char *zDb,
|
||||
int nIn, const void *pIn, /* Input changeset */
|
||||
int *pnOut, void **ppOut /* OUT: Inverse of input */
|
||||
);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Changegroup Handle
|
||||
**
|
||||
|
||||
@@ -34,7 +34,7 @@ struct TestStreamInput {
|
||||
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), NULL);
|
||||
Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(pObj), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ static int SQLITE_TCLAPI test_sql_exec_changeset(
|
||||
rc = sql_exec_changeset(db, zSql, &nChangeset, &pChangeset);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_AppendResult(interp, "error in sql_exec_changeset()", NULL);
|
||||
Tcl_AppendResult(interp, "error in sql_exec_changeset()", 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ static int test_session_error(Tcl_Interp *interp, int rc, char *zErr){
|
||||
extern const char *sqlite3ErrName(int);
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
||||
if( zErr ){
|
||||
Tcl_AppendResult(interp, " - ", zErr, NULL);
|
||||
Tcl_AppendResult(interp, " - ", zErr, 0);
|
||||
sqlite3_free(zErr);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
@@ -435,7 +435,7 @@ static int SQLITE_TCLAPI test_sqlite3session(
|
||||
}
|
||||
|
||||
if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(objv[2]), &info) ){
|
||||
Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(objv[2]), NULL);
|
||||
Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(objv[2]), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
db = *(sqlite3 **)info.objClientData;
|
||||
@@ -832,7 +832,7 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &info) ){
|
||||
Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(objv[1]), NULL);
|
||||
Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(objv[1]), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
db = *(sqlite3 **)info.objClientData;
|
||||
@@ -924,7 +924,7 @@ static int SQLITE_TCLAPI test_sqlite3changeset_apply_replace_all(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &info) ){
|
||||
Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(objv[2]), NULL);
|
||||
Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(objv[2]), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
db = *(sqlite3 **)info.objClientData;
|
||||
@@ -1551,7 +1551,7 @@ static int SQLITE_TCLAPI test_changegroup_cmd(
|
||||
TestChangeIter *pIter = 0;
|
||||
const char *zIter = Tcl_GetString(objv[2]);
|
||||
if( 0==Tcl_GetCommandInfo(interp, zIter, &cmdInfo) ){
|
||||
Tcl_AppendResult(interp, "no such iter: ", Tcl_GetString(objv[2]), NULL);
|
||||
Tcl_AppendResult(interp, "no such iter: ", Tcl_GetString(objv[2]), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
+11
-13
@@ -103,7 +103,7 @@ else
|
||||
ifeq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS)))
|
||||
$(info ==============================================================)
|
||||
$(info == Development build. Make one of (dist, snapshot) for a)
|
||||
$(info == smaller and faster release build.)
|
||||
$(info == smaller release build.)
|
||||
$(info ==============================================================)
|
||||
endif
|
||||
endif
|
||||
@@ -136,9 +136,8 @@ JS_BUILD_NAMES := sqlite3 sqlite3-wasmfs
|
||||
# target of browsers.
|
||||
#
|
||||
# - node = for use by node.js for node.js, as opposed to by node.js on
|
||||
# behalf of browser-side code (use bundler-friendly for that). Note
|
||||
# behalf o browser-side code (use bundler-friendly for that). Note
|
||||
# that persistent storage (OPFS) is not available in these builds.
|
||||
# These builds are UNTESTED and UNSUPPORTED!
|
||||
#
|
||||
JS_BUILD_MODES := vanilla esm bunder-friendly node
|
||||
|
||||
@@ -327,7 +326,7 @@ endif
|
||||
# If the canonical build process finds the file
|
||||
# sqlite3_wasm_extra_init.c in the main wasm build directory, it
|
||||
# arranges to include that file in the build of sqlite3.wasm and
|
||||
# defines SQLITE_EXTRA_INIT_MUTEXED=sqlite3_wasm_extra_init.
|
||||
# defines SQLITE_EXTRA_INIT=sqlite3_wasm_extra_init.
|
||||
#
|
||||
# sqlite3_wasm_extra_init() must be a function with this signature:
|
||||
#
|
||||
@@ -359,7 +358,7 @@ endif
|
||||
# Slight caveat: this uses the version info from the in-tree
|
||||
# sqlite3.c/h, which may diff from a user-provided $(sqlite3.c). The
|
||||
# end result is that the generated JS files may have static version
|
||||
# info from $(bin.version-info) which differ from their runtime-emitted
|
||||
# info from $(bin.version-info) which differ from their runtime-emited
|
||||
# version info (e.g. from sqlite3_libversion()).
|
||||
bin.version-info := $(dir.top)/version-info
|
||||
.NOTPARALLEL: $(bin.version-info)
|
||||
@@ -513,7 +512,7 @@ sqlite3-api-build-version.js := $(dir.tmp)/sqlite3-api-build-version.js
|
||||
# sqlite3-api.jses = the list of JS files which make up
|
||||
# $(sqlite3-api.js.in), in the order they need to be assembled.
|
||||
sqlite3-api.jses := $(sqlite3-license-version.js)
|
||||
# sqlite3-api-prologue.js: initial bootstrapping bits:
|
||||
# sqlite3-api-prologue.js: initial boostrapping bits:
|
||||
sqlite3-api.jses += $(dir.api)/sqlite3-api-prologue.js
|
||||
# whwhasm.js and jaccwabyt.js: Low-level utils, mostly replacing
|
||||
# Emscripten glue:
|
||||
@@ -892,13 +891,12 @@ EXPORTED_FUNCTIONS.fiddle := $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle
|
||||
########################################################################
|
||||
########################################################################
|
||||
# We have to ensure that we do not build $(sqlite3*.*js) in parallel
|
||||
# for any builds which result in the creation of $(sqlite3.wasm). We
|
||||
# have no way to build just a .[m]js file without also building the
|
||||
# .wasm file because the generated .[m]js file has to include info
|
||||
# about the imports needed by the wasm file, so they have to be built
|
||||
# because they all result in the creation of $(sqlite3.wasm). We have
|
||||
# no way to build just a .[m]js file without also building the .wasm
|
||||
# file because the generated .[m]js file has to include info about the
|
||||
# imports needed by the wasm file, so they have to be built
|
||||
# together. i.e. we're building $(sqlite3.wasm) multiple times, but
|
||||
# that's unavoidable (and harmless, but is a significant waste of
|
||||
# build time).
|
||||
# that's unavoidable (and harmless, just a waste of build time).
|
||||
$(sqlite3.wasm): $(sqlite3.js)
|
||||
$(sqlite3.mjs): $(sqlite3.js)
|
||||
$(sqlite3-bundler-friendly.mjs): $(sqlite3.mjs)
|
||||
@@ -909,7 +907,7 @@ $(sqlite3-node.mjs): $(sqlite3.mjs)
|
||||
# We need separate copies of certain supplementary JS files for the
|
||||
# bundler-friendly build. Concretely, any supplemental JS files which
|
||||
# themselves use importScripts() or Workers or URL() constructors
|
||||
# which refer to other in-tree (m)JS files require a bundler-friendly
|
||||
# which refer to other in-tree (m)JS files quire a bundler-friendly
|
||||
# copy.
|
||||
sqlite3-worker1.js.in := $(dir.api)/sqlite3-worker1.c-pp.js
|
||||
sqlite3-worker1-promiser.js.in := $(dir.api)/sqlite3-worker1-promiser.c-pp.js
|
||||
|
||||
@@ -1835,7 +1835,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
if(!(tgt instanceof StructBinder.StructType)){
|
||||
toss("Usage error: target object is-not-a StructType.");
|
||||
}else if(!(func instanceof Function) && !wasm.isPtr(func)){
|
||||
toss("Usage error: expecting a Function or WASM pointer to one.");
|
||||
toss("Usage errror: expecting a Function or WASM pointer to one.");
|
||||
}
|
||||
if(1===arguments.length){
|
||||
return (n,f)=>callee(tgt, n, f, applyArgcCheck);
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
apiConfig = (globalThis.sqlite3ApiConfig || sqlite3ApiBootstrap.defaultConfig)
|
||||
){
|
||||
if(sqlite3ApiBootstrap.sqlite3){ /* already initialized */
|
||||
if(sqlite3ApiBootstrap.sqlite3){ /* already initalized */
|
||||
(sqlite3ApiBootstrap.sqlite3.config || console).warn(
|
||||
"sqlite3ApiBootstrap() called multiple times.",
|
||||
"Config and external initializers are ignored on calls after the first."
|
||||
@@ -869,7 +869,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
Emscripten -sWASM_BIGINT flag, else false. When
|
||||
enabled, certain 64-bit sqlite3 APIs are enabled which
|
||||
are not otherwise enabled due to JS/WASM int64
|
||||
impedance mismatches.
|
||||
impedence mismatches.
|
||||
*/
|
||||
bigIntEnabled: !!config.bigIntEnabled,
|
||||
/**
|
||||
@@ -880,7 +880,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
|
||||
/**
|
||||
When Emscripten compiles with `-sIMPORTED_MEMORY`, it
|
||||
initializes the heap and imports it into wasm, as opposed to
|
||||
initalizes the heap and imports it into wasm, as opposed to
|
||||
the other way around. In this case, the memory is not
|
||||
available via this.exports.memory.
|
||||
*/
|
||||
@@ -1453,7 +1453,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
creates (or overwrites) the given file using those APIs. This is
|
||||
primarily intended for use in Emscripten-based builds where the POSIX
|
||||
APIs are transparently proxied by an in-memory virtual filesystem.
|
||||
It may behave differently in other environments.
|
||||
It may behave diffrently in other environments.
|
||||
|
||||
The first argument must be either a JS string or WASM C-string
|
||||
holding the filename. Note that this routine does _not_ create
|
||||
@@ -1555,7 +1555,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
||||
- "memdb": results are undefined.
|
||||
|
||||
- "kvvfs": will fail with an I/O error due to strict internal
|
||||
requirements of that VFS's xTruncate().
|
||||
requirments of that VFS's xTruncate().
|
||||
|
||||
- "unix" and related: will use the WASM build's equivalent of the
|
||||
POSIX I/O APIs. This will work so long as neither a specific
|
||||
|
||||
@@ -61,7 +61,7 @@ const installAsyncProxy = function(){
|
||||
}
|
||||
|
||||
/**
|
||||
Will hold state copied to this object from the synchronous side of
|
||||
Will hold state copied to this object from the syncronous side of
|
||||
this API.
|
||||
*/
|
||||
const state = Object.create(null);
|
||||
@@ -722,7 +722,7 @@ const installAsyncProxy = function(){
|
||||
|
||||
https://github.com/tomayac/sqlite-wasm/issues/12
|
||||
|
||||
is reporting that this occasionally, under high loads,
|
||||
is reporting that this occassionally, under high loads,
|
||||
returns 'ok', which leads to the whichOp being 0 (which
|
||||
isn't a valid operation ID and leads to an exception,
|
||||
along with a corresponding ugly console log
|
||||
|
||||
@@ -79,48 +79,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
capi.SQLITE_OPEN_MAIN_JOURNAL |
|
||||
capi.SQLITE_OPEN_SUPER_JOURNAL |
|
||||
capi.SQLITE_OPEN_WAL;
|
||||
const FLAG_COMPUTE_DIGEST_V2 = capi.SQLITE_OPEN_MEMORY
|
||||
/* Part of the fix for
|
||||
https://github.com/sqlite/sqlite-wasm/issues/97
|
||||
|
||||
Summary: prior to version 3.50.0 computeDigest() always computes
|
||||
a value of [0,0] due to overflows, so it does not do anything
|
||||
useful. Fixing it invalidates old persistent files, so we
|
||||
instead only fix it for files created or updated since the bug
|
||||
was discovered and fixed.
|
||||
|
||||
This flag determines whether we use the broken legacy
|
||||
computeDigest() or the v2 variant. We only use this flag for
|
||||
newly-created/overwritten files. Pre-existing files have the
|
||||
broken digest stored in them so need to continue to use that.
|
||||
|
||||
What this means, in terms of db file compatibility between
|
||||
versions:
|
||||
|
||||
- DBs created with versions older than this fix (<3.50.0)
|
||||
can be read by post-fix versions. Such DBs which are written
|
||||
to in-place (not replaced) by newer versions can still be read
|
||||
by older versions, as the affected digest is only modified
|
||||
when the SAH slot is assigned to a given filename.
|
||||
|
||||
- DBs created with post-fix versions will, when read by a pre-fix
|
||||
version, be seen as having a "bad digest" and will be
|
||||
unceremoniously replaced by that pre-fix version. When swapping
|
||||
back to a post-fix version, that version will see that the file
|
||||
entry is missing the FLAG_COMPUTE_DIGEST_V2 bit so will treat it
|
||||
as a legacy file.
|
||||
|
||||
This flag is stored in the same memory as the various
|
||||
SQLITE_OPEN_... flags and we must be careful here to not use a
|
||||
flag bit which is otherwise relevant for the VFS.
|
||||
SQLITE_OPEN_MEMORY is handled by sqlite3_open_v2() and friends,
|
||||
not the VFS, so we'll repurpose that one. If we take a
|
||||
currently-unused bit and it ends up, at some later point, being
|
||||
used, we would have to invalidate existing VFS files in order to
|
||||
move to another bit. Similarly, if the SQLITE_OPEN_MEMORY bit
|
||||
were ever reassigned (which it won't be!), we'd invalidate all
|
||||
VFS-side files.
|
||||
*/;
|
||||
|
||||
/** Subdirectory of the VFS's space where "opaque" (randomly-named)
|
||||
files are stored. Changing this effectively invalidates the data
|
||||
@@ -371,7 +329,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
xOpen: function f(pVfs, zName, pFile, flags, pOutFlags){
|
||||
const pool = getPoolForVfs(pVfs);
|
||||
try{
|
||||
flags &= ~FLAG_COMPUTE_DIGEST_V2;
|
||||
pool.log(`xOpen ${wasm.cstrToJs(zName)} ${flags}`);
|
||||
// First try to open a path that already exists in the file system.
|
||||
const path = (zName && wasm.peek8(zName))
|
||||
@@ -544,10 +501,22 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
currently-opened client-specified filenames. */
|
||||
getFileNames(){
|
||||
const rc = [];
|
||||
for(const n of this.#mapFilenameToSAH.keys()) rc.push(n);
|
||||
const iter = this.#mapFilenameToSAH.keys();
|
||||
for(const n of iter) rc.push(n);
|
||||
return rc;
|
||||
}
|
||||
|
||||
// #createFileObject(sah,clientName,opaqueName){
|
||||
// const f = Object.assign(Object.create(null),{
|
||||
// clientName, opaqueName
|
||||
// });
|
||||
// this.#mapSAHToMeta.set(sah, f);
|
||||
// return f;
|
||||
// }
|
||||
// #unmapFileObject(sah){
|
||||
// this.#mapSAHToMeta.delete(sah);
|
||||
// }
|
||||
|
||||
/**
|
||||
Adds n files to the pool's capacity. This change is
|
||||
persistent across settings. Returns a Promise which resolves
|
||||
@@ -588,9 +557,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
}
|
||||
|
||||
/**
|
||||
Releases all currently-opened SAHs. The only legal operation
|
||||
after this is acquireAccessHandles() or (if this is called from
|
||||
pauseVfs()) either of isPaused() or unpauseVfs().
|
||||
Releases all currently-opened SAHs. The only legal
|
||||
operation after this is acquireAccessHandles().
|
||||
*/
|
||||
releaseAccessHandles(){
|
||||
for(const ah of this.#mapSAHToName.keys()) ah.close();
|
||||
@@ -600,21 +568,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
}
|
||||
|
||||
/**
|
||||
Opens all files under this.vfsDir/this.#dhOpaque and acquires a
|
||||
SAH for each. Returns a Promise which resolves to no value but
|
||||
completes once all SAHs are acquired. If acquiring an SAH
|
||||
throws, this.$error will contain the corresponding Error
|
||||
object.
|
||||
|
||||
If it throws, it releases any SAHs which it may have
|
||||
acquired before the exception was thrown, leaving the VFS in a
|
||||
well-defined but unusable state.
|
||||
Opens all files under this.vfsDir/this.#dhOpaque and acquires
|
||||
a SAH for each. returns a Promise which resolves to no value
|
||||
but completes once all SAHs are acquired. If acquiring an SAH
|
||||
throws, SAHPool.$error will contain the corresponding
|
||||
exception.
|
||||
|
||||
If clearFiles is true, the client-stored state of each file is
|
||||
cleared when its handle is acquired, including its name, flags,
|
||||
and any data stored after the metadata block.
|
||||
*/
|
||||
async acquireAccessHandles(clearFiles=false){
|
||||
async acquireAccessHandles(clearFiles){
|
||||
const files = [];
|
||||
for await (const [name,h] of this.#dhOpaque){
|
||||
if('file'===h.kind){
|
||||
@@ -667,8 +631,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
|
||||
const fileDigest = new Uint32Array(HEADER_DIGEST_SIZE / 4);
|
||||
sah.read(fileDigest, {at: HEADER_OFFSET_DIGEST});
|
||||
const compDigest = this.computeDigest(this.#apBody, flags);
|
||||
//warn("getAssociatedPath() flags",'0x'+flags.toString(16), "compDigest", compDigest);
|
||||
const compDigest = this.computeDigest(this.#apBody);
|
||||
if(fileDigest.every((v,i) => v===compDigest[i])){
|
||||
// Valid digest
|
||||
const pathBytes = this.#apBody.findIndex((v)=>0===v);
|
||||
@@ -677,7 +640,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
// leaving stale db data laying around.
|
||||
sah.truncate(HEADER_OFFSET_DATA);
|
||||
}
|
||||
//warn("getAssociatedPath() flags",'0x'+flags.toString(16), "compDigest", compDigest,"pathBytes",pathBytes);
|
||||
return pathBytes
|
||||
? textDecoder.decode(this.#apBody.subarray(0,pathBytes))
|
||||
: '';
|
||||
@@ -700,17 +662,10 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
if(HEADER_MAX_PATH_SIZE <= enc.written + 1/*NUL byte*/){
|
||||
toss("Path too long:",path);
|
||||
}
|
||||
if(path && flags){
|
||||
/* When creating or re-writing files, update their digest, if
|
||||
needed, to v2. We continue to use v1 for the (!path) case
|
||||
(empty files) because there's little reason not to use a
|
||||
digest of 0 for empty entries. */
|
||||
flags |= FLAG_COMPUTE_DIGEST_V2;
|
||||
}
|
||||
this.#apBody.fill(0, enc.written, HEADER_MAX_PATH_SIZE);
|
||||
this.#dvBody.setUint32(HEADER_OFFSET_FLAGS, flags);
|
||||
const digest = this.computeDigest(this.#apBody, flags);
|
||||
//console.warn("setAssociatedPath(",path,") digest",digest);
|
||||
|
||||
const digest = this.computeDigest(this.#apBody);
|
||||
sah.write(this.#apBody, {at: 0});
|
||||
sah.write(digest, {at: HEADER_OFFSET_DIGEST});
|
||||
sah.flush();
|
||||
@@ -731,22 +686,15 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
metadata for each file as a validation check. Changing this
|
||||
algorithm invalidates all existing databases for this VFS, so
|
||||
don't do that.
|
||||
|
||||
See the docs for FLAG_COMPUTE_DIGEST_V2 for more details.
|
||||
*/
|
||||
computeDigest(byteArray, fileFlags){
|
||||
if( fileFlags & FLAG_COMPUTE_DIGEST_V2 ){
|
||||
let h1 = 0xdeadbeef;
|
||||
let h2 = 0x41c6ce57;
|
||||
for(const v of byteArray){
|
||||
h1 = Math.imul(h1 ^ v, 2654435761);
|
||||
h2 = Math.imul(h2 ^ v, 104729);
|
||||
}
|
||||
return new Uint32Array([h1>>>0, h2>>>0]);
|
||||
}else{
|
||||
/* this is what the buggy legacy computation worked out to */
|
||||
return new Uint32Array([0,0]);
|
||||
computeDigest(byteArray){
|
||||
let h1 = 0xdeadbeef;
|
||||
let h2 = 0x41c6ce57;
|
||||
for(const v of byteArray){
|
||||
h1 = 31 * h1 + (v * 307);
|
||||
h2 = 31 * h2 + (v * 307);
|
||||
}
|
||||
return new Uint32Array([h1>>>0, h2>>>0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -884,18 +832,12 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
Removes this object's sqlite3_vfs registration and shuts down
|
||||
this object, releasing all handles, mappings, and whatnot,
|
||||
including deleting its data directory. There is currently no
|
||||
way to "revive" the object and reaquire its
|
||||
resources. Similarly, there is no recovery strategy if removal
|
||||
of any given SAH fails, so such errors are ignored by this
|
||||
function.
|
||||
way to "revive" the object and reaquire its resources.
|
||||
|
||||
This function is intended primarily for testing.
|
||||
|
||||
Resolves to true if it did its job, false if the
|
||||
VFS has already been shut down.
|
||||
|
||||
@see pauseVfs()
|
||||
@see unpauseVfs()
|
||||
*/
|
||||
async removeVfs(){
|
||||
if(!this.#cVfs.pointer || !this.#dhOpaque) return false;
|
||||
@@ -911,77 +853,13 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
);
|
||||
this.#dhVfsRoot = this.#dhVfsParent = undefined;
|
||||
}catch(e){
|
||||
sqlite3.config.error(this.vfsName,"removeVfs() failed with no recovery strategy:",e);
|
||||
sqlite3.config.error(this.vfsName,"removeVfs() failed:",e);
|
||||
/*otherwise ignored - there is no recovery strategy*/
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
"Pauses" this VFS by unregistering it from SQLite and
|
||||
relinquishing all open SAHs, leaving the associated files
|
||||
intact. If this object is already paused, this is a
|
||||
no-op. Returns this object.
|
||||
|
||||
This function throws if SQLite has any opened file handles
|
||||
hosted by this VFS, as the alternative would be to invoke
|
||||
Undefined Behavior by closing file handles out from under the
|
||||
library. Similarly, automatically closing any database handles
|
||||
opened by this VFS would invoke Undefined Behavior in
|
||||
downstream code which is holding those pointers.
|
||||
|
||||
If this function throws due to open file handles then it has
|
||||
no side effects. If the OPFS API throws while closing handles
|
||||
then the VFS is left in an undefined state.
|
||||
|
||||
@see isPaused()
|
||||
@see unpauseVfs()
|
||||
*/
|
||||
pauseVfs(){
|
||||
if(this.#mapS3FileToOFile_.size>0){
|
||||
sqlite3.SQLite3Error.toss(
|
||||
capi.SQLITE_MISUSE, "Cannot pause VFS",
|
||||
this.vfsName,"because it has opened files."
|
||||
);
|
||||
}
|
||||
if(this.#mapSAHToName.size>0){
|
||||
capi.sqlite3_vfs_unregister(this.vfsName);
|
||||
this.releaseAccessHandles();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if this pool is currently paused else false.
|
||||
|
||||
@see pauseVfs()
|
||||
@see unpauseVfs()
|
||||
*/
|
||||
isPaused(){
|
||||
return 0===this.#mapSAHToName.size;
|
||||
}
|
||||
|
||||
/**
|
||||
"Unpauses" this VFS, reacquiring all SAH's and (if successful)
|
||||
re-registering it with SQLite. This is a no-op if the VFS is
|
||||
not currently paused.
|
||||
|
||||
The returned Promise resolves to this object. See
|
||||
acquireAccessHandles() for how it behaves if it throws due to
|
||||
SAH acquisition failure.
|
||||
|
||||
@see isPaused()
|
||||
@see pauseVfs()
|
||||
*/
|
||||
async unpauseVfs(){
|
||||
if(0===this.#mapSAHToName.size){
|
||||
return this.acquireAccessHandles(false).
|
||||
then(()=>capi.sqlite3_vfs_register(this.#cVfs, 0),this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
//! Documented elsewhere in this file.
|
||||
exportFile(name){
|
||||
const sah = this.#mapFilenameToSAH.get(name) || toss("File not found:",name);
|
||||
@@ -1106,10 +984,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
|
||||
async removeVfs(){ return this.#p.removeVfs() }
|
||||
|
||||
pauseVfs(){ this.#p.pauseVfs(); return this; }
|
||||
async unpauseVfs(){ return this.#p.unpauseVfs().then(()=>this); }
|
||||
isPaused(){ return this.#p.isPaused() }
|
||||
|
||||
}/* class OpfsSAHPoolUtil */;
|
||||
|
||||
/**
|
||||
@@ -1164,7 +1038,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
|
||||
- `clearOnInit`: (default=false) if truthy, contents and filename
|
||||
mapping are removed from each SAH it is acquired during
|
||||
initialization of the VFS, leaving the VFS's storage in a pristine
|
||||
initalization of the VFS, leaving the VFS's storage in a pristine
|
||||
state. Use this only for databases which need not survive a page
|
||||
reload.
|
||||
|
||||
@@ -1291,7 +1165,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
VFS-hosted database file. The result of the resolved Promise when
|
||||
called this way is the size of the resulting database.
|
||||
|
||||
On success this routine rewrites the database header bytes in the
|
||||
On succes this routine rewrites the database header bytes in the
|
||||
output file (not the input array) to force disabling of WAL mode.
|
||||
|
||||
On a write error, the handle is removed from the pool and made
|
||||
@@ -1343,41 +1217,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
|
||||
Clears all client-defined state of all SAHs and makes all of them
|
||||
available for re-use by the pool. Results are undefined if any such
|
||||
handles are currently in use, e.g. by an sqlite3 db.
|
||||
|
||||
APIs specific to the "pause" capability (added in version 3.49):
|
||||
|
||||
Summary: "pausing" the VFS disassociates it from SQLite and
|
||||
relinquishes its SAHs so that they may be opened by another
|
||||
instance of this VFS (running in a separate tab/page or Worker).
|
||||
"Unpausing" it takes back control, if able.
|
||||
|
||||
- pauseVfs()
|
||||
|
||||
"Pauses" this VFS by unregistering it from SQLite and
|
||||
relinquishing all open SAHs, leaving the associated files intact.
|
||||
This enables pages/tabs to coordinate semi-concurrent usage of
|
||||
this VFS. If this object is already paused, this is a
|
||||
no-op. Returns this object. Throws if SQLite has any opened file
|
||||
handles hosted by this VFS. If this function throws due to open
|
||||
file handles then it has no side effects. If the OPFS API throws
|
||||
while closing handles then the VFS is left in an undefined state.
|
||||
|
||||
- isPaused()
|
||||
|
||||
Returns true if this VFS is paused, else false.
|
||||
|
||||
- [async] unpauseVfs()
|
||||
|
||||
Restores the VFS to an active state after having called
|
||||
pauseVfs() on it. This is a no-op if the VFS is not paused. The
|
||||
returned Promise resolves to this object on success. A rejected
|
||||
Promise means there was a problem reacquiring the SAH handles
|
||||
(possibly because they're in use by another instance or have
|
||||
since been removed). Generically speaking, there is no recovery
|
||||
strategy for that type of error, but if the problem is simply
|
||||
that the OPFS files are locked, then a later attempt to unpause
|
||||
it, made after the concurrent instance releases the SAHs, may
|
||||
recover from the situation.
|
||||
*/
|
||||
sqlite3.installOpfsSAHPoolVfs = async function(options=Object.create(null)){
|
||||
options = Object.assign(Object.create(null), optionDefaults, (options||{}));
|
||||
|
||||
@@ -459,7 +459,7 @@ const installOpfsVfs = function callee(options){
|
||||
Runs the given operation (by name) in the async worker
|
||||
counterpart, waits for its response, and returns the result
|
||||
which the async worker writes to SAB[state.opIds.rc]. The
|
||||
2nd and subsequent arguments must be the arguments for the
|
||||
2nd and subsequent arguments must be the aruguments for the
|
||||
async op.
|
||||
*/
|
||||
const opRun = (op,...args)=>{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user