Compare commits

..

1 Commits

Author SHA1 Message Date
drh 676f17a570 Proof of concept for a new sqlite3_function_needed() interface.
FossilOrigin-Name: cd67edc032983b5111ffcf6c73ca1308ef67cf2f16baa25788121827b3038d2f
2023-07-07 16:58:20 +00:00
31 changed files with 847 additions and 694 deletions
+1 -5
View File
@@ -4655,13 +4655,9 @@ static void fts5SecureDeleteOverflow(
int i1 = pLeaf->szLeaf;
int i2 = 0;
i1 += fts5GetVarint32(&aPg[i1], iFirst);
if( iFirst<iNext ){
p->rc = FTS5_CORRUPT;
break;
}
aIdx = sqlite3Fts5MallocZero(&p->rc, (pLeaf->nn-pLeaf->szLeaf)+2);
if( aIdx==0 ) break;
i1 += fts5GetVarint32(&aPg[i1], iFirst);
i2 = sqlite3Fts5PutVarint(aIdx, iFirst-nShift);
if( i1<pLeaf->nn ){
memcpy(&aIdx[i2], &aPg[i1], pLeaf->nn-i1);
+94 -115
View File
@@ -68,6 +68,13 @@ ifeq (,$(emcc.version))
else
$(info using emcc version [$(emcc.version)])
endif
emcc.version := $(shell "$(emcc.bin)" --version | sed -n 1p \
| sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;')
ifeq (,$(emcc.version))
$(warning Cannot determine emcc version. This might unduly impact build flags.)
else
$(info using emcc version [$(emcc.version)])
endif
wasm-strip ?= $(shell which wasm-strip 2>/dev/null)
ifeq (,$(filter clean,$(MAKECMDGOALS)))
@@ -152,9 +159,6 @@ endif
# bundle.
#
# A custom sqlite3.c must not have any spaces in its name.
# $(sqlite3.canonical.c) must point to the sqlite3.c in
# the sqlite3 canonical source tree, as that source file
# is required for certain utility and test code.
sqlite3.canonical.c := $(dir.top)/sqlite3.c
sqlite3.c ?= $(firstword $(wildcard $(dir.top)/sqlite3-see.c) $(sqlite3.canonical.c))
sqlite3.h := $(dir.top)/sqlite3.h
@@ -377,14 +381,18 @@ sqlite3-api.jses += $(dir.api)/sqlite3-v-helper.js
sqlite3-api.jses += $(dir.api)/sqlite3-vfs-opfs.c-pp.js
sqlite3-api.jses += $(dir.api)/sqlite3-api-cleanup.js
# SOAP.js is an external API file which is part of our distribution
# "External" API files which are part of our distribution
# but not part of the sqlite3-api.js amalgamation.
SOAP.js := $(dir.api)/sqlite3-opfs-async-proxy.js
SOAP.js.bld := $(dir.dout)/$(notdir $(SOAP.js))
sqlite3-api.ext.jses += $(SOAP.js.bld)
$(SOAP.js.bld): $(SOAP.js)
cp $< $@
# COPY_XAPI = a $(call)able function to copy $1 to $(dir.dout), where
# $1 must be one of the "external" JS API files.
define COPY_XAPI
sqlite3-api.ext.jses += $$(dir.dout)/$$(notdir $(1))
$$(dir.dout)/$$(notdir $(1)): $(1) $$(MAKEFILE)
cp $$< $$@
endef
$(foreach X,$(SOAP.js),\
$(eval $(call COPY_XAPI,$(X))))
all quick: $(sqlite3-api.ext.jses)
q: quick
@@ -607,40 +615,26 @@ $(post-js.js.in): $(post-jses.js) $(MAKEFILE)
########################################################################
# call-make-pre-post is a $(call)able which creates rules for
# pre-js-$(1)-$(2).js. $1 = the base name of the JS file on whose
# behalf this pre-js is for (one of: sqlite3, sqlite3-wasmfs). $2 is
# the build mode: one of $(JS_BUILD_MODES). This sets up
# --[extern-][pre/post]-js flags in $(pre-post-$(1)-$(2).flags) and
# dependencies in $(pre-post-$(1)-$(2).deps). The resulting files get
# filtered using $(C-PP.FILTER). Any flags necessary for such
# filtering need to be set in $(c-pp.D.$(1)-$(2)) before $(call)ing
# this.
# pre-js-$(1).js. $1 = the base name of the JS file on whose behalf
# this pre-js is for (one of: sqlite3, sqlite3-wasmfs). $2 is the
# build mode: one of $(JS_BUILD_MODES). This
# sets up --[extern-][pre/post]-js flags in
# $(pre-post-$(1).flags.$(2)) and dependencies in
# $(pre-post-$(1).deps.$(2)).
define call-make-pre-post
pre-post-$(1)-$(2).flags ?=
pre-js.js.$(1)-$(2) := $$(dir.tmp)/pre-js.$(1)-$(2).intermediary.js
$$(eval $$(call C-PP.FILTER,$$(pre-js.js.in),$$(pre-js.js.$(1)-$(2)),$$(c-pp.D.$(1)-$(2))))
post-js.js.$(1)-$(2) := $$(dir.tmp)/post-js.$(1)-$(2).js
$$(eval $$(call C-PP.FILTER,$$(post-js.js.in),$$(post-js.js.$(1)-$(2)),$$(c-pp.D.$(1)-$(2))))
extern-post-js.js.$(1)-$(2) := $$(dir.tmp)/extern-post-js.$(1)-$(2).js
$$(eval $$(call C-PP.FILTER,$$(extern-post-js.js.in),$$(extern-post-js.js.$(1)-$(2)),$$(c-pp.D.$(1)-$(2))))
pre-post-common.flags.$(1)-$(2) := \
$$(pre-post-common.flags) \
--post-js=$$(post-js.js.$(1)-$(2)) \
--extern-post-js=$$(extern-post-js.js.$(1)-$(2))
pre-post-jses.$(1)-$(2).deps := $$(pre-post-jses.deps.common) \
$$(post-js.js.$(1)-$(2)) $$(extern-post-js.js.$(1)-$(2))
$$(dir.tmp)/pre-js-$(1)-$(2).js: $$(pre-js.js.$(1)-$(2)) $$(MAKEFILE)
cp $$(pre-js.js.$(1)-$(2)) $$@
pre-post-$(1).flags.$(2) ?=
$$(dir.tmp)/pre-js-$(1)-$(2).js: $$(pre-js.js.$(2)) $$(MAKEFILE)
cp $$(pre-js.js.$(2)) $$@
@if [ sqlite3-wasmfs = $(1) ]; then \
echo "delete Module[xNameOfInstantiateWasm] /*for WASMFS build*/;"; \
elif [ sqlite3 != $(1) ]; then \
echo "Module[xNameOfInstantiateWasm].uri = '$(1).wasm';"; \
fi >> $$@
pre-post-$(1)-$(2).deps := \
$$(pre-post-jses.$(1)-$(2).deps) \
pre-post-$(1).deps.$(2) := \
$$(pre-post-jses.deps.$(2)) \
$$(dir.tmp)/pre-js-$(1)-$(2).js
pre-post-$(1)-$(2).flags += \
$$(pre-post-common.flags.$(1)-$(2)) \
pre-post-$(1).flags.$(2) += \
$$(pre-post-common.flags.$(2)) \
--pre-js=$$(dir.tmp)/pre-js-$(1)-$(2).js
endef
# /post-js and pre-js
@@ -651,8 +645,7 @@ endef
# https://github.com/emscripten-core/emscripten/issues/14383
sqlite3.wasm := $(dir.dout)/sqlite3.wasm
sqlite3-wasm.c := $(dir.api)/sqlite3-wasm.c
sqlite3-wasm.cfiles := $(sqlite3-wasm.c) $(sqlite3_wasm_extra_init.c)
sqlite3-wasmfs.cfiles := $(sqlite3-wasm.cfiles)
sqlite3-wasm.cses := $(sqlite3-wasm.c) $(sqlite3_wasm_extra_init.c)
# sqlite3-wasm.o vs sqlite3-wasm.c: building against the latter
# (predictably) results in a slightly faster binary. We're close
# enough to the target speed requirements that the 500ms makes a
@@ -662,8 +655,7 @@ sqlite3-wasmfs.cfiles := $(sqlite3-wasm.cfiles)
# SQLITE3.xJS.EXPORT-DEFAULT is part of SQLITE3-WASMFS.xJS.RECIPE and
# SETUP_LIB_BUILD_MODE, factored into a separate piece to avoid code
# duplication. $1 is 1 if the build mode needs this workaround (esm,
# bundler-friendly, node) and 0 if not (vanilla). $2 must be empty for
# all builds except sqlite3-wasmfs.mjs, in which case it must be 1.
# bundler-friendly) and 0 if not (vanilla).
#
# Reminder for ESM builds: even if we use -sEXPORT_ES6=0, emcc _still_
# adds:
@@ -679,13 +671,11 @@ sqlite3-wasmfs.cfiles := $(sqlite3-wasm.cfiles)
# https://github.com/emscripten-core/emscripten/issues/18237
define SQLITE3.xJS.ESM-EXPORT-DEFAULT
if [ x1 = x$(1) ]; then \
echo "Fragile workaround for emscripten/issues/18237. See SQLITE3.xJS.RECIPE."; \
echo "Fragile workaround for an Emscripten annoyance. See SQLITE3.xJS.RECIPE."; \
sed -i -e '0,/^export default/{/^export default/d;}' $@ || exit $$?; \
if [ x != x$(2) ]; then \
if ! grep -q '^export default' $@; then \
echo "Cannot find export default." 1>&2; \
exit 1; \
fi; \
if ! grep -q '^export default' $@; then \
echo "Cannot find export default." 1>&2; \
exit 1; \
fi; \
fi
endef
@@ -705,57 +695,53 @@ pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js)
# SETUP_LIB_BUILD_MODE is a $(call)'able which sets up numerous pieces
# for one of the build modes.
#
# $1 = one of: sqlite3, sqlite3-wasmfs
# $2 = build mode name: one of $(JS_BUILD_MODES)
# $3 = 1 for ESM build mode, else 0
# $4 = resulting sqlite-api JS/MJS file
# $5 = resulting JS/MJS file
# $6 = -D... flags for $(bin.c-pp)
# $7 = emcc -sXYZ flags (CURRENTLY UNUSED - was factored out)
# $1 = build mode name: one of $(JS_BUILD_MODES)
# $2 = 1 for ESM build mode, else 0
# $3 = resulting sqlite-api JS/MJS file
# $4 = resulting JS/MJS file
# $5 = -D... flags for $(bin.c-pp)
# $6 = emcc -sXYZ flags (CURRENTLY UNUSED - was factored out)
#
# Maintenance reminder: be careful not to introduce spaces around args
# ($1, $2), otherwise string concatenation will malfunction.
#
# emcc.environment.$(2) must be set to a value for the -sENVIRONMENT flag.
#
# $(cflags.$(1)) and $(cflags.$(1).$(2)) may be defined to append
# CFLAGS to a given build mode.
#
# $(emcc.flags.$(1)) and $(emcc.flags.$(1).$(2)) may be defined to
# append emcc-specific flags to a given build mode.
# emcc.environment.$(1) must be set to a value for the -sENVIRONMENT flag.
define SETUP_LIB_BUILD_MODE
$(info Setting up build [$(1)-$(2)]: $(5))
c-pp.D.$(1)-$(2) := $(6)
$$(eval $$(call call-make-pre-post,$(1),$(2)))
emcc.flags.$(1).$(2) ?=
emcc.flags.$(1).$(2) += $(7)
$$(eval $$(call C-PP.FILTER, $$(sqlite3-api.js.in), $(4), $(6)))
$(5): $(4) $$(MAKEFILE) $$(sqlite3-wasm.cfiles) $$(EXPORTED_FUNCTIONS.api) $$(pre-post-$(1)-$(2).deps)
$(info Setting up build [$(1)]: $(4))
c-pp.D.$(1) := $(5)
pre-js.js.$(1) := $$(dir.tmp)/pre-js.$(1).js
$$(eval $$(call C-PP.FILTER,$$(pre-js.js.in),$$(pre-js.js.$(1)),$$(c-pp.D.$(1))))
post-js.js.$(1) := $$(dir.tmp)/post-js.$(1).js
$$(eval $$(call C-PP.FILTER,$$(post-js.js.in),$$(post-js.js.$(1)),$$(c-pp.D.$(1))))
extern-post-js.js.$(1) := $$(dir.tmp)/extern-post-js.$(1).js
$$(eval $$(call C-PP.FILTER,$$(extern-post-js.js.in),$$(extern-post-js.js.$(1)),$$(c-pp.D.$(1))))
pre-post-common.flags.$(1) := \
$$(pre-post-common.flags) \
--post-js=$$(post-js.js.$(1)) \
--extern-post-js=$$(extern-post-js.js.$(1))
pre-post-jses.deps.$(1) := $$(pre-post-jses.deps.common) \
$$(post-js.js.$(1)) $$(extern-post-js.js.$(1))
$$(eval $$(call call-make-pre-post,sqlite3,$(1)))
emcc.flags.sqlite3.$(1) := $(6)
$$(eval $$(call C-PP.FILTER, $$(sqlite3-api.js.in), $(3), $(5)))
$(4): $(3) $$(MAKEFILE) $$(sqlite3-wasm.cses) $$(EXPORTED_FUNCTIONS.api) $$(pre-post-sqlite3.deps.$(1))
@echo "Building $$@ ..."
$$(emcc.bin) -o $$@ $$(emcc_opt_full) $$(emcc.flags) \
$$(emcc.jsflags) \
-sENVIRONMENT=$$(emcc.environment.$(2)) \
$$(pre-post-$(1)-$(2).flags) \
$$(emcc.flags.$(1)) $$(emcc.flags.$(1).$(2)) \
$$(cflags.common) $$(SQLITE_OPT) \
$$(cflags.$(1)) $$(cflags.$(1).$(2)) \
$$(cflags.wasm_extra_init) $$(sqlite3-wasm.cfiles)
@$$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,$(3))
@dotwasm=$$(basename $$@).wasm; \
chmod -x $$$$dotwasm; \
$(maybe-wasm-strip) $$$$dotwasm; \
case $(2) in \
-sENVIRONMENT=$$(emcc.environment.$(1)) \
$$(pre-post-sqlite3.flags.$(1)) $$(emcc.flags.sqlite3.$(1)) \
$$(cflags.common) $$(SQLITE_OPT) $$(cflags.wasm_extra_init) $$(sqlite3-wasm.cses)
@$$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,$(2))
@case $(1) in \
bundler-friendly|node) \
echo "Patching $$@ for $(1).wasm..."; \
rm -f $$$$dotwasm; \
dotwasm=; \
sed -i -e 's/$(1)-$(2).wasm/$(1).wasm/g' $$@ || exit $$$$?; \
echo "Patching $(3) for sqlite3.wasm..."; \
rm -f $$(dir.dout)/sqlite3-$(1).wasm; \
sed -i -e 's/sqlite3-$(1).wasm/sqlite3.wasm/g' $$@ || exit $$$$?; \
;; \
esac; \
ls -la $$$$dotwasm $$@
all: $(5)
quick: $(5)
CLEAN_FILES += $(4) $(5)
esac
chmod -x $$(sqlite3.wasm)
$$(maybe-wasm-strip) $$(sqlite3.wasm)
@ls -la $@ $$(sqlite3.wasm)
all: $(4)
quick: $(4)
CLEAN_FILES += $(3) $(4)
endef
# ^^^ /SETUP_LIB_BUILD_MODE
########################################################################
@@ -767,24 +753,21 @@ sqlite3-api-bundler-friendly.mjs := $(dir.dout)/sqlite3-api-bundler-friendly.mjs
sqlite3-bundler-friendly.mjs := $(dir.dout)/sqlite3-bundler-friendly.mjs
sqlite3-api-node.mjs := $(dir.dout)/sqlite3-api-node.mjs
sqlite3-node.mjs := $(dir.dout)/sqlite3-node.mjs
#$(info $(call SETUP_LIB_BUILD_MODE,sqlite3,vanilla,0, $(sqlite3-api.js), $(sqlite3.js)))
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,vanilla,0,\
$(sqlite3-api.js), $(sqlite3.js)))
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,esm,1,\
$(sqlite3-api.mjs), $(sqlite3.mjs), \
# Maintenance reminder: careful not to introduce spaces around args $1, $2
#$(info $(call SETUP_LIB_BUILD_MODE,vanilla,0, $(sqlite3-api.js), $(sqlite3.js)))
$(eval $(call SETUP_LIB_BUILD_MODE,vanilla,0, $(sqlite3-api.js), $(sqlite3.js)))
$(eval $(call SETUP_LIB_BUILD_MODE,esm,1, $(sqlite3-api.mjs), $(sqlite3.mjs), \
-Dtarget=es6-module, -sEXPORT_ES6 -sUSE_ES6_IMPORT_META))
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,bundler-friendly,1,\
$(eval $(call SETUP_LIB_BUILD_MODE,bundler-friendly,1,\
$(sqlite3-api-bundler-friendly.mjs),$(sqlite3-bundler-friendly.mjs),\
$(c-pp.D.sqlite3-esm) -Dtarget=es6-bundler-friendly))
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,node,1,\
$(c-pp.D.esm) -Dtarget=es6-bundler-friendly))
$(eval $(call SETUP_LIB_BUILD_MODE,node,1,\
$(sqlite3-api-node.mjs),$(sqlite3-node.mjs),\
$(c-pp.D.sqlite3-bundler-friendly) -Dtarget=node))
$(c-pp.D.bundler-friendly) -Dtarget=node))
# The various -D... values used by *.c-pp.js include:
#
# -Dtarget=es6-module: for all ESM module builds
#
# -Dtarget=node: for node.js builds
#
# -Dtarget=es6-module -Dtarget=es6-bundler-friendly: intended for
# "bundler-friendly" ESM module build. These have some restrictions
# on how URL() objects are constructed in some contexts: URLs which
@@ -866,7 +849,7 @@ all: batch
# emcc.speedtest1.common = emcc flags used by multiple builds of speedtest1
# emcc.speedtest1 = emcc flags used by main build of speedtest1
emcc.speedtest1.common := $(emcc_opt_full)
emcc.speedtest1 := -I. -I$(dir $(sqlite3.canonical.c))
emcc.speedtest1 :=
emcc.speedtest1 += -sENVIRONMENT=web
emcc.speedtest1 += -sALLOW_MEMORY_GROWTH
emcc.speedtest1 += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY))
@@ -909,24 +892,22 @@ $(EXPORTED_FUNCTIONS.speedtest1): $(EXPORTED_FUNCTIONS.api.main)
@{ echo _wasm_main; cat $(EXPORTED_FUNCTIONS.api.main); } > $@
speedtest1.js := $(dir.dout)/speedtest1.js
speedtest1.wasm := $(dir.dout)/speedtest1.wasm
emcc.flags.speedtest1-vanilla := $(cflags.common) -DSQLITE_SPEEDTEST1_WASM
speedtest1.cfiles := $(speedtest1.c) $(sqlite3-wasm.c)
cflags.speedtest1 := $(cflags.common) -DSQLITE_SPEEDTEST1_WASM
speedtest1.cses := $(speedtest1.c) $(sqlite3-wasm.c)
$(eval $(call call-make-pre-post,speedtest1,vanilla))
$(speedtest1.js): $(MAKEFILE) $(speedtest1.cfiles) \
$(pre-post-speedtest1-vanilla.deps) \
$(speedtest1.js): $(MAKEFILE) $(speedtest1.cses) \
$(pre-post-speedtest1.deps.vanilla) \
$(EXPORTED_FUNCTIONS.speedtest1)
@echo "Building $@ ..."
$(emcc.bin) \
$(emcc.speedtest1) \
$(emcc.speedtest1) -I$(dir $(sqlite3.canonical.c)) \
$(emcc.speedtest1.common) \
$(emcc.flags.speedtest1-vanilla) $(pre-post-speedtest1-vanilla.flags) \
$(cflags.speedtest1) $(pre-post-speedtest1.flags.vanilla) \
$(SQLITE_OPT) \
-USQLITE_C -DSQLITE_C=$(sqlite3.canonical.c) \
$(speedtest1.exit-runtime0) \
-o $@ $(speedtest1.cfiles) -lm
-o $@ $(speedtest1.cses) -lm
$(maybe-wasm-strip) $(speedtest1.wasm)
chmod -x $(speedtest1.wasm)
ls -la $@ $(speedtest1.wasm)
speedtest1: $(speedtest1.js)
@@ -952,9 +933,9 @@ CLEAN_FILES += $(speedtest1.js) $(speedtest1.wasm)
#
# To create those, we filter tester1.c-pp.js with $(bin.c-pp)...
$(eval $(call C-PP.FILTER,tester1.c-pp.js,tester1.js))
$(eval $(call C-PP.FILTER,tester1.c-pp.js,tester1.mjs,$(c-pp.D.sqlite3-esm)))
$(eval $(call C-PP.FILTER,tester1.c-pp.js,tester1.mjs,$(c-pp.D.esm)))
$(eval $(call C-PP.FILTER,tester1.c-pp.html,tester1.html))
$(eval $(call C-PP.FILTER,tester1.c-pp.html,tester1-esm.html,$(c-pp.D.sqlite3-esm)))
$(eval $(call C-PP.FILTER,tester1.c-pp.html,tester1-esm.html,$(c-pp.D.esm)))
tester1: tester1.js tester1.mjs tester1.html tester1-esm.html
# Note that we do not include $(sqlite3-bundler-friendly.mjs) in this
# because bundlers are client-specific.
@@ -1000,8 +981,6 @@ include fiddle.make
ifneq (,$(filter wasmfs,$(MAKECMDGOALS)))
wasmfs.enable ?= 1
else
# Unconditionally enable wasmfs for [dist]clean so that the wasmfs
# sub-make can clean up.
wasmfs.enable ?= $(if $(filter %clean,$(MAKECMDGOALS)),1,0)
endif
ifeq (1,$(wasmfs.enable))
+13 -8
View File
@@ -23,7 +23,10 @@ const toExportForESM =
impls which Emscripten installs at some point in the file above
this.
*/
const originalInit = sqlite3InitModule;
const originalInit =
/* Maintenance reminder: DO NOT use `self.` here. It's correct
for non-ES6 Module cases but wrong for ES6 modules because those
resolve this symbol differently. */ sqlite3InitModule;
if(!originalInit){
throw new Error("Expecting globalThis.sqlite3InitModule to be defined by the Emscripten build.");
}
@@ -63,16 +66,18 @@ const toExportForESM =
//console.warn("Using replaced sqlite3InitModule()",globalThis.location);
return originalInit(...args).then((EmscriptenModule)=>{
if('undefined'!==typeof WorkerGlobalScope &&
EmscriptenModule['ENVIRONMENT_IS_PTHREAD']){
(EmscriptenModule['ENVIRONMENT_IS_PTHREAD']
|| EmscriptenModule['_pthread_self']
|| 'function'===typeof threadAlert
|| globalThis?.location?.pathname?.endsWith?.('.worker.js')
)){
/** Workaround for wasmfs-generated worker, which calls this
routine from each individual thread and requires that its
argument be returned. The conditional criteria above are
fragile, based solely on inspection of the offending code,
not public Emscripten details. */
//console.warn("sqlite3InitModule() returning E-module.",EmscriptenModule);
argument be returned. All of the criteria above are fragile,
based solely on inspection of the offending code, not public
Emscripten details. */
return EmscriptenModule;
}
//console.warn("sqlite3InitModule() returning sqlite3 object.");
const s = EmscriptenModule.sqlite3;
s.scriptInfo = initModuleState;
//console.warn("sqlite3.scriptInfo =",s.scriptInfo);
@@ -119,5 +124,5 @@ const toExportForESM =
return globalThis.sqlite3InitModule /* required for ESM */;
})();
//#if target=es6-module
export { toExportForESM as default, toExportForESM as sqlite3InitModule }
export default toExportForESM;
//#endif
+1 -1
View File
@@ -23,7 +23,7 @@ if('undefined' !== typeof Module){ // presumably an Emscripten build
const SABC = Object.assign(
Object.create(null), {
exports: Module['asm'],
memory: Module.wasmMemory /* gets set if built with -sIMPORTED_MEMORY */
memory: Module.wasmMemory /* gets set if built with -sIMPORT_MEMORY */
},
globalThis.sqlite3ApiConfig || {}
);
+31 -17
View File
@@ -53,7 +53,7 @@
- `memory`[^1]: optional WebAssembly.Memory object, defaulting to
`exports.memory`. In Emscripten environments this should be set
to `Module.wasmMemory` if the build uses `-sIMPORTED_MEMORY`, or be
to `Module.wasmMemory` if the build uses `-sIMPORT_MEMORY`, or be
left undefined/falsy to default to `exports.memory` when using
WASM-exported memory.
@@ -92,8 +92,8 @@
currently work due to incompatible Emscripten-side changes made
in the WASMFS+OPFS combination. This option is currently ignored.
[^1] = This property may optionally be a function, in which case
this function calls that function to fetch the value,
[^1] = This property may optionally be a function, in which case this
function re-assigns calls that function to fetch the value,
enabling delayed evaluation.
The returned object is the top-level sqlite3 namespace object.
@@ -149,6 +149,11 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
config[k] = config[k]();
}
});
config.wasmOpfsDir =
/* 2022-12-17: WASMFS+OPFS can no longer be activated from the
main thread (aborts via a failed assert() if it's attempted),
which eliminates any(?) benefit to supporting it. */ false;
/**
The main sqlite3 binding API gets installed into this object,
mimicking the C API as closely as we can. The numerous members
@@ -804,7 +809,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|| toss3("Missing API config.exports (WASM module exports)."),
/**
When Emscripten compiles with `-sIMPORTED_MEMORY`, it
When Emscripten compiles with `-sIMPORT_MEMORY`, it
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.
@@ -1172,31 +1177,31 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
/** State for sqlite3_wasmfs_opfs_dir(). */
let __wasmfsOpfsDir = undefined;
/**
2022-12-17: incompatible WASMFS changes have made WASMFS+OPFS
unavailable from the main thread, which eliminates the most
significant benefit of supporting WASMFS. This function is now a
no-op which always returns a falsy value. Before that change,
this function behaved as documented below (and how it will again
if we can find a compelling reason to support it).
If the wasm environment has a WASMFS/OPFS-backed persistent
storage directory, its path is returned by this function. If it
does not then it returns "" (noting that "" is a falsy value).
The first time this is called, this function inspects the current
environment to determine whether persistence support is available
and, if it is, enables it (if needed). After the first call it
always returns the cached result.
and, if it is, enables it (if needed).
If the returned string is not empty, any files stored under the
given path (recursively) are housed in OPFS storage. If the
returned string is empty, this particular persistent storage
option is not available on the client.
Though the mount point name returned by this function is intended
to remain stable, clients should not hard-coded it anywhere. Always call this function to get the path.
Note that this function is a no-op in must builds of this
library, as the WASMFS capability requires a custom
build.
This function currently only recognizes the WASMFS/OPFS storage
combination and its path refers to storage rooted in the
Emscripten-managed virtual filesystem.
*/
capi.sqlite3_wasmfs_opfs_dir = function(){
if(undefined !== __wasmfsOpfsDir) return __wasmfsOpfsDir;
// If we have no OPFS, there is no persistent dir
const pdir = config.wasmfsOpfsDir;
console.error("sqlite3_wasmfs_opfs_dir() can no longer work due "+
"to incompatible WASMFS changes. It will be removed.");
if(!pdir
|| !globalThis.FileSystemHandle
|| !globalThis.FileSystemDirectoryHandle
@@ -1218,6 +1223,8 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
};
/**
Experimental and subject to change or removal.
Returns true if sqlite3.capi.sqlite3_wasmfs_opfs_dir() is a
non-empty string and the given name starts with (that string +
'/'), else returns false.
@@ -1227,6 +1234,13 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
return (p && name) ? name.startsWith(p+'/') : false;
};
// This bit is highly arguable and is incompatible with the fiddle shell.
if(false && 0===wasm.exports.sqlite3_vfs_find(0)){
/* Assume that sqlite3_initialize() has not yet been called.
This will be the case in an SQLITE_OS_KV build. */
wasm.exports.sqlite3_initialize();
}
/**
Given an `sqlite3*`, an sqlite3_vfs name, and an optional db name
(defaulting to "main"), returns a truthy value (see below) if
+27 -29
View File
@@ -118,11 +118,11 @@ const installOpfsVfs = function callee(options){
options.proxyUri = options.proxyUri();
}
const thePromise = new Promise(function(promiseResolve_, promiseReject_){
const loggers = [
sqlite3.config.error,
sqlite3.config.warn,
sqlite3.config.log
];
const loggers = {
0:sqlite3.config.error,
1:sqlite3.config.warn,
2:sqlite3.config.log
};
const logImpl = (level,...args)=>{
if(options.verbose>level) loggers[level]("OPFS syncer:",...args);
};
@@ -191,9 +191,8 @@ const installOpfsVfs = function callee(options){
s.count = s.time = 0;
}
}/*metrics*/;
const opfsVfs = new sqlite3_vfs();
const opfsIoMethods = new sqlite3_io_methods();
const opfsVfs = new sqlite3_vfs()
.addOnDispose( ()=>opfsIoMethods.dispose());
let promiseWasRejected = undefined;
const promiseReject = (err)=>{
promiseWasRejected = true;
@@ -242,10 +241,11 @@ const installOpfsVfs = function callee(options){
opfsVfs.$zName = wasm.allocCString("opfs");
// All C-side memory of opfsVfs is zeroed out, but just to be explicit:
opfsVfs.$xDlOpen = opfsVfs.$xDlError = opfsVfs.$xDlSym = opfsVfs.$xDlClose = null;
opfsVfs.addOnDispose(
opfsVfs.ondispose = [
'$zName', opfsVfs.$zName,
'cleanup default VFS wrapper', ()=>(dVfs ? dVfs.dispose() : null)
);
'cleanup default VFS wrapper', ()=>(dVfs ? dVfs.dispose() : null),
'cleanup opfsIoMethods', ()=>opfsIoMethods.dispose()
];
/**
Pedantic sidebar about opfsVfs.ondispose: the entries in that array
are items to clean up when opfsVfs.dispose() is called, but in this
@@ -298,7 +298,6 @@ const installOpfsVfs = function callee(options){
lock contention to free up.
*/
state.asyncIdleWaitTime = 150;
/**
Whether the async counterpart should log exceptions to
the serialization channel. That produces a great deal of
@@ -833,19 +832,22 @@ const installOpfsVfs = function callee(options){
/* If it turns out that we need to adjust for timezone, see:
https://stackoverflow.com/a/11760121/1458521 */
wasm.poke(pOut, 2440587.5 + (new Date().getTime()/86400000),
'double');
'double');
return 0;
},
xCurrentTimeInt64: function(pVfs,pOut){
// TODO: confirm that this calculation is correct
wasm.poke(pOut, (2440587.5 * 86400000) + new Date().getTime(),
'i64');
'i64');
return 0;
},
xDelete: function(pVfs, zName, doSyncDir){
mTimeStart('xDelete');
const rc = opRun('xDelete', wasm.cstrToJs(zName), doSyncDir, false);
opRun('xDelete', wasm.cstrToJs(zName), doSyncDir, false);
/* We're ignoring errors because we cannot yet differentiate
between harmless and non-harmless failures. */
mTimeEnd();
return rc;
return 0;
},
xFullPathname: function(pVfs,zName,nOut,pOut){
/* Until/unless we have some notion of "current dir"
@@ -1087,7 +1089,7 @@ const installOpfsVfs = function callee(options){
propagate any exception on error, rather than returning false.
*/
opfsUtil.unlink = async function(fsEntryName, recursive = false,
throwOnError = false){
throwOnError = false){
try {
const [hDir, filenamePart] =
await opfsUtil.getDirForFilename(fsEntryName, false);
@@ -1184,23 +1186,19 @@ const installOpfsVfs = function callee(options){
contention. */
sqlite3.capi.sqlite3_busy_timeout(oo1Db, 10000);
sqlite3.capi.sqlite3_exec(oo1Db, [
/* As of July 2023, the PERSIST journal mode on OPFS is
somewhat slower than DELETE or TRUNCATE (it was faster
before Chrome version 108 or 109). TRUNCATE and DELETE
have very similar performance on OPFS.
/* Truncate journal mode is faster than delete for
this vfs, per speedtest1. That gap seems to have closed with
Chrome version 108 or 109, but "persist" is very roughly 5-6%
faster than truncate in initial tests.
Roy Hashimoto notes that TRUNCATE and PERSIST modes may
decrease OPFS concurrency because multiple connections
can open the journal file in those modes:
For later analysis: Roy Hashimoto notes that TRUNCATE
and PERSIST modes may decrease OPFS concurrency because
multiple connections can open the journal file in those
modes:
https://github.com/rhashimoto/wa-sqlite/issues/68
Given that, and the fact that testing has not revealed
any appreciable difference between performance of
TRUNCATE and DELETE modes on OPFS, we currently (as of
2023-07-13) default to DELETE mode.
*/
"pragma journal_mode=DELETE;",
"pragma journal_mode=persist;",
/*
This vfs benefits hugely from cache on moderate/large
speedtest1 --size 50 and --size 100 workloads. We
+69
View File
@@ -0,0 +1,69 @@
/**
Dummy function stubs to get sqlite3.c compiling with
wasi-sdk. This requires, in addition:
-D_WASI_EMULATED_MMAN -D_WASI_EMULATED_GETPID
-lwasi-emulated-getpid
*/
typedef unsigned mode_t;
int fchmod(int fd, mode_t mode);
int fchmod(int fd, mode_t mode){
return (fd && mode) ? 0 : 0;
}
typedef unsigned uid_t;
typedef uid_t gid_t;
int fchown(int fd, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group){
return (fd && owner && group) ? 0 : 0;
}
uid_t geteuid(void);
uid_t geteuid(void){return 0;}
#if !defined(F_WRLCK)
enum {
F_WRLCK,
F_RDLCK,
F_GETLK,
F_SETLK,
F_UNLCK
};
#endif
#undef HAVE_PREAD
#include <wasi/api.h>
#define WASM__KEEP __attribute__((used))
#if 0
/**
wasi-sdk cannot build sqlite3's default VFS without at least the following
functions. They are apparently syscalls which clients have to implement or
otherwise obtain.
https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md
*/
environ_get
environ_sizes_get
clock_time_get
fd_close
fd_fdstat_get
fd_fdstat_set_flags
fd_filestat_get
fd_filestat_set_size
fd_pread
fd_prestat_get
fd_prestat_dir_name
fd_read
fd_seek
fd_sync
fd_write
path_create_directory
path_filestat_get
path_filestat_set_times
path_open
path_readlink
path_remove_directory
path_unlink_file
poll_oneoff
proc_exit
#endif
+19 -25
View File
@@ -1656,11 +1656,25 @@ globalThis.WhWasmUtilInstaller = function(target){
? opt.callProxy : undefined;
}
/**
Note that static class members are defined outside of the class
to work around an emcc toolchain build problem: one of the
tools in emsdk v3.1.42 does not support the static keyword.
*/
/** If true, the constructor emits a warning. The intent is that
this be set to true after bootstrapping of the higher-level
client library is complete, to warn downstream clients that
they shouldn't be relying on this implemenation detail which
does not have a stable interface. */
static warnOnUse = false;
/** If true, convertArg() will FuncPtrAdapter.debugOut() when it
(un)installs a function binding to/from WASM. Note that
deinstallation of bindScope=transient bindings happens
via scopedAllocPop() so will not be output. */
static debugFuncInstall = false;
/** Function used for debug output. */
static debugOut = console.debug.bind(console);
static bindScopes = [
'transient', 'context', 'singleton', 'permanent'
];
/* Dummy impl. Overwritten per-instance as needed. */
contextKey(argv,argIndex){
@@ -1747,26 +1761,6 @@ globalThis.WhWasmUtilInstaller = function(target){
}/*convertArg()*/
}/*FuncPtrAdapter*/;
/** If true, the constructor emits a warning. The intent is that
this be set to true after bootstrapping of the higher-level
client library is complete, to warn downstream clients that
they shouldn't be relying on this implemenation detail which
does not have a stable interface. */
xArg.FuncPtrAdapter.warnOnUse = false;
/** If true, convertArg() will FuncPtrAdapter.debugOut() when it
(un)installs a function binding to/from WASM. Note that
deinstallation of bindScope=transient bindings happens
via scopedAllocPop() so will not be output. */
xArg.FuncPtrAdapter.debugFuncInstall = false;
/** Function used for debug output. */
xArg.FuncPtrAdapter.debugOut = console.debug.bind(console);
xArg.FuncPtrAdapter.bindScopes = [
'transient', 'context', 'singleton', 'permanent'
];
const __xArgAdapterCheck =
(t)=>xArg.get(t) || toss("Argument adapter not found:",t);
+11 -12
View File
@@ -93,8 +93,8 @@
<ul>
<li><a href='speedtest1.html'>speedtest1</a>: a main-thread WASM build of speedtest1.</li>
<li><a href='speedtest1.html?vfs=kvvfs'>speedtest1?vfs=kvvfs</a>: speedtest1 with the kvvfs.</li>
<li><a href='speedtest1-worker.html?size=15'>speedtest1-worker</a>: an interactive Worker-thread variant of speedtest1.</li>
<li><a href='speedtest1-worker.html?vfs=opfs&size=10'>speedtest1-worker?vfs=opfs</a>: speedtest1-worker with the
<li><a href='speedtest1-worker.html?size=25'>speedtest1-worker</a>: an interactive Worker-thread variant of speedtest1.</li>
<li><a href='speedtest1-worker.html?vfs=opfs&size=25'>speedtest1-worker?vfs=opfs</a>: speedtest1-worker with the
OPFS VFS preselected and configured for a moderate workload.</li>
</ul>
</li>
@@ -117,19 +117,18 @@
</li>
</ul>
</li>
<li><strong>WASMFS</strong>-specific tests which require that
the WASMFS build is available on this server (it is not by
default) and that this server emits the COOP/COEP headers.
<!--li>WASMFS-specific tests which currently do not work due to incompatible changes
made to the WASMFS+OPFS combination.
<ul>
<li><a href='scratchpad-wasmfs.html'>scratchpad-wasmfs</a>:
experimenting with WASMFS/OPFS-based persistence.
</li>
<li><a href='speedtest1-wasmfs.html?flags=--size,15'>speedtest1-wasmfs</a>:
<li><a href='speedtest1-wasmfs.html?flags=--size,25'>speedtest1-wasmfs</a>:
a variant of speedtest1 built solely for the wasmfs/opfs
feature.
</li>
feature.</li>
<li><a href='scratchpad-wasmfs-main.html'>scratchpad-wasmfs-main</a>:
experimenting with WASMFS/OPFS-based persistence. Maintenance
reminder: we cannot currently (2022-09-15) load WASMFS in a
worker due to an Emscripten wasm loader limitation.</li>
</ul>
</li>
</li-->
<!--li><a href='x.html'></a></li-->
</ul>
</div>
@@ -10,6 +10,20 @@
</head>
<body>
<header id='titlebar'><span>sqlite3 WASMFS/OPFS Main-thread Scratchpad</span></header>
<!-- emscripten bits -->
<figure id="module-spinner">
<div class="spinner"></div>
<div class='center'><strong>Initializing app...</strong></div>
<div class='center'>
On a slow internet connection this may take a moment. If this
message displays for "a long time", intialization may have
failed and the JavaScript console may contain clues as to why.
</div>
</figure>
<div class="emscripten" id="module-status">Downloading...</div>
<div class="emscripten">
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
</div><!-- /emscripten bits -->
<p>Scratchpad/test app for the WASMF/OPFS integration in the
main window thread. This page requires that the sqlite3 API have
been built with WASMFS support. If OPFS support is available then
@@ -19,12 +33,8 @@
<p>All stuff on this page happens in the dev console.</p>
<hr>
<div id='test-output'></div>
<script>
(function(){
const W = new Worker('scratchpad-wasmfs.mjs',{
type: 'module'
});
})();
</script>
<script src="sqlite3-wasmfs.js"></script>
<script src="common/SqliteTestUtil.js"></script>
<script src="scratchpad-wasmfs-main.js"></script>
</body>
</html>
+70
View File
@@ -0,0 +1,70 @@
/*
2022-05-22
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
A basic test script for sqlite3-api.js. This file must be run in
main JS thread and sqlite3.js must have been loaded before it.
*/
'use strict';
(function(){
const toss = function(...args){throw new Error(args.join(' '))};
const log = console.log.bind(console),
warn = console.warn.bind(console),
error = console.error.bind(console);
const stdout = log;
const stderr = error;
const test1 = function(db){
db.exec("create table if not exists t(a);")
.transaction(function(db){
db.prepare("insert into t(a) values(?)")
.bind(new Date().getTime())
.stepFinalize();
stdout("Number of values in table t:",
db.selectValue("select count(*) from t"));
});
};
const runTests = function(sqlite3){
const capi = sqlite3.capi,
oo = sqlite3.oo1,
wasm = sqlite3.wasm;
stdout("Loaded sqlite3:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
const persistentDir = capi.sqlite3_wasmfs_opfs_dir();
if(persistentDir){
stdout("Persistent storage dir:",persistentDir);
}else{
stderr("No persistent storage available.");
}
const startTime = performance.now();
let db;
try {
db = new oo.DB(persistentDir+'/foo.db');
stdout("DB filename:",db.filename);
const banner1 = '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>',
banner2 = '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<';
[
test1
].forEach((f)=>{
const n = performance.now();
stdout(banner1,"Running",f.name+"()...");
f(db, sqlite3);
stdout(banner2,f.name+"() took ",(performance.now() - n),"ms");
});
}finally{
if(db) db.close();
}
stdout("Total test time:",(performance.now() - startTime),"ms");
};
sqlite3InitModule(self.sqlite3TestModule).then(runTests);
})();
-70
View File
@@ -1,70 +0,0 @@
/*
2022-05-22
The author disclaims copyright to this source code. In place of a
legal notice, here is a blessing:
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
***********************************************************************
A basic test script for sqlite3-api.js. This file must be run in
main JS thread and sqlite3.js must have been loaded before it.
*/
import sqlite3InitModule from './jswasm/sqlite3-wasmfs.mjs';
//console.log('sqlite3InitModule =',sqlite3InitModule);
const toss = function(...args){throw new Error(args.join(' '))};
const log = console.log.bind(console),
warn = console.warn.bind(console),
error = console.error.bind(console);
const stdout = log;
const stderr = error;
const test1 = function(db){
db.exec("create table if not exists t(a);")
.transaction(function(db){
db.prepare("insert into t(a) values(?)")
.bind(new Date().getTime())
.stepFinalize();
stdout("Number of values in table t:",
db.selectValue("select count(*) from t"));
});
};
const runTests = function(sqlite3){
const capi = sqlite3.capi,
oo = sqlite3.oo1,
wasm = sqlite3.wasm;
stdout("Loaded module:",sqlite3);
stdout("Loaded sqlite3:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
const persistentDir = capi.sqlite3_wasmfs_opfs_dir();
if(persistentDir){
stdout("Persistent storage dir:",persistentDir);
}else{
stderr("No persistent storage available.");
}
const startTime = performance.now();
let db;
try {
db = new oo.DB(persistentDir+'/foo.db');
stdout("DB filename:",db.filename);
const banner1 = '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>',
banner2 = '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<';
[
test1
].forEach((f)=>{
const n = performance.now();
stdout(banner1,"Running",f.name+"()...");
f(db, sqlite3);
stdout(banner2,f.name+"() took ",(performance.now() - n),"ms");
});
}finally{
if(db) db.close();
}
stdout("Total test time:",(performance.now() - startTime),"ms");
};
sqlite3InitModule().then(runTests);
+131 -36
View File
@@ -10,46 +10,141 @@
</head>
<body>
<header id='titlebar'><span>speedtest1-wasmfs.wasm</span></header>
<div>See also: <a href='speedtest1-worker.html'>speedtest1-worker</a></div>
<div>See also: <a href='speedtest1-worker.html'>A Worker-thread variant of this page.</a></div>
<!-- emscripten bits -->
<figure id="module-spinner">
<div class="spinner"></div>
<div class='center'><strong>Initializing app...</strong></div>
<div class='center'>
On a slow internet connection this may take a moment. If this
message displays for "a long time", intialization may have
failed and the JavaScript console may contain clues as to why.
</div>
</figure>
<div class="emscripten" id="module-status">Downloading...</div>
<div class="emscripten">
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
</div><!-- /emscripten bits -->
<div class='warning'>This page starts running the main exe when it loads, which will
block the UI until it finishes! Adding UI controls to manually configure and start it
are TODO.</div>
</div>
<div class='warning'>Achtung: running it with the dev tools open may
<em>drastically</em> slow it down. For faster results, keep the dev
tools closed when running it!
</div>
<div>Output is delayed/buffered because we cannot update the UI while the
speedtest is running. Output will appear below when ready...
<div id='test-output'></div>
<script>
(function(){
const eOut = document.querySelector('#test-output');
const log2 = function(cssClass,...args){
const ln = document.createElement('div');
if(cssClass) ln.classList.add(cssClass);
ln.append(document.createTextNode(args.join(' ')));
eOut.append(ln);
//this.e.output.lastElementChild.scrollIntoViewIfNeeded();
};
/* can't update DOM while speedtest is running unless we run
speedtest in a worker thread. */;
const log = (...args)=>{
console.log(...args);
log2('',...args);
};
const logErr = function(...args){
console.error(...args);
log2('error',...args);
};
const W = new Worker(
'speedtest1-wasmfs.mjs'+globalThis.location.search,{
type: 'module'
});
log("Starting up...");
W.onmessage = function({data}){
switch(data.type){
case 'log': log(...data.args); break;
case 'logErr': logErr(...data.args); break;
default:
break;
}
};
})();
</script>
<script src="common/SqliteTestUtil.js"></script>
<script src="speedtest1-wasmfs.js"></script>
<script>(function(){
/**
If this environment contains OPFS, this function initializes it and
returns the name of the dir on which OPFS is mounted, else it returns
an empty string.
*/
const wasmfsDir = function f(wasmUtil,dirName="/opfs"){
if(undefined !== f._) return f._;
if( !self.FileSystemHandle
|| !self.FileSystemDirectoryHandle
|| !self.FileSystemFileHandle){
return f._ = "";
}
try{
if(0===wasmUtil.xCallWrapped(
'sqlite3_wasm_init_wasmfs', 'i32', ['string'], dirName
)){
return f._ = dirName;
}else{
return f._ = "";
}
}catch(e){
// sqlite3_wasm_init_wasmfs() is not available
return f._ = "";
}
};
wasmfsDir._ = undefined;
const eOut = document.querySelector('#test-output');
const log2 = function(cssClass,...args){
const ln = document.createElement('div');
if(cssClass) ln.classList.add(cssClass);
ln.append(document.createTextNode(args.join(' ')));
eOut.append(ln);
//this.e.output.lastElementChild.scrollIntoViewIfNeeded();
};
const logList = [];
const dumpLogList = function(){
logList.forEach((v)=>log2('',v));
logList.length = 0;
};
/* can't update DOM while speedtest is running unless we run
speedtest in a worker thread. */;
const log = (...args)=>{
console.log(...args);
logList.push(args.join(' '));
};
const logErr = function(...args){
console.error(...args);
logList.push('ERROR: '+args.join(' '));
};
const runTests = function(sqlite3){
console.log("Module inited.");
const wasm = sqlite3.wasm;
const __unlink = wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["*","string"]);
const unlink = (fn)=>__unlink(0,fn);
const pDir = wasmfsDir(wasm);
if(pDir) log2('',"Persistent storage:",pDir);
else{
log2('error',"Expecting persistent storage in this build.");
return;
}
const scope = wasm.scopedAllocPush();
const dbFile = pDir+"/speedtest1.db";
const urlParams = new URL(self.location.href).searchParams;
const argv = ["speedtest1"];
if(urlParams.has('flags')){
argv.push(...(urlParams.get('flags').split(',')));
let i = argv.indexOf('--vfs');
if(i>=0) argv.splice(i,2);
}else{
argv.push(
"--singlethread",
"--nomutex",
"--nosync",
"--nomemstat"
);
//"--memdb", // note that memdb trumps the filename arg
}
if(argv.indexOf('--memdb')>=0){
log2('error',"WARNING: --memdb flag trumps db filename.");
}
argv.push("--big-transactions"/*important for tests 410 and 510!*/,
dbFile);
console.log("argv =",argv);
// These log messages are not emitted to the UI until after main() returns. Fixing that
// requires moving the main() call and related cleanup into a timeout handler.
if(pDir) unlink(dbFile);
log2('',"Starting native app:\n ",argv.join(' '));
log2('',"This will take a while and the browser might warn about the runaway JS.",
"Give it time...");
logList.length = 0;
setTimeout(function(){
wasm.xCall('wasm_main', argv.length,
wasm.scopedAllocMainArgv(argv));
wasm.scopedAllocPop(scope);
if(pDir) unlink(dbFile);
logList.unshift("Done running native main(). Output:");
dumpLogList();
}, 25);
}/*runTests()*/;
self.sqlite3TestModule.print = log;
self.sqlite3TestModule.printErr = logErr;
sqlite3InitModule(self.sqlite3TestModule).then(runTests);
})();</script>
</body>
</html>
-90
View File
@@ -1,90 +0,0 @@
import sqlite3InitModule from './jswasm/speedtest1-wasmfs.mjs';
const wMsg = (type,...args)=>{
postMessage({type, args});
};
wMsg('log',"speedtest1-wasmfs starting...");
/**
If this environment contains OPFS, this function initializes it and
returns the name of the dir on which OPFS is mounted, else it returns
an empty string.
*/
const wasmfsDir = function f(wasmUtil,dirName="/opfs"){
if(undefined !== f._) return f._;
if( !self.FileSystemHandle
|| !self.FileSystemDirectoryHandle
|| !self.FileSystemFileHandle){
return f._ = "";
}
try{
if(0===wasmUtil.xCallWrapped(
'sqlite3_wasm_init_wasmfs', 'i32', ['string'], dirName
)){
return f._ = dirName;
}else{
return f._ = "";
}
}catch(e){
// sqlite3_wasm_init_wasmfs() is not available
return f._ = "";
}
};
wasmfsDir._ = undefined;
const log = (...args)=>wMsg('log',...args);
const logErr = (...args)=>wMsg('logErr',...args);
const runTests = function(sqlite3){
console.log("Module inited.",sqlite3);
const wasm = sqlite3.wasm;
const __unlink = wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["*","string"]);
const unlink = (fn)=>__unlink(0,fn);
const pDir = wasmfsDir(wasm);
if(pDir) log("Persistent storage:",pDir);
else{
logErr("Expecting persistent storage in this build.");
return;
}
const scope = wasm.scopedAllocPush();
const dbFile = pDir+"/speedtest1.db";
const urlParams = new URL(self.location.href).searchParams;
const argv = ["speedtest1"];
if(urlParams.has('flags')){
argv.push(...(urlParams.get('flags').split(',')));
let i = argv.indexOf('--vfs');
if(i>=0) argv.splice(i,2);
}else{
argv.push(
"--singlethread",
"--nomutex",
//"--nosync",
"--nomemstat",
"--size", "10"
);
}
if(argv.indexOf('--memdb')>=0){
logErr("WARNING: --memdb flag trumps db filename.");
}
argv.push("--big-transactions"/*important for tests 410 and 510!*/,
dbFile);
//log("argv =",argv);
// These log messages are not emitted to the UI until after main() returns. Fixing that
// requires moving the main() call and related cleanup into a timeout handler.
if(pDir) unlink(dbFile);
log("Starting native app:\n ",argv.join(' '));
log("This will take a while and the browser might warn about the runaway JS.",
"Give it time...");
setTimeout(function(){
if(pDir) unlink(dbFile);
wasm.xCall('wasm_main', argv.length,
wasm.scopedAllocMainArgv(argv));
wasm.scopedAllocPop(scope);
if(pDir) unlink(dbFile);
log("Done running native main()");
}, 25);
}/*runTests()*/;
sqlite3InitModule({
print: log,
printErr: logErr
}).then(runTests);
+1 -1
View File
@@ -259,7 +259,7 @@
flags["--utf16be"] = "Set text encoding to UTF-16BE";
flags["--utf16le"] = "Set text encoding to UTF-16LE";
flags["--verify"] = "Run additional verification steps.";
flags["--without-rowid"] = "Use WITHOUT ROWID where appropriate";
flags["--without"] = "rowid Use WITHOUT ROWID where appropriate";
const preselectedFlags = [
'--big-transactions',
'--singlethread'
+9 -11
View File
@@ -45,7 +45,7 @@
*/
//#if target=es6-module
import {default as sqlite3InitModule} from './jswasm/sqlite3.mjs';
globalThis.sqlite3InitModule = sqlite3InitModule;
self.sqlite3InitModule = sqlite3InitModule;
//#else
'use strict';
//#endif
@@ -57,7 +57,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
*/
let logClass;
/* Predicate for tests/groups. */
const isUIThread = ()=>(globalThis.window===self && globalThis.document);
const isUIThread = ()=>(self.window===self && self.document);
/* Predicate for tests/groups. */
const isWorker = ()=>!isUIThread();
/* Predicate for tests/groups. */
@@ -3050,15 +3050,14 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
////////////////////////////////////////////////////////////////////////
log("Loading and initializing sqlite3 WASM module...");
if(0){
globalThis.sqlite3ApiConfig = {
self.sqlite3ApiConfig = {
debug: ()=>{},
log: ()=>{},
warn: ()=>{},
error: ()=>{}
}
}
//#ifnot target=es6-module
if(!globalThis.sqlite3InitModule && !isUIThread()){
if(!self.sqlite3InitModule && !isUIThread()){
/* Vanilla worker, as opposed to an ES6 module worker */
/*
If sqlite3.js is in a directory other than this script, in order
@@ -3071,28 +3070,27 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
that's not needed.
URL arguments passed as part of the filename via importScripts()
are simply lost, and such scripts see the globalThis.location of
are simply lost, and such scripts see the self.location of
_this_ script.
*/
let sqlite3Js = 'sqlite3.js';
const urlParams = new URL(globalThis.location.href).searchParams;
const urlParams = new URL(self.location.href).searchParams;
if(urlParams.has('sqlite3.dir')){
sqlite3Js = urlParams.get('sqlite3.dir') + '/' + sqlite3Js;
}
importScripts(sqlite3Js);
}
//#endif
globalThis.sqlite3InitModule.__isUnderTest =
self.sqlite3InitModule.__isUnderTest =
true /* disables certain API-internal cleanup so that we can
test internal APIs from here */;
globalThis.sqlite3InitModule({
self.sqlite3InitModule({
print: log,
printErr: error
}).then(function(sqlite3){
//console.log('sqlite3 =',sqlite3);
log("Done initializing WASM/JS bits. Running tests...");
sqlite3.config.warn("Installing sqlite3 bits as global S for local dev/test purposes.");
globalThis.S = sqlite3;
self.S = sqlite3;
capi = sqlite3.capi;
wasm = sqlite3.wasm;
log("sqlite3 version:",capi.sqlite3_libversion(),
+75 -58
View File
@@ -6,10 +6,14 @@
# GNUMakefile.
########################################################################
MAKEFILE.wasmfs := $(lastword $(MAKEFILE_LIST))
$(warning The WASMFS build is currently incomplete.)
#dir.wasmfs := $(dir.wasm)
dir.wasmfs := $(dir.dout)
# Maintenance reminder: these particular files cannot be built into a
# subdirectory because loading of the auxiliary
# sqlite3-wasmfs.worker.js file it creates fails if sqlite3-wasmfs.js
# is loaded from any directory other than the one in which the
# containing HTML lives. Similarly, they cannot be loaded from a
# Worker to an Emscripten quirk regarding loading nested Workers.
dir.wasmfs := $(dir.wasm)
sqlite3-wasmfs.js := $(dir.wasmfs)/sqlite3-wasmfs.js
sqlite3-wasmfs.mjs := $(dir.wasmfs)/sqlite3-wasmfs.mjs
sqlite3-wasmfs.wasm := $(dir.wasmfs)/sqlite3-wasmfs.wasm
@@ -24,92 +28,105 @@ CLEAN_FILES += $(sqlite3-wasmfs.js) $(sqlite3-wasmfs.wasm) \
cflags.sqlite3-wasmfs :=
cflags.sqlite3-wasmfs += -std=c99 -fPIC
cflags.sqlite3-wasmfs += -pthread
cflags.sqlite3-wasmfs += -DSQLITE_ENABLE_WASMFS
cflags.sqlite3-wasmfs += $(cflags.speedtest1)
cflags.sqlite3-wasmfs += $(SQLITE_OPT) -DSQLITE_ENABLE_WASMFS
########################################################################
# emcc flags specific to building the final .js/.wasm file...
emcc.flags.sqlite3-wasmfs :=
emcc.flags.sqlite3-wasmfs += \
-sEXPORTED_RUNTIME_METHODS=wasmMemory,allocateUTF8OnStack,stringToUTF8OnStack
emcc.flags.sqlite3-wasmfs := -fPIC
emcc.flags.sqlite3-wasmfs += --no-entry
emcc.flags.sqlite3-wasmfs += --minify 0
emcc.flags.sqlite3-wasmfs += -sMODULARIZE
emcc.flags.sqlite3-wasmfs += -sEXPORT_NAME=$(sqlite3.js.init-func)
emcc.flags.sqlite3-wasmfs += -sSTRICT_JS
emcc.flags.sqlite3-wasmfs += -sDYNAMIC_EXECUTION=0
emcc.flags.sqlite3-wasmfs += -sNO_POLYFILL
emcc.flags.sqlite3-wasmfs += -sWASM_BIGINT=$(emcc.WASM_BIGINT)
emcc.flags.sqlite3-wasmfs += -sEXPORTED_FUNCTIONS=@$(abspath $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-api)
emcc.flags.sqlite3-wasmfs += -sEXPORTED_RUNTIME_METHODS=FS,wasmMemory,allocateUTF8OnStack
# wasmMemory ==> for -sIMPORTED_MEMORY
# *OnStack ==> wasmfs internals (leaky abstraction)
# allocateUTF8OnStack ==> wasmfs internals
emcc.flags.sqlite3-wasmfs += -sUSE_CLOSURE_COMPILER=0
emcc.flags.sqlite3-wasmfs += -Wno-limited-postlink-optimizations
# ^^^^^ it likes to warn when we have "limited optimizations" via the -g3 flag.
emcc.flags.sqlite3-wasmfs += -sALLOW_TABLE_GROWTH
emcc.flags.sqlite3-wasmfs += -sSTACK_SIZE=512KB
emcc.flags.sqlite3-wasmfs += -sGLOBAL_BASE=4096 # HYPOTHETICALLY keep func table indexes from overlapping w/ heap addr.
emcc.flags.sqlite3-wasmfs += -sMEMORY64=0
emcc.flags.sqlite3-wasmfs += -sIMPORTED_MEMORY
emcc.flags.sqlite3-wasmfs += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.128)
# ^^^^ 64MB is not enough for WASMFS/OPFS test runs using batch-runner.js
sqlite3-wasmfs.fsflags := -pthread -sWASMFS \
-sPTHREAD_POOL_SIZE=1 \
-sERROR_ON_UNDEFINED_SYMBOLS=0 -sLLD_REPORT_UNDEFINED
-sPTHREAD_POOL_SIZE=2 -sENVIRONMENT=web,worker \
-sERROR_ON_UNDEFINED_SYMBOLS=0 -sLLD_REPORT_UNDEFINED
# ^^^^^ why undefined symbols are necessary for the wasmfs build is anyone's guess.
emcc.flags.sqlite3-wasmfs += $(sqlite3-wasmfs.fsflags)
emcc.flags.sqlite3-wasmfs += -sALLOW_MEMORY_GROWTH=0
#emcc.flags.sqlite3-wasmfs += -sALLOW_MEMORY_GROWTH
#^^^ using ALLOW_MEMORY_GROWTH produces a warning from emcc:
# USE_PTHREADS + ALLOW_MEMORY_GROWTH may run non-wasm code slowly,
# see https://github.com/WebAssembly/design/issues/1271 [-Wpthreads-mem-growth]
# And, indeed, it runs slowly if memory is permitted to grow.
#emcc.flags.sqlite3-wasmfs.vanilla :=
#emcc.flags.sqlite3-wasmfs.esm := -sEXPORT_ES6 -sUSE_ES6_IMPORT_META
sqlite3-api.mjs.wasmfs := $(dir.tmp)/sqlite3-api-wasmfs.mjs
$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3-wasmfs,esm,1,\
$(sqlite3-api.mjs.wasmfs), $(sqlite3-wasmfs.mjs),\
$(c-pp.D.sqlite3-bundler-friendly) -Dwasmfs,\
-sEXPORT_ES6 -sUSE_ES6_IMPORT_META\
))
$(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs): $(MAKEFILE.wasmfs)
########################################################################
# Build quirk: we cannot build BOTH .js and .mjs with our current
# build infrastructure because the supplemental *.worker.js files get
# generated with the name of the main module file
# ($(sqlite3-wasmfs.{js,mjs})) hard-coded in them. Thus the last one
# to get built gets the *.worker.js files mapped to it. In order to
# build both modes they would need to have distinct base names or
# output directories. "The problem" with giving them distinct base
# names is that it means that the corresponding .wasm file is also
# built/saved multiple times.
#
wasmfs.build.ext := mjs
$(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs): $(SOAP.js.bld)
ifeq (js,$(wasmfs.build.ext))
$(sqlite3-wasmfs.wasm): $(sqlite3-wasmfs.js)
wasmfs: $(sqlite3-wasmfs.js)
else
$(sqlite3-wasmfs.wasm): $(sqlite3-wasmfs.mjs)
wasmfs: $(sqlite3-wasmfs.mjs)
endif
emcc.flags.sqlite3-wasmfs.vanilla :=
emcc.flags.sqlite3-wasmfs.esm := -sEXPORT_ES6 -sUSE_ES6_IMPORT_META
$(eval $(call call-make-pre-js,sqlite3-wasmfs,vanilla))
$(eval $(call call-make-pre-js,sqlite3-wasmfs,esm))
Xemcc.flags.sqlite3-wasmfs.vanilla += \
$(pre-post-common.flags.vanilla) \
$(pre-post-sqlite3-wasmfs.flags.vanilla)
Xemcc.flags.sqlite3-wasmfs.esm += \
$(pre-post-common.flags.esm) \
$(pre-post-sqlite3-wasmfs.flags.esm)
$(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs): $(sqlite3-wasm.c) \
$(EXPORTED_FUNCTIONS.api) $(MAKEFILE) $(MAKEFILE.wasmfs)
$(sqlite3-wasmfs.js): $(pre-post-sqlite3-wasmfs.deps.vanilla)
$(sqlite3-wasmfs.mjs): $(pre-post-sqlite3-wasmfs.deps.esm)
# SQLITE3-WASMFS.xJS.RECIPE is the wasmfs-specific counterpart
# of SQLITE3.xJS.RECIPE from the main makefile.
define SQLITE3-WASMFS.xJS.RECIPE
@echo "Building $@ ..."
$(emcc.bin) -o $@ $(emcc_opt_full) $(emcc.flags) \
$(cflags.sqlite3-wasmfs) \
$(emcc.flags.sqlite3-wasmfs) $(emcc.flags.sqlite3-wasmfs.$(1)) \
$(pre-post-sqlite3-wasmfs.flags.$(1)) \
$(sqlite3-wasm.c)
@$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,$(1))
chmod -x $(sqlite3-wasmfs.wasm)
$(maybe-wasm-strip) $(sqlite3-wasmfs.wasm)
@ls -la $(sqlite3-wasmfs.wasm) sqlite3-wasmfs*js
endef
$(sqlite3-wasmfs.js):
$(call SQLITE3-WASMFS.xJS.RECIPE,vanilla)
$(sqlite3-wasmfs.mjs): $(sqlite3-wasmfs.js)
$(call SQLITE3-WASMFS.xJS.RECIPE,esm)
$(sqlite3-wasmfs.wasm): $(sqlite3-wasmfs.js)
wasmfs: $(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs)
#all: wasmfs
########################################################################
# speedtest1 for wasmfs.
speedtest1-wasmfs.mjs := $(dir.wasmfs)/speedtest1-wasmfs.mjs
speedtest1-wasmfs.wasm := $(subst .mjs,.wasm,$(speedtest1-wasmfs.mjs))
speedtest1-wasmfs.js := $(dir.wasmfs)/speedtest1-wasmfs.js
speedtest1-wasmfs.wasm := $(subst .js,.wasm,$(speedtest1-wasmfs.js))
emcc.flags.speedtest1-wasmfs := $(sqlite3-wasmfs.fsflags)
emcc.flags.speedtest1-wasmfs += $(SQLITE_OPT)
emcc.flags.speedtest1-wasmfs += $(SQLITE_OPT) -DSQLITE_ENABLE_WASMFS
emcc.flags.speedtest1-wasmfs += -sALLOW_MEMORY_GROWTH=0
emcc.flags.speedtest1-wasmfs += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.128)
#$(eval $(call call-make-pre-js,speedtest1-wasmfs,ems))
$(speedtest1-wasmfs.mjs): $(speedtest1.cfiles) $(sqlite3-wasmfs.js) \
#$(eval $(call call-make-pre-js,speedtest1-wasmfs,vanilla))
$(speedtest1-wasmfs.js): $(speedtest1.cses) $(sqlite3-wasmfs.js) \
$(MAKEFILE) $(MAKEFILE.wasmfs) \
$(pre-post-sqlite3-wasmfs-esm.deps) \
$(pre-post-sqlite3-wasmfs.deps) \
$(EXPORTED_FUNCTIONS.speedtest1)
@echo "Building $@ ..."
$(emcc.bin) \
$(pre-post-sqlite3-wasmfs-esm.flags) \
$(cflags.common) \
$(emcc.speedtest1.common) $(emcc.flags.speedtest1-wasmfs) \
$(pre-post-sqlite3-wasmfs.flags.vanilla) \
$(cflags.sqlite3-wasmfs) \
$(emcc.speedtest1.common) \
$(emcc.flags.speedtest1-vanilla) \
$(emcc.flags.sqlite3-wasmfs) \
$(emcc.flags.speedtest1-wasmfs) \
-o $@ $(speedtest1.cfiles) -lm
@$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,1)
-o $@ $(speedtest1.cses) -lm
$(maybe-wasm-strip) $(speedtest1-wasmfs.wasm)
chmod -x $(speedtest1-wasmfs.wasm)
ls -la $@ $(speedtest1-wasmfs.wasm)
wasmfs: $(speedtest1-wasmfs.mjs)
CLEAN_FILES += $(speedtest1-wasmfs.mjs) $(speedtest1-wasmfs.wasm) \
$(subst .js,.worker.js,$(speedtest1-wasmfs.mjs))
#speedtest1: $(speedtest1-wasmfs.js)
wasmfs: $(speedtest1-wasmfs.js)
CLEAN_FILES += $(speedtest1-wasmfs.js) $(speedtest1-wasmfs.wasm) \
$(subst .js,.worker.js,$(speedtest1-wasmfs.js))
# end speedtest1.js
########################################################################
+34 -34
View File
@@ -1,5 +1,5 @@
C Enhance\sthe\sJSON\sparser\scache\ssuch\sthat\sit\sis\sable\sto\sextract\slines\sfrom\nthe\scache\sand\suse\sthem\sfor\swriting,\sthough\sthey\sthen\shave\sto\sbe\sevicted\sfrom\nthe\scache.\s\sThis\swas\san\sexperiment\sin\strying\sto\sreduce\sthe\samount\sof\sparsing\nneeded\sfor\sa\sbig\sUPDATE,\sbut\sit\sdoes\snot\sseem\sto\shelp\sany.\s\sRetained\sfor\nreference\sonly.
D 2023-07-19T12:52:09.770
C Proof\sof\sconcept\sfor\sa\snew\ssqlite3_function_needed()\sinterface.
D 2023-07-07T16:58:20.565
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -92,7 +92,7 @@ F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b7292
F ext/fts5/fts5_config.c 051056a9052f5d3a4d1c695f996fd364f920e341f136c60ab2c04aa7e267113f
F ext/fts5/fts5_expr.c 58fb8ceddfb1cefcd54510f9f2f33c220ef9d1b3fa77462111f5ae2a825ab7b1
F ext/fts5/fts5_hash.c d4fb70940359f2120ccd1de7ffe64cc3efe65de9e8995b822cd536ff64c96982
F ext/fts5/fts5_index.c 430d3edfc5b51d02f0671e2b8268c12bf485f7dc80db2b61c996e74814bc46b0
F ext/fts5/fts5_index.c fe98ebd8835760b9c787d20f6b50d648a761afd8e3b55780e718ee34c694743b
F ext/fts5/fts5_main.c b4dba04a36aaf9b8e8cef0100b6dbb422cc74753eacc11d6401cac7a87c0f38d
F ext/fts5/fts5_storage.c 76c6085239eb44424004c022e9da17a5ecd5aaec859fba90ad47d3b08f4c8082
F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
@@ -482,27 +482,28 @@ F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
F ext/wasm/GNUmakefile 74e351ff45b4061cfed8df237d301819a04182ae304a99118883b064baa25fc2
F ext/wasm/GNUmakefile 38700d5074af690f004e4e5f3533164ab49693b9d0832929c4ecf97a0bc09494
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
F ext/wasm/README.md ef39861aa21632fdbca0bdd469f78f0096f6449a720f3f39642594af503030e9
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2506e1360c1f0dee0c7816c10acd9ab
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
F ext/wasm/api/README.md 77a2f1f2fc60a35def7455dffc8d3f2c56385d6ac5c6cecc60fa938252ea2c54
F ext/wasm/api/extern-post-js.c-pp.js 116749b7e55b7519129de06d3d353e19df68cfb24b12204aa4dc30c9a83023fe
F ext/wasm/api/extern-post-js.c-pp.js 393ab78b807da94096eae1a68bfddb999a2299936a185d910162fe87a57a9a3a
F ext/wasm/api/extern-pre-js.js cc61c09c7a24a07dbecb4c352453c3985170cec12b4e7e7e7a4d11d43c5c8f41
F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08902f15c34720ee4a1
F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219
F ext/wasm/api/sqlite3-api-cleanup.js 23ceec5ef74a0e649b19694ca985fd89e335771e21f24f50df352a626a8c81bf
F ext/wasm/api/sqlite3-api-cleanup.js cc21e3486da748463e02bbe51e2464c6ac136587cdfd5aa00cd0b5385f6ca808
F ext/wasm/api/sqlite3-api-glue.js f1b2dcb944de5138bb5bd9a1559d2e76a4f3ec25260963d709e8237476688803
F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8
F ext/wasm/api/sqlite3-api-prologue.js 7d1c1ef59b9dcc42ad3a9cec9da972c42e29316a270cd126e7f660509b09027b
F ext/wasm/api/sqlite3-api-prologue.js 17f4ec398ba34c5c666fea8e8c4eb82064a35b302f2f2eb355283cd8d3f68ed5
F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b1738645c0134562bb84e88e2fec
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
F ext/wasm/api/sqlite3-opfs-async-proxy.js 961bbc3ccc1fa4e91d6519a96e8811ad7ae60173bd969fee7775dacb6eee1da2
F ext/wasm/api/sqlite3-v-helper.js e5c202a9ecde9ef818536d3f5faf26c03a1a9f5192b1ddea8bdabf30d75ef487
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 891f3a18d9ac9b0422b32fd975319dfcd0af5a8ca392f0cce850524e51b49c87
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 05f2563ddebfdc7a0f0ac0eb7cb381bb72043299aae1600ba9367c12f52b3fcc
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
F ext/wasm/api/sqlite3-wasm.c 12a096d8e58a0af0589142bae5a3c27a0c7e19846755a1a37d2c206352fbedda
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f
F ext/wasm/api/sqlite3-worker1.c-pp.js da509469755035e919c015deea41b4514b5e84c12a1332e6cc8d42cb2cc1fb75
@@ -512,7 +513,7 @@ F ext/wasm/c-pp.c 6d80d8569d85713effe8b0818a3cf51dc779e3f0bf8dc88771b8998552ee25
F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
F ext/wasm/common/testing.css 0ff15602a3ab2bad8aef2c3bd120c7ee3fd1c2054ad2ace7e214187ae68d926f
F ext/wasm/common/whwasmutil.js ae263dec9d7384f4c530f324b99d00516a4d6f26424372daee65031e00eb49b3
F ext/wasm/common/whwasmutil.js 03407d7b61b817fd135c82401987e56688a45ee4d6b9c0eced160c0000d6e4c2
F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6
@@ -530,15 +531,14 @@ F ext/wasm/fiddle/fiddle-worker.js 163d6139a93fab4bcb72064923df050d4e7c0ff0d8aa0
F ext/wasm/fiddle/fiddle.js 974b995119ac443685d7d94d3b3c58c6a36540e9eb3fed7069d5653284071715
F ext/wasm/fiddle/index.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2
F ext/wasm/index-dist.html 22379774f0ad4edcaaa8cf9c674c82e794cc557719a8addabed74eb8069d412e
F ext/wasm/index.html b768e8659b4fe311912e54d42906449d51c0f84b7f036cca47ec1f93bf3f91de
F ext/wasm/index.html dd900891844caebd9cadbddd704f66bd841d7c12fd69ce5af490e2c10fb49f45
F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54
F ext/wasm/jaccwabyt/jaccwabyt.md 37911f00db12cbcca73aa1ed72594430365f30aafae2fa9c886961de74e5e0eb
F ext/wasm/module-symbols.html 841de62fc198988b8330e238c260e70ec93028b096e1a1234db31b187a899d10
F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
F ext/wasm/speedtest1-wasmfs.html 0e9d335a9b5b5fafe6e1bc8dc0f0ca7e22e6eb916682a2d7c36218bb7d67379d
F ext/wasm/speedtest1-wasmfs.mjs ac5cadbf4ffe69e9eaac8b45e8523f030521e02bb67d654c6eb5236d9c456cbe
F ext/wasm/speedtest1-worker.html 97c2bf5f8534091ce718de05801090d5a80c3f13575996f095ba23638e1bdca0
F ext/wasm/scratchpad-wasmfs-main.html 20cf6f1a8f368e70d01e8c17200e3eaa90f1c8e1029186d836d14b83845fbe06
F ext/wasm/scratchpad-wasmfs-main.js 4c140457f4d6da9d646a49addd91edb6e9ad1643c6c48e3258b5bce24725dc18
F ext/wasm/speedtest1-wasmfs.html 7a301f4f5b6ad4f5d37fd6e7ca03a2f5d5547fd289da60a39075a93d7646d354
F ext/wasm/speedtest1-worker.html 82869822e641c1bef3ec0cd2d7d2b6a42d0b4f68a7b160fb2e1dd0b523940a9b
F ext/wasm/speedtest1-worker.js 13b57c4a41729678a1194014afec2bd5b94435dcfc8d1039dfa9a533ac819ee1
F ext/wasm/speedtest1.html ff048b4a623aa192e83e143e48f1ce2a899846dd42c023fdedc8772b6e3f07da
F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x
@@ -548,12 +548,12 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555
F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
F ext/wasm/tester1.c-pp.js 4420eb97b6b4fc79e4e156b4b8010dd9f373365f4230dd76d823fb04ce28ffde
F ext/wasm/tester1.c-pp.js 1a05497ae2b2fcca008d43b37072f9b841e1c970c06c01eb0faf675db567bfc8
F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1
F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
F ext/wasm/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd72273503ae7d5
F ext/wasm/wasmfs.make 8a4955882aaa0783b3f60a9484a1f0f3d8b6f775c0fcd17c082f31966f1bc16a
F ext/wasm/wasmfs.make cf9a68162d92ca2bcb0b9528b244cb36d5cc2d84ccc9c2d398461927d6e75aea
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
@@ -576,11 +576,11 @@ F src/auth.c 19b7ccacae3dfba23fc6f1d0af68134fa216e9040e53b0681b4715445ea030b4
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
F src/btree.c 2281facb0531d53fb42c03d1f32bc1b5903564d782ec5ff4ffc63171d960e2aa
F src/btree.c c0c93b6cb4dc133b528c1290bb4ad0f2414452f9a5758ff2b106af718874f39e
F src/btree.h aa354b9bad4120af71e214666b35132712b8f2ec11869cb2315c52c81fad45cc
F src/btreeInt.h 3b4eff7155c0cea6971dc51f62e3529934a15a6640ec607dd42a767e379cb3a9
F src/build.c a8ae3b32d9aa9bbd2c0e97d7c0dd80def9fbca408425de1608f57ee6f47f45f4
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
F src/callback.c 3520e686ab1d427f33cffb46d554d0a0a2a588866a195c69d1a17103b67dde18
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 20507cc0b0a6c19cd882fcd0eaeda32ae6a4229fb4b024cfdf3183043d9b703d
F src/date.c f73f203b3877cef866c60ab402aec2bf89597219b60635cf50cbe3c5e4533e94
@@ -590,17 +590,17 @@ F src/delete.c cd5f5cd06ed0b6a882ec1a8c2a0d73b3cecb28479ad19e9931c4706c5e2182be
F src/expr.c 8d1656b65e26af3e34f78e947ac423f0d20c214ed25a67486e433bf16ca6b543
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c a7fcbf7e66d14dbb73cf49f31489ebf66d0e6006c62b95246924a3bae9f37b36
F src/func.c 25f2e0204c011be56fc3c9a180534b68ca4866c61ec19806880136450434112d
F src/func.c b2325dc2fb0b43874fa5f2ae4e83262bdda952fc317b294dfca5ce70d5049bcd
F src/global.c 29f56a330ed9d1b5cd9b79ac0ca36f97ac3afc730ff8bfa987b0db9e559d684d
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
F src/json.c c011e8a5c2a6ef3b310412dd16de933370655d643c0dff33c81cf96a1088e223
F src/json.c 14c474fb1249a46eb44e878e2361f36abfe686b134039b0d1883d93d61505b4a
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 176d6b2cb18a6ad73b133db17f6fc351c4d9a2d510deebdb76c22bde9cfd1465
F src/main.c 512b1d45bc556edf4471a845afb7ba79e64bd5b832ab222dc195c469534cd002
F src/main.c d869b4032a2717b24ad0fd82266ea4d79304a25d942a4b332ff307009f6f10e3
F src/malloc.c 47b82c5daad557d9b963e3873e99c22570fb470719082c6658bf64e3012f7d23
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@@ -638,11 +638,11 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 37953a5f36c60bea413c3c04efcd433b6177009f508ef2ace0494728912fe2e9
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 3ab1186290a311a8ceed1286c0e286209f7fe97b2d02c7593258004ce295dd88
F src/shell.c.in d320d8a13636de06d777cc1eab981caca304e175464e98183cf4ea68d93db818
F src/sqlite.h.in f999ef3642f381d69679b2516b430dbcb6c5a2a951b7f5e43dc4751b474a5774
F src/shell.c.in d6c9ac6ab2c56eac0009ad383f6fd31a410d4cfa04ddf5875496207773fc60b1
F src/sqlite.h.in 287bce997bc287c251558b41ffb4ec025b98e7d0c74e3bf22c4919d2edb6d44c
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4
F src/sqliteInt.h dcb1a885e8b6cb78df618944b89d44361a99d0fe33e1bba2c150a855f7dc5599
F src/sqlite3ext.h 51ee0eff1f843bd233c3441d220812964d2166f3c5e5714e7a3d847a778310c4
F src/sqliteInt.h 3323b237e3f951a4e0297ce797fb7e65bade820f04aa90876a3cf7c1eee029eb
F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -705,7 +705,7 @@ F src/trigger.c ad6ab9452715fa9a8075442e15196022275b414b9141b566af8cdb7a1605f2b0
F src/update.c 0aa36561167a7c40d01163238c297297962f31a15a8d742216b3c37cdf25f731
F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c fea6fffdee3cdae917a66b70deec59d4f238057cfd6de623d15cf990c196940d
F src/util.c eac357cf07fd9be14e467e9f38e9888acf2bec8d6221903c5e57136725170880
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
F src/vdbe.c 74282a947234513872a83b0bab1b8c644ece64b3e27b053ef17677c8ff9c81e0
F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0
@@ -719,10 +719,10 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8
F src/vdbevtab.c aae4bd769410eb7e1d02c42613eec961d514459b1c3c1c63cfc84e92a137daac
F src/vtab.c 1ecf8c3745d29275688d583e12822fa984d421e0286b5ef50c137bc3bf6d7a64
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c dd843f619ac60d5dadab7109cf402432ba74dde0c301505fd1c202add07659e3
F src/wal.c cbfeeb7415baa545efa244dd34bb5af4ae953a206fed720c6fa7f1ef763ec122
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
F src/where.c 477fcc5e561ef169e6002499602af6b805156c2aae6b2f5c2c93ef8c1cd64768
F src/where.c 2dc708cf8b6a691fb79f16bbc46567497ee6f991043318d421e294b2da114d93
F src/whereInt.h c7d19902863beadec1d04e66aca39c0bcd60b74f05f0eaa7422c7005dfc5d51a
F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1
F src/whereexpr.c dc5096eca5ed503999be3bdee8a90c51361289a678d396a220912e9cb73b3c00
@@ -2043,11 +2043,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P a0d3e7571aded8d1e03908059d2d5aa5d62ec49bff099cb38f6f35df5e4b18b5
R 1ad9eb2d7a5390b633470ac87bec02c6
T *branch * json-write-cache
T *sym-json-write-cache *
P d3532eaed1cc671d8149b1bd34ead2a88fb83502a2898a5f60aea0a7daf18958
R d4ed9da3aa6365c836a379cf03c29a8d
T *branch * need-function
T *sym-need-function *
T -sym-trunk *
U drh
Z 11a0a92f5fb8088da9a1185f8dea3559
Z e80e56952de95f04df4da782eb785cf5
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
2e6fbebc41f1a24f8233b136131e6c392d7474f24946ef164fe3600afbd02357
cd67edc032983b5111ffcf6c73ca1308ef67cf2f16baa25788121827b3038d2f
+3 -4
View File
@@ -1534,7 +1534,7 @@ static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){
pPage->xParseCell(pPage, pCell, &info);
if( info.nLocal<info.nPayload ){
Pgno ovfl;
if( SQLITE_OVERFLOW(pSrc->aDataEnd, pCell, pCell+info.nLocal) ){
if( SQLITE_WITHIN(pSrc->aDataEnd, pCell, pCell+info.nLocal) ){
testcase( pSrc!=pPage );
*pRC = SQLITE_CORRUPT_BKPT;
return;
@@ -5341,7 +5341,6 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
pCur->ix = 0;
pCur->iPage++;
rc = getAndInitPage(pCur->pBt, newPgno, &pCur->pPage, pCur->curPagerFlags);
assert( pCur->pPage!=0 || rc!=SQLITE_OK );
if( rc==SQLITE_OK
&& (pCur->pPage->nCell<1 || pCur->pPage->intKey!=pCur->curIntKey)
){
@@ -5570,7 +5569,7 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
*pRes = 0;
rc = moveToLeftmost(pCur);
}else if( rc==SQLITE_EMPTY ){
assert( pCur->pgnoRoot==0 || (pCur->pPage!=0 && pCur->pPage->nCell==0) );
assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
*pRes = 1;
rc = SQLITE_OK;
}
@@ -8695,7 +8694,7 @@ static int balance_nonroot(
assert( iOvflSpace <= (int)pBt->pageSize );
for(k=0; ALWAYS(k<NB*2) && b.ixNx[k]<=j; k++){}
pSrcEnd = b.apEnd[k];
if( SQLITE_OVERFLOW(pSrcEnd, pCell, pCell+sz) ){
if( SQLITE_WITHIN(pSrcEnd, pCell, pCell+sz) ){
rc = SQLITE_CORRUPT_BKPT;
goto balance_cleanup;
}
+21
View File
@@ -474,7 +474,28 @@ FuncDef *sqlite3FindFunction(
if( pBest && (pBest->xSFunc || createFlag) ){
return pBest;
}else if( db->xFuncNeeded!=0 ){
int rc;
int (*xFN)(void*,sqlite3*,const char*,int,int) = db->xFuncNeeded;
db->xFuncNeeded = 0;
rc = xFN(db->pFuncNeededArg,db,zName,nArg,enc);
db->xFuncNeeded = xFN;
pBest = 0;
bestScore = 0;
if( rc==SQLITE_OK ){
p = (FuncDef*)sqlite3HashFind(&db->aFunc,zName);
while( p ){
int score = matchQuality(p, nArg, enc);
if( score>bestScore ){
pBest = p;
bestScore = score;
}
p = p->pNext;
}
return pBest;
}
}
return 0;
}
+4 -3
View File
@@ -1704,7 +1704,7 @@ static void kahanBabuskaNeumaierStep(
** Add a (possibly large) integer to the running sum.
*/
static void kahanBabuskaNeumaierStepInt64(volatile SumCtx *pSum, i64 iVal){
if( iVal<=-4503599627370496LL || iVal>=+4503599627370496LL ){
if( iVal<=-4503599627370496 || iVal>=+4503599627370496 ){
i64 iBig, iSm;
iSm = iVal % 16384;
iBig = iVal - iSm;
@@ -1722,7 +1722,7 @@ static void kahanBabuskaNeumaierInit(
volatile SumCtx *p,
i64 iVal
){
if( iVal<=-4503599627370496LL || iVal>=+4503599627370496LL ){
if( iVal<=-4503599627370496 || iVal>=+4503599627370496 ){
i64 iSm = iVal % 16384;
p->rSum = (double)(iVal - iSm);
p->rErr = (double)iSm;
@@ -1764,10 +1764,11 @@ static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
p->ovrfl = 1;
kahanBabuskaNeumaierInit(p, p->iSum);
p->approx = 1;
kahanBabuskaNeumaierStepInt64(p, sqlite3_value_int64(argv[0]));
kahanBabuskaNeumaierStep(p, sqlite3_value_double(argv[0]));
}
}
}else{
p->approx = 1;
if( type==SQLITE_INTEGER ){
kahanBabuskaNeumaierStepInt64(p, sqlite3_value_int64(argv[0]));
}else{
+54 -93
View File
@@ -135,10 +135,9 @@ struct JsonParse {
u8 nErr; /* Number of errors seen */
u8 oom; /* Set to true if out of memory */
u8 hasNonstd; /* True if input uses non-standard features like JSON5 */
u8 nRef; /* Number of references to this object */
int nJson; /* Length of the zJson string in bytes */
u32 iErr; /* Error location in zJson[] */
u32 iHold; /* Creation sequence number, for LRU replacement */
u32 iHold; /* Replace cache line with the lowest iHold value */
};
/*
@@ -506,19 +505,14 @@ static void jsonParseReset(JsonParse *pParse){
pParse->nAlloc = 0;
sqlite3_free(pParse->aUp);
pParse->aUp = 0;
pParse->nRef = 0;
}
/*
** Free a JsonParse object that was obtained from sqlite3_malloc().
*/
static void jsonParseFree(JsonParse *pParse){
if( pParse->nRef>1 ){
pParse->nRef--;
}else{
jsonParseReset(pParse);
sqlite3_free(pParse);
}
jsonParseReset(pParse);
sqlite3_free(pParse);
}
/*
@@ -1522,7 +1516,6 @@ static int jsonParse(
memset(pParse, 0, sizeof(*pParse));
if( zJson==0 ) return 1;
pParse->zJson = zJson;
/* printf("JSON parse: %s\n", zJson); fflush(stdout); */
i = jsonParseValue(pParse, 0);
if( pParse->oom ) i = -1;
if( i>0 ){
@@ -1603,21 +1596,11 @@ static int jsonParseFindParents(JsonParse *pParse){
** Obtain a complete parse of the JSON found in the first argument
** of the argv array. Use the sqlite3_get_auxdata() cache for this
** parse if it is available. If the cache is not available or if it
** is no longer valid, parse the JSON again and return the new parse.
** is no longer valid, parse the JSON again and return the new parse,
** and also register the new parse so that it will be available for
** future sqlite3_get_auxdata() calls.
**
** If a new parse is created, it is stored in the cache unless bWrite
** is true. If the parse is cached and pErrCtx!=0 then the caller does
** not need to free the returned parse since the parse belongs to the
** cache and will be freed when the cache is cleared. On the other hand,
** the returned parse should be treated as read-only.
**
** If the bWrite field is true, then it is assumed that the caller will
** make changes to the parse. In this case, the parse is not cached (or
** it is removed from the cache). Ownership of the parse passes to the
** caller and the caller is expected to call jsonParseFree() when it has
** finished using the parse.
**
** If an error occurs and pErrCtx!=0 then an error is reported on pErrCtx
** If an error occurs and pErrCtx!=0 then report the error on pErrCtx
** and return NULL.
**
** If an error occurs and pErrCtx==0 then return the Parse object with
@@ -1629,8 +1612,7 @@ static int jsonParseFindParents(JsonParse *pParse){
static JsonParse *jsonParseCached(
sqlite3_context *pCtx,
sqlite3_value **argv,
sqlite3_context *pErrCtx,
int bWrite
sqlite3_context *pErrCtx
){
const char *zJson = (const char*)sqlite3_value_text(argv[0]);
int nJson = sqlite3_value_bytes(argv[0]);
@@ -1647,19 +1629,12 @@ static JsonParse *jsonParseCached(
iMinKey = iKey;
break;
}
assert( p->nRef==1 );
if( pMatch==0
&& p->nJson==nJson
&& memcmp(p->zJson,zJson,nJson)==0
){
p->nErr = 0;
pMatch = p;
if( bWrite ){
p->nRef = 2;
sqlite3_set_auxdata(pCtx, JSON_CACHE_ID+iKey, 0, 0);
/* printf("JSON cache hit and purge (%d)\n", iKey); fflush(stdout); */
}
/* else{ printf("JSON cache hit (%d)\n", iKey); fflush(stdout); } */
}else if( p->iHold<iMinHold ){
iMinHold = p->iHold;
iMinKey = iKey;
@@ -1671,7 +1646,6 @@ static JsonParse *jsonParseCached(
if( pMatch ){
pMatch->nErr = 0;
pMatch->iHold = iMaxHold+1;
assert( pMatch->nRef==1 );
return pMatch;
}
p = sqlite3_malloc64( sizeof(*p) + nJson + 1 );
@@ -1682,11 +1656,9 @@ static JsonParse *jsonParseCached(
memset(p, 0, sizeof(*p));
p->zJson = (char*)&p[1];
memcpy((char*)p->zJson, zJson, nJson+1);
/* printf("JSON cache miss\n"); fflush(stdout); */
if( jsonParse(p, pErrCtx, p->zJson) ){
if( pErrCtx==0 ){
p->nErr = 1;
p->nRef = 1;
return p;
}
sqlite3_free(p);
@@ -1694,15 +1666,9 @@ static JsonParse *jsonParseCached(
}
p->nJson = nJson;
p->iHold = iMaxHold+1;
p->nRef = 1;
if( !bWrite ){
/* printf("JSON cache insert (%d)\n", iMinKey); fflush(stdout); */
sqlite3_set_auxdata(pCtx, JSON_CACHE_ID+iMinKey, p,
(void(*)(void*))jsonParseFree);
p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iMinKey);
}
assert( p==0 || p->nRef==1 );
return p;
sqlite3_set_auxdata(pCtx, JSON_CACHE_ID+iMinKey, p,
(void(*)(void*))jsonParseFree);
return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iMinKey);
}
/*
@@ -2129,7 +2095,7 @@ static void jsonArrayLengthFunc(
u32 i;
JsonNode *pNode;
p = jsonParseCached(ctx, argv, ctx, 0);
p = jsonParseCached(ctx, argv, ctx);
if( p==0 ) return;
assert( p->nNode );
if( argc==2 ){
@@ -2191,7 +2157,7 @@ static void jsonExtractFunc(
JsonString jx;
if( argc<2 ) return;
p = jsonParseCached(ctx, argv, ctx, 0);
p = jsonParseCached(ctx, argv, ctx);
if( p==0 ) return;
if( argc==2 ){
/* With a single PATH argument */
@@ -2347,27 +2313,25 @@ static void jsonPatchFunc(
int argc,
sqlite3_value **argv
){
JsonParse *pX; /* The JSON that is being patched */
JsonParse *pY; /* The patch */
JsonParse x; /* The JSON that is being patched */
JsonParse y; /* The patch */
JsonNode *pResult; /* The result of the merge */
UNUSED_PARAMETER(argc);
pX = jsonParseCached(ctx, argv, ctx, 1);
if( pX==0 ) return;
pY = jsonParseCached(ctx, argv+1, ctx, 1);
if( pY==0 ){
jsonParseFree(pX);
if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){
jsonParseReset(&x);
return;
}
pResult = jsonMergePatch(pX, 0, pY->aNode);
assert( pResult!=0 || pX->oom );
pResult = jsonMergePatch(&x, 0, y.aNode);
assert( pResult!=0 || x.oom );
if( pResult ){
jsonReturnJson(pResult, ctx, 0);
}else{
sqlite3_result_error_nomem(ctx);
}
jsonParseFree(pX);
jsonParseFree(pY);
jsonParseReset(&x);
jsonParseReset(&y);
}
@@ -2423,27 +2387,26 @@ static void jsonRemoveFunc(
int argc,
sqlite3_value **argv
){
JsonParse *p; /* The parse */
JsonParse x; /* The parse */
JsonNode *pNode;
const char *zPath;
u32 i;
if( argc<1 ) return;
p = jsonParseCached(ctx, argv, ctx, 1);
if( p==0 ) return;
assert( p->nNode );
if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
assert( x.nNode );
for(i=1; i<(u32)argc; i++){
zPath = (const char*)sqlite3_value_text(argv[i]);
if( zPath==0 ) goto remove_done;
pNode = jsonLookup(p, zPath, 0, ctx);
if( p->nErr ) goto remove_done;
pNode = jsonLookup(&x, zPath, 0, ctx);
if( x.nErr ) goto remove_done;
if( pNode ) pNode->jnFlags |= JNODE_REMOVE;
}
if( (p->aNode[0].jnFlags & JNODE_REMOVE)==0 ){
jsonReturnJson(p->aNode, ctx, 0);
if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){
jsonReturnJson(x.aNode, ctx, 0);
}
remove_done:
jsonParseFree(p);
jsonParseReset(&x);
}
/*
@@ -2457,7 +2420,7 @@ static void jsonReplaceFunc(
int argc,
sqlite3_value **argv
){
JsonParse *p; /* The parse */
JsonParse x; /* The parse */
JsonNode *pNode;
const char *zPath;
u32 i;
@@ -2467,13 +2430,12 @@ static void jsonReplaceFunc(
jsonWrongNumArgs(ctx, "replace");
return;
}
p = jsonParseCached(ctx, argv, ctx, 1);
if( p==0 ) return;
assert( p->nNode );
if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
assert( x.nNode );
for(i=1; i<(u32)argc; i+=2){
zPath = (const char*)sqlite3_value_text(argv[i]);
pNode = jsonLookup(p, zPath, 0, ctx);
if( p->nErr ) goto replace_err;
pNode = jsonLookup(&x, zPath, 0, ctx);
if( x.nErr ) goto replace_err;
if( pNode ){
assert( pNode->eU==0 || pNode->eU==1 || pNode->eU==4 );
testcase( pNode->eU!=0 && pNode->eU!=1 );
@@ -2482,14 +2444,14 @@ static void jsonReplaceFunc(
pNode->u.iReplace = i + 1;
}
}
if( p->aNode[0].jnFlags & JNODE_REPLACE ){
assert( p->aNode[0].eU==4 );
sqlite3_result_value(ctx, argv[p->aNode[0].u.iReplace]);
if( x.aNode[0].jnFlags & JNODE_REPLACE ){
assert( x.aNode[0].eU==4 );
sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
}else{
jsonReturnJson(p->aNode, ctx, argv);
jsonReturnJson(x.aNode, ctx, argv);
}
replace_err:
jsonParseFree(p);
jsonParseReset(&x);
}
@@ -2510,7 +2472,7 @@ static void jsonSetFunc(
int argc,
sqlite3_value **argv
){
JsonParse *p; /* The parse */
JsonParse x; /* The parse */
JsonNode *pNode;
const char *zPath;
u32 i;
@@ -2522,17 +2484,16 @@ static void jsonSetFunc(
jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert");
return;
}
p = jsonParseCached(ctx, argv, ctx, 1);
if( p==0 ) return;
assert( p->nNode );
if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
assert( x.nNode );
for(i=1; i<(u32)argc; i+=2){
zPath = (const char*)sqlite3_value_text(argv[i]);
bApnd = 0;
pNode = jsonLookup(p, zPath, &bApnd, ctx);
if( p->oom ){
pNode = jsonLookup(&x, zPath, &bApnd, ctx);
if( x.oom ){
sqlite3_result_error_nomem(ctx);
goto jsonSetDone;
}else if( p->nErr ){
}else if( x.nErr ){
goto jsonSetDone;
}else if( pNode && (bApnd || bIsSet) ){
testcase( pNode->eU!=0 && pNode->eU!=1 );
@@ -2542,14 +2503,14 @@ static void jsonSetFunc(
pNode->u.iReplace = i + 1;
}
}
if( p->aNode[0].jnFlags & JNODE_REPLACE ){
assert( p->aNode[0].eU==4 );
sqlite3_result_value(ctx, argv[p->aNode[0].u.iReplace]);
if( x.aNode[0].jnFlags & JNODE_REPLACE ){
assert( x.aNode[0].eU==4 );
sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
}else{
jsonReturnJson(p->aNode, ctx, argv);
jsonReturnJson(x.aNode, ctx, argv);
}
jsonSetDone:
jsonParseFree(p);
jsonParseReset(&x);
}
/*
@@ -2568,7 +2529,7 @@ static void jsonTypeFunc(
const char *zPath;
JsonNode *pNode;
p = jsonParseCached(ctx, argv, ctx, 0);
p = jsonParseCached(ctx, argv, ctx);
if( p==0 ) return;
if( argc==2 ){
zPath = (const char*)sqlite3_value_text(argv[1]);
@@ -2595,7 +2556,7 @@ static void jsonValidFunc(
JsonParse *p; /* The parse */
UNUSED_PARAMETER(argc);
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
p = jsonParseCached(ctx, argv, 0, 0);
p = jsonParseCached(ctx, argv, 0);
if( p==0 || p->oom ){
sqlite3_result_error_nomem(ctx);
sqlite3_free(p);
@@ -2641,7 +2602,7 @@ static void jsonErrorFunc(
JsonParse *p; /* The parse */
UNUSED_PARAMETER(argc);
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
p = jsonParseCached(ctx, argv, 0, 0);
p = jsonParseCached(ctx, argv, 0);
if( p==0 || p->oom ){
sqlite3_result_error_nomem(ctx);
sqlite3_free(p);
+25
View File
@@ -1219,6 +1219,9 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){
db->trace.xV2(SQLITE_TRACE_CLOSE, db->pTraceArg, db, 0);
}
/* Free the function-needed payload pointer */
if( db->xFuncNeededFree ) db->xFuncNeededFree(db->pFuncNeededArg);
/* Force xDisconnect calls on all virtual tables */
disconnectAllVtab(db);
@@ -3705,6 +3708,28 @@ int sqlite3_collation_needed16(
}
#endif /* SQLITE_OMIT_UTF16 */
/*
** Register a collation sequence factory callback with the database handle
** db. Replace any previously installed collation sequence factory.
*/
int sqlite3_function_needed(
sqlite3 *db,
void *pFuncNeededArg,
int (*xFuncNeeded)(void*,sqlite3*,const char*,int,int),
void (*xFuncNeededFree)(void*)
){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
sqlite3_mutex_enter(db->mutex);
if( db->xFuncNeededFree ) db->xFuncNeededFree(db->pFuncNeededArg);
db->pFuncNeededArg = pFuncNeededArg;
db->xFuncNeeded = xFuncNeeded;
db->xFuncNeededFree = xFuncNeededFree;
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
#ifndef SQLITE_OMIT_DEPRECATED
/*
** This function is now an anachronism. It used to be used to recover from a
+53 -20
View File
@@ -5383,6 +5383,57 @@ static void shellUSleepFunc(
#define OPEN_DB_KEEPALIVE 0x001 /* Return after error if true */
#define OPEN_DB_ZIPFILE 0x002 /* Open as ZIP if name matches *.zip */
/*
** Unknown function callback
*/
static int shellUnknownFunction(
void *pUserData,
sqlite3 *db,
const char *zFunc,
int nArg,
int enc
){
ShellState *p = (ShellState*)pUserData;
(void)enc;
(void)nArg;
if( sqlite3_stricmp(zFunc,"strtod")==0 ){
sqlite3_create_function(db, "strtod", 1, SQLITE_UTF8, 0,
shellStrtod, 0, 0);
}else
if( sqlite3_stricmp(zFunc,"dtostr")==0 ){
sqlite3_create_function(db, "dtostr", 1, SQLITE_UTF8, 0,
shellDtostr, 0, 0);
sqlite3_create_function(db, "dtostr", 2, SQLITE_UTF8, 0,
shellDtostr, 0, 0);
}else
if( sqlite3_stricmp(zFunc,"shell_add_schema")==0 ){
sqlite3_create_function(db, "shell_add_schema", 3, SQLITE_UTF8, 0,
shellAddSchemaName, 0, 0);
}else
if( sqlite3_stricmp(zFunc,"shell_module_schema")==0 ){
sqlite3_create_function(db, "shell_module_schema", 1, SQLITE_UTF8, 0,
shellModuleSchema, 0, 0);
}else
if( sqlite3_stricmp(zFunc,"shell_putsnl")==0 ){
sqlite3_create_function(db, "shell_putsnl", 1, SQLITE_UTF8, p,
shellPutsFunc, 0, 0);
}else
if( sqlite3_stricmp(zFunc,"usleep")==0 ){
sqlite3_create_function(db, "usleep",1,SQLITE_UTF8,0,
shellUSleepFunc, 0, 0);
}
#ifndef SQLITE_NOHAVE_SYSTEM
else
if( sqlite3_stricmp(zFunc,"edit")==0 ){
sqlite3_create_function(db, "edit", 1, SQLITE_UTF8, 0,
editFunc, 0, 0);
sqlite3_create_function(db, "edit", 2, SQLITE_UTF8, 0,
editFunc, 0, 0);
}
#endif
return SQLITE_OK;
}
/*
** Make sure the database is open. If it is not, then open it. If
** the database fails to open, print an error message and exit.
@@ -5503,27 +5554,9 @@ static void open_db(ShellState *p, int openFlags){
}
#endif
sqlite3_create_function(p->db, "strtod", 1, SQLITE_UTF8, 0,
shellStrtod, 0, 0);
sqlite3_create_function(p->db, "dtostr", 1, SQLITE_UTF8, 0,
shellDtostr, 0, 0);
sqlite3_create_function(p->db, "dtostr", 2, SQLITE_UTF8, 0,
shellDtostr, 0, 0);
sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
shellAddSchemaName, 0, 0);
sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
shellModuleSchema, 0, 0);
sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
shellPutsFunc, 0, 0);
sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
shellUSleepFunc, 0, 0);
#ifndef SQLITE_NOHAVE_SYSTEM
sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
editFunc, 0, 0);
sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
editFunc, 0, 0);
#endif
sqlite3_function_needed(p->db, p, shellUnknownFunction, 0);
if( p->openMode==SHELL_OPEN_ZIPFILE ){
char *zSql = sqlite3_mprintf(
"CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
+48
View File
@@ -6206,6 +6206,54 @@ int sqlite3_create_collation16(
int(*xCompare)(void*,int,const void*,int,const void*)
);
/*
** CAPI3REF: Function Needed Callbacks
** METHOD: sqlite3
**
** The sqlite3_function_needed(D,P,C,X) interface registers a callback
** function C which is invoked whenever the SQL parser encounters an
** unknown SQL function. The callback may optionally register a suitable
** implementation for that unknown function (using [sqlite3_create_function()]
** or similar), in which case parsing will continue normally. In this way,
** applications with hundreds or thousands of seldom-used application defined
** SQL functions can avoid having register them at start-up and instead
** register each function if and only if it it actually gets used.
**
** ^If the callback function C has been registered using the
** sqlite3_function_needed(D,P,C,X), then whenever the SQL parser encounters
** an unknown SQL function, it will invoke the C callback with 5 arguments:
** P, D, F, N, E. P is a copy of the generic pointer P parameter to
** the original sqlite3_function_needed() call that registered the
** callback. D is the database connection. F is the name of the unknown
** function (UTF-8 encoded and zero-terminated but in an arbitrary case).
** N is the number of arguments on the F function.
** E is the preferred text encoding.
**
** If the C callback registers a new function with the correct
** name and number of arguments and if the callback returns SQLITE_OK, then
** the newly registered function is used and parsing continues. If an
** appropriate function does not get registered, or if the callback returns
** anything other than SQLITE_OK, then an "unknown function" error is generated
** as normal.
**
** Only a single function-needed callback is supported per database connection.
** Each call to sqlite3_function_needed() replaces the callback identified
** by the previous call to sqlite3_function_needed(). The function-needed
** callback mechanism may be disabled by invoking sqlite3_function_needed(D,P,C,X)
** using a NULL pointer for the C parameter.
**
** The X argument to sqlite3_function_needed(D,P,C,X) is an optional
** destructor for generic pointer parameter P. If X and C are both not NULL,
** then X(P) is invoked when the database connection closes or at the next
** call to sqlite3_function_needed().
*/
int sqlite3_function_needed(
sqlite3*,
void*,
int(*)(void*,sqlite3*,const char*,int,int),
void(*)(void*)
);
/*
** CAPI3REF: Collation Needed Callbacks
** METHOD: sqlite3
+4
View File
@@ -361,6 +361,8 @@ struct sqlite3_api_routines {
int (*value_encoding)(sqlite3_value*);
/* Version 3.41.0 and later */
int (*is_interrupted)(sqlite3*);
/* Version 3.43.0 and later */
int (*function_needed)(sqlite3*,void*,const char*,int,int);
};
/*
@@ -689,6 +691,8 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_value_encoding sqlite3_api->value_encoding
/* Version 3.41.0 and later */
#define sqlite3_is_interrupted sqlite3_api->is_interrupted
/* Version 3.43.0 and later */
#define sqlite3_function_needed sqlite3_api->function_needed
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
+5 -26
View File
@@ -889,31 +889,8 @@ typedef INT16_TYPE LogEst;
** the end of buffer S. This macro returns true if P points to something
** contained within the buffer S.
*/
#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E)))
#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E)))
/*
** P is one byte past the end of a large buffer. Return true if a span of bytes
** between S..E crosses the end of that buffer. In other words, return true
** if the sub-buffer S..E-1 overflows the buffer show last byte is P-1.
**
** S is the start of the span. E is one byte past the end of end of span.
**
** P
** |-----------------| FALSE
** |-------|
** S E
**
** P
** |-----------------|
** |-------| TRUE
** S E
**
** P
** |-----------------|
** |-------| FALSE
** S E
*/
#define SQLITE_OVERFLOW(P,S,E) (((uptr)(S)<(uptr)(P))&&((uptr)(E)>(uptr)(P)))
/*
** Macros to determine whether the machine is big or little endian,
@@ -1697,6 +1674,9 @@ struct sqlite3 {
int (*xWalCallback)(void *, sqlite3 *, const char *, int);
void *pWalArg;
#endif
int(*xFuncNeeded)(void*,sqlite3*,const char*,int,int);
void *pFuncNeededArg;
void(*xFuncNeededFree)(void*);
void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
void *pCollNeededArg;
@@ -4631,8 +4611,7 @@ struct FpDecode {
char isSpecial; /* 1: Infinity 2: NaN */
int n; /* Significant digits in the decode */
int iDP; /* Location of the decimal point */
char *z; /* Start of significant digits */
char zBuf[24]; /* Storage for significant digits */
char z[24]; /* Significiant digits */
};
void sqlite3FpDecode(FpDecode*,double,int,int);
+11 -22
View File
@@ -405,11 +405,11 @@ static void dekkerMul2(volatile double *x, double y, double yy){
double hx, hy;
u64 m;
memcpy(&m, (void*)&x[0], 8);
m &= 0xfffffffffc000000LL;
m &= 0xfffffffffc000000L;
memcpy(&hx, &m, 8);
tx = x[0] - hx;
memcpy(&m, &y, 8);
m &= 0xfffffffffc000000LL;
m &= 0xfffffffffc000000L;
memcpy(&hy, &m, 8);
ty = y - hy;
p = hx*hy;
@@ -933,18 +933,12 @@ int sqlite3Atoi(const char *z){
** n is positive. Or round to -n signficant digits after the
** decimal point if n is negative. No rounding is performed if
** n is zero.
**
** The significant digits of the decimal representation are
** stored in p->z[] which is a often (but not always) a pointer
** into the middle of p->zBuf[]. There are p->n significant digits.
** The p->z[] array is *not* zero-terminated.
*/
void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
int i;
u64 v;
int e, exp = 0;
p->isSpecial = 0;
p->z = p->zBuf;
/* Convert negative numbers to positive. Deal with Infinity, 0.0, and
** NaN. */
@@ -955,7 +949,7 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
p->sign = '+';
p->n = 1;
p->iDP = 1;
p->z = "0";
p->z[0] = '0';
return;
}else{
p->sign = '+';
@@ -963,7 +957,7 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
memcpy(&v,&r,8);
e = v>>52;
if( (e&0x7ff)==0x7ff ){
p->isSpecial = 1 + (v!=0x7ff0000000000000LL);
p->isSpecial = 1 + (v!=0x7ff0000000000000L);
p->n = 0;
p->iDP = 0;
return;
@@ -1029,25 +1023,21 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
/* Extract significant digits. */
i = sizeof(p->zBuf)-1;
assert( v>0 );
while( v ){ p->zBuf[i--] = (v%10) + '0'; v /= 10; }
assert( i>=0 && i<sizeof(p->zBuf)-1 );
p->n = sizeof(p->zBuf) - 1 - i;
assert( p->n>0 );
assert( p->n<sizeof(p->zBuf) );
i = sizeof(p->z)-1;
while( v ){ p->z[i--] = (v%10) + '0'; v /= 10; }
p->n = sizeof(p->z) - 1 - i;
p->iDP = p->n + exp;
if( iRound<0 ){
iRound = p->iDP - iRound;
if( iRound==0 && p->zBuf[i+1]>='5' ){
if( iRound==0 && p->z[i+1]>='5' ){
iRound = 1;
p->zBuf[i--] = '0';
p->z[i--] = '0';
p->n++;
p->iDP++;
}
}
if( iRound>0 && (iRound<p->n || p->n>mxRound) ){
char *z = &p->zBuf[i+1];
char *z = &p->z[i+1];
if( iRound>mxRound ) iRound = mxRound;
p->n = iRound;
if( z[iRound]>='5' ){
@@ -1067,8 +1057,7 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
}
}
}
p->z = &p->zBuf[i+1];
assert( i+p->n < sizeof(p->zBuf) );
memmove(p->z, &p->z[i+1], p->n);
while( ALWAYS(p->n>0) && p->z[p->n-1]=='0' ){ p->n--; }
}
+14 -4
View File
@@ -1818,15 +1818,23 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
nByte = sizeof(WalIterator)
+ (nSegment-1)*sizeof(struct WalSegment)
+ iLast*sizeof(ht_slot);
p = (WalIterator *)sqlite3_malloc64(nByte
+ sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
);
p = (WalIterator *)sqlite3_malloc64(nByte);
if( !p ){
return SQLITE_NOMEM_BKPT;
}
memset(p, 0, nByte);
p->nSegment = nSegment;
aTmp = (ht_slot*)&(((u8*)p)[nByte]);
/* Allocate temporary space used by the merge-sort routine. This block
** of memory will be freed before this function returns.
*/
aTmp = (ht_slot *)sqlite3_malloc64(
sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
);
if( !aTmp ){
rc = SQLITE_NOMEM_BKPT;
}
for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){
WalHashLoc sLoc;
@@ -1854,6 +1862,8 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
p->aSegment[i].aPgno = (u32 *)sLoc.aPgno;
}
}
sqlite3_free(aTmp);
if( rc!=SQLITE_OK ){
walIteratorFree(p);
p = 0;
+1 -2
View File
@@ -5122,10 +5122,9 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
/* TUNING: A full-scan of a VIEW or subquery in the outer loop
** is not so bad. */
if( iLoop==0 && (pWLoop->wsFlags & WHERE_VIEWSCAN)!=0 && nLoop>1 ){
if( iLoop==0 && (pWLoop->wsFlags & WHERE_VIEWSCAN)!=0 ){
rCost += -10;
nOut += -30;
WHERETRACE(0x80,("VIEWSCAN cost reduction for %c\n",pWLoop->cId));
}
/* Check to see if pWLoop should be added to the set of