1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Merge trunk changes into this branch.

FossilOrigin-Name: 7d27451804e525190f8e67da75aaeb3bf2de677021f7566c6681398e60a88c72
This commit is contained in:
dan
2025-06-02 17:44:10 +00:00
26 changed files with 495 additions and 218 deletions

View File

@@ -2674,7 +2674,14 @@ srctree-check: $(TOP)\tool\srctree-check.tcl
# Testing for a release
#
releasetest:
releasetest: verify-source
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl release
# xdevtest is like releasetest, except that it skips the
# dependency on verify-source so that xdevtest can be run from
# a modified source tree.
#
xdevtest:
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl release

View File

@@ -41,24 +41,32 @@ step-by-step instructions at the links below for more information:
https://sqlite.org/src/doc/trunk/doc/compile-for-unix.md
https://sqlite.org/src/doc/trunk/doc/compile-for-windows.md
The whole point of the amalgamation-autoconf tarball (in which this
README.txt file is embedded) is to provide a means of compiling
SQLite that does not require first installing TCL and/or "tclsh".
The canonical Makefile in the SQLite source tree provides more
capabilities (such as the the ability to run test cases to ensure
that the build worked) and is better maintained. The only
downside of the canonical Makefile is that it requires a TCL
installation. But if you are wanting to build the TCL extension for
SQLite, then presumably you already have a TCL installation. So why
not just use the more-capable and better-maintained canoncal Makefile?
And info about the extension's Tcl interface can be found at:
This TEA builder is derived from code found at
https://sqlite.org/tclsqlite.html
The whole point of the amalgamation-autoconf tarball (in which this
README.txt file is embedded) is to provide a means of compiling SQLite
that does not require first installing TCL and/or "tclsh". The
canonical Makefile in the SQLite source tree provides more
capabilities (such as the the ability to run test cases to ensure that
the build worked) and is better maintained. The only downside of the
canonical Makefile is that it requires a TCL installation. But if you
are wanting to build the TCL extension for SQLite, then presumably you
already have a TCL installation. So why not just use the more-capable
and better-maintained canoncal Makefile?
As of version 3.50.0, this build process uses "teaish":
https://fossil.wanderinghorse.net/r/teaish
which is conceptually derived from the pre-3.50 toolchain, TEA:
http://core.tcl-lang.org/tclconfig
http://core.tcl-lang.org/sampleextension
The SQLite developers do not understand how it works. It seems to
work for us. It might also work for you. But we cannot promise that.
It to works for us. It might also work for you. But we cannot
promise that.
If you want to use this TEA builder and it works for you, that's fine.
But if you have trouble, the first thing you should do is go back
@@ -70,30 +78,17 @@ to using the canonical Makefile in the SQLite source tree.
UNIX BUILD
==========
Building under most UNIX systems is easy, just run the configure script
and then run make. For more information about the build process, see
the tcl/unix/README file in the Tcl src dist. The following minimal
example will install the extension in the /opt/tcl directory.
Building under most UNIX systems is easy, just run the configure
script and then run make. For example:
$ cd sqlite-*-tea
$ ./configure --prefix=/opt/tcl
$ make
$ ./configure --with-tcl=/path/to/tcl/install/root
$ make test
$ make install
WINDOWS BUILD
=============
The recommended method to build extensions under windows is to use the
Msys + Mingw build process. This provides a Unix-style build while
generating native Windows binaries. Using the Msys + Mingw build tools
means that you can use the same configure script as per the Unix build
to create a Makefile. See the tcl/win/README file for the URL of
the Msys + Mingw download.
If you have VC++ then you may wish to use the files in the win
subdirectory and build the extension using just VC++. These files have
been designed to be as generic as possible but will require some
additional maintenance by the project developer to synchronise with
the TEA configure.in and Makefile.in files. Instructions for using the
VC++ makefile are written in the first part of the Makefile.vc
file.
On Windows this build is known to work on Cygwin and some Msys2
environments. We do not currently support Microsoft makefiles for
native Windows builds.

View File

@@ -1,15 +0,0 @@
.TH sqlite3 n 4.1 "Tcl-Extensions"
.HS sqlite3 tcl
.BS
.SH NAME
sqlite3 \- an interface to the SQLite3 database engine
.SH SYNOPSIS
\fBsqlite3\fI command_name ?filename?\fR
.br
.SH DESCRIPTION
SQLite3 is a self-contains, zero-configuration, transactional SQL database
engine. This extension provides an easy to use interface for accessing
SQLite database files from Tcl.
.PP
For full documentation see \fIhttps://sqlite.org/\fR and
in particular \fIhttps://sqlite.org/tclsqlite.html\fR.

View File

@@ -598,8 +598,6 @@ emcc.flags += -v
endif
# wasmMemory ==> required by our code for use with -sIMPORTED_MEMORY
# Emscripten 4.0.7 (2025-04-15) stops exporting HEAP* by default
########################################################################
# emcc flags for .c/.o.
emcc.cflags :=
@@ -619,6 +617,8 @@ emcc.jsflags += -sNO_POLYFILL
emcc.jsflags += -sEXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS.api)
emcc.exportedRuntimeMethods := \
-sEXPORTED_RUNTIME_METHODS=wasmMemory,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAP64,HEAPU64
# wasmMemory ==> required by our code for use with -sIMPORTED_MEMORY
# Emscripten 4.0.7 (2025-04-15) stops exporting HEAP* by default
emcc.jsflags += $(emcc.exportedRuntimeMethods)
emcc.jsflags += -sUSE_CLOSURE_COMPILER=0
emcc.jsflags += -sIMPORTED_MEMORY

View File

@@ -1835,6 +1835,12 @@ mdevtest: srctree-check has_tclsh85
sdevtest: has_tclsh85
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl sdevtest $(TSTRNNR_OPTS)
# Like releasetest, except it omits srctree-check and verify-source so
# that it can be used on a modified source tree.
#
xdevtest: has_tclsh85
$(TCLSH_CMD) $(TOP)/test/testrunner.tcl release $(TSTRNNR_OPTS)
#
# Validate that various generated files in the source tree
# are up-to-date.

View File

@@ -1,12 +1,12 @@
C Update\sa\sfew\stest\sscripts\sso\sthat\sthey\srun\son\swindows.
D 2025-05-31T19:55:07.528
C Merge\strunk\schanges\sinto\sthis\sbranch.
D 2025-06-02T17:44:10.848
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.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
F Makefile.msc 0206f28988bb6634c7e8aff05bf6cfa65d6dfe1d2b6bd95160dd99290a83dfc7
F Makefile.msc aa4f9ae86cf59fe94a3e93bf1a4c241b3ffffe96cf4d823517acf593c277223b
F README.md e28077cfbef795e99c9c75ed95aa7257a1166709b562076441a8506ac421b7c1
F VERSION 001dea55eb8304ec9130b6b44a32d3fc349f279d45a7e224fc0730c3cb8e2372
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
@@ -23,11 +23,10 @@ F autoconf/README.first f1d3876e9a7852c22f275a6f06814e64934cecbc0b5b9617d6484909
F autoconf/README.txt b749816b8452b3af994dc6d607394bef3df1736d7e09359f1087de8439a52807
F autoconf/auto.def 3d994f3a9cc9b712dbce92a5708570ddcf3b988141b6eb738f2ed16127a9f0ac
F autoconf/tea/Makefile.in bf6b43eafcd18766d81a8f0085cfc9cb051d8abae9031a8e7c3f5f1246e8f166
F autoconf/tea/README.txt 656d4686c509d375f5988ff3deda94f65fe6cd8358cd55d1f1dcc7b6e2ff73aa
F autoconf/tea/README.txt 23475876343498ef2b514cc7510e8f1559a17e8e03fbc7a41c1c8a3b89e7b7e3
F autoconf/tea/_teaish.tester.tcl.in 8253b44be88e2e3f21de95a65d3a90c2be8e70b7bdd08a5b80e337ba7402f8f1
F autoconf/tea/auto.def ce95b9450e2fa4ba5dc857e208fe10f4e6f2d737796ac3278aee6079db417529
F autoconf/tea/configure d0b12b984edca6030d1976375b80157ac78b5b90a5b4f0dcee39357f63f4a80b x
F autoconf/tea/doc/sqlite3.n 9a97f4f717ceab73004ea412af7960625c1cb24b5c25e4ae4c8b5d8fa4300f4e
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
F autoconf/tea/pkgIndex.tcl.in e07da6b94561f4aa382bab65b1ccceb04701b97bf59d007c1d1f20a222b22d07
F autoconf/tea/teaish.tcl a2224762a039ed30c45cc1ce4b2fde5667fb0aa2569bb56590f5cb5d45d7410b
@@ -621,7 +620,7 @@ F ext/session/sqlite3session.c 6b0877fe1ab832aa4b85eaca72606dfd1630a1363a1be7af1
F ext/session/sqlite3session.h 9bb1a6687b467764b35178dc29bbd2c57ab8cd3acdc8a62f088c34ad17e4fe2b
F ext/session/test_session.c 2ddff73ea368d827028c32851b291416e1008845832feb27b751d15e57e13cc3
F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c
F ext/wasm/GNUmakefile d6b869cf3d3eaaec8cf56adf925910c3e443f455562bcb4a4cd2d1e43c933d8d
F ext/wasm/GNUmakefile e315b903c33b28ca074367041849de9dd2681c96d1437c11a5e9596abc265012
F ext/wasm/README-dist.txt f01081a850ce38a56706af6b481e3a7878e24e42b314cfcd4b129f0f8427066a
F ext/wasm/README.md b89605f65661cf35bf034ff6d43e448cc169b8017fc105d498e33b81218b482c
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
@@ -709,7 +708,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 517db864e770c486bd1465298c20d91899918d395263266997d477b20ef9eec8
F main.mk 34290a772ec671de1fa5defd4fa4074aad24b1ea7eaabebba071e30564c6498c
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
@@ -726,14 +725,14 @@ F src/auth.c 54ab9c6c5803b47c0d45b76ce27eff22a03b4b1f767c5945a3a4eb13aa4c78dc
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
F src/bitvec.c 782cc29b42b47e7ec6348eb0aaf9ffe60063f498387e7249f458d445af4b53e9
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
F src/btree.c da98489a981c347cc3a3982ea2810bbb583511a73cc34762547f30dbb4cda7f0
F src/btree.c 53a9c7b243e94c992853d90f1dac0959028433b4b0d27e04409cee04e001b508
F src/btree.h 18e5e7b2124c23426a283523e5f31a4bff029131b795bb82391f9d2f3136fc50
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
F src/build.c 67c1db4c5e89a8519fe9b6dafc287f6bc3627696b5b8536dc5e06db570d8c05f
F src/callback.c acae8c8dddda41ee85cfdf19b926eefe830f371069f8aadca3aa39adf5b1c859
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/date.c 9db4d604e699a73e10b8e85a44db074a1f04c0591a77e2abfd77703f50dce1e9
F src/dbpage.c fcb1aafe00872a8aff9a7aa0ef7ff1b01e5817ec7bbd521f8f3e1e674ac8d609
F src/dbpage.c b3e218f8ed74fcbb7fa805df8ca669a3718d397617b3d8a8aac3307dc315c4d6
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42
F src/expr.c 6f184da1f36576ad1ecc48a03f14774235373c64f88d462c710834930ee6c145
@@ -785,18 +784,18 @@ F src/printf.c 3b91c334f528359145f4dde0dedd945bbb21044d0825ea064934d7222d61662c
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c d40fe18d7c2fd0339f5846ffcf7d6809866e380acdf14c76fb2af87e9fe13f64
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c ee072fe20566119a195a5a3df454479bb6e944de7aef7006ff0b4d4612f9cb86
F src/shell.c.in ba53a52dafb167ac6320703da741386c34fbcabe8c078a188bb9f89808e3ef8f
F src/select.c 9929e56e78f958657bfbb8234916473468243f90af359cc646d97c3ee809c79c
F src/shell.c.in 1da613953db4c8d50e3a4a66fa7d69b4c95edb3628941d732637d3c35ea0dce6
F src/sqlite.h.in 22882ddd3a70751aa8864c81993ee4562ed54c2c508b6270f75e223ffee38e1b
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 0bfd049bb2088cc44c2ad54f2079d1c6e43091a4e1ce8868779b75f6c1484f1e
F src/sqliteInt.h bb9137b860b2416b12788f09b32384ceab96b720aae07a6e9afacc545e43619a
F src/sqliteInt.h 75290111d8e37d35ec48a4fbb4e6af5611c9a551dedecceb896734ace9f60018
F src/sqliteLimit.h 6d817c28a8f19af95e6f4921933b7fbbca48a962bce0eb0ec81e8bb3ef38e68b
F src/status.c 0e72e4f6be6ccfde2488eb63210297e75f569f3ce9920f6c3d77590ec6ce5ffd
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c d0e63ffe7944dd223bf62066d9f982cbee1978811c7fbfd889f4ba9c5baed3d1
F src/tclsqlite.c 3c604c49e6cf4211960a9ddb9505280fd22cde32175f40884c641c0f5a286036
F src/tclsqlite.h 65e2c761446e1c9fa0342b7d2612a703483643c8b6a316d12a65b745a4727395
F src/test1.c 9b54135e5f1352f06b1d23d7c183f124c1f33de6ea8997cd801f0f215c43591d
F src/test1.c 13cc07851f989141b29f7ca3c6c90f6d18f90081ab423c66716c8cb29d277d1f
F src/test2.c 62f0830958f9075692c29c6de51b495ae8969e1bef85f239ffcd9ba5fb44a5ff
F src/test3.c 432646f581d8af1bb495e58fc98234380250954f5d5535e507fc785eccc3987a
F src/test4.c 0ac87fc13cdb334ab3a71823f99b6c32a6bebe5d603cd6a71d84c823d43a25a0
@@ -853,15 +852,15 @@ F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
F src/util.c 36fb1150062957280777655976f3f9a75db236cb8207a0770ceae8d5ec17fcd3
F src/vacuum.c d580ceb395c1ae3d59da41cbfea60683ff7dd2b94ddf4d0f5657620159e2eeb7
F src/vdbe.c 0feab5781141acca67bd5de84172fff902304274ec5cfe58609f005b8d160050
F src/vdbe.h 31eddcffc1d14c76c2a20fe4e137e1ee43d44f370896fae14a067052801a3625
F src/vacuum.c 1bacdd0a81d2b5dc1c508fbf0d938c89fa78dd8d5b46ec92686d44030d4f4789
F src/vdbe.c 714fab7aa7c516edbcf5e4f653ae8f548a3e24c0ed19086d7383bb5851983992
F src/vdbe.h 93761ed7c6b8bc19524912fd9b9b587d41bf4f1d0ade650a00dadc10518d8958
F src/vdbeInt.h 0bc581a9763be385e3af715e8c0a503ba8422c2b7074922faf4bb0d6ae31b15e
F src/vdbeapi.c 28fab30ed0acc981aecfdcaab0a421503609078e29850eb28494816682baf0a7
F src/vdbeaux.c 948c379976885a073b54cc7d8ffda087dc1a1095d1f5bb8df218796f8c933ac3
F src/vdbeapi.c 613a6f29efacd6ed83e886b6e52db0fe52ba80a596b0a137608db1948bad90a9
F src/vdbeaux.c fd2c6b19a8892c31a2adc719f156f313560f9cc490cdbd04ff08fdae5d7aedb7
F src/vdbeblob.c b1b4032cac46b41e44b957c4d00aee9851f862dfd85ecb68116ba49884b03dfd
F src/vdbemem.c e67d9c6484d868c879d20c70d00bf4a9058082f1d4058607ca15d50eb3aebc21
F src/vdbesort.c 49e366d0216c782eba287bf602384e4330d2526a22f1275492d2785ce103c79b
F src/vdbesort.c cb6f472e83ca12c46aa7de0ac0a9d11458b357986f2617a1c90dfb19a542ecbe
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
F src/vtab.c 828221bdbeaaa6d62126ee6d07fd4ec0d09dcaea846f87ad01944d8b7e548859
@@ -1084,6 +1083,7 @@ F test/dbfuzz.c fc566102f72c8af84ae8077b4faf7f056c571e6fa7a32e98b66e42b7505f47b6
F test/dbfuzz001.test 6c9a4622029d69dc38926f115864b055cb2f39badd25ec22cbfb130c8ba8e9c3
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
F test/dbfuzz2.c 4b3c12de4d98b1b2d908ab03d217d4619e47c8b23d5e67f8a6f2b1bdee7cae23
F test/dblwidth-a.sql eb4141518610e52f931a55a984310075e98dc31eee5a28ae806b1e35377be85a
F test/dbpage.test 63fab1eb026bada121107e53436fa749bbf83281dc9dea17af422f7a5c0f289f
F test/dbpagefault.test ea39de2ca86041a9c6df1135645180a76d0a8da93ac159e2fafe38e39636530b
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
@@ -1222,7 +1222,7 @@ F test/fts3fault3.test ccdd2292dd2d4e21e30fc5f4c8e064f79e516087eec5ff57ab6bc4f6a
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
F test/fts3fuzz001.test c78afcd8ad712ea0b8d2ed50851a8aab3bc9dc52c64a536291e07112f519357c
F test/fts3integrity.test 0c6fe7353d7b24d78862f4272ee9df4da2f32b3ff30fa3396945cda8119580a8
F test/fts3join.test 1a4d786539b2b79a41c28ef2ac22cacd92a8ee830249b68a7dee4a020848e3bb
F test/fts3join.test de31d304ba479043a7d33d2f201c514b3e1da809da6797d7a58704d00e8da2e6
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
F test/fts3matchinfo.test aa66cc50615578b30f6df9984819ae5b702511cf8a94251ec7c594096a703a4a
F test/fts3matchinfo2.test 00144e841704b8debfcdf6097969cd9f2a1cf759e2203cda42583648f2e6bf58
@@ -1361,7 +1361,7 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
F test/ioerr5.test 5984da7bf74b6540aa356f2ab0c6ae68a6d12039a3d798a9ac6a100abc17d520
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
F test/istrue.test e7f285bb70282625c258e866ce6337d4c762922f5a300e1b50f958aef6e7d9c9
F test/join.test aca62194ad41b522c55577e0e1bd99da6d5436827225aa850801c36e5f4cc914
F test/join.test 255c1f42b7fe027b518cadb2bf40f41a793a95e7f8db2bceb54faaf59ff19c6c
F test/join2.test f59d63264fb24784ae9c3bc9d867eb569cd6d442da5660f8852effe5c1938c27
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
@@ -1376,7 +1376,7 @@ F test/joinC.test 1f1a602c2127f55f136e2cbd3bf2d26546614bf8cffe5902ec1ac9c07f87f2
F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be28
F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
F test/joinH.test 55f69e64da74d4eca2235237f3acb657aef181e22e45daa228e35bba865e0255
F test/joinH.test 29a25ea2c6323c6dd1ee7f2da906f24efbd467d60a9531e6704b8e2c88de9b9a
F test/journal1.test bc61a4228db11bffca118bd358ba4b868524bf080f3532749de6c539656e20fa
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
F test/journal3.test e5aeff93a7776cf644dbc48dec277655cff80a1cd24689036abc87869b120ea6
@@ -1725,7 +1725,7 @@ F test/tabfunc01.test 8a484fe8b19fc24844f72ca1ceb7c9ae8c9a6bca000a5c6ccab5d89f5c
F test/table.test e87294bf1c80bfd7792142b84ab32ea5beb4f3f71e535d7fb263a6b2068377bf
F test/tableapi.test e37c33e6be2276e3a96bb54b00eea7f321277115d10e5b30fdb52a112b432750
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
F test/tclsqlite.test ad0bbd92edabe64cc91d990a0748142fe5ab962d74ac71fa3bfa94d50d2f4c87
F test/tclsqlite.test 3f697424cfc1cdc9c076ec0cadb0e700f059400a3e3ce134b7d856fc9f880e1c
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
F test/tempdb2.test 353864e96fd3ae2f70773d0ffbf8b1fe48589b02c2ec05013b540879410c3440
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
@@ -1959,7 +1959,7 @@ F test/uri.test 1250724af9beeed2d6c3716f5b990c483200c54f408d3c0ec9543a3c7961f8fc
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
F test/utf16align.test 9fde0bb5d3a821594aa68c6829ab9c5453a084384137ebb9f6153e2d678039da
F test/vacuum-into.test 5a489714feecfdabfc7b293be4111564a173dee92c0d6818dd0207f3ade65783
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
F test/vacuum.test f3b2257a4fcd659513c866a5d9e5f70999cc58fd5d74e979290385fa350b79ee
F test/vacuum2.test 9fd45ce6ce29f5614c249e03938d3567c06a9e772d4f155949f8eafe2d8af520
F test/vacuum3.test d9d9a04ee58c485b94694fd4f68cffaba49c32234fdefe1ac1a622c5e17d4ce3
F test/vacuum4.test 7ea76b769fffeb41f925303b04cbcf5a5bbeabe55e4c60ae754ff24eeeb7c010
@@ -2209,8 +2209,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 9f521ecda2b8d2f383cc84e308b3a4adfcf1bd6339eb834c8fa76c8704c861b7
R 56c04d3126b92aeee5cfa0b7b54b5339
P 14a18f4e3a3f35e636262a253364ab1e8054ed38c0c7fd482633522cbcf5ffc4 bf7be67e3fb7b75fc281997f7bf9aa69eaf4da6bdf2fefe359b12d25ec95f512
R 9d4b9998d3f8edcfb9815d7e9467875d
U dan
Z ced89a3dbbea8e62a4a96a4110c9937a
Z c11641e9268877729cb4210049f5ff6d
# Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
14a18f4e3a3f35e636262a253364ab1e8054ed38c0c7fd482633522cbcf5ffc4
7d27451804e525190f8e67da75aaeb3bf2de677021f7566c6681398e60a88c72

View File

@@ -872,7 +872,7 @@ static int btreeMoveto(
assert( nKey==(i64)(int)nKey );
pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
sqlite3VdbeRecordUnpack((int)nKey, pKey, pIdxKey);
if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
rc = SQLITE_CORRUPT_BKPT;
}else{
@@ -2856,6 +2856,7 @@ static int removeFromSharingList(BtShared *pBt){
sqlite3_mutex_leave(pMainMtx);
return removed;
#else
UNUSED_PARAMETER( pBt );
return 1;
#endif
}
@@ -11324,6 +11325,7 @@ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
*/
int sqlite3BtreeSchemaLocked(Btree *p){
int rc;
UNUSED_PARAMETER(p); /* only used in DEBUG builds */
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK);

View File

@@ -237,7 +237,8 @@ static int dbpageFilter(
sqlite3 *db = pTab->db;
Btree *pBt;
(void)idxStr;
UNUSED_PARAMETER(idxStr);
UNUSED_PARAMETER(argc);
/* Default setting is no rows of result */
pCsr->pgno = 1;

View File

@@ -596,7 +596,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
}
pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol);
sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol);
if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 && pParse->nErr==0 ){
/* This branch runs if the query contains one or more RIGHT or FULL
** JOINs. If only a single table on the left side of this join
** contains the zName column, then this branch is a no-op.
@@ -612,6 +612,8 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
*/
ExprList *pFuncArgs = 0; /* Arguments to the coalesce() */
static const Token tkCoalesce = { "coalesce", 8 };
assert( pE1!=0 );
ExprSetProperty(pE1, EP_CanBeNull);
while( tableAndColumnIndex(pSrc, iLeft+1, i, zName, &iLeft, &iLeftCol,
pRight->fg.isSynthUsing)!=0 ){
if( pSrc->a[iLeft].fg.isUsing==0
@@ -628,7 +630,13 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
if( pFuncArgs ){
pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1);
pE1 = sqlite3ExprFunction(pParse, pFuncArgs, &tkCoalesce, 0);
if( pE1 ){
pE1->affExpr = sqlite3ExprAffinity(pFuncArgs->a[0].pExpr);
}
}
}else if( (pSrc->a[i+1].fg.jointype & JT_LEFT)!=0 && pParse->nErr==0 ){
assert( pE1!=0 );
ExprSetProperty(pE1, EP_CanBeNull);
}
pE2 = sqlite3CreateColumnExpr(db, pSrc, i+1, iRightCol);
sqlite3SrcItemColumnUsed(pRight, iRightCol);
@@ -2105,6 +2113,10 @@ static void generateColumnTypes(
#endif
sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
}
#else
UNUSED_PARAMETER(pParse);
UNUSED_PARAMETER(pTabList);
UNUSED_PARAMETER(pEList);
#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
}
@@ -4236,9 +4248,9 @@ static int compoundHasDifferentAffinities(Select *p){
** from 2015-02-09.)
**
** (3) If the subquery is the right operand of a LEFT JOIN then
** (3a) the subquery may not be a join and
** (3b) the FROM clause of the subquery may not contain a virtual
** table and
** (3a) the subquery may not be a join
** (**) Was (3b): "the FROM clause of the subquery may not contain
** a virtual table"
** (**) Was: "The outer query may not have a GROUP BY." This case
** is now managed correctly
** (3d) the outer query may not be DISTINCT.
@@ -4454,7 +4466,7 @@ static int flattenSubquery(
*/
if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){
if( pSubSrc->nSrc>1 /* (3a) */
|| IsVirtual(pSubSrc->a[0].pSTab) /* (3b) */
/**** || IsVirtual(pSubSrc->a[0].pSTab) (3b)-omitted */
|| (p->selFlags & SF_Distinct)!=0 /* (3d) */
|| (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */
){

View File

@@ -887,12 +887,21 @@ static int strlen30(const char *z){
/*
** Return the length of a string in characters. Multibyte UTF8 characters
** count as a single character.
** count as a single character for single-width characters, or as two
** characters for double-width characters.
*/
static int strlenChar(const char *z){
int n = 0;
while( *z ){
if( (0xc0&*(z++))!=0x80 ) n++;
if( (0x80&z[0])==0 ){
n++;
z++;
}else{
int u = 0;
int len = decodeUtf8((const u8*)z, &u);
z += len;
n += cli_wcwidth(u);
}
}
return n;
}

View File

@@ -2644,9 +2644,15 @@ struct FKey {
** argument to sqlite3VdbeKeyCompare and is used to control the
** comparison of the two index keys.
**
** Note that aSortOrder[] and aColl[] have nField+1 slots. There
** are nField slots for the columns of an index then one extra slot
** for the rowid at the end.
** The aSortOrder[] and aColl[] arrays have nAllField slots each. There
** are nKeyField slots for the columns of an index then extra slots
** for the rowid or key at the end. The aSortOrder array is located after
** the aColl[] array.
**
** If SQLITE_ENABLE_PREUPDATE_HOOK is defined, then aSortFlags might be NULL
** to indicate that this object is for use by a preupdate hook. When aSortFlags
** is NULL, then nAllField is uninitialized and no space is allocated for
** aColl[], so those fields may not be used.
*/
struct KeyInfo {
u32 nRef; /* Number of references to this KeyInfo object */
@@ -2658,7 +2664,9 @@ struct KeyInfo {
CollSeq *aColl[FLEXARRAY]; /* Collating sequence for each term of the key */
};
/* The size (in bytes) of a KeyInfo object with up to N fields */
/* The size (in bytes) of a KeyInfo object with up to N fields. This includes
** the main body of the KeyInfo object and the aColl[] array of N elements,
** but does not count the memory used to hold aSortFlags[]. */
#define SZ_KEYINFO(N) (offsetof(KeyInfo,aColl) + (N)*sizeof(CollSeq*))
/* The size of a bare KeyInfo with no aColl[] entries */
@@ -2686,9 +2694,8 @@ struct KeyInfo {
**
** An instance of this object serves as a "key" for doing a search on
** an index b+tree. The goal of the search is to find the entry that
** is closed to the key described by this object. This object might hold
** just a prefix of the key. The number of fields is given by
** pKeyInfo->nField.
** is closest to the key described by this object. This object might hold
** just a prefix of the key. The number of fields is given by nField.
**
** The r1 and r2 fields are the values to return if this key is less than
** or greater than a key in the btree, respectively. These are normally
@@ -2698,7 +2705,7 @@ struct KeyInfo {
** The key comparison functions actually return default_rc when they find
** an equals comparison. default_rc can be -1, 0, or +1. If there are
** multiple entries in the b-tree with the same key (when only looking
** at the first pKeyInfo->nFields,) then default_rc can be set to -1 to
** at the first nField elements) then default_rc can be set to -1 to
** cause the search to find the last match, or +1 to cause the search to
** find the first match.
**
@@ -2710,8 +2717,8 @@ struct KeyInfo {
** b-tree.
*/
struct UnpackedRecord {
KeyInfo *pKeyInfo; /* Collation and sort-order information */
Mem *aMem; /* Values */
KeyInfo *pKeyInfo; /* Comparison info for the index that is unpacked */
Mem *aMem; /* Values for columns of the index */
union {
char *z; /* Cache of aMem[0].z for vdbeRecordCompareString() */
i64 i; /* Cache of aMem[0].u.i for vdbeRecordCompareInt() */

View File

@@ -49,6 +49,10 @@
# define CONST const
#elif !defined(Tcl_Size)
typedef int Tcl_Size;
# ifndef Tcl_BounceRefCount
# define Tcl_BounceRefCount(X) Tcl_IncrRefCount(X); Tcl_DecrRefCount(X)
/* https://www.tcl-lang.org/man/tcl9.0/TclLib/Object.html */
# endif
#endif
/**** End copy of tclsqlite.h ****/
@@ -1084,7 +1088,9 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
Tcl_DecrRefCount(pCmd);
}
if( rc && rc!=TCL_RETURN ){
if( TCL_BREAK==rc ){
sqlite3_result_null(context);
}else if( rc && rc!=TCL_RETURN ){
sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
}else{
Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
@@ -1616,11 +1622,12 @@ struct DbEvalContext {
SqlPreparedStmt *pPreStmt; /* Current statement */
int nCol; /* Number of columns returned by pStmt */
int evalFlags; /* Flags used */
Tcl_Obj *pArray; /* Name of array variable */
Tcl_Obj *pVarName; /* Name of target array/dict variable */
Tcl_Obj **apColName; /* Array of column names */
};
#define SQLITE_EVAL_WITHOUTNULLS 0x00001 /* Unset array(*) for NULL */
#define SQLITE_EVAL_ASDICT 0x00002 /* Use dict instead of array */
/*
** Release any cache of column names currently held as part of
@@ -1641,20 +1648,20 @@ static void dbReleaseColumnNames(DbEvalContext *p){
/*
** Initialize a DbEvalContext structure.
**
** If pArray is not NULL, then it contains the name of a Tcl array
** If pVarName is not NULL, then it contains the name of a Tcl array
** variable. The "*" member of this array is set to a list containing
** the names of the columns returned by the statement as part of each
** call to dbEvalStep(), in order from left to right. e.g. if the names
** of the returned columns are a, b and c, it does the equivalent of the
** tcl command:
**
** set ${pArray}(*) {a b c}
** set ${pVarName}(*) {a b c}
*/
static void dbEvalInit(
DbEvalContext *p, /* Pointer to structure to initialize */
SqliteDb *pDb, /* Database handle */
Tcl_Obj *pSql, /* Object containing SQL script */
Tcl_Obj *pArray, /* Name of Tcl array to set (*) element of */
Tcl_Obj *pVarName, /* Name of Tcl array to set (*) element of */
int evalFlags /* Flags controlling evaluation */
){
memset(p, 0, sizeof(DbEvalContext));
@@ -1662,9 +1669,9 @@ static void dbEvalInit(
p->zSql = Tcl_GetString(pSql);
p->pSql = pSql;
Tcl_IncrRefCount(pSql);
if( pArray ){
p->pArray = pArray;
Tcl_IncrRefCount(pArray);
if( pVarName ){
p->pVarName = pVarName;
Tcl_IncrRefCount(pVarName);
}
p->evalFlags = evalFlags;
addDatabaseRef(p->pDb);
@@ -1687,7 +1694,7 @@ static void dbEvalRowInfo(
Tcl_Obj **apColName = 0; /* Array of column names */
p->nCol = nCol = sqlite3_column_count(pStmt);
if( nCol>0 && (papColName || p->pArray) ){
if( nCol>0 && (papColName || p->pVarName) ){
apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol );
for(i=0; i<nCol; i++){
apColName[i] = Tcl_NewStringObj(sqlite3_column_name(pStmt,i), -1);
@@ -1696,20 +1703,35 @@ static void dbEvalRowInfo(
p->apColName = apColName;
}
/* If results are being stored in an array variable, then create
** the array(*) entry for that array
/* If results are being stored in a variable then create the
** array(*) or dict(*) entry for that variable.
*/
if( p->pArray ){
if( p->pVarName ){
Tcl_Interp *interp = p->pDb->interp;
Tcl_Obj *pColList = Tcl_NewObj();
Tcl_Obj *pStar = Tcl_NewStringObj("*", -1);
Tcl_IncrRefCount(pColList);
Tcl_IncrRefCount(pStar);
for(i=0; i<nCol; i++){
Tcl_ListObjAppendElement(interp, pColList, apColName[i]);
}
Tcl_IncrRefCount(pStar);
Tcl_ObjSetVar2(interp, p->pArray, pStar, pColList, 0);
if( 0==(SQLITE_EVAL_ASDICT & p->evalFlags) ){
Tcl_ObjSetVar2(interp, p->pVarName, pStar, pColList, 0);
}else{
Tcl_Obj * pDict = Tcl_ObjGetVar2(interp, p->pVarName, NULL, 0);
if( !pDict ){
pDict = Tcl_NewDictObj();
}else if( Tcl_IsShared(pDict) ){
pDict = Tcl_DuplicateObj(pDict);
}
if( Tcl_DictObjPut(interp, pDict, pStar, pColList)==TCL_OK ){
Tcl_ObjSetVar2(interp, p->pVarName, NULL, pDict, 0);
}
Tcl_BounceRefCount(pDict);
}
Tcl_DecrRefCount(pStar);
Tcl_DecrRefCount(pColList);
}
}
@@ -1751,7 +1773,7 @@ static int dbEvalStep(DbEvalContext *p){
if( rcs==SQLITE_ROW ){
return TCL_OK;
}
if( p->pArray ){
if( p->pVarName ){
dbEvalRowInfo(p, 0, 0);
}
rcs = sqlite3_reset(pStmt);
@@ -1802,9 +1824,9 @@ static void dbEvalFinalize(DbEvalContext *p){
dbReleaseStmt(p->pDb, p->pPreStmt, 0);
p->pPreStmt = 0;
}
if( p->pArray ){
Tcl_DecrRefCount(p->pArray);
p->pArray = 0;
if( p->pVarName ){
Tcl_DecrRefCount(p->pVarName);
p->pVarName = 0;
}
Tcl_DecrRefCount(p->pSql);
dbReleaseColumnNames(p);
@@ -1879,7 +1901,7 @@ static int DbUseNre(void){
/*
** This function is part of the implementation of the command:
**
** $db eval SQL ?ARRAYNAME? SCRIPT
** $db eval SQL ?TGT-NAME? SCRIPT
*/
static int SQLITE_TCLAPI DbEvalNextCmd(
ClientData data[], /* data[0] is the (DbEvalContext*) */
@@ -1893,8 +1915,8 @@ static int SQLITE_TCLAPI DbEvalNextCmd(
** is a pointer to a Tcl_Obj containing the script to run for each row
** returned by the queries encapsulated in data[0]. */
DbEvalContext *p = (DbEvalContext *)data[0];
Tcl_Obj *pScript = (Tcl_Obj *)data[1];
Tcl_Obj *pArray = p->pArray;
Tcl_Obj * const pScript = (Tcl_Obj *)data[1];
Tcl_Obj * const pVarName = p->pVarName;
while( (rc==TCL_OK || rc==TCL_CONTINUE) && TCL_OK==(rc = dbEvalStep(p)) ){
int i;
@@ -1902,15 +1924,46 @@ static int SQLITE_TCLAPI DbEvalNextCmd(
Tcl_Obj **apColName;
dbEvalRowInfo(p, &nCol, &apColName);
for(i=0; i<nCol; i++){
if( pArray==0 ){
if( pVarName==0 ){
Tcl_ObjSetVar2(interp, apColName[i], 0, dbEvalColumnValue(p,i), 0);
}else if( (p->evalFlags & SQLITE_EVAL_WITHOUTNULLS)!=0
&& sqlite3_column_type(p->pPreStmt->pStmt, i)==SQLITE_NULL
){
Tcl_UnsetVar2(interp, Tcl_GetString(pArray),
Tcl_GetString(apColName[i]), 0);
/* Remove NULL-containing column from the target container... */
if( 0==(SQLITE_EVAL_ASDICT & p->evalFlags) ){
/* Target is an array */
Tcl_UnsetVar2(interp, Tcl_GetString(pVarName),
Tcl_GetString(apColName[i]), 0);
}else{
/* Target is a dict */
Tcl_Obj *pDict = Tcl_ObjGetVar2(interp, pVarName, NULL, 0);
if( pDict ){
if( Tcl_IsShared(pDict) ){
pDict = Tcl_DuplicateObj(pDict);
}
if( Tcl_DictObjRemove(interp, pDict, apColName[i])==TCL_OK ){
Tcl_ObjSetVar2(interp, pVarName, NULL, pDict, 0);
}
Tcl_BounceRefCount(pDict);
}
}
}else if( 0==(SQLITE_EVAL_ASDICT & p->evalFlags) ){
/* Target is an array: set target(colName) = colValue */
Tcl_ObjSetVar2(interp, pVarName, apColName[i],
dbEvalColumnValue(p,i), 0);
}else{
Tcl_ObjSetVar2(interp, pArray, apColName[i], dbEvalColumnValue(p,i), 0);
/* Target is a dict: set target(colName) = colValue */
Tcl_Obj *pDict = Tcl_ObjGetVar2(interp, pVarName, NULL, 0);
if( !pDict ){
pDict = Tcl_NewDictObj();
}else if( Tcl_IsShared(pDict) ){
pDict = Tcl_DuplicateObj(pDict);
}
if( Tcl_DictObjPut(interp, pDict, apColName[i],
dbEvalColumnValue(p,i))==TCL_OK ){
Tcl_ObjSetVar2(interp, pVarName, NULL, pDict, 0);
}
Tcl_BounceRefCount(pDict);
}
}
@@ -2853,13 +2906,15 @@ deserialize_error:
}
/*
** $db eval ?options? $sql ?array? ?{ ...code... }?
** $db eval ?options? $sql ?varName? ?{ ...code... }?
**
** The SQL statement in $sql is evaluated. For each row, the values are
** placed in elements of the array named "array" and ...code... is executed.
** If "array" and "code" are omitted, then no callback is every invoked.
** If "array" is an empty string, then the values are placed in variables
** that have the same name as the fields extracted by the query.
** The SQL statement in $sql is evaluated. For each row, the values
** are placed in elements of the array or dict named $varName and
** ...code... is executed. If $varName and $code are omitted, then
** no callback is ever invoked. If $varName is an empty string,
** then the values are placed in variables that have the same name
** as the fields extracted by the query, and those variables are
** accessible during the eval of $code.
*/
case DB_EVAL: {
int evalFlags = 0;
@@ -2867,8 +2922,9 @@ deserialize_error:
while( objc>3 && (zOpt = Tcl_GetString(objv[2]))!=0 && zOpt[0]=='-' ){
if( strcmp(zOpt, "-withoutnulls")==0 ){
evalFlags |= SQLITE_EVAL_WITHOUTNULLS;
}
else{
}else if( strcmp(zOpt, "-asdict")==0 ){
evalFlags |= SQLITE_EVAL_ASDICT;
}else{
Tcl_AppendResult(interp, "unknown option: \"", zOpt, "\"", (void*)0);
return TCL_ERROR;
}
@@ -2877,7 +2933,7 @@ deserialize_error:
}
if( objc<3 || objc>5 ){
Tcl_WrongNumArgs(interp, 2, objv,
"?OPTIONS? SQL ?ARRAY-NAME? ?SCRIPT?");
"?OPTIONS? SQL ?VAR-NAME? ?SCRIPT?");
return TCL_ERROR;
}
@@ -2903,17 +2959,17 @@ deserialize_error:
}else{
ClientData cd2[2];
DbEvalContext *p;
Tcl_Obj *pArray = 0;
Tcl_Obj *pVarName = 0;
Tcl_Obj *pScript;
if( objc>=5 && *(char *)Tcl_GetString(objv[3]) ){
pArray = objv[3];
pVarName = objv[3];
}
pScript = objv[objc-1];
Tcl_IncrRefCount(pScript);
p = (DbEvalContext *)Tcl_Alloc(sizeof(DbEvalContext));
dbEvalInit(p, pDb, objv[2], pArray, evalFlags);
dbEvalInit(p, pDb, objv[2], pVarName, evalFlags);
cd2[0] = (void *)p;
cd2[1] = (void *)pScript;

View File

@@ -8458,7 +8458,12 @@ static int SQLITE_TCLAPI test_sqlite3_db_config(
{ "DQS_DML", SQLITE_DBCONFIG_DQS_DML },
{ "DQS_DDL", SQLITE_DBCONFIG_DQS_DDL },
{ "LEGACY_FILE_FORMAT", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
{ "TRUSTED_SCHEMA", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
{ "STMT_SCANSTATUS", SQLITE_DBCONFIG_STMT_SCANSTATUS },
{ "REVERSE_SCANORDER", SQLITE_DBCONFIG_REVERSE_SCANORDER },
{ "ATTACH_CREATE", SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE },
{ "ATTACH_WRITE", SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE },
{ "COMMENTS", SQLITE_DBCONFIG_ENABLE_COMMENTS },
};
int i;
int v = 0;

View File

@@ -195,7 +195,8 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
saved_nChange = db->nChange;
saved_nTotalChange = db->nTotalChange;
saved_mTrace = db->mTrace;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments
| SQLITE_AttachCreate | SQLITE_AttachWrite;
db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder
| SQLITE_Defensive | SQLITE_CountRows);

View File

@@ -2476,6 +2476,7 @@ case OP_Compare: {
pKeyInfo = pOp->p4.pKeyInfo;
assert( n>0 );
assert( pKeyInfo!=0 );
assert( pKeyInfo->aSortFlags!=0 );
p1 = pOp->p1;
p2 = pOp->p2;
#ifdef SQLITE_DEBUG
@@ -5349,7 +5350,7 @@ case OP_Found: { /* jump, in3, ncycle */
if( rc ) goto no_mem;
pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
if( pIdxKey==0 ) goto no_mem;
sqlite3VdbeRecordUnpack(pC->pKeyInfo, r.aMem->n, r.aMem->z, pIdxKey);
sqlite3VdbeRecordUnpack(r.aMem->n, r.aMem->z, pIdxKey);
pIdxKey->default_rc = 0;
rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &pC->seekResult);
sqlite3DbFreeNN(db, pIdxKey);

View File

@@ -301,7 +301,7 @@ void sqlite3VdbeSetVarmask(Vdbe*, int);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
int sqlite3BlobCompare(const Mem*, const Mem*);
void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
void sqlite3VdbeRecordUnpack(int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);

View File

@@ -2163,7 +2163,7 @@ static UnpackedRecord *vdbeUnpackRecord(
pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pRet ){
memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1));
sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet);
sqlite3VdbeRecordUnpack(nKey, pKey, pRet);
}
return pRet;
}

View File

@@ -4202,30 +4202,22 @@ void sqlite3VdbeSerialGet(
return;
}
/*
** This routine is used to allocate sufficient space for an UnpackedRecord
** structure large enough to be used with sqlite3VdbeRecordUnpack() if
** the first argument is a pointer to KeyInfo structure pKeyInfo.
** Allocate sufficient space for an UnpackedRecord structure large enough
** to hold a decoded index record for pKeyInfo.
**
** The space is either allocated using sqlite3DbMallocRaw() or from within
** the unaligned buffer passed via the second and third arguments (presumably
** stack space). If the former, then *ppFree is set to a pointer that should
** be eventually freed by the caller using sqlite3DbFree(). Or, if the
** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
** before returning.
**
** If an OOM error occurs, NULL is returned.
** The space is allocated using sqlite3DbMallocRaw(). If an OOM error
** occurs, NULL is returned.
*/
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
KeyInfo *pKeyInfo /* Description of the record */
){
UnpackedRecord *p; /* Unpacked record to return */
int nByte; /* Number of bytes required for *p */
u64 nByte; /* Number of bytes required for *p */
assert( sizeof(UnpackedRecord) + sizeof(Mem)*65536 < 0x7fffffff );
nByte = ROUND8P(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1);
p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
if( !p ) return 0;
p->aMem = (Mem*)&((char*)p)[ROUND8P(sizeof(UnpackedRecord))];
assert( pKeyInfo->aSortFlags!=0 );
p->pKeyInfo = pKeyInfo;
p->nField = pKeyInfo->nKeyField + 1;
return p;
@@ -4237,7 +4229,6 @@ UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
** contents of the decoded record.
*/
void sqlite3VdbeRecordUnpack(
KeyInfo *pKeyInfo, /* Information about the record format */
int nKey, /* Size of the binary record */
const void *pKey, /* The binary record */
UnpackedRecord *p /* Populate this structure before returning. */
@@ -4248,6 +4239,7 @@ void sqlite3VdbeRecordUnpack(
u16 u; /* Unsigned loop counter */
u32 szHdr;
Mem *pMem = p->aMem;
KeyInfo *pKeyInfo = p->pKeyInfo;
p->default_rc = 0;
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
@@ -4275,6 +4267,8 @@ void sqlite3VdbeRecordUnpack(
** warnings from MSAN. */
sqlite3VdbeMemSetNull(pMem-1);
}
testcase( u == pKeyInfo->nKeyField + 1 );
testcase( u < pKeyInfo->nKeyField + 1 );
assert( u<=pKeyInfo->nKeyField + 1 );
p->nField = u;
}
@@ -5134,6 +5128,7 @@ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
** The easiest way to enforce this limit is to consider only records with
** 13 fields or less. If the first field is an integer, the maximum legal
** header size is (12*5 + 1 + 1) bytes. */
assert( p->pKeyInfo->aSortFlags!=0 );
if( p->pKeyInfo->nAllField<=13 ){
int flags = p->aMem[0].flags;
if( p->pKeyInfo->aSortFlags[0] ){
@@ -5492,7 +5487,6 @@ void sqlite3VdbePreUpdateHook(
i64 iKey2;
PreUpdate preupdate;
const char *zTbl = pTab->zName;
static const u8 fakeSortOrder = 0;
#ifdef SQLITE_DEBUG
int nRealCol;
if( pTab->tabFlags & TF_WithoutRowid ){
@@ -5531,7 +5525,7 @@ void sqlite3VdbePreUpdateHook(
preupdate.pKeyinfo->db = db;
preupdate.pKeyinfo->enc = ENC(db);
preupdate.pKeyinfo->nKeyField = pTab->nCol;
preupdate.pKeyinfo->aSortFlags = (u8*)&fakeSortOrder;
preupdate.pKeyinfo->aSortFlags = 0; /* Indicate .aColl, .nAllField uninit */
preupdate.iKey1 = iKey1;
preupdate.iKey2 = iKey2;
preupdate.pTab = pTab;

View File

@@ -766,7 +766,7 @@ static int vdbeSorterCompareTail(
){
UnpackedRecord *r2 = pTask->pUnpacked;
if( *pbKey2Cached==0 ){
sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
sqlite3VdbeRecordUnpack(nKey2, pKey2, r2);
*pbKey2Cached = 1;
}
return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1);
@@ -793,7 +793,7 @@ static int vdbeSorterCompare(
){
UnpackedRecord *r2 = pTask->pUnpacked;
if( !*pbKey2Cached ){
sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
sqlite3VdbeRecordUnpack(nKey2, pKey2, r2);
*pbKey2Cached = 1;
}
return sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
@@ -833,6 +833,7 @@ static int vdbeSorterCompareText(
);
}
}else{
assert( pTask->pSorter->pKeyInfo->aSortFlags!=0 );
assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) );
if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){
res = res * -1;
@@ -896,6 +897,7 @@ static int vdbeSorterCompareInt(
}
}
assert( pTask->pSorter->pKeyInfo->aSortFlags!=0 );
if( res==0 ){
if( pTask->pSorter->pKeyInfo->nKeyField>1 ){
res = vdbeSorterCompareTail(
@@ -969,7 +971,8 @@ int sqlite3VdbeSorterInit(
assert( pCsr->eCurType==CURTYPE_SORTER );
assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*)
< 0x7fffffff );
szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nKeyField+1);
assert( pCsr->pKeyInfo->nKeyField<=pCsr->pKeyInfo->nAllField );
szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nAllField);
sz = SZ_VDBESORTER(nWorker+1);
pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo);
@@ -983,7 +986,12 @@ int sqlite3VdbeSorterInit(
pKeyInfo->db = 0;
if( nField && nWorker==0 ){
pKeyInfo->nKeyField = nField;
assert( nField<=pCsr->pKeyInfo->nAllField );
}
/* It is OK that pKeyInfo reuses the aSortFlags field from pCsr->pKeyInfo,
** since the pCsr->pKeyInfo->aSortFlags[] array is invariant and lives
** longer that pSorter. */
assert( pKeyInfo->aSortFlags==pCsr->pKeyInfo->aSortFlags );
sqlite3BtreeEnter(pBt);
pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(pBt);
sqlite3BtreeLeave(pBt);
@@ -2763,7 +2771,7 @@ int sqlite3VdbeSorterCompare(
assert( r2->nField==nKeyCol );
pKey = vdbeSorterRowkey(pSorter, &nKey);
sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, r2);
sqlite3VdbeRecordUnpack(nKey, pKey, r2);
for(i=0; i<nKeyCol; i++){
if( r2->aMem[i].flags & MEM_Null ){
*pRes = -1;

20
test/dblwidth-a.sql Normal file
View File

@@ -0,0 +1,20 @@
/*
** Run this script using "sqlite3" to confirm that the command-line
** shell properly handles the output of double-width characters.
**
** https://sqlite.org/forum/forumpost/008ac80276
*/
.mode box
CREATE TABLE data(word TEXT, description TEXT);
INSERT INTO data VALUES('〈οὐκέτι〉','Greek without dblwidth <...>');
.print .mode box
SELECT * FROM data;
.mode table
.print .mode table
SELECT * FROM data;
.mode qbox
.print .mode qbox
SELECT * FROM data;
.mode column
.print .mode column
SELECT * FROM data;

View File

@@ -97,11 +97,8 @@ do_eqp_test 4.2 {
WHERE t4.y = ?;
} {
QUERY PLAN
|--MATERIALIZE rr
| `--SCAN ft4 VIRTUAL TABLE INDEX 3:
|--SCAN t4
|--BLOOM FILTER ON rr (docid=?)
`--SEARCH rr USING AUTOMATIC COVERING INDEX (docid=?) LEFT-JOIN
`--SCAN ft4 VIRTUAL TABLE INDEX 3: LEFT-JOIN
}
finish_test

View File

@@ -1304,4 +1304,42 @@ do_execsql_test join-30.3 {
WHERE x <= y;
} {}
# 2025-05-30 https://sqlite.org/forum/forumpost/4fc70203b61c7e12
#
# When converting a USING(x) or NATURAL into the constraint expression
# t1.x==t2.x, mark the t1.x term as EP_CanBeNull if it is the left table
# of a RIGHT JOIN.
#
reset_db
db null NULL
do_execsql_test join-31.1 {
CREATE TABLE t1(c0 INT , c1 INT); INSERT INTO t1(c0, c1) VALUES(NULL,11);
CREATE TABLE t2(c0 INT NOT NULL);
CREATE TABLE t2n(c0 INT);
CREATE TABLE t3(x INT); INSERT INTO t3(x) VALUES(3);
CREATE TABLE t4(y INT); INSERT INTO t4(y) VALUES(4);
CREATE TABLE t5(c0 INT, x INT); INSERT INTO t5 VALUES(NULL, 5);
}
do_execsql_test join-31.2 {
SELECT * FROM t2 RIGHT JOIN t3 ON true LEFT JOIN t1 USING(c0);
} {NULL 3 NULL}
do_execsql_test join-31.3 {
SELECT * FROM t2 RIGHT JOIN t3 ON true NATURAL LEFT JOIN t1;
} {NULL 3 NULL}
do_execsql_test join-31.4 {
SELECT * FROM t2n RIGHT JOIN t3 ON true LEFT JOIN t1 USING(c0);
} {NULL 3 NULL}
do_execsql_test join-31.5 {
SELECT * FROM t5 LEFT JOIN t1 USING(c0);
} {NULL 5 NULL}
do_execsql_test join-31.6 {
SELECT * FROM t3 LEFT JOIN t2 ON true LEFT JOIN t1 USING(c0);
} {3 NULL NULL}
do_execsql_test join-31.7 {
SELECT * FROM t3 LEFT JOIN t2 ON true NATURAL LEFT JOIN t1;
} {3 NULL NULL}
do_execsql_test join-31.8 {
SELECT * FROM t3 LEFT JOIN t2 ON true JOIN t4 ON true NATURAL LEFT JOIN t1;
} {3 NULL 4 NULL}
finish_test

View File

@@ -341,4 +341,53 @@ do_execsql_test 13.4 {
GROUP BY a1.a ORDER BY 1;
} {-1480 240 480}
#-------------------------------------------------------------------------
# 2025-05-30
# https://sqlite.org/forum/forumpost/5028c785b6
#
reset_db
do_execsql_test 14.0 {
CREATE TABLE t1(c0 INT);
CREATE TABLE t2(c0 BLOB);
CREATE TABLE t3(c0 BLOB);
CREATE TABLE t4(c4 BLOB);
INSERT INTO t1(c0) VALUES(0);
INSERT INTO t3(c0) VALUES('0');
}
do_execsql_test 14.1.1 {
SELECT * FROM t1 NATURAL LEFT JOIN t2 NATURAL JOIN t3;
} {0}
do_execsql_test 14.1.2 {
SELECT * FROM t1 NATURAL LEFT JOIN t2 NATURAL JOIN t3 FULL JOIN t4 ON true;
} {0 {}}
do_execsql_test 14.1.3 {
SELECT * FROM (t1 NATURAL LEFT JOIN t2 NATURAL JOIN t3) FULL JOIN t4 ON true;
} {0 {}}
do_execsql_test 14.1.4 {
SELECT *
FROM (t1 NATURAL LEFT JOIN t2 NATURAL JOIN t3) AS qq FULL JOIN t4 ON true;
} {0 {}}
do_execsql_test 14.2.1 {
SELECT * FROM t3 NATURAL LEFT JOIN t2 NATURAL JOIN t1;
} {0}
do_execsql_test 14.2.2 {
SELECT * FROM t3 NATURAL LEFT JOIN t2 NATURAL JOIN t1 FULL JOIN t4 ON true;
} {0 {}}
do_execsql_test 14.2.3 {
SELECT * FROM (t3 NATURAL LEFT JOIN t2 NATURAL JOIN t1) FULL JOIN t4 ON true;
} {0 {}}
do_execsql_test 14.2.4 {
SELECT *
FROM (t3 NATURAL LEFT JOIN t2 NATURAL JOIN t1) AS qq FULL JOIN t4 ON true;
} {0 {}}
finish_test

View File

@@ -121,7 +121,7 @@ ifcapable {complete} {
do_test tcl-1.14 {
set v [catch {db eval} msg]
lappend v $msg
} {1 {wrong # args: should be "db eval ?OPTIONS? SQL ?ARRAY-NAME? ?SCRIPT?"}}
} {1 {wrong # args: should be "db eval ?OPTIONS? SQL ?VAR-NAME? ?SCRIPT?"}}
do_test tcl-1.15 {
set v [catch {db function} msg]
lappend v $msg
@@ -359,6 +359,19 @@ do_test tcl-9.3 {
execsql {SELECT typeof(ret_int())}
} {integer}
proc breakAsNullUdf args {
if {"1" eq [lindex $args 0]} {return -code break}
}
do_test tcl-9.4 {
db function banu breakAsNullUdf
execsql {SELECT typeof(banu()), typeof(banu(1))}
} {text null}
do_test tcl-9.5 {
db nullvalue banunull
db eval {SELECT banu(), banu(1)}
} {{} banunull}
# Recursive calls to the same user-defined function
#
ifcapable tclvar {
@@ -674,11 +687,11 @@ do_test tcl-15.5 {
} {0}
# 2017-06-26: The --withoutnulls flag to "db eval".
# 2017-06-26: The -withoutnulls flag to "db eval".
#
# In the "db eval --withoutnulls SQL ARRAY" form, NULL results cause the
# corresponding array entry to be unset. The default behavior (without
# the -withoutnulls flags) is for the corresponding array value to get
# In the "db eval -withoutnulls SQL TARGET" form, NULL results cause the
# corresponding target entry to be unset. The default behavior (without
# the -withoutnulls flags) is for the corresponding target value to get
# the [db nullvalue] string.
#
catch {db close}
@@ -848,14 +861,62 @@ do_catchsql_test 19.911 {
} {1 {invalid command name "bind_fallback_does_not_exist"}}
db bind_fallback {}
#-------------------------------------------------------------------------
# 2025-05-05: the -asdict eval flag
#
do_test 20.0 {
execsql {CREATE TABLE tad(a,b)}
execsql {INSERT INTO tad(a,b) VALUES('aa','bb'),('AA','BB')}
db eval -asdict {
SELECT a, b FROM tad WHERE 0
} D {}
set D
} {* {a b}}
do_test 20.1 {
unset D
set i 0
set res {}
set colNames {}
db eval -asdict {
SELECT a, b FROM tad ORDER BY a
} D {
dict set D i [incr i]
lappend res $i [dict get $D a] [dict get $D b]
if {1 == $i} {
set colNames [dict get $D *]
}
}
lappend res $colNames
unset D
set res
} {1 AA BB 2 aa bb {a b}}
do_test 20.2 {
set res {}
db eval -asdict -withoutnulls {
SELECT n, a, b FROM (
SELECT 1 as n, 'aa' as a, NULL as b
UNION ALL
SELECT 2 as n, NULL as a, 'bb' as b
)
ORDER BY n
} D {
dict unset D *
lappend res [dict values $D]
}
unset D
execsql {DROP TABLE tad}
set res
} {{1 aa} {2 bb}}
#-------------------------------------------------------------------------
do_test 21.0 {
db transaction {
db close
}
} {}
do_test 20.1 {
do_test 21.1 {
sqlite3 db test.db
set rc [catch {
db eval {SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3} { db close }
@@ -864,6 +925,7 @@ do_test 20.1 {
} {1 {invalid command name "db"}}
proc closedb {} {
db close
return 10
@@ -874,7 +936,7 @@ sqlite3 db test.db
db func closedb closedb
db func func1 func1
do_test 20.2 {
do_test 21.2 {
set rc [catch {
db eval {
SELECT closedb(),func1() UNION ALL SELECT 20,30 UNION ALL SELECT 30,40
@@ -884,9 +946,10 @@ do_test 20.2 {
} {0 {10 1 20 30 30 40}}
sqlite3 db :memory:
do_test 21.1 {
do_test 22.1 {
catch {db eval {SELECT 1 2 3;}} msg
db erroroffset
} {9}
finish_test

View File

@@ -401,4 +401,25 @@ do_test vacuum-10.1 {
} {}
do_test vacuum-10.2 { execsql VACUUM } {}
# Verify that VACUUM still works if ATTACH is disabled.
#
do_execsql_test vacuum-11.1 {
PRAGMA page_size=1024;
VACUUM;
PRAGMA page_size;
} {1024}
sqlite3_db_config db ATTACH_CREATE 0
do_execsql_test vacuum-11.2 {
PRAGMA page_size=2048;
VACUUM;
PRAGMA page_size;
} {2048}
sqlite3_db_config db ATTACH_CREATE 1
sqlite3_db_config db ATTACH_WRITE 0
do_execsql_test vacuum-11.3 {
PRAGMA page_size=4096;
VACUUM;
PRAGMA page_size;
} {4096}
finish_test