aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in7
-rw-r--r--autoconf/tea/teaish.tcl7
-rw-r--r--autosetup/sqlite-config.tcl41
-rw-r--r--main.mk51
-rw-r--r--manifest31
-rw-r--r--manifest.uuid2
-rw-r--r--src/expr.c7
-rw-r--r--src/insert.c5
-rw-r--r--src/sqliteInt.h2
-rw-r--r--src/vdbe.c33
-rw-r--r--test/strict1.test97
-rw-r--r--tool/buildtclext.tcl68
12 files changed, 276 insertions, 75 deletions
diff --git a/Makefile.in b/Makefile.in
index 57728b049..995bbde44 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -213,6 +213,13 @@ TCL_CONFIG_SH = @TCL_CONFIG_SH@
#TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
#TCL_EXEC_PREFIX = @TCL_EXEC_PREFIX@
#TCL_VERSION = @TCL_VERSION@
+TCL_MAJOR_VERSION = @TCL_MAJOR_VERSION@
+# ^^^ main.mk optionally uses this for determining the Tcl extension's
+# DLL name.
+TCL_EXT_DLL_BASENAME = @TCL_EXT_DLL_BASENAME@
+# ^^^ base name of the Tcl extension DLL. It varies by platform and
+# Tcl version.
+
#
# $(TCLLIBDIR) = where to install the tcl plugin. If this is empty, it
# is calculated at make-time by the targets which need it but we
diff --git a/autoconf/tea/teaish.tcl b/autoconf/tea/teaish.tcl
index c52d58f07..47e0ea701 100644
--- a/autoconf/tea/teaish.tcl
+++ b/autoconf/tea/teaish.tcl
@@ -64,13 +64,18 @@ apply {{dir} {
-name.pkg sqlite3
-version $version
-name.dist $distname
- -vsatisfies 8.6-
-libDir sqlite$version
-pragmas $pragmas
-src generic/tclsqlite3.c
}
+ # We should also have:
+ # -vsatisfies 8.6-
+ # But at least one platform is failing this vsatisfies check
+ # for no apparent reason:
+ # https://sqlite.org/forum/forumpost/fde857fb8101a4be
}} [teaish-get -dir]
+
#
# Must return either an empty string or a list in the form accepted by
# autosetup's [options] function.
diff --git a/autosetup/sqlite-config.tcl b/autosetup/sqlite-config.tcl
index 85fe41438..bb8112320 100644
--- a/autosetup/sqlite-config.tcl
+++ b/autosetup/sqlite-config.tcl
@@ -217,6 +217,11 @@ proc sqlite-configure {buildMode configScript} {
=> {This legacy flag has no effect on the library but may influence
the generated sqlite_cfg.h by adding #define HAVE_LFS}
}
+ {canonical} {
+ column-metadata => {Enable the column metadata APIs}
+ # ^^^ Affects how sqlite3.c is generated, so is not available in
+ # the autoconf build.
+ }
}
# Options for TCL support
@@ -227,8 +232,6 @@ proc sqlite-configure {buildMode configScript} {
This tree requires TCL for code generation but can use the in-tree
copy of autosetup/jimsh0.c for that. The SQLite TCL extension and the
test code require a canonical tclsh.}
- }
- {canonical} {
with-tcl:DIR
=> {Directory containing tclConfig.sh or a directory one level up from
that, from which we can derive a directory containing tclConfig.sh.
@@ -236,11 +239,10 @@ proc sqlite-configure {buildMode configScript} {
the --prefix flag.}
with-tclsh:PATH
=> {Full pathname of tclsh to use. It is used for (A) trying to find
- tclConfig.sh and (B) all TCL-based code generation. Warning: if
- its containing dir has multiple tclsh versions, it may select the
+ tclConfig.sh and (B) all TCL-based code generation. Use --with-tcl
+ unless you have a specific need for this flag. Warning: if its
+ containing dir has multiple tclsh versions, it may select the
wrong tclConfig.sh!}
- }
- {canonical} {
static-tclsqlite3=0
=> {Statically-link tclsqlite3. This only works if TCL support is
enabled and all requisite libraries are available in
@@ -772,7 +774,8 @@ proc sqlite-handle-common-feature-flags {} {
sqlite-add-feature-flag -DSQLITE_ENABLE_MEMSYS3
}
}
- scanstatus -DSQLITE_ENABLE_STMT_SCANSTATUS {}
+ scanstatus -DSQLITE_ENABLE_STMT_SCANSTATUS {}
+ column-metadata -DSQLITE_ENABLE_COLUMN_METADATA {}
}] {
if {$boolFlag ni $::autosetup(options)} {
# Skip flags which are in the canonical build but not
@@ -1969,13 +1972,14 @@ proc sqlite-check-tcl {} {
# TCLLIBDIR from here, which will cause the canonical makefile to
# use this one rather than to re-calculate it at make-time.
set tcllibdir [get-env TCLLIBDIR ""]
+ set sq3Ver [get-define PACKAGE_VERSION]
if {"" eq $tcllibdir} {
# Attempt to extract TCLLIBDIR from TCL's $auto_path
if {"" ne $with_tclsh &&
[catch {exec echo "puts stdout \$auto_path" | "$with_tclsh"} result] == 0} {
foreach i $result {
if {[file isdir $i]} {
- set tcllibdir $i/sqlite3
+ set tcllibdir $i/sqlite${sq3Ver}
break
}
}
@@ -2111,9 +2115,26 @@ proc sqlite-determine-codegen-tcl {} {
# sqlite-determine-codegen-tcl.
proc sqlite-handle-tcl {} {
sqlite-check-tcl
- if {"canonical" eq $::sqliteConfig(build-mode)} {
- msg-result "TCL for code generation: [sqlite-determine-codegen-tcl]"
+ if {"canonical" ne $::sqliteConfig(build-mode)} return
+ msg-result "TCL for code generation: [sqlite-determine-codegen-tcl]"
+
+ # Determine the base name of the Tcl extension's DLL
+ #
+ if {[get-define HAVE_TCL]} {
+ if {[string match *-cygwin [get-define host]]} {
+ set libname cyg
+ } else {
+ set libname lib
+ }
+ if {[get-define TCL_MAJOR_VERSION] > 8} {
+ append libname tcl9
+ }
+ append libname sqlite
+ } else {
+ set libname ""
}
+ define TCL_EXT_DLL_BASENAME $libname
+ # The extension is added in the makefile
}
########################################################################
diff --git a/main.mk b/main.mk
index 405d5672c..34c1cc3cf 100644
--- a/main.mk
+++ b/main.mk
@@ -1047,13 +1047,17 @@ $(T.tcl.env.sh): $(TCLSH_CMD) $(TCL_CONFIG_SH) $(MAKEFILE_LIST)
@if [ x = "x$(TCL_CONFIG_SH)" ]; then \
echo 'TCL_CONFIG_SH must be set to point to a "tclConfig.sh"' 1>&2; exit 1; \
fi; \
- if [ x != "x$(TCLLIBDIR)" ]; then echo TCLLIBDIR="$(TCLLIBDIR)"; else \
+ if [ x != "x$(TCLLIBDIR)" ]; then \
+ echo "# generated by main.mk"; \
+ echo TCLLIBDIR="$(TCLLIBDIR)"; \
+ else \
ld= ; \
for d in `echo "puts stdout \\$$auto_path" | $(TCLSH_CMD)`; do \
if [ -d "$$d" ]; then ld=$$d; break; fi; \
done; \
if [ x = "x$$ld" ]; then echo "Cannot determine TCLLIBDIR" 1>&2; exit 1; fi; \
- echo "TCLLIBDIR=$$ld/sqlite3"; \
+ echo "# generated by main.mk"; \
+ echo "TCLLIBDIR=$$ld/sqlite3$(PACKAGE_VERSION)"; \
fi > $@; \
echo ". \"$(TCL_CONFIG_SH)\" || exit \$$?" >> $@; \
echo "Created $@"
@@ -1623,14 +1627,28 @@ install-headers: sqlite3.h $(install-dir.include)
install: install-headers
#
+# If TCL_EXT_DLL_BASENAME is not set then guess the Tcl extension's
+# DLL name depending on the Tcl version. This does not account for
+# Cygwin's naming - the canonical build will usually set it, but
+# static makefiles importing this one will need to account for that on
+# their own. They can do that by setting libtclsqlite3.basename-[89]
+# to appropriate names (cygsqlite resp. cygtcl9sqlite).
+#
+TCL_MAJOR_VERSION ?= 0
+libtclsqlite3.basename-8 ?= libsqlite
+libtclsqlite3.basename-9 ?= libtcl9sqlite
+TCL_EXT_DLL_BASENAME ?= $(libtclsqlite3.basename-$(TCL_MAJOR_VERSION))
+libtclsqlite3.DLL ?= $(TCL_EXT_DLL_BASENAME)$(PACKAGE_VERSION)$(T.dll)
+
+#
# libtclsqlite3...
#
-pkgIndex.tcl:
- echo 'package ifneeded sqlite3 $(PACKAGE_VERSION) [list load [file join $$dir libtclsqlite3[info sharedlibextension]] Sqlite3]' > $@
+pkgIndex.tcl: $(TOP)/main.mk
+ echo 'package ifneeded sqlite3 $(PACKAGE_VERSION) [list load [file join $$dir $(libtclsqlite3.DLL)] Sqlite3]' > $@
pkgIndex.tcl-1: pkgIndex.tcl
pkgIndex.tcl-0 pkgIndex.tcl-:
tcl: pkgIndex.tcl-$(HAVE_TCL)
-libtclsqlite3.DLL = libtclsqlite3$(T.dll)
+
$(libtclsqlite3.DLL): $(T.tcl.env.sh) tclsqlite.o $(LIBOBJ)
$(T.tcl.env.source); \
$(T.link.shared) -o $@ tclsqlite.o \
@@ -1671,34 +1689,47 @@ CFLAGS.tclextension = $(CFLAGS.intree_includes) $(CFLAGS.env) $(OPT_FEATURE_FLAG
# by --with-tclsh=
#
tclextension: tclsqlite3.c
- $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --build-only --cc "$(T.cc)" $(CFLAGS.tclextension)
+ $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --build-only \
+ --tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension)
#
# Install the SQLite TCL extension in a way that is appropriate for $TCLSH_CMD
# to find it.
#
tclextension-install: tclsqlite3.c
- $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --destdir "$(DESTDIR)" --cc "$(T.cc)" $(CFLAGS.tclextension)
+ $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --destdir "$(DESTDIR)" \
+ --tclConfig.sh $(TCL_CONFIG_SH) --cc "$(T.cc)" $(CFLAGS.tclextension)
#
# Uninstall the SQLite TCL extension that is used by $TCLSH_CMD.
#
tclextension-uninstall:
- $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --uninstall
+ $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --uninstall \
+ --tclConfig.sh $(TCL_CONFIG_SH)
#
# List all installed the SQLite TCL extensions that is are accessible
# by $TCLSH_CMD, including prior versions.
#
tclextension-list:
- @ $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --info
+ @ $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --info \
+ --tclConfig.sh $(TCL_CONFIG_SH)
# Verify that the SQLite TCL extension that is loaded by default
# in $(TCLSH_CMD) is the same as the version of SQLite for the
# current source tree
#
tclextension-verify: sqlite3.h
- @ $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --version-check
+ @ $(TCLSH_CMD) $(TOP)/tool/buildtclext.tcl --version-check \
+ --tclConfig.sh $(TCL_CONFIG_SH)
+
+# Run all of the tclextension targets in order, ending with uninstall.
+tclextension-all:
+ $(MAKE) tclextension
+ $(MAKE) tclextension-install
+ $(MAKE) tclextension-list
+ $(MAKE) tclextension-verify
+ $(MAKE) tclextension-uninstall
#
# FTS5 things
diff --git a/manifest b/manifest
index 2571b3ac4..375b50e51 100644
--- a/manifest
+++ b/manifest
@@ -1,10 +1,10 @@
-C Avoid\swriting\sframes\swith\sno\schecksums\sinto\sthe\swal\sfile\sif\sa\nsavepoint\sis\srolled\sback\safter\sdirty\spages\shave\salready\sbeen\nspilled\sinto\sthe\swal\sfile.
-D 2025-06-17T19:10:33.524
+C Extend\sthe\spedantic\senforcement\sof\stype\sto\sVIRTUAL\scolumns.
+D 2025-06-18T19:04:28.743
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d
-F Makefile.in c3e414df4dc8dfb12f1f6baf129fcb6d18cd0ebd3c9109370fb3fceeeef9a37a
+F Makefile.in d8bc4aee9fb645c9f2ff0e3a30585d17a0df076bb6a33f0f20bab4999abb45a0
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
F Makefile.msc ec2011bbdfc917d6a1c7c173dabb29c14ead0dd8e2e0b67278a00ae4ba576a77
F README.md e28077cfbef795e99c9c75ed95aa7257a1166709b562076441a8506ac421b7c1
@@ -29,7 +29,7 @@ F autoconf/tea/auto.def ce95b9450e2fa4ba5dc857e208fe10f4e6f2d737796ac3278aee6079
F autoconf/tea/configure d0b12b984edca6030d1976375b80157ac78b5b90a5b4f0dcee39357f63f4a80b x
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
F autoconf/tea/pkgIndex.tcl.in e07da6b94561f4aa382bab65b1ccceb04701b97bf59d007c1d1f20a222b22d07
-F autoconf/tea/teaish.tcl a2224762a039ed30c45cc1ce4b2fde5667fb0aa2569bb56590f5cb5d45d7410b
+F autoconf/tea/teaish.tcl 81feb417e718ed75cdd7e2fdf6771f3da80dae97377a90c4d5b62b3754abbf1d
F autoconf/tea/teaish.test.tcl cfe94e1fb79dd078f650295be59843d470125e0cc3a17a1414c1fb8d77f4aea6
F autosetup/LICENSE 41a26aebdd2cd185d1e2b210f71b7ce234496979f6b35aef2cbf6b80cbed4ce4
F autosetup/README.autosetup a78ff8c4a3d2636a4268736672a74bf14a82f42687fcf0631a70c516075c031e
@@ -47,7 +47,7 @@ F autosetup/find_tclconfig.tcl e64886ffe3b982d4df42cd28ed91fe0b5940c2c5785e126c1
F autosetup/jimsh0.c 563b966c137a4ce3c9333e5196723b7ac0919140a9d7989eb440463cd855c367
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
F autosetup/proj.tcl 6aac1eb3059fc511c8e1659f33b96eb2a216a371ed9b28be6661374061be9b15
-F autosetup/sqlite-config.tcl ccda82e43e377b832aae72a1678b1dc17dcaff36ed0ebbd8f0cfc88612ae8de3
+F autosetup/sqlite-config.tcl 0bcb12c99a1673a2009164a3318890d5820701d329bf12702daa96a38d064bde
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
F autosetup/teaish/README.txt b40071e6f8506500a2f7f71d5fc69e0bf87b9d7678dd9da1e5b4d0acbf40b1ca
F autosetup/teaish/core.tcl aee092fc71986d1272b835ea7492bb55ffc213a289502e4f14da80cf67b7e3c3
@@ -709,7 +709,7 @@ F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36
F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
F ext/wasm/wasmfs.make 68999f5bd8c489239592d59a420f8c627c99169bbd6fa16a404751f757b9f702
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
-F main.mk 17744293e7af7c39936c3f220ebb8eaff4f0ad1be1e186efb584dbc34bbea2c1
+F main.mk 3ced12d068b22957f4e82a0b94a2c1d83b37dcf39c087263691267f7bfb39a84
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
@@ -736,7 +736,7 @@ F src/date.c 9db4d604e699a73e10b8e85a44db074a1f04c0591a77e2abfd77703f50dce1e9
F src/dbpage.c b3e218f8ed74fcbb7fa805df8ca669a3718d397617b3d8a8aac3307dc315c4d6
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42
-F src/expr.c f16fa5cbd849991462edf1d31bb7def5b970bb9611afcb4ea21c77e88e52a220
+F src/expr.c 5f7fe80f3397597565b43154bed8b012aacc81e0d30706c742e3b975c591db3b
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
F src/func.c de47a8295503aa130baae5e6d9868ecf4f7c4dbffa65d83ad1f70bdbac0ee2d6
@@ -745,7 +745,7 @@ F src/hash.c 73934a7f7ab1cb110614a9388cb516893b0cf5b7b69e4fd1a0780ac4ce166be7
F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
-F src/insert.c d05934dfab2c5c0c480fc6fd2038f11215661de08ea6ff38d2563216bd555c1b
+F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
F src/json.c cb87977b1ee25ee7d27505d65a9261b687395bf895342c8ba566b7c01aee2047
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c d7edd8e671237539d795d30daaf888908a2c82e99bade4c78f3be021e8b7d655
@@ -790,7 +790,7 @@ F src/shell.c.in 4ae9ff8e8b23d9a309e50d5b5ef2768b9bb18f748ece2acc2641a3c23b71e2b
F src/sqlite.h.in 22882ddd3a70751aa8864c81993ee4562ed54c2c508b6270f75e223ffee38e1b
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 0bfd049bb2088cc44c2ad54f2079d1c6e43091a4e1ce8868779b75f6c1484f1e
-F src/sqliteInt.h 493202a7dec31d58ac246252b7f03645160e3709102255a79136b4aa8f863e74
+F src/sqliteInt.h 60172f8b15efb8e9ae37bcb5ce596f1c55fee01b555b80f1c9056e55a6ee7d28
F src/sqliteLimit.h 6d817c28a8f19af95e6f4921933b7fbbca48a962bce0eb0ec81e8bb3ef38e68b
F src/status.c 0e72e4f6be6ccfde2488eb63210297e75f569f3ce9920f6c3d77590ec6ce5ffd
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -852,7 +852,7 @@ F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
F src/util.c 36fb1150062957280777655976f3f9a75db236cb8207a0770ceae8d5ec17fcd3
F src/vacuum.c 1bacdd0a81d2b5dc1c508fbf0d938c89fa78dd8d5b46ec92686d44030d4f4789
-F src/vdbe.c 714fab7aa7c516edbcf5e4f653ae8f548a3e24c0ed19086d7383bb5851983992
+F src/vdbe.c e320cd37883dd3458d70c8cf714750c51957c38b87ebb5e24a56d5e5f7434656
F src/vdbe.h 93761ed7c6b8bc19524912fd9b9b587d41bf4f1d0ade650a00dadc10518d8958
F src/vdbeInt.h 0bc581a9763be385e3af715e8c0a503ba8422c2b7074922faf4bb0d6ae31b15e
F src/vdbeapi.c 613a6f29efacd6ed83e886b6e52db0fe52ba80a596b0a137608db1948bad90a9
@@ -1701,7 +1701,7 @@ F test/statfault.test 064f43379e4992b5221b7d9ac887c313b3191f85cce605d78e416fc404
F test/stmt.test 54ed2cc0764bf3e48a058331813c3dbd19fc1d0827c3d8369914a5d8f564ec75
F test/stmtrand.test 340e2ea4841c5cdc02d36e33739769c5d907ab529b12bb535407def0e413ca17
F test/stmtvtab1.test 6873dfb24f8e79cbb5b799b95c2e4349060eb7a3b811982749a84b359468e2d5
-F test/strict1.test 4d2b492152b984fd7e8196d23eb88e2ccb0ef9e46ca2f96c2ce7147ceef9d168
+F test/strict1.test a7f9091603fe71cdc62baab0766684cba12a97ec69bfbb70be965532669cd77a
F test/strict2.test b22c7a98b5000aef937f1990776497f0e979b1a23bc4f63e2d53b00e59b20070
F test/subjournal.test 8d4e2572c0ee9a15549f0d8e40863161295107e52f07a3e8012a2e1fdd093c49
F test/subquery.test 23087f9b1c15ab9cc5231d04946bdebc51db527c95eb9d7434a2222127e17a84
@@ -2124,7 +2124,7 @@ F tool/GetTclKit.bat d84033c6a93dfe735d247f48ba00292a1cc284dcf69963e5e672444e045
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
F tool/build-all-msvc.bat 1960a7a3e5d8176c4329e31476f6e3dfa9543675355fa9020a569f4452628458 x
F tool/build-shell.sh 369c4b171cc877ad974fef691e4da782b4c1e99fe8f4361316c735f64d49280f
-F tool/buildtclext.tcl 85d1bcd5410d0a4c739e2d013106f03674d082cc4d573bcc57a68546b6db67cd
+F tool/buildtclext.tcl d09b753d7858314104eeaf5f4def85d35784470279809e47a633f142226f2b3f
F tool/cg_anno.tcl c1f875f5a4c9caca3d59937b16aff716f8b1883935f1b4c9ae23124705bc8099 x
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
F tool/cktclsh.sh 6075eef9c6b9ba4b38fef2ca2a66d25f2311bd3c610498d18a9b01f861629cca
@@ -2208,9 +2208,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 336a59eb3afd80ce048de472368df6dfc32934ee783859d37663ed8f5cf169a5 0da16f6c625bff9f2ca5624afa6dce6b5a157f44c1d56b25b92946c13217ab02
-R 4f15daf1345886267fb9e7e113ac5ab2
-T +closed 0da16f6c625bff9f2ca5624afa6dce6b5a157f44c1d56b25b92946c13217ab02
+P 5e9279bff0482806f86657ae05ca3e916708d138bc3c3ceb3fbf454818649d44
+R f7012a27e3f9276304f8e87574dec03d
U drh
-Z 6c7c1ae528922d359a2a0f722b244029
+Z 4d43da8fdd303e39e12f04e0b9379a29
# Remove this line to create a well-formed Fossil manifest.
diff --git a/manifest.uuid b/manifest.uuid
index a46ddc76e..91b07eee7 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-5973f9b9aa828ec9274b02a124b95f452c58235eaafffbdda1c32b4ae2d5616d
+b734c74e55acb26eb61b60937bef870f4b55b2e2e7560a22362f5f31ba2fcd03
diff --git a/src/expr.c b/src/expr.c
index 606a4cd7e..6730128fb 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -4269,7 +4269,12 @@ void sqlite3ExprCodeGeneratedColumn(
iAddr = 0;
}
sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab,pCol), regOut);
- if( pCol->affinity>=SQLITE_AFF_TEXT ){
+ if( (pCol->colFlags & COLFLAG_VIRTUAL)!=0
+ && (pTab->tabFlags & TF_Strict)!=0
+ ){
+ int p3 = 2+(int)(pCol - pTab->aCol);
+ sqlite3VdbeAddOp4(v, OP_TypeCheck, regOut, 1, p3, (char*)pTab, P4_TABLE);
+ }else if( pCol->affinity>=SQLITE_AFF_TEXT ){
sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1);
}
if( iAddr ) sqlite3VdbeJumpHere(v, iAddr);
diff --git a/src/insert.c b/src/insert.c
index fdd9c8da2..f0c56a7a8 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -185,12 +185,15 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
** by one slot and insert a new OP_TypeCheck where the current
** OP_MakeRecord is found */
VdbeOp *pPrev;
+ int p3;
sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
pPrev = sqlite3VdbeGetLastOp(v);
assert( pPrev!=0 );
assert( pPrev->opcode==OP_MakeRecord || sqlite3VdbeDb(v)->mallocFailed );
pPrev->opcode = OP_TypeCheck;
- sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, pPrev->p3);
+ p3 = pPrev->p3;
+ pPrev->p3 = 0;
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, p3);
}else{
/* Insert an isolated OP_Typecheck */
sqlite3VdbeAddOp2(v, OP_TypeCheck, iReg, pTab->nNVCol);
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 88272920c..ce1b77bfe 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -1271,7 +1271,7 @@ struct BusyHandler {
** pointer will work here as long as it is distinct from SQLITE_STATIC
** and SQLITE_TRANSIENT.
*/
-#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3OomClear)
+#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3RowSetClear)
/*
** When SQLITE_OMIT_WSD is defined, it means that the target platform does
diff --git a/src/vdbe.c b/src/vdbe.c
index b23bd38d2..8a3c0381c 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -3239,6 +3239,15 @@ op_column_corrupt:
** Take the affinities from the Table object in P4. If any value
** cannot be coerced into the correct type, then raise an error.
**
+** If P3==0, then omit checking of VIRTUAL columns.
+**
+** If P3==1, then omit checking of all generated column, both VIRTUAL
+** and STORED.
+**
+** If P3>=2, then only check column number P3-2 in the table (which will
+** be a VIRTUAL column) against the value in reg[P1]. In this case,
+** P2 will be 1.
+**
** This opcode is similar to OP_Affinity except that this opcode
** forces the register type to the Table column type. This is used
** to implement "strict affinity".
@@ -3252,8 +3261,8 @@ op_column_corrupt:
**
** <ul>
** <li> P2 should be the number of non-virtual columns in the
-** table of P4.
-** <li> Table P4 should be a STRICT table.
+** table of P4 unless P3>1, in which case P2 will be 1.
+** <li> Table P4 is a STRICT table.
** </ul>
**
** If any precondition is false, an assertion fault occurs.
@@ -3262,16 +3271,28 @@ case OP_TypeCheck: {
Table *pTab;
Column *aCol;
int i;
+ int nCol;
assert( pOp->p4type==P4_TABLE );
pTab = pOp->p4.pTab;
assert( pTab->tabFlags & TF_Strict );
- assert( pTab->nNVCol==pOp->p2 );
+ assert( pOp->p3>=0 && pOp->p3<pTab->nCol+2 );
aCol = pTab->aCol;
pIn1 = &aMem[pOp->p1];
- for(i=0; i<pTab->nCol; i++){
- if( aCol[i].colFlags & COLFLAG_GENERATED ){
- if( aCol[i].colFlags & COLFLAG_VIRTUAL ) continue;
+ if( pOp->p3<2 ){
+ assert( pTab->nNVCol==pOp->p2 );
+ i = 0;
+ nCol = pTab->nCol;
+ }else{
+ i = pOp->p3-2;
+ nCol = i+1;
+ assert( i<pTab->nCol );
+ assert( aCol[i].colFlags & COLFLAG_VIRTUAL );
+ assert( pOp->p2==1 );
+ }
+ for(; i<nCol; i++){
+ if( (aCol[i].colFlags & COLFLAG_GENERATED)!=0 && pOp->p3<2 ){
+ if( (aCol[i].colFlags & COLFLAG_VIRTUAL)!=0 ) continue;
if( pOp->p3 ){ pIn1++; continue; }
}
assert( pIn1 < &aMem[pOp->p1+pOp->p2] );
diff --git a/test/strict1.test b/test/strict1.test
index fc6438843..c4c086bdb 100644
--- a/test/strict1.test
+++ b/test/strict1.test
@@ -162,4 +162,101 @@ do_execsql_test strict1-8.2 {
SELECT *, '|' FROM t1;
} {/5.0 5.0 4.6116\d*e\+18 4.6116\d+e\+18 |/}
+# 2025-06-18 https://sqlite.org/forum/forumpost/6caf195248a849e4
+#
+# Enforce STRICT table type constraints on STORED generated columns
+#
+do_execsql_test strict1-9.1 {
+ CREATE TABLE strict (
+ k INTEGER PRIMARY KEY,
+ c1 REAL AS(if(k=11,1.5, k=12,2, k=13,'x', k=14,x'34', 0.0)) STORED,
+ c2 INT AS(if(k=21,1.5, k=22,2, k=23,'x', k=24,x'34', 0)) STORED,
+ c3 TEXT AS(if(k=31,1.5, k=32,2, k=33,'x', k=34,x'34', 'x')) STORED,
+ c4 BLOB AS(if(k=41,1.5, k=42,2, k=43,'x', k=44,x'34', x'00')) STORED,
+ c5 ANY AS(if(k=51,1.5, k=52,2, k=53,'x', k=54,x'34', 0)) STORED
+ ) STRICT;
+ INSERT INTO strict(k) VALUES(11);
+ INSERT INTO strict(k) VALUES(12);
+ INSERT INTO strict(k) VALUES(22);
+ INSERT INTO strict(k) VALUES(31);
+ INSERT INTO strict(k) VALUES(32);
+ INSERT INTO strict(k) VALUES(33);
+ INSERT INTO strict(k) VALUES(44);
+ PRAGMA integrity_check;
+} {ok}
+do_catchsql_test strict1-9.2.13 {
+ INSERT INTO strict(k) VALUES(13);
+} {1 {cannot store TEXT value in REAL column strict.c1}}
+do_catchsql_test strict1-9.2.14 {
+ INSERT INTO strict(k) VALUES(14);
+} {1 {cannot store BLOB value in REAL column strict.c1}}
+do_catchsql_test strict1-9.2.21 {
+ INSERT INTO strict(k) VALUES(21);
+} {1 {cannot store REAL value in INT column strict.c2}}
+do_catchsql_test strict1-9.2.23 {
+ INSERT INTO strict(k) VALUES(23);
+} {1 {cannot store TEXT value in INT column strict.c2}}
+do_catchsql_test strict1-9.2.24 {
+ INSERT INTO strict(k) VALUES(24);
+} {1 {cannot store BLOB value in INT column strict.c2}}
+do_catchsql_test strict1-9.2.34 {
+ INSERT INTO strict(k) VALUES(34);
+} {1 {cannot store BLOB value in TEXT column strict.c3}}
+do_catchsql_test strict1-9.2.41 {
+ INSERT INTO strict(k) VALUES(41);
+} {1 {cannot store REAL value in BLOB column strict.c4}}
+do_catchsql_test strict1-9.2.42 {
+ INSERT INTO strict(k) VALUES(42);
+} {1 {cannot store INT value in BLOB column strict.c4}}
+do_catchsql_test strict1-9.2.43 {
+ INSERT INTO strict(k) VALUES(43);
+} {1 {cannot store TEXT value in BLOB column strict.c4}}
+
+do_execsql_test strict1-9.3 {
+ DROP TABLE strict;
+ CREATE TABLE strict (
+ k INTEGER PRIMARY KEY,
+ c1 REAL AS(if(k=11,1.5, k=12,2, k=13,'x', k=14,x'34', 0.0)) VIRTUAL,
+ c2 INT AS(if(k=21,1.5, k=22,2, k=23,'x', k=24,x'34', 0)) VIRTUAL,
+ c3 TEXT AS(if(k=31,1.5, k=32,2, k=33,'x', k=34,x'34', 'x')) VIRTUAL,
+ c4 BLOB AS(if(k=41,1.5, k=42,2, k=43,'x', k=44,x'34', x'00')) VIRTUAL,
+ c5 ANY AS(if(k=51,1.5, k=52,2, k=53,'x', k=54,x'34', 0)) VIRTUAL
+ ) STRICT;
+ INSERT INTO strict(k) VALUES(11);
+ INSERT INTO strict(k) VALUES(12);
+ INSERT INTO strict(k) VALUES(22);
+ INSERT INTO strict(k) VALUES(31);
+ INSERT INTO strict(k) VALUES(32);
+ INSERT INTO strict(k) VALUES(33);
+ INSERT INTO strict(k) VALUES(44);
+ PRAGMA integrity_check;
+} {ok}
+do_catchsql_test strict1-9.4.13 {
+ INSERT INTO strict(k) VALUES(13);
+} {1 {cannot store TEXT value in REAL column strict.c1}}
+do_catchsql_test strict1-9.4.14 {
+ INSERT INTO strict(k) VALUES(14);
+} {1 {cannot store BLOB value in REAL column strict.c1}}
+do_catchsql_test strict1-9.4.21 {
+ INSERT INTO strict(k) VALUES(21);
+} {1 {cannot store REAL value in INT column strict.c2}}
+do_catchsql_test strict1-9.4.23 {
+ INSERT INTO strict(k) VALUES(23);
+} {1 {cannot store TEXT value in INT column strict.c2}}
+do_catchsql_test strict1-9.4.24 {
+ INSERT INTO strict(k) VALUES(24);
+} {1 {cannot store BLOB value in INT column strict.c2}}
+do_catchsql_test strict1-9.4.34 {
+ INSERT INTO strict(k) VALUES(34);
+} {1 {cannot store BLOB value in TEXT column strict.c3}}
+do_catchsql_test strict1-9.4.41 {
+ INSERT INTO strict(k) VALUES(41);
+} {1 {cannot store REAL value in BLOB column strict.c4}}
+do_catchsql_test strict1-9.4.42 {
+ INSERT INTO strict(k) VALUES(42);
+} {1 {cannot store INT value in BLOB column strict.c4}}
+do_catchsql_test strict1-9.4.43 {
+ INSERT INTO strict(k) VALUES(43);
+} {1 {cannot store TEXT value in BLOB column strict.c4}}
+
finish_test
diff --git a/tool/buildtclext.tcl b/tool/buildtclext.tcl
index 8e5bef38a..535ed37e7 100644
--- a/tool/buildtclext.tcl
+++ b/tool/buildtclext.tcl
@@ -17,6 +17,7 @@ Options:
--uninstall Uninstall the extension
--version-check Check extension version against this source tree
--destdir DIR Installation root (used by "make install DESTDIR=...")
+ --tclConfig.sh FILE Use this tclConfig.sh instead of looking for one
Other options are retained and passed through into the compiler.}
@@ -29,6 +30,7 @@ set versioncheck 0
set CC {}
set OPTS {}
set DESTDIR ""; # --destdir "$(DESTDIR)"
+set tclConfigSh ""; # --tclConfig.sh FILE
for {set ii 0} {$ii<[llength $argv]} {incr ii} {
set a0 [lindex $argv $ii]
if {$a0=="--install-only"} {
@@ -56,6 +58,9 @@ for {set ii 0} {$ii<[llength $argv]} {incr ii} {
} elseif {$a0=="--destdir" && $ii+1<[llength $argv]} {
incr ii
set DESTDIR [lindex $argv $ii]
+ } elseif {$a0=="--tclConfig.sh" && $ii+1<[llength $argv]} {
+ incr ii
+ set tclConfigSh [lindex $argv $ii]
} elseif {[string match -* $a0]} {
append OPTS " $a0"
} else {
@@ -88,40 +93,47 @@ if {$tcl_platform(platform) eq "windows"} {
}
set OUT tclsqlite3.dll
} else {
- # Figure out the location of the tclConfig.sh file used by the
- # tclsh that is executing this script.
+ # Read the tclConfig.sh file into the $tclConfig variable
#
- if {[catch {
- set LIBDIR [tcl::pkgconfig get libdir,install]
- }]} {
- puts stderr "$argv0: tclsh does not support tcl::pkgconfig."
- exit 1
- }
- if {![file exists $LIBDIR]} {
- puts stderr "$argv0: cannot find the tclConfig.sh file."
- puts stderr "$argv0: tclsh reported library directory \"$LIBDIR\"\
+ if {"" eq $tclConfigSh} {
+ # Figure out the location of the tclConfig.sh file used by the
+ # tclsh that is executing this script.
+ #
+ if {[catch {
+ set LIBDIR [tcl::pkgconfig get libdir,install]
+ }]} {
+ puts stderr "$argv0: tclsh does not support tcl::pkgconfig."
+ exit 1
+ }
+ if {![file exists $LIBDIR]} {
+ puts stderr "$argv0: cannot find the tclConfig.sh file."
+ puts stderr "$argv0: tclsh reported library directory \"$LIBDIR\"\
does not exist."
- exit 1
- }
- if {![file exists $LIBDIR/tclConfig.sh]
- || [file size $LIBDIR/tclConfig.sh]<5000} {
- set n1 $LIBDIR/tcl$::tcl_version
- if {[file exists $n1/tclConfig.sh]
- && [file size $n1/tclConfig.sh]>5000} {
- set LIBDIR $n1
- } else {
- puts stderr "$argv0: cannot find tclConfig.sh in either $LIBDIR or $n1"
exit 1
}
+ if {![file exists $LIBDIR/tclConfig.sh]
+ || [file size $LIBDIR/tclConfig.sh]<5000} {
+ set n1 $LIBDIR/tcl$::tcl_version
+ if {[file exists $n1/tclConfig.sh]
+ && [file size $n1/tclConfig.sh]>5000} {
+ set LIBDIR $n1
+ } else {
+ puts stderr "$argv0: cannot find tclConfig.sh in either $LIBDIR or $n1"
+ exit 1
+ }
+ }
+ #puts "using $LIBDIR/tclConfig.sh"
+ set fd [open $LIBDIR/tclConfig.sh rb]
+ set tclConfig [read $fd]
+ close $fd
+ } else {
+ # User-provided tclConfig.sh
+ #
+ set fd [open $tclConfigSh rb]
+ set tclConfig [read $fd]
+ close $fd
}
- # Read the tclConfig.sh file into the $tclConfig variable
- #
- #puts "using $LIBDIR/tclConfig.sh"
- set fd [open $LIBDIR/tclConfig.sh rb]
- set tclConfig [read $fd]
- close $fd
-
# Extract parameter we will need from the tclConfig.sh file
#
set TCLMAJOR 8