Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 676f17a570 |
@@ -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
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 || {}
|
||||
);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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>
|
||||
@@ -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);
|
||||
})();
|
||||
@@ -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
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
@@ -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'
|
||||
|
||||
@@ -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
@@ -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
|
||||
########################################################################
|
||||
|
||||
@@ -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
@@ -1 +1 @@
|
||||
2e6fbebc41f1a24f8233b136131e6c392d7474f24946ef164fe3600afbd02357
|
||||
cd67edc032983b5111ffcf6c73ca1308ef67cf2f16baa25788121827b3038d2f
|
||||
+3
-4
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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--; }
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user